gecko-dev/xpcom/ds/nsStaticAtom.h
Nicholas Nethercote 8ad99dd7fa Bug 1411893 - Introduce nsStaticAtom. r=emilio,froydnj.
It's a sub-class of nsAtom, useful for cases where you know you are dealing
exclusively with static atoms. The nice thing about it is that you can use
raw nsStaticAtom pointers instead of RefPtr<>. (In fact, the AddRef/Release
implementations ensure that we'll crash if we use RefPtr<nsStaticAtom>.)

MozReview-Commit-ID: 4Q6QHX5h44V

--HG--
extra : rebase_source : e4237f85b4821b684db0ef84d1f9c5e17cdee428
2017-10-27 10:31:13 +11:00

130 lines
4.4 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsStaticAtom_h__
#define nsStaticAtom_h__
#include <stdint.h>
class nsStaticAtom;
// The following macros are used to define static atoms, typically in
// conjunction with a .h file that defines the names and values of the atoms.
//
// For example, the .h file might be called MyAtomList.h and look like this:
//
// MY_ATOM(one, "one")
// MY_ATOM(two, "two")
// MY_ATOM(three, "three")
//
// The code defining the static atoms might look like this:
//
// class MyAtoms {
// public:
// #define MY_ATOM(_name, _value) NS_STATIC_ATOM_DECL(_name)
// #include "MyAtomList.h"
// #undef MY_ATOM
// };
//
// #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DEFN(MyAtoms, name_)
// #include "MyAtomList.h"
// #undef MY_ATOM
//
// #define MY_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_, value_)
// #include "MyAtomList.h"
// #undef MY_ATOM
//
// static const nsStaticAtomSetup sMyAtomSetup[] = {
// #define MY_ATOM(name_, value_) NS_STATIC_ATOM_SETUP(MyAtoms, name_)
// #include "MyAtomList.h"
// #undef MY_ATOM
// };
//
// The macros expand to the following:
//
// class MyAtoms
// {
// public:
// static nsStaticAtom* one;
// static nsStaticAtom* two;
// static nsStaticAtom* three;
// };
//
// nsStaticAtom* MyAtoms::one;
// nsStaticAtom* MyAtoms::two;
// nsStaticAtom* MyAtoms::three;
//
// static const char16_t one_buffer[4] = u"one"; // plus a static_assert
// static const char16_t two_buffer[4] = u"two"; // plus a static_assert
// static const char16_t three_buffer[6] = u"three"; // plus a static_assert
//
// static const nsStaticAtomSetup sMyAtomSetup[] = {
// { one_buffer, &MyAtoms::one },
// { two_buffer, &MyAtoms::two },
// { three_buffer, &MyAtoms::three },
// };
//
// When RegisterStaticAtoms(sMyAtomSetup) is called it iterates over
// sMyAtomSetup[]. E.g. for the first atom it does roughly the following:
// - MyAtoms::one = new nsStaticAtom(one_buffer)
// - inserts MyAtoms::one into the atom table
// The declaration of the pointer to the static atom, which must be within a
// class.
#define NS_STATIC_ATOM_DECL(name_) \
static nsStaticAtom* name_;
// Like NS_STATIC_ATOM_DECL, but for sub-classes of nsStaticAtom.
#define NS_STATIC_ATOM_SUBCLASS_DECL(type_, name_) \
static type_* name_;
// The definition of the pointer to the static atom. Initially null, it is
// set by RegisterStaticAtoms() to point to a heap-allocated nsStaticAtom.
#define NS_STATIC_ATOM_DEFN(class_, name_) \
nsStaticAtom* class_::name_;
// Like NS_STATIC_ATOM_DEFN, but for sub-classes of nsStaticAtom.
#define NS_STATIC_ATOM_SUBCLASS_DEFN(type_, class_, name_) \
type_* class_::name_;
// The buffer of 16-bit chars that constitute the static atom.
//
// Note that |value_| is an 8-bit string, and so |sizeof(value_)| is equal
// to the number of chars (including the terminating '\0'). The |u""| prefix
// converts |value_| to a 16-bit string, which is what is assigned.
#define NS_STATIC_ATOM_BUFFER(name_, value_) \
static const char16_t name_##_buffer[sizeof(value_)] = u"" value_; \
static_assert(sizeof(value_[0]) == 1, "non-8-bit static atom literal");
// The StaticAtomSetup. Used only during start-up.
#define NS_STATIC_ATOM_SETUP(class_, name_) \
{ name_##_buffer, &class_::name_ },
// Like NS_STATIC_ATOM_SUBCLASS, but for sub-classes of nsStaticAtom.
#define NS_STATIC_ATOM_SUBCLASS_SETUP(class_, name_) \
{ name_##_buffer, reinterpret_cast<nsStaticAtom**>(&class_::name_) },
// Holds data used to initialize large number of atoms during startup. Use
// NS_STATIC_ATOM_SETUP to initialize these structs. They should never be
// accessed directly other than from nsAtomTable.cpp.
struct nsStaticAtomSetup
{
const char16_t* const mString;
nsStaticAtom** const mAtom;
};
// Register an array of static atoms with the atom table.
template<uint32_t N>
void
NS_RegisterStaticAtoms(const nsStaticAtomSetup (&aSetup)[N])
{
extern void RegisterStaticAtoms(const nsStaticAtomSetup* aSetup,
uint32_t aCount);
RegisterStaticAtoms(aSetup, N);
}
#endif