MAINT-1175: merge backout LLRegistrySingleton<std::type_info::name()>
commit
5e1e44ca7e
|
|
@ -212,14 +212,6 @@ namespace LLInitParam
|
|||
|
||||
public:
|
||||
|
||||
struct CompareTypeID
|
||||
{
|
||||
bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
|
||||
{
|
||||
return lhs->before(*rhs);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<std::pair<std::string, bool> > name_stack_t;
|
||||
typedef std::pair<name_stack_t::iterator, name_stack_t::iterator> name_stack_range_t;
|
||||
typedef std::vector<std::string> possible_values_t;
|
||||
|
|
@ -242,20 +234,20 @@ namespace LLInitParam
|
|||
|
||||
template <typename T> bool readValue(T& param)
|
||||
{
|
||||
parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
|
||||
if (found_it != mParserReadFuncs->end())
|
||||
boost::optional<parser_read_func_t> found_it = mParserReadFuncs->find<T>();
|
||||
if (found_it)
|
||||
{
|
||||
return found_it->second(*this, (void*)¶m);
|
||||
return (*found_it)(*this, (void*)¶m);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
|
||||
{
|
||||
parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
|
||||
if (found_it != mParserWriteFuncs->end())
|
||||
boost::optional<parser_write_func_t> found_it = mParserWriteFuncs->find<T>();
|
||||
if (found_it)
|
||||
{
|
||||
return found_it->second(*this, (const void*)¶m, name_stack);
|
||||
return (*found_it)(*this, (const void*)¶m, name_stack);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -263,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)
|
||||
{
|
||||
parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
|
||||
if (found_it != mParserInspectFuncs->end())
|
||||
boost::optional<parser_inspect_func_t> found_it = mParserInspectFuncs->find<T>();
|
||||
if (found_it)
|
||||
{
|
||||
found_it->second(name_stack, min_count, max_count, possible_values);
|
||||
(*found_it)(name_stack, min_count, max_count, possible_values);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -281,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(std::make_pair(&typeid(T), read_func));
|
||||
mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
|
||||
mParserReadFuncs->insert<T>(read_func);
|
||||
mParserWriteFuncs->insert<T>(write_func);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void registerInspectFunc(parser_inspect_func_t inspect_func)
|
||||
{
|
||||
mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
|
||||
mParserInspectFuncs->insert<T>(inspect_func);
|
||||
}
|
||||
|
||||
bool mParseSilently;
|
||||
|
|
|
|||
|
|
@ -34,9 +34,21 @@
|
|||
#include "lltypeinfolookup.h"
|
||||
|
||||
template <typename T>
|
||||
class LLRegistryDefaultComparator
|
||||
struct LLRegistryDefaultComparator
|
||||
{
|
||||
bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; }
|
||||
// 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
|
||||
{
|
||||
return strcmp(lhs, rhs) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename KEY, typename VALUE>
|
||||
|
|
@ -72,7 +84,7 @@ public:
|
|||
{
|
||||
friend class LLRegistry<KEY, VALUE, COMPARATOR>;
|
||||
public:
|
||||
typedef typename LLRegistryMapSelector<KEY, VALUE>::type registry_map_t;
|
||||
typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;
|
||||
|
||||
bool add(ref_const_key_t key, ref_const_value_t value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,11 +13,47 @@
|
|||
#define LL_LLTYPEINFOLOOKUP_H
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/mem_fn.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <functional> // std::binary_function
|
||||
#include <typeinfo>
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* The following helper classes are based on the Boost.Unordered documentation:
|
||||
* http://www.boost.org/doc/libs/1_45_0/doc/html/unordered/hash_equality.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compute hash for a string passed as const char*
|
||||
*/
|
||||
struct const_char_star_hash: public std::unary_function<const char*, std::size_t>
|
||||
{
|
||||
std::size_t operator()(const char* str) const
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
for ( ; *str; ++str)
|
||||
{
|
||||
boost::hash_combine(seed, *str);
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute equality for strings passed as const char*
|
||||
*
|
||||
* I (nat) suspect that this is where the default behavior breaks for the
|
||||
* const char* values returned from std::type_info::name(). If you compare the
|
||||
* two const char* pointer values, as a naive, unspecialized implementation
|
||||
* will surely do, they'll compare unequal.
|
||||
*/
|
||||
struct const_char_star_equal: public std::binary_function<const char*, const char*, bool>
|
||||
{
|
||||
bool operator()(const char* lhs, const char* rhs) const
|
||||
{
|
||||
return strcmp(lhs, rhs) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* LLTypeInfoLookup is specifically designed for use cases for which you might
|
||||
|
|
@ -26,87 +62,55 @@
|
|||
* you can't rely on always getting the same std::type_info* for a given type:
|
||||
* different load modules will produce different std::type_info*.
|
||||
* LLTypeInfoLookup contains a workaround to address this issue.
|
||||
*
|
||||
* The API deliberately diverges from std::map in several respects:
|
||||
* * It avoids iterators, not only begin()/end() but also as return values
|
||||
* from insert() and find(). This bypasses transform_iterator overhead.
|
||||
* * Since we literally use compile-time types as keys, the essential insert()
|
||||
* and find() methods accept the key type as a @em template parameter,
|
||||
* accepting and returning value_type as a normal runtime value. This is to
|
||||
* permit future optimization (e.g. compile-time type hashing) without
|
||||
* changing the API.
|
||||
*/
|
||||
template <typename VALUE>
|
||||
class LLTypeInfoLookup
|
||||
{
|
||||
// We present an interface like this:
|
||||
typedef std::map<const std::type_info*, VALUE> intf_map_type;
|
||||
// Use this for our underlying implementation: lookup by
|
||||
// std::type_info::name() string. Note that we must store a std::pair<const
|
||||
// std::type_info*, VALUE> -- in other words, an intf_map_type::value_type
|
||||
// pair -- so we can present iterators that do the right thing.
|
||||
// (This might result in a lookup with one std::type_info* returning an
|
||||
// iterator to a different std::type_info*, but frankly, my dear, we don't
|
||||
// give a damn.)
|
||||
typedef boost::unordered_map<std::string, typename intf_map_type::value_type> impl_map_type;
|
||||
// Iterator shorthand
|
||||
typedef typename intf_map_type::iterator intf_iterator;
|
||||
typedef typename intf_map_type::const_iterator intf_const_iterator;
|
||||
typedef typename intf_map_type::value_type intf_value_type;
|
||||
typedef typename impl_map_type::iterator impl_iterator;
|
||||
typedef typename impl_map_type::const_iterator impl_const_iterator;
|
||||
typedef typename impl_map_type::value_type impl_value_type;
|
||||
// Type of function that transforms impl_value_type to intf_value_type
|
||||
typedef boost::function<intf_value_type&(impl_value_type&)> iterfunc;
|
||||
typedef boost::function<const intf_value_type&(const impl_value_type&)> const_iterfunc;
|
||||
// std::type_info::name() string. This is one of the rare cases in which I
|
||||
// dare use const char* directly, rather than std::string, because I'm
|
||||
// sure that every value returned by std::type_info::name() is static.
|
||||
// HOWEVER, specify our own hash + equality functors: naively comparing
|
||||
// distinct const char* values won't work.
|
||||
typedef boost::unordered_map<const char*, VALUE,
|
||||
const_char_star_hash, const_char_star_equal> impl_map_type;
|
||||
|
||||
public:
|
||||
typedef LLTypeInfoLookup<VALUE> self;
|
||||
typedef typename intf_map_type::key_type key_type;
|
||||
typedef typename intf_map_type::mapped_type mapped_type;
|
||||
typedef intf_value_type value_type;
|
||||
|
||||
// Iterators are different because we have to transform
|
||||
// impl_map_type::iterator to intf_map_type::iterator.
|
||||
typedef boost::transform_iterator<iterfunc, impl_iterator> iterator;
|
||||
typedef boost::transform_iterator<const_iterfunc, impl_const_iterator> const_iterator;
|
||||
typedef VALUE value_type;
|
||||
|
||||
LLTypeInfoLookup() {}
|
||||
|
||||
iterator begin() { return transform(mMap.begin()); }
|
||||
iterator end() { return transform(mMap.end()); }
|
||||
const_iterator begin() const { return const_transform(mMap.begin()); }
|
||||
const_iterator end() const { return const_transform(mMap.end()); }
|
||||
bool empty() const { return mMap.empty(); }
|
||||
std::size_t size() const { return mMap.size(); }
|
||||
|
||||
// Shorthand -- I've always wished std::map supported this signature.
|
||||
std::pair<iterator, bool> insert(const std::type_info* key, const VALUE& value)
|
||||
{
|
||||
return insert(value_type(key, value));
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& pair)
|
||||
template <typename KEY>
|
||||
bool insert(const value_type& value)
|
||||
{
|
||||
// Obtain and store the std::type_info::name() string as the key.
|
||||
// Save the whole incoming pair as the value!
|
||||
std::pair<impl_iterator, bool>
|
||||
inserted(mMap.insert(impl_value_type(pair.first->name(), pair)));
|
||||
// Have to transform the iterator before returning.
|
||||
return std::pair<iterator, bool>(transform(inserted.first), inserted.second);
|
||||
// Return just the bool from std::map::insert()'s return pair.
|
||||
return mMap.insert(typename impl_map_type::value_type(typeid(KEY).name(), value)).second;
|
||||
}
|
||||
|
||||
iterator find(const std::type_info* key)
|
||||
template <typename KEY>
|
||||
boost::optional<value_type> find() const
|
||||
{
|
||||
return transform(mMap.find(key->name()));
|
||||
}
|
||||
|
||||
const_iterator find(const std::type_info* key) const
|
||||
{
|
||||
return const_transform(mMap.find(key->name()));
|
||||
// Use the std::type_info::name() string as the key.
|
||||
typename impl_map_type::const_iterator found = mMap.find(typeid(KEY).name());
|
||||
if (found == mMap.end())
|
||||
return boost::optional<value_type>();
|
||||
return found->second;
|
||||
}
|
||||
|
||||
private:
|
||||
iterator transform(impl_iterator iter)
|
||||
{
|
||||
return iterator(iter, boost::mem_fn(&impl_value_type::second));
|
||||
}
|
||||
const_iterator const_transform(impl_const_iterator iter)
|
||||
{
|
||||
return const_iterator(iter, boost::mem_fn(&impl_value_type::second));
|
||||
}
|
||||
|
||||
impl_map_type mMap;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -34,15 +34,6 @@
|
|||
|
||||
class LLView;
|
||||
|
||||
// sort functor for typeid maps
|
||||
struct LLCompareTypeID
|
||||
{
|
||||
bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
|
||||
{
|
||||
return lhs->before(*rhs);
|
||||
}
|
||||
};
|
||||
|
||||
// lookup widget constructor funcs by widget name
|
||||
template <typename DERIVED_TYPE>
|
||||
class LLChildRegistry : public LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE>
|
||||
|
|
|
|||
Loading…
Reference in New Issue