Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: src/foreach.h

Issue 433813002: Add iteration macros. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: No rvalues with MSVC Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // This code is heavily based on Eric Niebler's article "Conditional Love:
6 // FOREACH Redux" in the "The C++ Source" journal (February 17, 2005,
7 // http://www.artima.com/cppsource/foreach.html) plus some snippets from its
8 // Boost incarnation, see http://www.boost.org/doc/libs/release/libs/foreach/.
9 //
10 // NOTE: Boost's foreach macro is much more powerful, but the header
11 // transitively pulls in roughly 250 other headers. To keep things (relatively)
12 // simple, we don't support iteration over arrays and C strings, and we have
13 // different macros for const and non-const iteration. This can probably be
14 // fixed incrementally later, but it's good enough for now.
15
16 #ifndef V8_FOREACH_H_
17 #define V8_FOREACH_H_
18
19 #include "include/v8config.h"
20
21 // VisualStudio's typing for ternaries seems to be broken, we can't handle
22 // rvalues in this case.
23 #if V8_CC_MSVC
24 #define V8_FOREACH_RVALUE_BROKEN 1
25 #endif
26
27 namespace v8 {
28 namespace internal {
29
30 // -----------------------------------------------------------------------------
31
32 // A mechanism for putting an object of unknown type in automatic storage.
33 struct auto_any_base {
34 // auto_any_base must evaluate to false in boolean context so that they can be
35 // declared in if statements.
36 operator bool() const { return false; }
37 };
38
39 template <class T>
40 struct auto_any : auto_any_base {
41 auto_any(T const& t) : item(t) {} // NOLINT
42 mutable T item;
43 };
44
45 // Extract a reference to the internally stored item.
46 template <class T>
47 T& auto_any_cast(auto_any_base const& base) {
48 return static_cast<auto_any<T> const&>(base).item;
49 }
50
51 // -----------------------------------------------------------------------------
52
53 // Holds either a T or a T const*.
54 template <typename T>
55 struct simple_variant {
56 simple_variant(T const* t) : is_rvalue(false) { // NOLINT
57 *static_cast<T const**>(this->address()) = t;
58 }
59
60 simple_variant(T const& t) : is_rvalue(true) { // NOLINT
61 ::new (this->address()) T(t);
62 }
63
64 simple_variant(simple_variant const& that) : is_rvalue(that.is_rvalue) {
65 if (this->is_rvalue) {
66 ::new (this->address()) T(*that.get_c());
67 } else {
68 *static_cast<T const**>(this->address()) = that.get_c();
69 }
70 }
71
72 ~simple_variant() {
73 if (this->is_rvalue) this->get_c()->~T();
74 }
75
76 T const* get_c() const {
77 if (this->is_rvalue) {
78 return static_cast<T const*>(this->address());
79 } else {
80 return *static_cast<T const* const*>(this->address());
81 }
82 }
83
84 T* get() {
85 if (this->is_rvalue) {
86 return static_cast<T*>(this->address());
87 } else {
88 return *static_cast<T**>(this->address());
89 }
90 }
91
92 private:
93 const void* address() const { return buf; }
94 void* address() { return buf; }
95 enum size_type { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) };
96 simple_variant& operator=(simple_variant const&);
97 char buf[size]; // NOLINT
98 bool const is_rvalue;
99 };
100
101 // -----------------------------------------------------------------------------
102
103 // A simple type wrapper.
104 template <class T>
105 struct type2type {};
106
107 // Convert an expression of type T to an expression of type type2type<T>.
108 template <class T>
109 type2type<T> encode_type(T const& t) {
110 return type2type<T>();
111 }
112
113 // Convertible to type2type<T> for any T.
114 struct any_type {
115 template <class T>
116 operator type2type<T>() const {
117 return type2type<T>();
118 }
119 };
120
121 // Convert an expression of type T to an expression of type type2type<T>
122 // without evaluating the expression.
123 #define V8_TYPEOF(x) (true ? any_type() : encode_type(x))
124
125 // -----------------------------------------------------------------------------
126
127 struct rvalue_probe {
128 template <class T>
129 rvalue_probe(T const& t, bool& b) // NOLINT
130 : ptemp(const_cast<T*>(&t)),
131 is_rvalue(b) {}
132
133 template <class R>
134 operator R() {
135 is_rvalue = true;
136 return *static_cast<R*>(ptemp);
137 }
138
139 template <class L>
140 operator L&() const {
141 is_rvalue = false;
142 return *static_cast<L*>(ptemp);
143 }
144
145 void* ptemp;
146 bool& is_rvalue;
147 };
148
149 #if V8_FOREACH_RVALUE_BROKEN
150 #define V8_EVAL(x, is_rvalue) (x)
151 #else
152 // Evaluation and rvalue detection.
153 #define V8_EVAL(x, is_rvalue) (true ? rvalue_probe((x), is_rvalue) : (x))
154 #endif
155
156 // -----------------------------------------------------------------------------
157
158 // Returns a C or a C*.
159 template <class C>
160 auto_any<simple_variant<C> > contain(C const& t, bool const& is_rvalue) {
161 // Return either a C or a C* depending on whether the container is an rvalue
162 // or not.
163 return is_rvalue ? simple_variant<C>(t) : simple_variant<C>(&t);
164 }
165
166 // -----------------------------------------------------------------------------
167
168 template <class C>
169 auto_any<typename C::iterator> begin(auto_any_base const& container,
170 type2type<C>) {
171 return auto_any_cast<simple_variant<C> >(container).get()->begin();
172 }
173
174 template <class C>
175 auto_any<typename C::iterator> end(auto_any_base const& container,
176 type2type<C>) {
177 return auto_any_cast<simple_variant<C> >(container).get()->end();
178 }
179
180 template <typename C>
181 bool done(auto_any_base const& cur, auto_any_base const& end, type2type<C>) {
182 typedef typename C::iterator iter_type;
183 return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
184 }
185
186 template <class C>
187 void next(auto_any_base const& iter, type2type<C>) {
188 ++auto_any_cast<typename C::iterator>(iter);
189 }
190
191 template <class C>
192 typename C::reference deref(auto_any_base const& iter, type2type<C>) {
193 return *auto_any_cast<typename C::iterator>(iter);
194 }
195
196 // non-const forward iteration.
197 #define V8_FOREACH(VAR, COL) \
198 if (bool _rval = false) {} else \
199 if (auto_any_base const& _col = contain(V8_EVAL(COL, _rval), _rval)) {} else \
200 if (auto_any_base const& _cur = begin(_col, V8_TYPEOF(COL))) {} else \
201 if (auto_any_base const& _end = end(_col, V8_TYPEOF(COL))) {} else \
202 for (bool _continue = true; \
203 _continue && !done(_cur, _end, V8_TYPEOF(COL)); \
204 _continue ? next(_cur, V8_TYPEOF(COL)) : (void)0) \
205 if ((_continue = false)) {} else \
206 for (VAR = deref(_cur, V8_TYPEOF(COL)); !_continue; _continue = true)
207
208 // -----------------------------------------------------------------------------
209
210 template <class C>
211 auto_any<typename C::reverse_iterator> rbegin(auto_any_base const& container,
212 type2type<C>) {
213 return auto_any_cast<simple_variant<C> >(container).get()->rbegin();
214 }
215
216 template <class C>
217 auto_any<typename C::reverse_iterator> rend(auto_any_base const& container,
218 type2type<C>) {
219 return auto_any_cast<simple_variant<C> >(container).get()->rend();
220 }
221
222 template <typename C>
223 bool rdone(auto_any_base const& cur, auto_any_base const& end, type2type<C>) {
224 typedef typename C::reverse_iterator iter_type;
225 return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
226 }
227
228 template <class C>
229 void rnext(auto_any_base const& iter, type2type<C>) {
230 ++auto_any_cast<typename C::reverse_iterator>(iter);
231 }
232
233 template <class C>
234 typename C::reference rderef(auto_any_base const& iter, type2type<C>) {
235 return *auto_any_cast<typename C::reverse_iterator>(iter);
236 }
237
238 // non-const reverse iteration.
239 #define V8_FOREACH_REV(VAR, COL) \
240 if (bool _rval = false) {} else \
241 if (auto_any_base const& _col = contain(V8_EVAL(COL, _rval), _rval)) {} else \
242 if (auto_any_base const& _cur = rbegin(_col, V8_TYPEOF(COL))) {} else \
243 if (auto_any_base const& _end = rend(_col, V8_TYPEOF(COL))) {} else \
244 for (bool _continue = true; \
245 _continue && !rdone(_cur, _end, V8_TYPEOF(COL)); \
246 _continue ? rnext(_cur, V8_TYPEOF(COL)) : (void)0) \
247 if ((_continue = false)) {} else \
248 for (VAR = rderef(_cur, V8_TYPEOF(COL)); !_continue; _continue = true)
249
250 // -----------------------------------------------------------------------------
251
252 template <class C>
253 auto_any<typename C::const_iterator> cbegin(auto_any_base const& container,
254 type2type<C>) {
255 return auto_any_cast<simple_variant<C> >(container).get_c()->begin();
256 }
257
258 template <class C>
259 auto_any<typename C::const_iterator> cend(auto_any_base const& container,
260 type2type<C>) {
261 return auto_any_cast<simple_variant<C> >(container).get_c()->end();
262 }
263
264 template <typename C>
265 bool cdone(auto_any_base const& cur, auto_any_base const& end, type2type<C>) {
266 typedef typename C::const_iterator iter_type;
267 return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
268 }
269
270 template <class C>
271 void cnext(auto_any_base const& iter, type2type<C>) {
272 ++auto_any_cast<typename C::const_iterator>(iter);
273 }
274
275 template <class C>
276 typename C::const_reference cderef(auto_any_base const& iter, type2type<C>) {
277 return *auto_any_cast<typename C::const_iterator>(iter);
278 }
279
280 // const forward iteration.
281 #define V8_FOREACH_C(VAR, COL) \
282 if (bool _rval = false) {} else \
283 if (auto_any_base const& _col = contain(V8_EVAL(COL, _rval), _rval)) {} else \
284 if (auto_any_base const& _cur = cbegin(_col, V8_TYPEOF(COL))) {} else \
285 if (auto_any_base const& _end = cend(_col, V8_TYPEOF(COL))) {} else \
286 for (bool _continue = true; \
287 _continue && !cdone(_cur, _end, V8_TYPEOF(COL)); \
288 _continue ? cnext(_cur, V8_TYPEOF(COL)) : (void)0) \
289 if ((_continue = false)) {} else \
290 for (VAR = cderef(_cur, V8_TYPEOF(COL)); !_continue; _continue = true)
291
292 // -----------------------------------------------------------------------------
293
294 template <class C>
295 auto_any<typename C::const_reverse_iterator> rcbegin(
296 auto_any_base const& container, type2type<C>) {
297 return auto_any_cast<simple_variant<C> >(container).get_c()->rbegin();
298 }
299
300 template <class C>
301 auto_any<typename C::const_reverse_iterator> rcend(
302 auto_any_base const& container, type2type<C>) {
303 return auto_any_cast<simple_variant<C> >(container).get_c()->rend();
304 }
305
306 template <typename C>
307 bool rcdone(auto_any_base const& cur, auto_any_base const& end, type2type<C>) {
308 typedef typename C::const_reverse_iterator iter_type;
309 return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
310 }
311
312 template <class C>
313 void rcnext(auto_any_base const& iter, type2type<C>) {
314 ++auto_any_cast<typename C::const_reverse_iterator>(iter);
315 }
316
317 template <class C>
318 typename C::const_reference rcderef(auto_any_base const& iter, type2type<C>) {
319 return *auto_any_cast<typename C::const_reverse_iterator>(iter);
320 }
321
322 // const reverse iteration.
323 #define V8_FOREACH_C_REV(VAR, COL) \
324 if (bool _rval = false) {} else \
325 if (auto_any_base const& _col = contain(V8_EVAL(COL, _rval), _rval)) {} else \
326 if (auto_any_base const& _cur = rcbegin(_col, V8_TYPEOF(COL))) {} else \
327 if (auto_any_base const& _end = rcend(_col, V8_TYPEOF(COL))) {} else \
328 for (bool _continue = true; \
329 _continue && !rcdone(_cur, _end, V8_TYPEOF(COL)); \
330 _continue ? rcnext(_cur, V8_TYPEOF(COL)) : (void)0) \
331 if ((_continue = false)) {} else \
332 for (VAR = rcderef(_cur, V8_TYPEOF(COL)); !_continue; _continue = true)
333
334 } } // namespace v8::internal
335
336 #endif // V8_H_
OLDNEW
« no previous file with comments | « no previous file | src/utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698