Sun, 08 May 2016 20:12:54 +0300
Replaced the ugly for_enum macro with a generator class
Fixed: qHash(const Vertex&) got sucked into infinite recursion
src/addObjectDialog.cpp | file | annotate | diff | comparison | revisions | |
src/basics.cpp | file | annotate | diff | comparison | revisions | |
src/basics.h | file | annotate | diff | comparison | revisions | |
src/glCompiler.cpp | file | annotate | diff | comparison | revisions | |
src/glRenderer.cpp | file | annotate | diff | comparison | revisions | |
src/glShared.h | file | annotate | diff | comparison | revisions | |
src/ldDocument.cpp | file | annotate | diff | comparison | revisions | |
src/macros.h | file | annotate | diff | comparison | revisions |
--- 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<BfcStatement>()) { // Separate these in two columns - if (int(i) == ENUM_LIMIT(BfcStatement, Count) / 2) + if (int(statement) == EnumLimits<BfcStatement>::Count / 2) rb_bfcType->rowBreak(); - rb_bfcType->addButton (LDBfc::statementToString (i)); + rb_bfcType->addButton (LDBfc::statementToString(statement)); } if (obj)
--- 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<typename T> +inline int rotl10(T x) +{ + return (((x) << 10) | (((x) >> 22) & 0x000000ff)); +} + +template<typename T> +inline int rotl20(T x) +{ + return (((x) << 20) | (((x) >> 12) & 0x000000ff)); +} + uint qHash(const Vertex& key) { - return qHash(static_cast<const QVector3D&>(key)); + return qHash(key.x()) ^ rotl10(qHash(key.y())) ^ rotl20(qHash(key.z())); }
--- 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<typename Enum> +struct EnumIterShell +{ + struct Iterator + { + Iterator(typename std::underlying_type<Enum>::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<Enum>::type i; + }; + + Iterator begin() + { + return Iterator(EnumLimits<Enum>::First); + }; + + Iterator end() + { + return Iterator(EnumLimits<Enum>::End); + } +}; + +template<typename Enum> +EnumIterShell<Enum> iterateEnum() +{ + return EnumIterShell<Enum>(); +} + +// Is a value inside an enum? +template<typename Enum> +bool valueInEnum(typename std::underlying_type<Enum>::type x) +{ + return x >= EnumLimits<Enum>::First and x <= EnumLimits<Enum>::Last; +} \ No newline at end of file
--- 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<ComplementVboType>()) { const int vbonum = vboNumber (surface, complement); QVector<GLfloat>& 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<ComplementVboType>::Count) + complement; }
--- 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<Camera>::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<Camera>()) { - const char* cameraIconNames[ENUM_LIMIT(Camera, Count)] = + const char* cameraIconNames[EnumLimits<Camera>::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<Camera>()) { if (camera == FreeCamera) continue; @@ -1457,7 +1457,7 @@ // void GLRenderer::updateOverlayObjects() { - for_enum(Camera, camera) + for (Camera camera : iterateEnum<Camera>()) { if (camera == FreeCamera) continue;
--- 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<SurfaceVboType>::Count * EnumLimits<ComplementVboType>::Count }; #ifndef USE_QT5
--- 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<BfcStatement>()) { - if (commentTextSimplified == format ("BFC %1", LDBfc::statementToString (i))) - return LDSpawn<LDBfc> (i); + if (commentTextSimplified == format("BFC %1", LDBfc::statementToString (statement))) + return LDSpawn<LDBfc>(statement); } // MLCAD is notorious for stuffing these statements in parts it
--- 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<T> \ {\ - 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<typename T> +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<ENUM>::type -#define ENUM_LIMIT(ENUM, T) FOR_ENUM_TYPE(ENUM)(EnumLimits<ENUM>::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<ENUM>::Last + 1)) - -template<typename T> -struct EnumLimits {}; - -template<typename Enum> -bool valueInEnum(typename std::underlying_type<Enum>::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; } \