* New enum system that works alot better 4.x-dev

Thu, 19 Jun 2014 07:31:29 +0300

author
cemkalyoncu
date
Thu, 19 Jun 2014 07:31:29 +0300
branch
4.x-dev
changeset 479
7d0924c7cfde
parent 478
0e80f575d20e
child 480
56e0f16aef0d

* New enum system that works alot better
* Enum system is moved out of string

.hgignore file | annotate | diff | comparison | revisions
Source/Enum.h file | annotate | diff | comparison | revisions
Source/String/Enum.h file | annotate | diff | comparison | revisions
Source/String/dir.cmake file | annotate | diff | comparison | revisions
Source/dir.cmake file | annotate | diff | comparison | revisions
--- a/.hgignore	Thu Jun 19 07:24:17 2014 +0300
+++ b/.hgignore	Thu Jun 19 07:31:29 2014 +0300
@@ -14,3 +14,6 @@
 *.suo
 *.sdf
 *.opensdf
+.kdev_include_paths
+syntax: regexp
+.*\.kdev4(_.*)?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Enum.h	Thu Jun 19 07:31:29 2014 +0300
@@ -0,0 +1,175 @@
+/// @file Enum.h contains Enum class that allows C++ enums to have string capabilities. 
+
+#pragma once
+#include <string>
+#include <iostream>
+
+	class gorgon__no_enum_trait {
+	public:
+		static const bool isupgradedenum=false;
+	};
+
+	
+	template<class T_>
+	gorgon_no_enum_trait gorgon__enum_trait_locator(T_);
+
+namespace Gorgon {
+
+	/// @cond INTERNAL
+
+	/// Expands user declared enumtraits for additional capabilities
+	template<class T_>
+	class expandedenumtraits {
+	public:
+		static_assert(decltype(gorgon__enum_trait_locator(T_()))::isupgradedenum, "Should be an enum");
+		
+		expandedenumtraits() {
+			T_ prev=traits.mapping.begin()->first;
+			listing.push_back(prev);
+			for(auto &p : traits.mapping) {
+				reversemapping.insert(std::make_pair(p.second, p.first));
+				if(p.first!=prev) {
+					listing.push_back(p.first);
+					prev=p.first;
+				}
+			}
+		}
+		
+		bool lookupstring(T_ e, std::string &s) const {
+			auto item=traits.mapping.find(e);
+			if(item==traits.mapping.end()) return false;
+			s=item->second;
+			return true;
+		}
+		
+		bool lookupvalue(const std::string &s, T_ &e) const {
+			auto item=reversemapping.find(s);
+			if(item==reversemapping.end()) return false;
+			e=item->second;
+			return true;
+		}
+		
+		typename std::vector<T_>::const_iterator begin() const {
+			return listing.begin();
+		}
+		
+		typename std::vector<T_>::const_iterator end() const {
+			return listing.end();
+		}
+		
+	private:
+		const decltype(gorgon__enum_trait_locator(T_())) traits;
+		std::map<std::string, T_> reversemapping;
+		std::vector<T_> listing;
+	};
+
+	/// This class performs instanced member to static conversion
+	template<class T_>
+	class staticenumtraits {
+	public:
+		static_assert(decltype(gorgon__enum_trait_locator(T_()))::isupgradedenum, "Should be an enum");
+		
+		static bool lookupstring(T_ e, std::string &s) {
+			return traits.lookupstring(e, s);
+		}
+		
+		static bool lookupvalue(const std::string &s, T_ &e) {
+			return traits.lookupvalue(s, e);
+		}
+		
+		static typename std::vector<T_>::const_iterator begin() {
+			return traits.begin();
+		}
+		
+		static typename std::vector<T_>::const_iterator end() {
+			return traits.end();
+		}
+		
+		static const expandedenumtraits<T_> traits;
+	};
+
+	template<class T_> 
+	const expandedenumtraits<T_> staticenumtraits<T_>::traits;
+	
+	template<class T_>
+	class enum_type_id {};
+	
+	/// @endcond
+
+	/// This macro converts a regular C++ enumeration in to an enumarable, streamable, and parsable
+	/// enumeration by assigning one or more strings to enum values. This version should be invoked
+	/// in the same namespace as the original enumeration. If this is not possible, you may use
+	/// DefineEnumStringsNS macro.
+	/// @see Enumerate 
+	/// @see Parse
+	#define DefineEnumStrings(type, ...) \
+	class gorgon_enumtraits_##type {\
+	public:\
+		static const bool isupgradedenum=true;\
+		\
+		const std::multimap<type, std::string> mapping={__VA_ARGS__};\
+	};\
+	gorgon_enumtraits_##type gorgon__enum_trait_locator(type);
+
+	/// This macro converts a regular C++ enumeration in to an enumarable, streamable, and parsable
+	/// enumeration by assigning one or more strings to enum values. This variant allows namespace
+	/// @see Enumerate 
+	/// @see Parse
+	#define DefineEnumStringsNS(ns, type, ...) \
+	class gorgon_enumtraits_##type {\
+	public:\
+		static const bool isupgradedenum=true;\
+		\
+		const std::multimap<ns::type, std::string> mapping={__VA_ARGS__};\
+	};\
+	gorgon_enumtraits_##type gorgon__enum_trait_locator(ns::type);
+	
+	/// Allows enumeration of upgraded enums using range based for.
+	/// @code
+	/// for(auto e : Enumerate<MyEnum>()) {
+	///     std::cout<<e<<std::endl;
+	/// }
+	/// @endcode
+	template<class T_>
+	typename std::enable_if<decltype(gorgon__enum_trait_locator(T_()))::isupgradedenum, enum_type_id<T_>>::type Enumerate() {
+		return enum_type_id<T_>();
+	}
+
+	template <class T_>
+	typename std::vector<T_>::const_iterator begin(enum_type_id<T_> &) {
+		return staticenumtraits<T_>::begin();
+	}
+
+	template <class T_>
+	typename std::vector<T_>::const_iterator end(enum_type_id<T_> &) {
+		return staticenumtraits<T_>::end();
+	}
+
+	template<class T_>
+	typename std::enable_if<decltype(gorgon__enum_trait_locator(T_()))::isupgradedenum, T_>::type Parse(const std::string &text) {
+		T_ e;
+		if(!staticenumtraits<T_>::lookupvalue(text, e)) return T_();
+		return e;
+	}
+}
+
+/// Stream writer for upgraded enums
+template<class T_>
+typename std::enable_if<decltype(gorgon__enum_trait_locator(T_()))::isupgradedenum, std::ostream&>::type operator <<(std::ostream &out, const T_ &e) {
+	std::string s;
+	if(!Gorgon::staticenumtraits<T_>::lookupstring(e, s)) return out;
+	out<<s;
+	
+	return out;
+}
+
+/// Stream reader for upgraded enums
+template<class T_>
+typename std::enable_if<decltype(gorgon__enum_trait_locator(T_()))::isupgradedenum, std::istream&>::type operator >>(std::istream &in, const T_ &e) {
+	std::string s;
+	e=T_();
+	in>>s;
+	if(!Gorgon::staticenumtraits<T_>::lookupvalue(s, e)) in.setstate(in.badbit);
+	
+	return in;
+}
--- a/Source/String/Enum.h	Thu Jun 19 07:24:17 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/// @file Enum.h contains Enum class that allows C++ 
-/// enums to have string capabilities
-
-#pragma once
-#include <string>
-
-namespace Gorgon { namespace String {
-
-	
-	/// Allows C++ enum to have string capabilities. These are,
-	/// conversion to string, conversion from string and add all members.
-	/// Additionally, this class provides interfaces for Listbox and the
-	/// like to convert enumeration to string without any need of extra
-	/// coding. Additional work has to be done to use enumerations with
-	/// this method. First of all, enum should be surrounded by a class.
-	/// This class should be supplied as template parameter. The enum
-	/// should be named as `Type` or typedef'd as `Type`. Additionally
-	/// This wrapper class should have a `static const char *` or `static
-	/// std::string` typed `Names` array, that contains string names
-	/// for enumeration items. Also the wrapper class should contain an
-	/// item named `end` which should be last enumeration item +1
-	/// This value can also be a part of the enum but not necessarily.
-	///
-	/// **Example 1**
-	/// @code
-	/// //MyEnum.h
-	/// class MyEnumWrapper {
-	/// public:
-	///     enum Type { Zero = 0, One, Two };
-	///     static const int   end;
-	///     static const char *Names[3];
-	/// };
-	/// typedef Gorgon::String::Enum<MyEnumWrapper> MyEnum;
-	///
-	/// //MyEnum.cpp
-	/// int MyEnumWrapper::end=MyEnumWrapper::two + 1;
-	/// const char *MyEnumWrapper::Names = {"Zero", "One", "Two" };
-	///
-	/// //Somewhere else
-	/// MyEnum::Type value=MyEnum::One;
-	/// std::cout<<MyEnum::ToString(value)<<std::endl;
-	///
-	/// @endcode
-	///
-	/// **Example 2**
-	/// @code
-	/// enum MyEnum { Zero = 0, One, Two };
-	/// class MyEnumWrapper : public MyEnum {
-	/// public:
-	///     typedef MyEnum     Type;
-	///     static const int   end;
-	///     static const char *Names[3];
-	/// };
-	/// typedef Gorgon::String::Enum<MyEnumWrapper> MyCapableEnum;
-	///
-	/// //MyEnum.cpp
-	/// int MyEnumWrapper::end=MyEnumWrapper::two + 1;
-	/// const char *MyEnumWrapper::Names = {"Zero", "One", "Two" };
-	///
-	/// //Somewhere else
-	/// MyEnum value=One;
-	/// std::cout<<MyCapableEnum::ToString(value)<<std::endl;
-	/// @endcode
-	template<class T_>
-	class Enum : public T_ {
-	public:
-
-		/// Converts given type to string, if the given value is out of
-		/// range, empty string is returned.
-		static std::string ToString(const typename T_::Type &e) {
-			if(e<T_::end && e>=0)
-				return T_::Names[e];
-			else
-				return "";
-		}
-
-		/// This method can be supplied to Listbox and the like to allow the use
-		/// of this enum without any extra coding
-		static void ConvertToString(const typename T_::Type &e, std::string &s) {
-			s=ToString(e);
-		}
-
-		/// Parses the given string to determine the enumeration value. Returns end
-		/// if not the same. Comparison is case sensitive
-		static typename T_::Type Parse(const std::string &s) {
-			for(typename T_::Type e=(typename T_::Type)0;e<T_::end;e++)
-				if(s==T_::Names[e])
-					return e;
-			
-			return T_::end;
-		}
-
-		/// This method can be supplied to Combobox and the like to allow the use
-		/// of this enum without any extra coding
-		static void ParseTo(typename T_::Type &e, const std::string &s) {
-			//TODO
-			for(e=(typename T_::Type)0;e<T_::end;e++)
-				if(s==T_::Names[e])
-					return;
-				
-			e=T_::end;
-		}
-
-		/// Adds all elements of this Enum to a given collection.
-		//TODO modify
-		template<class C_>
-		static void AddAll(C_ &collection) {
-			for(int i=0;i<T_::end;i++)
-				collection.Add((typename T_::Type)i);
-		}
-		
-		/// Helper function to work with Gorgon::String::From
-		friend std::string From<T_>(const T_::Type &e) {
-			return Enum<T_>ToString(e);
-		}
-		
-	};
-
-}}
--- a/Source/String/dir.cmake	Thu Jun 19 07:24:17 2014 +0300
+++ b/Source/String/dir.cmake	Thu Jun 19 07:31:29 2014 +0300
@@ -1,6 +1,5 @@
 SET(Local
 	../String.h
-	Enum.h
 	String.cpp
 	Tokenizer.h
 )
--- a/Source/dir.cmake	Thu Jun 19 07:24:17 2014 +0300
+++ b/Source/dir.cmake	Thu Jun 19 07:31:29 2014 +0300
@@ -13,6 +13,7 @@
 	Time
 	WindowManager
 	Any.h
+	Enum.h
 	Event.h
 	Keyboard.h
 	Layer.h

mercurial