Replaced the ugly for_enum macro with a generator class

Sun, 08 May 2016 20:12:54 +0300

author
Teemu Piippo <teemu@compsta2.com>
date
Sun, 08 May 2016 20:12:54 +0300
changeset 1036
993c46d7eb75
parent 1035
8a60250175ba
child 1037
4a9185e94d78

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; } \

mercurial