diff options
author | Rider Linden <rider@lindenlab.com> | 2017-11-27 10:19:43 -0800 |
---|---|---|
committer | Rider Linden <rider@lindenlab.com> | 2017-11-27 10:19:43 -0800 |
commit | 66ba27cb91b4f81625b8ab535f41bcf38a2aae99 (patch) | |
tree | a542d46607c4360a1648fd53c8dbe03f4690a9a7 | |
parent | 0bf6386c61c0c28b298c2cccd82c786f754024af (diff) |
Added boost::hash<> spec for LLSD
-rw-r--r-- | indra/llcommon/llsdutil.h | 65 | ||||
-rw-r--r-- | indra/llcommon/lluuid.h | 20 | ||||
-rw-r--r-- | indra/newview/llsettingsbase.cpp | 6 | ||||
-rw-r--r-- | indra/newview/llsettingsbase.h | 6 | ||||
-rw-r--r-- | indra/test/llsdutil_tut.cpp | 45 |
5 files changed, 140 insertions, 2 deletions
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 99cb79aa54..595bb91411 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -30,6 +30,7 @@ #define LL_LLSDUTIL_H #include "llsd.h" +#include <boost/functional/hash.hpp> // U32 LL_COMMON_API LLSD ll_sd_from_U32(const U32); @@ -419,4 +420,68 @@ private: } // namespace llsd + +// Specialization for generating a hash value from an LLSD block. +template <> +struct boost::hash<LLSD> +{ + typedef LLSD argument_type; + typedef std::size_t result_type; + result_type operator()(argument_type const& s) const + { + result_type seed(0); + + LLSD::Type stype = s.type(); + boost::hash_combine(seed, (S32)stype); + + switch (stype) + { + case LLSD::TypeBoolean: + boost::hash_combine(seed, s.asBoolean()); + break; + case LLSD::TypeInteger: + boost::hash_combine(seed, s.asInteger()); + break; + case LLSD::TypeReal: + boost::hash_combine(seed, s.asReal()); + break; + case LLSD::TypeURI: + case LLSD::TypeString: + boost::hash_combine(seed, s.asString()); + break; + case LLSD::TypeUUID: + boost::hash_combine(seed, s.asUUID()); + break; + case LLSD::TypeDate: + boost::hash_combine(seed, s.asDate().secondsSinceEpoch()); + break; + case LLSD::TypeBinary: + { + const LLSD::Binary &b(s.asBinary()); + boost::hash_range(seed, b.begin(), b.end()); + break; + } + case LLSD::TypeMap: + { + for (LLSD::map_const_iterator itm = s.beginMap(); itm != s.endMap(); ++itm) + { + boost::hash_combine(seed, (*itm).first); + boost::hash_combine(seed, (*itm).second); + } + break; + } + case LLSD::TypeArray: + for (LLSD::array_const_iterator ita = s.beginArray(); ita != s.endArray(); ++ita) + { + boost::hash_combine(seed, (*ita)); + } + break; + case LLSD::TypeUndefined: + break; + } + + return seed; + } +}; + #endif // LL_LLSDUTIL_H diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index dd8660a3c8..fe7482ba29 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -31,6 +31,7 @@ #include <vector> #include "stdtypes.h" #include "llpreprocessor.h" +#include <boost/functional/hash.hpp> class LLMutex; @@ -164,6 +165,25 @@ public: LLAssetID makeAssetID(const LLUUID& session) const; }; +// Generate a hash of an LLUUID object using the boost hash templates. +template <> +struct boost::hash<LLUUID> +{ + typedef LLUUID argument_type; + typedef std::size_t result_type; + result_type operator()(argument_type const& s) const + { + result_type seed(0); + + for (S32 i = 0; i < UUID_BYTES; ++i) + { + boost::hash_combine(seed, s.mData[i]); + } + + return seed; + } +}; + #endif diff --git a/indra/newview/llsettingsbase.cpp b/indra/newview/llsettingsbase.cpp index 904d0dd07c..e36c6d4a84 100644 --- a/indra/newview/llsettingsbase.cpp +++ b/indra/newview/llsettingsbase.cpp @@ -48,13 +48,15 @@ const F32Seconds LLSettingsBlender::DEFAULT_THRESHOLD(0.01); //========================================================================= LLSettingsBase::LLSettingsBase(): mSettings(LLSD::emptyMap()), - mDirty(true) + mDirty(true), + mHashValue(0) { } LLSettingsBase::LLSettingsBase(const LLSD setting) : mSettings(setting), - mDirty(true) + mDirty(true), + mHashValue(0) { } diff --git a/indra/newview/llsettingsbase.h b/indra/newview/llsettingsbase.h index d32fcb26e8..d304b8702a 100644 --- a/indra/newview/llsettingsbase.h +++ b/indra/newview/llsettingsbase.h @@ -67,6 +67,11 @@ public: inline bool isDirty() const { return mDirty; } inline void setDirtyFlag(bool dirty) { mDirty = dirty; } + inline size_t getHash() const + { + return boost::hash<LLSD>{}(mSettings); + } + inline LLUUID getId() const { return getValue(SETTING_ID).asUUID(); @@ -227,6 +232,7 @@ protected: private: bool mDirty; + size_t mHashValue; LLSD combineSDMaps(const LLSD &first, const LLSD &other) const; diff --git a/indra/test/llsdutil_tut.cpp b/indra/test/llsdutil_tut.cpp index 140f4b832b..6fce53f335 100644 --- a/indra/test/llsdutil_tut.cpp +++ b/indra/test/llsdutil_tut.cpp @@ -386,4 +386,49 @@ namespace tut lmap["Seattle"] = 72; ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap)); } + + template<> template<> + void llsdutil_object::test<10>() + { + set_test_name("llsd_hashing"); + + { + LLSD data_s1 = LLSD::String("The quick brown aardvark jumped over the lazy lemming."); + LLSD data_s2 = LLSD::String("The quick brown aardvark jumped over the lazy lemming."); + + ensure("hash: Identical string hashes match.", boost::hash<LLSD>{}(data_s1) == boost::hash<LLSD>{}(data_s2)); + } + { + LLSD data_r1 = LLSD::Real(3.0f); + LLSD data_i1 = LLSD::Integer(3); + ensure("hash: equivalent values but different types do not match.", boost::hash<LLSD>{}(data_r1) != boost::hash<LLSD>{}(data_i1)); + } + { + LLSD data_a1 = LLSDArray("A")("B")("C"); + LLSD data_a2 = LLSDArray("A")("B")("C"); + + ensure("hash: identical arrays produce identical results", boost::hash<LLSD>{}(data_a1) == boost::hash<LLSD>{}(data_a2)); + + data_a2.append(LLSDArray(1)(2)); + + ensure("hash: changing the array changes the hash.", boost::hash<LLSD>{}(data_a1) != boost::hash<LLSD>{}(data_a2)); + + data_a1.append(LLSDArray(1)(2)); + ensure("hash: identical arrays produce identical results with nested arrays", boost::hash<LLSD>{}(data_a1) == boost::hash<LLSD>{}(data_a2)); + } + { + LLSD data_m1 = LLSDMap("key1", LLSD::Real(3.0))("key2", "value2")("key3", LLSDArray(1)(2)(3)); + LLSD data_m2 = LLSDMap("key1", LLSD::Real(3.0))("key2", "value2")("key3", LLSDArray(1)(2)(3)); + + ensure("hash: identical maps produce identical results", boost::hash<LLSD>{}(data_m1) == boost::hash<LLSD>{}(data_m2)); + + LLSD data_m3 = LLSDMap("key1", LLSD::Real(5.0))("key2", "value2")("key3", LLSDArray(1)(2)(3)); + ensure("hash: Different values in the map produce different hashes.", boost::hash<LLSD>{}(data_m1) != boost::hash<LLSD>{}(data_m3)); + + LLSD data_m4 = LLSDMap("keyA", LLSD::Real(3.0))("key2", "value2")("key3", LLSDArray(1)(2)(3)); + ensure("hash: Different keys in the map produce different hashes.", boost::hash<LLSD>{}(data_m1) != boost::hash<LLSD>{}(data_m4)); + + } + } + } |