| Index: src/foreach.h
|
| diff --git a/src/foreach.h b/src/foreach.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..01d52a5de70ebfd3505b16585c0d72af90abe342
|
| --- /dev/null
|
| +++ b/src/foreach.h
|
| @@ -0,0 +1,336 @@
|
| +// Copyright 2014 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +//
|
| +// This code is heavily based on Eric Niebler's article "Conditional Love:
|
| +// FOREACH Redux" in the "The C++ Source" journal (February 17, 2005,
|
| +// http://www.artima.com/cppsource/foreach.html) plus some snippets from its
|
| +// Boost incarnation, see http://www.boost.org/doc/libs/release/libs/foreach/.
|
| +//
|
| +// NOTE: Boost's foreach macro is much more powerful, but the header
|
| +// transitively pulls in roughly 250 other headers. To keep things (relatively)
|
| +// simple, we don't support iteration over arrays and C strings, and we have
|
| +// different macros for const and non-const iteration. This can probably be
|
| +// fixed incrementally later, but it's good enough for now.
|
| +
|
| +#ifndef V8_FOREACH_H_
|
| +#define V8_FOREACH_H_
|
| +
|
| +#include "include/v8config.h"
|
| +
|
| +// VisualStudio's typing for ternaries seems to be broken, we can't handle
|
| +// rvalues in this case.
|
| +#if V8_CC_MSVC
|
| +#define V8_FOREACH_RVALUE_BROKEN 1
|
| +#endif
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +
|
| +// A mechanism for putting an object of unknown type in automatic storage.
|
| +struct auto_any_base {
|
| + // auto_any_base must evaluate to false in boolean context so that they can be
|
| + // declared in if statements.
|
| + operator bool() const { return false; }
|
| +};
|
| +
|
| +template <class T>
|
| +struct auto_any : auto_any_base {
|
| + auto_any(T const& t) : item(t) {} // NOLINT
|
| + mutable T item;
|
| +};
|
| +
|
| +// Extract a reference to the internally stored item.
|
| +template <class T>
|
| +T& auto_any_cast(auto_any_base const& base) {
|
| + return static_cast<auto_any<T> const&>(base).item;
|
| +}
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +
|
| +// Holds either a T or a T const*.
|
| +template <typename T>
|
| +struct simple_variant {
|
| + simple_variant(T const* t) : is_rvalue(false) { // NOLINT
|
| + *static_cast<T const**>(this->address()) = t;
|
| + }
|
| +
|
| + simple_variant(T const& t) : is_rvalue(true) { // NOLINT
|
| + ::new (this->address()) T(t);
|
| + }
|
| +
|
| + simple_variant(simple_variant const& that) : is_rvalue(that.is_rvalue) {
|
| + if (this->is_rvalue) {
|
| + ::new (this->address()) T(*that.get_c());
|
| + } else {
|
| + *static_cast<T const**>(this->address()) = that.get_c();
|
| + }
|
| + }
|
| +
|
| + ~simple_variant() {
|
| + if (this->is_rvalue) this->get_c()->~T();
|
| + }
|
| +
|
| + T const* get_c() const {
|
| + if (this->is_rvalue) {
|
| + return static_cast<T const*>(this->address());
|
| + } else {
|
| + return *static_cast<T const* const*>(this->address());
|
| + }
|
| + }
|
| +
|
| + T* get() {
|
| + if (this->is_rvalue) {
|
| + return static_cast<T*>(this->address());
|
| + } else {
|
| + return *static_cast<T**>(this->address());
|
| + }
|
| + }
|
| +
|
| + private:
|
| + const void* address() const { return buf; }
|
| + void* address() { return buf; }
|
| + enum size_type { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) };
|
| + simple_variant& operator=(simple_variant const&);
|
| + char buf[size]; // NOLINT
|
| + bool const is_rvalue;
|
| +};
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +
|
| +// A simple type wrapper.
|
| +template <class T>
|
| +struct type2type {};
|
| +
|
| +// Convert an expression of type T to an expression of type type2type<T>.
|
| +template <class T>
|
| +type2type<T> encode_type(T const& t) {
|
| + return type2type<T>();
|
| +}
|
| +
|
| +// Convertible to type2type<T> for any T.
|
| +struct any_type {
|
| + template <class T>
|
| + operator type2type<T>() const {
|
| + return type2type<T>();
|
| + }
|
| +};
|
| +
|
| +// Convert an expression of type T to an expression of type type2type<T>
|
| +// without evaluating the expression.
|
| +#define V8_TYPEOF(x) (true ? any_type() : encode_type(x))
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +
|
| +struct rvalue_probe {
|
| + template <class T>
|
| + rvalue_probe(T const& t, bool& b) // NOLINT
|
| + : ptemp(const_cast<T*>(&t)),
|
| + is_rvalue(b) {}
|
| +
|
| + template <class R>
|
| + operator R() {
|
| + is_rvalue = true;
|
| + return *static_cast<R*>(ptemp);
|
| + }
|
| +
|
| + template <class L>
|
| + operator L&() const {
|
| + is_rvalue = false;
|
| + return *static_cast<L*>(ptemp);
|
| + }
|
| +
|
| + void* ptemp;
|
| + bool& is_rvalue;
|
| +};
|
| +
|
| +#if V8_FOREACH_RVALUE_BROKEN
|
| +#define V8_EVAL(x, is_rvalue) (x)
|
| +#else
|
| +// Evaluation and rvalue detection.
|
| +#define V8_EVAL(x, is_rvalue) (true ? rvalue_probe((x), is_rvalue) : (x))
|
| +#endif
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +
|
| +// Returns a C or a C*.
|
| +template <class C>
|
| +auto_any<simple_variant<C> > contain(C const& t, bool const& is_rvalue) {
|
| + // Return either a C or a C* depending on whether the container is an rvalue
|
| + // or not.
|
| + return is_rvalue ? simple_variant<C>(t) : simple_variant<C>(&t);
|
| +}
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +
|
| +template <class C>
|
| +auto_any<typename C::iterator> begin(auto_any_base const& container,
|
| + type2type<C>) {
|
| + return auto_any_cast<simple_variant<C> >(container).get()->begin();
|
| +}
|
| +
|
| +template <class C>
|
| +auto_any<typename C::iterator> end(auto_any_base const& container,
|
| + type2type<C>) {
|
| + return auto_any_cast<simple_variant<C> >(container).get()->end();
|
| +}
|
| +
|
| +template <typename C>
|
| +bool done(auto_any_base const& cur, auto_any_base const& end, type2type<C>) {
|
| + typedef typename C::iterator iter_type;
|
| + return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
|
| +}
|
| +
|
| +template <class C>
|
| +void next(auto_any_base const& iter, type2type<C>) {
|
| + ++auto_any_cast<typename C::iterator>(iter);
|
| +}
|
| +
|
| +template <class C>
|
| +typename C::reference deref(auto_any_base const& iter, type2type<C>) {
|
| + return *auto_any_cast<typename C::iterator>(iter);
|
| +}
|
| +
|
| +// non-const forward iteration.
|
| +#define V8_FOREACH(VAR, COL) \
|
| + if (bool _rval = false) {} else \
|
| + if (auto_any_base const& _col = contain(V8_EVAL(COL, _rval), _rval)) {} else \
|
| + if (auto_any_base const& _cur = begin(_col, V8_TYPEOF(COL))) {} else \
|
| + if (auto_any_base const& _end = end(_col, V8_TYPEOF(COL))) {} else \
|
| + for (bool _continue = true; \
|
| + _continue && !done(_cur, _end, V8_TYPEOF(COL)); \
|
| + _continue ? next(_cur, V8_TYPEOF(COL)) : (void)0) \
|
| + if ((_continue = false)) {} else \
|
| + for (VAR = deref(_cur, V8_TYPEOF(COL)); !_continue; _continue = true)
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +
|
| +template <class C>
|
| +auto_any<typename C::reverse_iterator> rbegin(auto_any_base const& container,
|
| + type2type<C>) {
|
| + return auto_any_cast<simple_variant<C> >(container).get()->rbegin();
|
| +}
|
| +
|
| +template <class C>
|
| +auto_any<typename C::reverse_iterator> rend(auto_any_base const& container,
|
| + type2type<C>) {
|
| + return auto_any_cast<simple_variant<C> >(container).get()->rend();
|
| +}
|
| +
|
| +template <typename C>
|
| +bool rdone(auto_any_base const& cur, auto_any_base const& end, type2type<C>) {
|
| + typedef typename C::reverse_iterator iter_type;
|
| + return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
|
| +}
|
| +
|
| +template <class C>
|
| +void rnext(auto_any_base const& iter, type2type<C>) {
|
| + ++auto_any_cast<typename C::reverse_iterator>(iter);
|
| +}
|
| +
|
| +template <class C>
|
| +typename C::reference rderef(auto_any_base const& iter, type2type<C>) {
|
| + return *auto_any_cast<typename C::reverse_iterator>(iter);
|
| +}
|
| +
|
| +// non-const reverse iteration.
|
| +#define V8_FOREACH_REV(VAR, COL) \
|
| + if (bool _rval = false) {} else \
|
| + if (auto_any_base const& _col = contain(V8_EVAL(COL, _rval), _rval)) {} else \
|
| + if (auto_any_base const& _cur = rbegin(_col, V8_TYPEOF(COL))) {} else \
|
| + if (auto_any_base const& _end = rend(_col, V8_TYPEOF(COL))) {} else \
|
| + for (bool _continue = true; \
|
| + _continue && !rdone(_cur, _end, V8_TYPEOF(COL)); \
|
| + _continue ? rnext(_cur, V8_TYPEOF(COL)) : (void)0) \
|
| + if ((_continue = false)) {} else \
|
| + for (VAR = rderef(_cur, V8_TYPEOF(COL)); !_continue; _continue = true)
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +
|
| +template <class C>
|
| +auto_any<typename C::const_iterator> cbegin(auto_any_base const& container,
|
| + type2type<C>) {
|
| + return auto_any_cast<simple_variant<C> >(container).get_c()->begin();
|
| +}
|
| +
|
| +template <class C>
|
| +auto_any<typename C::const_iterator> cend(auto_any_base const& container,
|
| + type2type<C>) {
|
| + return auto_any_cast<simple_variant<C> >(container).get_c()->end();
|
| +}
|
| +
|
| +template <typename C>
|
| +bool cdone(auto_any_base const& cur, auto_any_base const& end, type2type<C>) {
|
| + typedef typename C::const_iterator iter_type;
|
| + return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
|
| +}
|
| +
|
| +template <class C>
|
| +void cnext(auto_any_base const& iter, type2type<C>) {
|
| + ++auto_any_cast<typename C::const_iterator>(iter);
|
| +}
|
| +
|
| +template <class C>
|
| +typename C::const_reference cderef(auto_any_base const& iter, type2type<C>) {
|
| + return *auto_any_cast<typename C::const_iterator>(iter);
|
| +}
|
| +
|
| +// const forward iteration.
|
| +#define V8_FOREACH_C(VAR, COL) \
|
| + if (bool _rval = false) {} else \
|
| + if (auto_any_base const& _col = contain(V8_EVAL(COL, _rval), _rval)) {} else \
|
| + if (auto_any_base const& _cur = cbegin(_col, V8_TYPEOF(COL))) {} else \
|
| + if (auto_any_base const& _end = cend(_col, V8_TYPEOF(COL))) {} else \
|
| + for (bool _continue = true; \
|
| + _continue && !cdone(_cur, _end, V8_TYPEOF(COL)); \
|
| + _continue ? cnext(_cur, V8_TYPEOF(COL)) : (void)0) \
|
| + if ((_continue = false)) {} else \
|
| + for (VAR = cderef(_cur, V8_TYPEOF(COL)); !_continue; _continue = true)
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +
|
| +template <class C>
|
| +auto_any<typename C::const_reverse_iterator> rcbegin(
|
| + auto_any_base const& container, type2type<C>) {
|
| + return auto_any_cast<simple_variant<C> >(container).get_c()->rbegin();
|
| +}
|
| +
|
| +template <class C>
|
| +auto_any<typename C::const_reverse_iterator> rcend(
|
| + auto_any_base const& container, type2type<C>) {
|
| + return auto_any_cast<simple_variant<C> >(container).get_c()->rend();
|
| +}
|
| +
|
| +template <typename C>
|
| +bool rcdone(auto_any_base const& cur, auto_any_base const& end, type2type<C>) {
|
| + typedef typename C::const_reverse_iterator iter_type;
|
| + return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
|
| +}
|
| +
|
| +template <class C>
|
| +void rcnext(auto_any_base const& iter, type2type<C>) {
|
| + ++auto_any_cast<typename C::const_reverse_iterator>(iter);
|
| +}
|
| +
|
| +template <class C>
|
| +typename C::const_reference rcderef(auto_any_base const& iter, type2type<C>) {
|
| + return *auto_any_cast<typename C::const_reverse_iterator>(iter);
|
| +}
|
| +
|
| +// const reverse iteration.
|
| +#define V8_FOREACH_C_REV(VAR, COL) \
|
| + if (bool _rval = false) {} else \
|
| + if (auto_any_base const& _col = contain(V8_EVAL(COL, _rval), _rval)) {} else \
|
| + if (auto_any_base const& _cur = rcbegin(_col, V8_TYPEOF(COL))) {} else \
|
| + if (auto_any_base const& _end = rcend(_col, V8_TYPEOF(COL))) {} else \
|
| + for (bool _continue = true; \
|
| + _continue && !rcdone(_cur, _end, V8_TYPEOF(COL)); \
|
| + _continue ? rcnext(_cur, V8_TYPEOF(COL)) : (void)0) \
|
| + if ((_continue = false)) {} else \
|
| + for (VAR = rcderef(_cur, V8_TYPEOF(COL)); !_continue; _continue = true)
|
| +
|
| +} } // namespace v8::internal
|
| +
|
| +#endif // V8_H_
|
|
|