| OLD | NEW |
| (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_ |
| OLD | NEW |