# HG changeset patch # User Teemu Piippo # Date 1462727574 -10800 # Node ID 993c46d7eb7538206ae67a38f54cf92a71ea4b67 # Parent 8a60250175baa84b12da96b9415093068aa0a787 Replaced the ugly for_enum macro with a generator class Fixed: qHash(const Vertex&) got sucked into infinite recursion diff -r 8a60250175ba -r 993c46d7eb75 src/addObjectDialog.cpp --- a/src/addObjectDialog.cpp Sun May 08 16:26:16 2016 +0300 +++ b/src/addObjectDialog.cpp Sun May 08 20:12:54 2016 +0300 @@ -77,13 +77,13 @@ { rb_bfcType = new RadioGroup ("Statement", {}, 0, Qt::Vertical); - for_enum (BfcStatement, i) + for (BfcStatement statement : iterateEnum()) { // Separate these in two columns - if (int(i) == ENUM_LIMIT(BfcStatement, Count) / 2) + if (int(statement) == EnumLimits::Count / 2) rb_bfcType->rowBreak(); - rb_bfcType->addButton (LDBfc::statementToString (i)); + rb_bfcType->addButton (LDBfc::statementToString(statement)); } if (obj) diff -r 8a60250175ba -r 993c46d7eb75 src/basics.cpp --- a/src/basics.cpp Sun May 08 16:26:16 2016 +0300 +++ b/src/basics.cpp Sun May 08 20:12:54 2016 +0300 @@ -364,7 +364,20 @@ return m_vertex1; } +// http://stackoverflow.com/a/18204188/3629665 +template +inline int rotl10(T x) +{ + return (((x) << 10) | (((x) >> 22) & 0x000000ff)); +} + +template +inline int rotl20(T x) +{ + return (((x) << 20) | (((x) >> 12) & 0x000000ff)); +} + uint qHash(const Vertex& key) { - return qHash(static_cast(key)); + return qHash(key.x()) ^ rotl10(qHash(key.y())) ^ rotl20(qHash(key.z())); } diff -r 8a60250175ba -r 993c46d7eb75 src/basics.h --- a/src/basics.h Sun May 08 16:26:16 2016 +0300 +++ b/src/basics.h Sun May 08 20:12:54 2016 +0300 @@ -234,3 +234,46 @@ { a = not a; } + +// +// Iterates an enum +// +template +struct EnumIterShell +{ + struct Iterator + { + Iterator(typename std::underlying_type::type i) : + i(i) {} + + Iterator& operator++() { ++i; return *this; } + bool operator==(Iterator other) { return i == other.i; } + bool operator!=(Iterator other) { return i != other.i; } + Enum operator*() const { return Enum(i); } + + typename std::underlying_type::type i; + }; + + Iterator begin() + { + return Iterator(EnumLimits::First); + }; + + Iterator end() + { + return Iterator(EnumLimits::End); + } +}; + +template +EnumIterShell iterateEnum() +{ + return EnumIterShell(); +} + +// Is a value inside an enum? +template +bool valueInEnum(typename std::underlying_type::type x) +{ + return x >= EnumLimits::First and x <= EnumLimits::Last; +} \ No newline at end of file diff -r 8a60250175ba -r 993c46d7eb75 src/glCompiler.cpp --- a/src/glCompiler.cpp Sun May 08 16:26:16 2016 +0300 +++ b/src/glCompiler.cpp Sun May 08 20:12:54 2016 +0300 @@ -355,7 +355,7 @@ default: return; } - for_enum(ComplementVboType, complement) + for (ComplementVboType complement : iterateEnum()) { const int vbonum = vboNumber (surface, complement); QVector& vbodata = objinfo->data[vbonum]; @@ -390,7 +390,7 @@ int GLCompiler::vboNumber (SurfaceVboType surface, ComplementVboType complement) { - return (surface * ENUM_LIMIT(ComplementVboType, Count)) + complement; + return (surface * EnumLimits::Count) + complement; } diff -r 8a60250175ba -r 993c46d7eb75 src/glRenderer.cpp --- a/src/glRenderer.cpp Sun May 08 16:26:16 2016 +0300 +++ b/src/glRenderer.cpp Sun May 08 20:12:54 2016 +0300 @@ -43,7 +43,7 @@ #include "documentmanager.h" #include "grid.h" -const CameraInfo g_cameraInfo[ENUM_LIMIT(Camera, Count)] = +const CameraInfo g_cameraInfo[EnumLimits::Count] = { {{ 1, 0, 0 }, X, Z, false, false, false }, // top {{ 0, 0, 0 }, X, Y, false, true, false }, // front @@ -100,9 +100,9 @@ connect (m_toolTipTimer, SIGNAL (timeout()), this, SLOT (slot_toolTipTimer())); // Init camera icons - for_enum(Camera, camera) + for (Camera camera : iterateEnum()) { - const char* cameraIconNames[ENUM_LIMIT(Camera, Count)] = + const char* cameraIconNames[EnumLimits::Count] = { "camera-top", "camera-front", "camera-left", "camera-bottom", "camera-back", "camera-right", @@ -1428,7 +1428,7 @@ // void GLRenderer::initOverlaysFromObjects() { - for_enum(Camera, camera) + for (Camera camera : iterateEnum()) { if (camera == FreeCamera) continue; @@ -1457,7 +1457,7 @@ // void GLRenderer::updateOverlayObjects() { - for_enum(Camera, camera) + for (Camera camera : iterateEnum()) { if (camera == FreeCamera) continue; diff -r 8a60250175ba -r 993c46d7eb75 src/glShared.h --- a/src/glShared.h Sun May 08 16:26:16 2016 +0300 +++ b/src/glShared.h Sun May 08 20:12:54 2016 +0300 @@ -62,7 +62,7 @@ enum { - NumVbos = ENUM_LIMIT(SurfaceVboType, Count) * ENUM_LIMIT(ComplementVboType, Count), + NumVbos = EnumLimits::Count * EnumLimits::Count }; #ifndef USE_QT5 diff -r 8a60250175ba -r 993c46d7eb75 src/ldDocument.cpp --- a/src/ldDocument.cpp Sun May 08 16:26:16 2016 +0300 +++ b/src/ldDocument.cpp Sun May 08 20:12:54 2016 +0300 @@ -417,10 +417,10 @@ // Handle BFC statements if (tokens.size() > 2 and tokens[1] == "BFC") { - for_enum (BfcStatement, i) + for (BfcStatement statement : iterateEnum()) { - if (commentTextSimplified == format ("BFC %1", LDBfc::statementToString (i))) - return LDSpawn (i); + if (commentTextSimplified == format("BFC %1", LDBfc::statementToString (statement))) + return LDSpawn(statement); } // MLCAD is notorious for stuffing these statements in parts it diff -r 8a60250175ba -r 993c46d7eb75 src/macros.h --- a/src/macros.h Sun May 08 16:26:16 2016 +0300 +++ b/src/macros.h Sun May 08 20:12:54 2016 +0300 @@ -47,40 +47,22 @@ template<> \ struct EnumLimits \ {\ - enum { First = FIRST, Last = LAST, Count = LAST - FIRST + 1 };\ + enum { First = FIRST, Last = LAST, End = LAST + 1, Count = End - FIRST };\ }; \ inline T operator++ (T& a) { a = (T) ((int) a + 1); return a; } \ inline T operator-- (T& a) { a = (T) ((int) a - 1); return a; } \ inline T operator++ (T& a, int) { T result = a; a = (T) ((int) a + 1); return result; } \ inline T operator-- (T& a, int) { T result = a; a = (T) ((int) a - 1); return result; } +template +struct EnumLimits {}; + #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) # define USE_QT5 #endif #define ConfigOption(...) -#define FOR_ENUM_NAME_HELPER(LINE) enum_iterator_ ## LINE -#define FOR_ENUM_NAME(LINE) FOR_ENUM_NAME_HELPER(LINE) -#define FOR_ENUM_TYPE(ENUM) typename std::underlying_type::type -#define ENUM_LIMIT(ENUM, T) FOR_ENUM_TYPE(ENUM)(EnumLimits::T) - -#define for_enum(ENUM, NAME) \ - for (FOR_ENUM_TYPE(ENUM) FOR_ENUM_NAME(__LINE__) = ENUM_LIMIT(ENUM, First); \ - FOR_ENUM_NAME (__LINE__) <= ENUM_LIMIT(ENUM, Last); \ - ++FOR_ENUM_NAME (__LINE__)) \ - for (ENUM NAME = ENUM(FOR_ENUM_NAME(__LINE__)); NAME != ENUM_LIMIT(ENUM, Last) + 1; \ - NAME = ENUM(EnumLimits::Last + 1)) - -template -struct EnumLimits {}; - -template -bool valueInEnum(typename std::underlying_type::type x) -{ - return x >= ENUM_LIMIT(Enum, First) and x <= ENUM_LIMIT(Enum, Last); -} - #define DEFINE_FLAG_ACCESS_METHODS \ bool checkFlag(Flag flag) const { return !!(m_flags & flag); } \ void setFlag(Flag flag) { m_flags |= flag; } \