Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* Macros to emulate C++11 typed enums and enum classes. */
9 #ifndef mozilla_TypedEnum_h
10 #define mozilla_TypedEnum_h
12 #include "mozilla/TypedEnumInternal.h"
13 #include "mozilla/MacroArgs.h"
15 #if defined(__cplusplus)
17 /**
18 * MOZ_ENUM_TYPE specifies the underlying numeric type for an enum. It's
19 * specified by placing MOZ_ENUM_TYPE(type) immediately after the enum name in
20 * its declaration, and before the opening curly brace, like
21 *
22 * enum MyEnum MOZ_ENUM_TYPE(uint16_t)
23 * {
24 * A,
25 * B = 7,
26 * C
27 * };
28 *
29 * In supporting compilers, the macro will expand to ": uint16_t". The
30 * compiler will allocate exactly two bytes for MyEnum and will require all
31 * enumerators to have values between 0 and 65535. (Thus specifying "B =
32 * 100000" instead of "B = 7" would fail to compile.) In old compilers the
33 * macro expands to the empty string, and the underlying type is generally
34 * undefined.
35 */
36 #ifdef MOZ_HAVE_CXX11_ENUM_TYPE
37 # define MOZ_ENUM_TYPE(type) : type
38 #else
39 # define MOZ_ENUM_TYPE(type) /* no support */
40 #endif
42 /**
43 * MOZ_BEGIN_ENUM_CLASS and MOZ_END_ENUM_CLASS provide access to the
44 * strongly-typed enumeration feature of C++11 ("enum class"). If supported
45 * by the compiler, an enum defined using these macros will not be implicitly
46 * converted to any other type, and its enumerators will be scoped using the
47 * enumeration name. Place MOZ_BEGIN_ENUM_CLASS(EnumName [, type]) in place of
48 * "enum EnumName {", and MOZ_END_ENUM_CLASS(EnumName) in place of the closing
49 * "};". For example,
50 *
51 * MOZ_BEGIN_ENUM_CLASS(Enum, int32_t)
52 * A,
53 * B = 6
54 * MOZ_END_ENUM_CLASS(Enum)
55 *
56 * This will make "Enum::A" and "Enum::B" appear in the global scope, but "A"
57 * and "B" will not. In compilers that support C++11 strongly-typed
58 * enumerations, implicit conversions of Enum values to numeric types will
59 * fail. In other compilers, Enum itself will actually be defined as a class,
60 * and some implicit conversions will fail while others will succeed.
61 *
62 * The optional type argument specifies the underlying type for the enum where
63 * supported, as with MOZ_ENUM_TYPE(). As with MOZ_ENUM_TYPE(), it will do
64 * nothing on compilers that do not support it.
65 *
66 * MOZ_{BEGIN,END}_ENUM_CLASS doesn't work for defining enum classes nested
67 * inside classes. To define an enum class nested inside another class, use
68 * MOZ_{BEGIN,END}_NESTED_ENUM_CLASS, and place a MOZ_FINISH_NESTED_ENUM_CLASS
69 * in namespace scope to handle bits that can only be implemented with
70 * namespace-scoped code. For example:
71 *
72 * class FooBar {
73 *
74 * MOZ_BEGIN_NESTED_ENUM_CLASS(Enum, int32_t)
75 * A,
76 * B = 6
77 * MOZ_END_NESTED_ENUM_CLASS(Enum)
78 *
79 * };
80 *
81 * MOZ_FINISH_NESTED_ENUM_CLASS(FooBar::Enum)
82 */
83 #if defined(MOZ_HAVE_CXX11_STRONG_ENUMS)
84 /*
85 * All compilers that support strong enums also support an explicit
86 * underlying type, so no extra check is needed.
87 */
89 /* Single-argument form. */
90 # define MOZ_BEGIN_NESTED_ENUM_CLASS_HELPER1(Name) \
91 enum class Name {
92 /* Two-argument form. */
93 # define MOZ_BEGIN_NESTED_ENUM_CLASS_HELPER2(Name, type) \
94 enum class Name : type {
95 # define MOZ_END_NESTED_ENUM_CLASS(Name) \
96 };
97 # define MOZ_FINISH_NESTED_ENUM_CLASS(Name) /* nothing */
99 /*
100 * MOZ_ENUM_CLASS_ENUM_TYPE allows using enum classes
101 * as template parameter types. For that, we need integer types.
102 * In the present case where the compiler supports strong enums,
103 * these are already integer types so there is nothing more to do.
104 */
105 # define MOZ_ENUM_CLASS_ENUM_TYPE(Name) Name
106 /*
107 * See the comment below about MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE.
108 */
109 # define MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(Name) Name
110 #else
111 /**
112 * We need Name to both name a type, and scope the provided enumerator
113 * names. Namespaces and classes both provide scoping, but namespaces
114 * aren't types, so we need to use a class that wraps the enum values. We
115 * have an implicit conversion from the inner enum type to the class, so
116 * statements like
117 *
118 * Enum x = Enum::A;
119 *
120 * will still work. We need to define an implicit conversion from the class
121 * to the inner enum as well, so that (for instance) switch statements will
122 * work. This means that the class can be implicitly converted to a numeric
123 * value as well via the enum type, since C++ allows an implicit
124 * user-defined conversion followed by a standard conversion to still be
125 * implicit.
126 *
127 * We have an explicit constructor from int defined, so that casts like
128 * (Enum)7 will still work. We also have a zero-argument constructor with
129 * no arguments, so declaration without initialization (like "Enum foo;")
130 * will work.
131 *
132 * Additionally, we'll delete as many operators as possible for the inner
133 * enum type, so statements like this will still fail:
134 *
135 * f(5 + Enum::B); // deleted operator+
136 *
137 * But we can't prevent things like this, because C++ doesn't allow
138 * overriding conversions or assignment operators for enums:
139 *
140 * int x = Enum::A;
141 * int f()
142 * {
143 * return Enum::A;
144 * }
145 */
147 /* Single-argument form. */
148 # define MOZ_BEGIN_NESTED_ENUM_CLASS_HELPER1(Name) \
149 class Name \
150 { \
151 public: \
152 enum Enum \
153 {
154 /* Two-argument form. */
155 # define MOZ_BEGIN_NESTED_ENUM_CLASS_HELPER2(Name, type) \
156 class Name \
157 { \
158 public: \
159 enum Enum MOZ_ENUM_TYPE(type) \
160 {
161 # define MOZ_END_NESTED_ENUM_CLASS(Name) \
162 }; \
163 Name() {} \
164 MOZ_CONSTEXPR Name(Enum aEnum) : mEnum(aEnum) {} \
165 template<typename Other> \
166 explicit MOZ_CONSTEXPR Name(Other num) : mEnum((Enum)num) {} \
167 MOZ_CONSTEXPR operator Enum() const { return mEnum; } \
168 explicit MOZ_CONSTEXPR Name(const mozilla::CastableTypedEnumResult<Name>& aOther) \
169 : mEnum(aOther.get()) \
170 {} \
171 private: \
172 Enum mEnum; \
173 };
174 # define MOZ_FINISH_NESTED_ENUM_CLASS(Name) \
175 inline int operator+(const int&, const Name::Enum&) MOZ_DELETE; \
176 inline int operator+(const Name::Enum&, const int&) MOZ_DELETE; \
177 inline int operator-(const int&, const Name::Enum&) MOZ_DELETE; \
178 inline int operator-(const Name::Enum&, const int&) MOZ_DELETE; \
179 inline int operator*(const int&, const Name::Enum&) MOZ_DELETE; \
180 inline int operator*(const Name::Enum&, const int&) MOZ_DELETE; \
181 inline int operator/(const int&, const Name::Enum&) MOZ_DELETE; \
182 inline int operator/(const Name::Enum&, const int&) MOZ_DELETE; \
183 inline int operator%(const int&, const Name::Enum&) MOZ_DELETE; \
184 inline int operator%(const Name::Enum&, const int&) MOZ_DELETE; \
185 inline int operator+(const Name::Enum&) MOZ_DELETE; \
186 inline int operator-(const Name::Enum&) MOZ_DELETE; \
187 inline int& operator++(Name::Enum&) MOZ_DELETE; \
188 inline int operator++(Name::Enum&, int) MOZ_DELETE; \
189 inline int& operator--(Name::Enum&) MOZ_DELETE; \
190 inline int operator--(Name::Enum&, int) MOZ_DELETE; \
191 inline bool operator==(const int&, const Name::Enum&) MOZ_DELETE; \
192 inline bool operator==(const Name::Enum&, const int&) MOZ_DELETE; \
193 inline bool operator!=(const int&, const Name::Enum&) MOZ_DELETE; \
194 inline bool operator!=(const Name::Enum&, const int&) MOZ_DELETE; \
195 inline bool operator>(const int&, const Name::Enum&) MOZ_DELETE; \
196 inline bool operator>(const Name::Enum&, const int&) MOZ_DELETE; \
197 inline bool operator<(const int&, const Name::Enum&) MOZ_DELETE; \
198 inline bool operator<(const Name::Enum&, const int&) MOZ_DELETE; \
199 inline bool operator>=(const int&, const Name::Enum&) MOZ_DELETE; \
200 inline bool operator>=(const Name::Enum&, const int&) MOZ_DELETE; \
201 inline bool operator<=(const int&, const Name::Enum&) MOZ_DELETE; \
202 inline bool operator<=(const Name::Enum&, const int&) MOZ_DELETE; \
203 inline bool operator!(const Name::Enum&) MOZ_DELETE; \
204 inline bool operator&&(const bool&, const Name::Enum&) MOZ_DELETE; \
205 inline bool operator&&(const Name::Enum&, const bool&) MOZ_DELETE; \
206 inline bool operator||(const bool&, const Name::Enum&) MOZ_DELETE; \
207 inline bool operator||(const Name::Enum&, const bool&) MOZ_DELETE; \
208 inline int operator&(const int&, const Name::Enum&) MOZ_DELETE; \
209 inline int operator&(const Name::Enum&, const int&) MOZ_DELETE; \
210 inline int operator|(const int&, const Name::Enum&) MOZ_DELETE; \
211 inline int operator|(const Name::Enum&, const int&) MOZ_DELETE; \
212 inline int operator^(const int&, const Name::Enum&) MOZ_DELETE; \
213 inline int operator^(const Name::Enum&, const int&) MOZ_DELETE; \
214 inline int operator<<(const int&, const Name::Enum&) MOZ_DELETE; \
215 inline int operator<<(const Name::Enum&, const int&) MOZ_DELETE; \
216 inline int operator>>(const int&, const Name::Enum&) MOZ_DELETE; \
217 inline int operator>>(const Name::Enum&, const int&) MOZ_DELETE; \
218 inline int& operator+=(int&, const Name::Enum&) MOZ_DELETE; \
219 inline int& operator-=(int&, const Name::Enum&) MOZ_DELETE; \
220 inline int& operator*=(int&, const Name::Enum&) MOZ_DELETE; \
221 inline int& operator/=(int&, const Name::Enum&) MOZ_DELETE; \
222 inline int& operator%=(int&, const Name::Enum&) MOZ_DELETE; \
223 inline int& operator&=(int&, const Name::Enum&) MOZ_DELETE; \
224 inline int& operator|=(int&, const Name::Enum&) MOZ_DELETE; \
225 inline int& operator^=(int&, const Name::Enum&) MOZ_DELETE; \
226 inline int& operator<<=(int&, const Name::Enum&) MOZ_DELETE; \
227 inline int& operator>>=(int&, const Name::Enum&) MOZ_DELETE;
229 /*
230 * MOZ_ENUM_CLASS_ENUM_TYPE allows using enum classes
231 * as template parameter types. For that, we need integer types.
232 * In the present case, the integer type is the Enum nested type.
233 */
234 # define MOZ_ENUM_CLASS_ENUM_TYPE(Name) Name::Enum
235 /*
236 * MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE is a variant of MOZ_ENUM_CLASS_ENUM_TYPE
237 * to be used when the enum class at hand depends on template parameters.
238 *
239 * Indeed, if T depends on template parameters, in order to name a nested type
240 * in T, C++ does not allow to just write "T::NestedType". Instead, we have
241 * to write "typename T::NestedType". The role of this macro is to add
242 * this "typename" keywords where needed.
243 *
244 * Example:
245 *
246 * template<typename T, MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(T) Value>
247 * struct S {};
248 *
249 * MOZ_BEGIN_ENUM_CLASS(E)
250 * Foo,
251 * Bar
252 * MOZ_END_ENUM_CLASS(E)
253 *
254 * S<E, E::Bar> s;
255 *
256 * In this example, the second template parameter to S is meant to be of type T,
257 * but on non-C++11 compilers, type T is a class type, not an integer type, so
258 * it is not accepted as the type of a constant template parameter. One would
259 * then want to use MOZ_ENUM_CLASS_ENUM_TYPE(T), but that doesn't work either
260 * as T depends on template parameters (more specifically here, T _is_ a template
261 * parameter) so as MOZ_ENUM_CLASS_ENUM_TYPE(T) expands to T::Enum, we are missing
262 * the required "typename" keyword. So here, MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE
263 * is needed.
264 */
265 # define MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(Name) typename Name::Enum
266 #endif
268 # define MOZ_BEGIN_NESTED_ENUM_CLASS_GLUE(a, b) a b
269 # define MOZ_BEGIN_NESTED_ENUM_CLASS(...) \
270 MOZ_BEGIN_NESTED_ENUM_CLASS_GLUE( \
271 MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_BEGIN_NESTED_ENUM_CLASS_HELPER, \
272 __VA_ARGS__), \
273 (__VA_ARGS__))
275 # define MOZ_BEGIN_ENUM_CLASS(...) MOZ_BEGIN_NESTED_ENUM_CLASS(__VA_ARGS__)
276 # define MOZ_END_ENUM_CLASS(Name) \
277 MOZ_END_NESTED_ENUM_CLASS(Name) \
278 MOZ_FINISH_NESTED_ENUM_CLASS(Name)
280 #endif /* __cplusplus */
282 #endif /* mozilla_TypedEnum_h */