diff options
author | jackpoz <giacomopoz@gmail.com> | 2014-08-22 16:58:23 +0200 |
---|---|---|
committer | jackpoz <giacomopoz@gmail.com> | 2014-08-22 21:00:56 +0200 |
commit | 5e8277e923c5545a15bae7c740ab6afaa597a59f (patch) | |
tree | 4cf5212c080588a7e868ee60134fc7fff51e400a /dep/g3dlite/include/G3D/enumclass.h | |
parent | a63aa858dcb400eafb97eed1f590e34c27d934a4 (diff) |
Core/Dependencies: Update G3D to v9.0 r4036
Diffstat (limited to 'dep/g3dlite/include/G3D/enumclass.h')
-rw-r--r-- | dep/g3dlite/include/G3D/enumclass.h | 180 |
1 files changed, 153 insertions, 27 deletions
diff --git a/dep/g3dlite/include/G3D/enumclass.h b/dep/g3dlite/include/G3D/enumclass.h index 2874a630ad9..8e0c221f8fd 100644 --- a/dep/g3dlite/include/G3D/enumclass.h +++ b/dep/g3dlite/include/G3D/enumclass.h @@ -1,30 +1,39 @@ /** - @file G3D/enumclass.h + \file G3D/enumclass.h - @maintainer Morgan McGuire, http://graphics.cs.williams.edu - @created 2007-01-27 - @edited 2007-07-20 + \maintainer Morgan McGuire, http://graphics.cs.williams.edu + \created 2007-01-27 + \edited 2013-04-09 */ #ifndef G3D_enumclass_h #define G3D_enumclass_h +#include "G3D/platform.h" #include "G3D/HashTrait.h" #include "G3D/BinaryInput.h" #include "G3D/BinaryOutput.h" +#include "G3D/TextOutput.h" +#include "G3D/Any.h" + +namespace G3D { + namespace _internal { + const char** smartEnumParseNames(const char* enumValList); + } +} /** \def G3D_DECLARE_ENUM_CLASS_METHODS \brief Creates a series of methods that turn a class into a scoped enumeration. - Uses the "Intelligent Enum" design pattern - http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/ - - Enum classes are initialized to their zero value by default. - - You must implement the following method before calling G3D_DECLARE_ENUM_CLASS_METHODS, as either: + Example of use: - <pre> + \code + class Resource { + public: + enum Value {FUEL, FOOD, WATER} value; + + // i is the position the enum value in Value (not the enum value itself) static const char* toString(int i, Value& v) { static const char* str[] = {"FUEL", "FOOD", "WATER", NULL}; // Whatever your enum values are static const Value val[] = {FUEL, FOOD, WATER}; // Whatever your enum values are @@ -34,29 +43,42 @@ } return s; } - </pre> - See GLG3D/GKey.h for an example. + G3D_DECLARE_ENUM_CLASS_METHODS(Resource); + }; + G3D_DECLARE_ENUM_CLASS_HASHCODE(Resource); + \endcode + + Extends the "Intelligent Enum" design pattern + http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/ + + Enum classes are initialized to their zero value by default. + + See GLG3D/GKey.h and G3D/WrapMode for an example. \sa G3D_DECLARE_ENUM_CLASS_HASHCODE */ #define G3D_DECLARE_ENUM_CLASS_METHODS(Classname)\ private: \ void fromString(const std::string& x) {\ - Value v;\ + Value v = (Value)0;\ const char* s;\ int i = 0;\ \ do {\ s = toString(i, v);\ + if (s == NULL) { return; /** Needed to get correct compilation on gcc */ } \ if (x == s) {\ value = v;\ return;\ }\ ++i;\ - } while (s);\ + } while (true);\ }\ \ public:\ + static const char* classname() {\ + return #Classname;\ + }\ \ const char* toString() const {\ const char* s;\ @@ -69,22 +91,21 @@ public:\ }\ ++i;\ }\ - return NULL;\ }\ \ explicit Classname(const std::string& x) : value((Value)0) {\ fromString(x);\ }\ \ - Classname(const Any& a) : value((Value)0) {\ + explicit Classname(const G3D::Any& a) : value((Value)0) { \ fromString(a.string());\ }\ \ - operator Any() const {\ - return Any(toString());\ + G3D::Any toAny() const { \ + return G3D::Any(toString()); \ }\ \ - Classname(char v) : value((Value)v) {}\ + explicit Classname(char v) : value((Value)v) {}\ \ Classname() : value((Value)0) {}\ \ @@ -92,15 +113,15 @@ public:\ \ explicit Classname(int v) : value((Value)v) {}\ \ - /** Support cast back to the Value type, which is needed to allow implicit assignment inside unions. */\ - /*inline operator Value() const { - return value; - }*/\ -\ operator int() const {\ return (int)value;\ }\ \ + Classname& operator=(const Any& a) {\ + value = Classname(a).value;\ + return *this;\ + }\ +\ bool operator== (const Classname other) const {\ return value == other.value;\ }\ @@ -181,15 +202,16 @@ public:\ return (unsigned int)value;\ }\ \ - void serialize(BinaryOutput& b) const {\ + void serialize(G3D::BinaryOutput& b) const { \ b.writeInt32(value);\ }\ \ - void deserialize(BinaryInput& b) {\ + void deserialize(G3D::BinaryInput& b) { \ value = (Value)b.readInt32();\ } /** \def G3D_DECLARE_ENUM_CLASS_HASHCODE + Must be used at top level (i.e., not inside a class or namespace), with a fully qualified class name. */ #define G3D_DECLARE_ENUM_CLASS_HASHCODE(Classname)\ template <> struct HashTrait<Classname::Value> \ @@ -202,4 +224,108 @@ template <> struct HashTrait<Classname> static size_t hashCode(Classname key) { return static_cast<size_t>(key.hashCode()); } \ }; +/** +\def G3D_DECLARE_ENUM_CLASS + +\code +// Arguments may not have initializer expressions. Arguments may contain comments. +// Namespaces aren't *required*, this example just shows how to use them. +namespace Foo { + G3D_DECLARE_ENUM_CLASS(Day, SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY); +} +G3D_DECLARE_ENUM_CLASS_HASHCODE(Foo::Day); +... + +using namespace Foo; +// Example use of the smart enum +Day d = Day::TUESDAY; +Day d2("SATURDAY"); +Any a(d); +d = a; +printf("%s = %d\n", d.toString(), d.value); +\endcode + +\sa G3D_DECLARE_ENUM_CLASS_METHODS, G3D_DECLARE_ENUM_CLASS_HASHCODE, G3D::enumToJavaScriptDeclaration, G3D_BEGIN_ENUM_CLASS_DECLARATION +*/ +#define G3D_DECLARE_ENUM_CLASS(ClassName, ...)\ + G3D_BEGIN_ENUM_CLASS_DECLARATION(ClassName, __VA_ARGS__);\ + G3D_END_ENUM_CLASS_DECLARATION(); + +/** \def G3D_BEGIN_ENUM_CLASS_DECLARATION + +\code +G3D_BEGIN_ENUM_CLASS_DECLARATION(Day, SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY); + // Put extra methods here, e.g., + Value nextValue() { ... } +G3D_END_ENUM_CLASS_DECLARATION(); +} +G3D_DECLARE_ENUM_CLASS_HASHCODE(Foo::Day); + +\endcode + \sa G3D_DECLARE_ENUM_CLASS, G3D_END_ENUM_CLASS_DECLARATION +*/ +#define G3D_BEGIN_ENUM_CLASS_DECLARATION(ClassName, ...)\ +class ClassName {\ +public:\ + enum Value {\ + __VA_ARGS__\ + } value;\ +\ + /* The static variables here may be duplicated in different shared object binaries (DLLs), but that's ok--we only depend on their values, not their uniqueness. See also http://stackoverflow.com/questions/11962918/local-static-variable-is-instantiated-multiple-times-why */\ + static const char* toString(int i, Value& v) {\ + static const char** str = G3D::_internal::smartEnumParseNames(#__VA_ARGS__);\ + static const Value val[] = {__VA_ARGS__};\ + const char* s = str[i];\ + if (s) { v = val[i]; }\ + return s;\ + }\ +\ + G3D_DECLARE_ENUM_CLASS_METHODS(ClassName); + +/** \def G3D_END_ENUM_CLASS_DECLARATION + \sa G3D_BEGIN_ENUM_CLASS_DECLARATION */ +#define G3D_END_ENUM_CLASS_DECLARATION() } + + +namespace G3D { + +/** + \brief Generates JavaScript source code defining an enum equivalent to + EnumClass. + + \code + TextOutput t("WrapMode.js"); + enumToJavaScriptDeclaration<WrapMode, WrapMode::Value>(t); + t.commit(); + \endcode + */ +template<class EnumClass, class EnumClassValue> +void enumToJavaScriptDeclaration(TextOutput& t) { + t.printf("/* BEGIN GENERATED CODE. The following was automatically generated by G3D::enumToJavaScriptDeclaration(). Do not edit it manually. */\n\n"); + t.printf("var %s = (function (propList) {", EnumClass::classname()); t.writeNewline(); + t.pushIndent(); { + t.printf("// Define immutable properties"); t.writeNewline(); + t.printf("var en = {};"); t.writeNewline(); + t.printf("for (var i = 0; i < propList.length; i += 2)"); t.writeNewline(); + t.pushIndent(); { + t.printf("Object.defineProperty(en, propList[i], {enumerable: true, value: propList[i + 1]});"); t.writeNewline(); + } t.popIndent(); + t.printf("return en;"); + t.writeNewline(); + } t.popIndent(); + t.printf("})(["); + int i = 0; + EnumClassValue m; + const char* s = EnumClass::toString(i, m); + while (notNull(s)) { + t.printf("\"%s\", %d, ", s, int(m)); + ++i; + s = EnumClass::toString(i, m); + } + // JavaScript allows a trailing comma + t.printf("]);"); t.writeNewline(); + t.printf("/* END GENERATED CODE */"); t.writeNewline(); +} + +} #endif |