From 2e83dfa217feb90e7b94e499346ad9b98fa711b2 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 18 Jul 2012 20:33:54 -0400
Subject: [PATCH] MAINT-1175: Ditch LLTypeInfoLookup, make map<const
 type_info*> work. Instead of forbidding std::map<const std::type_info*, ...>
 outright (which includes LLRegistry<const std::type_info*, ...> and
 LLRegistrySingleton<const std::type_info*, ...>), try to make it work by
 specializing std::less<const std::type_info*> to use
 std::type_info::before(). Make LLRegistryDefaultComparator<T> use
 std::less<T> so it can capitalize on that specialization.

---
 indra/llcommon/llinitparam.h | 32 ++++++++++++++++----------------
 indra/llcommon/llregistry.h  | 34 ++++------------------------------
 indra/llcommon/llstl.h       | 30 ++++++++++++++++++++++++++++++
 indra/llui/lluictrlfactory.h |  5 +++--
 4 files changed, 53 insertions(+), 48 deletions(-)

diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 66c72c2d9f8..9a6d1eff5c2 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -35,7 +35,7 @@
 #include <boost/shared_ptr.hpp>
 
 #include "llerror.h"
-#include "lltypeinfolookup.h"
+#include "llstl.h"
 
 namespace LLInitParam
 {
@@ -220,9 +220,9 @@ namespace LLInitParam
 		typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
 		typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
 
-		typedef LLTypeInfoLookup<parser_read_func_t>		parser_read_func_map_t;
-		typedef LLTypeInfoLookup<parser_write_func_t>		parser_write_func_map_t;
-		typedef LLTypeInfoLookup<parser_inspect_func_t>		parser_inspect_func_map_t;
+		typedef std::map<const std::type_info*, parser_read_func_t>		parser_read_func_map_t;
+		typedef std::map<const std::type_info*, parser_write_func_t>	parser_write_func_map_t;
+		typedef std::map<const std::type_info*, parser_inspect_func_t>	parser_inspect_func_map_t;
 
 		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
 		:	mParseSilently(false),
@@ -234,20 +234,20 @@ namespace LLInitParam
 
 		template <typename T> bool readValue(T& param)
 	    {
-		    boost::optional<parser_read_func_t> found_it = mParserReadFuncs->find<T>();
-		    if (found_it)
+		    parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+		    if (found_it != mParserReadFuncs->end())
 		    {
-			    return (*found_it)(*this, (void*)&param);
+			    return found_it->second(*this, (void*)&param);
 		    }
 		    return false;
 	    }
 
 		template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
 		{
-		    boost::optional<parser_write_func_t> found_it = mParserWriteFuncs->find<T>();
-		    if (found_it)
+		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
+		    if (found_it != mParserWriteFuncs->end())
 		    {
-			    return (*found_it)(*this, (const void*)&param, name_stack);
+			    return found_it->second(*this, (const void*)&param, name_stack);
 		    }
 		    return false;
 		}
@@ -255,10 +255,10 @@ namespace LLInitParam
 		// dispatch inspection to registered inspection functions, for each parameter in a param block
 		template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
 		{
-		    boost::optional<parser_inspect_func_t> found_it = mParserInspectFuncs->find<T>();
-		    if (found_it)
+		    parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
+		    if (found_it != mParserInspectFuncs->end())
 		    {
-			    (*found_it)(name_stack, min_count, max_count, possible_values);
+			    found_it->second(name_stack, min_count, max_count, possible_values);
 				return true;
 		    }
 			return false;
@@ -273,14 +273,14 @@ namespace LLInitParam
 		template <typename T>
 		void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
 		{
-			mParserReadFuncs->insert<T>(read_func);
-			mParserWriteFuncs->insert<T>(write_func);
+			mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
+			mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
 		}
 
 		template <typename T>
 		void registerInspectFunc(parser_inspect_func_t inspect_func)
 		{
-			mParserInspectFuncs->insert<T>(inspect_func);
+			mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
 		}
 
 		bool				mParseSilently;
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index 2df9bc65415..853c427a13e 100644
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -31,44 +31,18 @@
 
 #include <boost/type_traits.hpp>
 #include "llsingleton.h"
-#include "lltypeinfolookup.h"
+#include "llstl.h"
 
 template <typename T>
 struct LLRegistryDefaultComparator
 {
-	// It would be Bad if this comparison were used for const char*
-	BOOST_STATIC_ASSERT(! (boost::is_same<typename boost::remove_const<typename boost::remove_pointer<T>::type>::type, char>::value));
-	bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; }
-};
-
-// comparator for const char* registry keys
-template <>
-struct LLRegistryDefaultComparator<const char*>
-{
-	bool operator()(const char* lhs, const char* rhs) const
+	bool operator()(const T& lhs, const T& rhs) const
 	{
-		return strcmp(lhs, rhs) < 0;
+		using std::less;
+		return less<T>()(lhs, rhs);
 	}
 };
 
-template <typename KEY, typename VALUE>
-struct LLRegistryMapSelector
-{
-    typedef std::map<KEY, VALUE> type;
-};
-
-template <typename VALUE>
-struct LLRegistryMapSelector<std::type_info*, VALUE>
-{
-    typedef LLTypeInfoLookup<VALUE> type;
-};
-
-template <typename VALUE>
-struct LLRegistryMapSelector<const std::type_info*, VALUE>
-{
-    typedef LLTypeInfoLookup<VALUE> type;
-};
-
 template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
 class LLRegistry
 {
diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h
index 8ad12c9a03c..6109b215468 100644
--- a/indra/llcommon/llstl.h
+++ b/indra/llcommon/llstl.h
@@ -33,6 +33,7 @@
 #include <vector>
 #include <set>
 #include <deque>
+#include <typeinfo>
 
 // Use to compare the first element only of a pair
 // e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t; 
@@ -470,4 +471,33 @@ llbind2nd(const _Operation& __oper, const _Tp& __x)
   return llbinder2nd<_Operation>(__oper, _Arg2_type(__x));
 }
 
+/**
+ * Specialize std::less<std::type_info*> to use std::type_info::before().
+ * See MAINT-1175. It is NEVER a good idea to directly compare std::type_info*
+ * because, on Linux, you might get different std::type_info* pointers for the
+ * same type (from different load modules)!
+ */
+namespace std
+{
+    template <>
+    struct less<const std::type_info*>:
+        public std::binary_function<const std::type_info*, const std::type_info*, bool>
+    {
+        bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
+        {
+            return lhs->before(*rhs);
+        }
+    };
+
+    template <>
+    struct less<std::type_info*>:
+        public std::binary_function<std::type_info*, std::type_info*, bool>
+    {
+        bool operator()(std::type_info* lhs, std::type_info* rhs) const
+        {
+            return lhs->before(*rhs);
+        }
+    };
+} // std
+
 #endif // LL_LLSTL_H
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index ab16805cb1a..4e54354731e 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -31,6 +31,7 @@
 #include "llinitparam.h"
 #include "llregistry.h"
 #include "llxuiparser.h"
+#include "llstl.h"
 
 class LLView;
 
@@ -62,14 +63,14 @@ class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry>
 
 // lookup widget name by type
 class LLWidgetNameRegistry 
-:	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry , LLCompareTypeID>
+:	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry>
 {};
 
 // lookup function for generating empty param block by widget type
 // this is used for schema generation
 //typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
 //class LLDefaultParamBlockRegistry
-//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID>
+//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry>
 //{};
 
 extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP;
-- 
GitLab