summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llassettype.cpp69
-rw-r--r--indra/llcommon/llassettype.h19
-rw-r--r--indra/llcommon/llsd.cpp26
-rw-r--r--indra/llcommon/llsd.h5
-rw-r--r--indra/llcommon/llsdserialize.cpp10
-rw-r--r--indra/llcommon/llsdserialize.h2
-rw-r--r--indra/llcommon/llsdutil.cpp275
-rw-r--r--indra/llcommon/llsdutil.h96
-rw-r--r--indra/llcommon/lluuid.h20
9 files changed, 472 insertions, 50 deletions
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 4304db36be..22d6bae0eb 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -70,35 +70,38 @@ LLAssetDictionary::LLAssetDictionary()
{
// DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? CAN FETCH? CAN KNOW?
// |--------------------|-----------|-------------------|-----------|-----------|---------|
- addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", true, false, true));
- addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", true, true, true));
- addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", true, false, false));
- addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", true, true, true));
- addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", true, false, false));
- addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true));
- addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false));
- addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", true, false, true));
- addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false));
- addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", true, false, false));
- addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", true, false, false));
- addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", true, false, false));
- addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true));
- addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", true, false, false));
- addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", true, false, false));
- addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", true, false, false));
- addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", true, true, true));
- addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true));
- addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false));
-
- addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true));
- addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true));
- addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false));
- addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
- addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
- addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
+ addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", true, false, true));
+ addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", true, true, true));
+ addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", true, false, false));
+ addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", true, true, true));
+ addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", true, false, false));
+ addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true));
+ addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false));
+ addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", true, false, true));
+ addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false));
+ addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", true, false, false));
+ addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", true, false, false));
+ addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", true, false, false));
+ addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true));
+ addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", true, false, false));
+ addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", true, false, false));
+ addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", true, false, false));
+ addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", true, true, true));
+ addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true));
+ addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false));
+
+ addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true));
+ addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true));
+ addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false));
+ addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
+ addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
+ addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", false, true, true));
+ addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
};
+const std::string LLAssetType::BADLOOKUP("llassettype_bad_lookup");
+
// static
LLAssetType::EType LLAssetType::getType(const std::string& desc_name)
{
@@ -117,7 +120,7 @@ const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)
}
else
{
- return badLookup();
+ return BADLOOKUP;
}
}
@@ -132,7 +135,7 @@ const char *LLAssetType::lookup(LLAssetType::EType asset_type)
}
else
{
- return badLookup().c_str();
+ return BADLOOKUP.c_str();
}
}
@@ -170,7 +173,7 @@ const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)
}
else
{
- return badLookup().c_str();
+ return BADLOOKUP.c_str();
}
}
@@ -221,14 +224,6 @@ bool LLAssetType::lookupIsLinkType(EType asset_type)
}
// static
-const std::string &LLAssetType::badLookup()
-{
- static const std::string sBadLookup = "llassettype_bad_lookup";
- return sBadLookup;
-
-}
-
-// static
bool LLAssetType::lookupIsAssetFetchByIDAllowed(EType asset_type)
{
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index b849be9f16..32502d5e33 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -116,10 +116,19 @@ public:
AT_PERSON = 45,
// A user uuid which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop.
- AT_MESH = 49,
- // Mesh data in our proprietary SLM format
-
- AT_COUNT = 50,
+ AT_MESH = 49,
+ // Mesh data in our proprietary SLM format
+
+ AT_RESERVED_1 = 50,
+ AT_RESERVED_2 = 51,
+ AT_RESERVED_3 = 52,
+ AT_RESERVED_4 = 53,
+ AT_RESERVED_5 = 54,
+ AT_RESERVED_6 = 55,
+
+ AT_SETTINGS = 56, // Collection of settings
+
+ AT_COUNT = 57,
// +*********************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
@@ -153,7 +162,7 @@ public:
static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
- static const std::string& badLookup(); // error string when a lookup fails
+ static const std::string BADLOOKUP;
protected:
LLAssetType() {}
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 57aa7d9c07..57b746889d 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -132,6 +132,7 @@ public:
virtual bool has(const String&) const { return false; }
virtual LLSD get(const String&) const { return LLSD(); }
+ virtual LLSD getKeys() const { return LLSD::emptyArray(); }
virtual void erase(const String&) { }
virtual const LLSD& ref(const String&) const{ return undef(); }
@@ -380,7 +381,8 @@ namespace
using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
virtual LLSD get(const LLSD::String&) const;
- void insert(const LLSD::String& k, const LLSD& v);
+ virtual LLSD getKeys() const;
+ void insert(const LLSD::String& k, const LLSD& v);
virtual void erase(const LLSD::String&);
LLSD& ref(const LLSD::String&);
virtual const LLSD& ref(const LLSD::String&) const;
@@ -421,7 +423,19 @@ namespace
DataMap::const_iterator i = mData.find(k);
return (i != mData.end()) ? i->second : LLSD();
}
-
+
+ LLSD ImplMap::getKeys() const
+ {
+ LLSD keys = LLSD::emptyArray();
+ DataMap::const_iterator iter = mData.begin();
+ while (iter != mData.end())
+ {
+ keys.append((*iter).first);
+ iter++;
+ }
+ return keys;
+ }
+
void ImplMap::insert(const LLSD::String& k, const LLSD& v)
{
mData.insert(DataMap::value_type(k, v));
@@ -502,7 +516,7 @@ namespace
virtual LLSD get(LLSD::Integer) const;
void set(LLSD::Integer, const LLSD&);
void insert(LLSD::Integer, const LLSD&);
- void append(const LLSD&);
+ LLSD& append(const LLSD&);
virtual void erase(LLSD::Integer);
LLSD& ref(LLSD::Integer);
virtual const LLSD& ref(LLSD::Integer) const;
@@ -570,9 +584,10 @@ namespace
mData.insert(mData.begin() + index, v);
}
- void ImplArray::append(const LLSD& v)
+ LLSD& ImplArray::append(const LLSD& v)
{
mData.push_back(v);
+ return mData.back();
}
void ImplArray::erase(LLSD::Integer i)
@@ -862,6 +877,7 @@ LLSD LLSD::emptyMap()
bool LLSD::has(const String& k) const { return safe(impl).has(k); }
LLSD LLSD::get(const String& k) const { return safe(impl).get(k); }
+LLSD LLSD::getKeys() const { return safe(impl).getKeys(); }
void LLSD::insert(const String& k, const LLSD& v) { makeMap(impl).insert(k, v); }
LLSD& LLSD::with(const String& k, const LLSD& v)
@@ -895,7 +911,7 @@ LLSD& LLSD::with(Integer i, const LLSD& v)
makeArray(impl).insert(i, v);
return *this;
}
-void LLSD::append(const LLSD& v) { makeArray(impl).append(v); }
+LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); }
void LLSD::erase(Integer i) { makeArray(impl).erase(i); }
LLSD& LLSD::operator[](Integer i)
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index 7b9b1285f5..5b6d5545af 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -79,7 +79,7 @@
an LLSD array).
An array is a sequence of zero or more LLSD values.
-
+
Thread Safety
In general, these LLSD classes offer *less* safety than STL container
@@ -284,6 +284,7 @@ public:
bool has(const String&) const;
LLSD get(const String&) const;
+ LLSD getKeys() const; // Return an LLSD array with keys as strings
void insert(const String&, const LLSD&);
void erase(const String&);
LLSD& with(const String&, const LLSD&);
@@ -301,7 +302,7 @@ public:
LLSD get(Integer) const;
void set(Integer, const LLSD&);
void insert(Integer, const LLSD&);
- void append(const LLSD&);
+ LLSD& append(const LLSD&);
void erase(Integer);
LLSD& with(Integer, const LLSD&);
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 1aaff5628f..c3fb4ebc2c 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -55,6 +55,7 @@ static const S32 UNZIP_LLSD_MAX_DEPTH = 96;
static const char LEGACY_NON_HEADER[] = "<llsd>";
const std::string LLSD_BINARY_HEADER("LLSD/Binary");
const std::string LLSD_XML_HEADER("LLSD/XML");
+const std::string LLSD_NOTATION_HEADER("llsd/notation");
//used to deflate a gzipped asset (currently used for navmeshes)
#define windowBits 15
@@ -81,6 +82,11 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
f = new LLSDXMLFormatter;
break;
+ case LLSD_NOTATION:
+ str << "<? " << LLSD_NOTATION_HEADER << " ?>\n";
+ f = new LLSDNotationFormatter;
+ break;
+
default:
LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
}
@@ -168,6 +174,10 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
{
p = new LLSDXMLParser;
}
+ else if (header == LLSD_NOTATION_HEADER)
+ {
+ p = new LLSDNotationParser;
+ }
else
{
LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 8165410e80..fe0f4443ef 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -706,7 +706,7 @@ class LL_COMMON_API LLSDSerialize
public:
enum ELLSD_Serialize
{
- LLSD_BINARY, LLSD_XML
+ LLSD_BINARY, LLSD_XML, LLSD_NOTATION
};
/**
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 9d00395c0a..6a23c443a0 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -322,6 +322,180 @@ BOOL compare_llsd_with_template(
return TRUE;
}
+// filter_llsd_with_template() is a direct clone (copy-n-paste) of
+// compare_llsd_with_template with the following differences:
+// (1) bool vs BOOL return types
+// (2) A map with the key value "*" is a special value and maps any key in the
+// test llsd that doesn't have an explicitly matching key in the template.
+// (3) The element of an array with exactly one element is taken as a template
+// for *all* the elements of the test array. If the template array is of
+// different size, compare_llsd_with_template() semantics apply.
+bool filter_llsd_with_template(
+ const LLSD & llsd_to_test,
+ const LLSD & template_llsd,
+ LLSD & resultant_llsd)
+{
+ if (llsd_to_test.isUndefined() && template_llsd.isDefined())
+ {
+ resultant_llsd = template_llsd;
+ return true;
+ }
+ else if (llsd_to_test.type() != template_llsd.type())
+ {
+ resultant_llsd = LLSD();
+ return false;
+ }
+
+ if (llsd_to_test.isArray())
+ {
+ //they are both arrays
+ //we loop over all the items in the template
+ //verifying that the to_test has a subset (in the same order)
+ //any shortcoming in the testing_llsd are just taken
+ //to be the rest of the template
+ LLSD data;
+ LLSD::array_const_iterator test_iter;
+ LLSD::array_const_iterator template_iter;
+
+ resultant_llsd = LLSD::emptyArray();
+ test_iter = llsd_to_test.beginArray();
+
+ if (1 == template_llsd.size())
+ {
+ // If the template has a single item, treat it as
+ // the template for *all* items in the test LLSD.
+ template_iter = template_llsd.beginArray();
+
+ for (; test_iter != llsd_to_test.endArray(); ++test_iter)
+ {
+ if (! filter_llsd_with_template(*test_iter, *template_iter, data))
+ {
+ resultant_llsd = LLSD();
+ return false;
+ }
+ else
+ {
+ resultant_llsd.append(data);
+ }
+ }
+ }
+ else
+ {
+ // Traditional compare_llsd_with_template matching
+
+ for (template_iter = template_llsd.beginArray();
+ template_iter != template_llsd.endArray() &&
+ test_iter != llsd_to_test.endArray();
+ ++template_iter, ++test_iter)
+ {
+ if (! filter_llsd_with_template(*test_iter, *template_iter, data))
+ {
+ resultant_llsd = LLSD();
+ return false;
+ }
+ else
+ {
+ resultant_llsd.append(data);
+ }
+ }
+
+ //so either the test or the template ended
+ //we do another loop now to the end of the template
+ //grabbing the default values
+ for (;
+ template_iter != template_llsd.endArray();
+ ++template_iter)
+ {
+ resultant_llsd.append(*template_iter);
+ }
+ }
+ }
+ else if (llsd_to_test.isMap())
+ {
+ resultant_llsd = LLSD::emptyMap();
+
+ //now we loop over the keys of the two maps
+ //any excess is taken from the template
+ //excess is ignored in the test
+
+ // Special tag for wildcarded LLSD map key templates
+ const LLSD::String wildcard_tag("*");
+
+ const bool template_has_wildcard = template_llsd.has(wildcard_tag);
+ LLSD wildcard_value;
+ LLSD value;
+
+ const LLSD::map_const_iterator template_iter_end(template_llsd.endMap());
+ for (LLSD::map_const_iterator template_iter(template_llsd.beginMap());
+ template_iter_end != template_iter;
+ ++template_iter)
+ {
+ if (wildcard_tag == template_iter->first)
+ {
+ wildcard_value = template_iter->second;
+ }
+ else if (llsd_to_test.has(template_iter->first))
+ {
+ //the test LLSD has the same key
+ if (! filter_llsd_with_template(llsd_to_test[template_iter->first],
+ template_iter->second,
+ value))
+ {
+ resultant_llsd = LLSD();
+ return false;
+ }
+ else
+ {
+ resultant_llsd[template_iter->first] = value;
+ }
+ }
+ else if (! template_has_wildcard)
+ {
+ // test llsd doesn't have it...take the
+ // template as default value
+ resultant_llsd[template_iter->first] = template_iter->second;
+ }
+ }
+ if (template_has_wildcard)
+ {
+ LLSD sub_value;
+ LLSD::map_const_iterator test_iter;
+
+ for (test_iter = llsd_to_test.beginMap();
+ test_iter != llsd_to_test.endMap();
+ ++test_iter)
+ {
+ if (resultant_llsd.has(test_iter->first))
+ {
+ // Final value has test key, assume more specific
+ // template matched and we shouldn't modify it again.
+ continue;
+ }
+ else if (! filter_llsd_with_template(test_iter->second,
+ wildcard_value,
+ sub_value))
+ {
+ // Test value doesn't match wildcarded template
+ resultant_llsd = LLSD();
+ return false;
+ }
+ else
+ {
+ // Test value matches template, add the actuals.
+ resultant_llsd[test_iter->first] = sub_value;
+ }
+ }
+ }
+ }
+ else
+ {
+ //of same type...take the test llsd's value
+ resultant_llsd = llsd_to_test;
+ }
+
+ return true;
+}
+
/*****************************************************************************
* Helpers for llsd_matches()
*****************************************************************************/
@@ -681,3 +855,104 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits)
return false; // pacify the compiler
}
}
+
+// Construct a deep partial clone of of an LLSD object. primitive types share
+// references, however maps, arrays and binary objects are duplicated. An optional
+// filter may be include to exclude/include keys in a map.
+LLSD llsd_clone(LLSD value, LLSD filter)
+{
+ LLSD clone;
+ bool has_filter(filter.isMap());
+
+ switch (value.type())
+ {
+ case LLSD::TypeMap:
+ clone = LLSD::emptyMap();
+ for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm)
+ {
+ if (has_filter)
+ {
+ if (filter.has((*itm).first))
+ {
+ if (!filter[(*itm).first].asBoolean())
+ continue;
+ }
+ else if (filter.has("*"))
+ {
+ if (!filter["*"].asBoolean())
+ continue;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ clone[(*itm).first] = llsd_clone((*itm).second, filter);
+ }
+ break;
+ case LLSD::TypeArray:
+ clone = LLSD::emptyArray();
+ for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+ {
+ clone.append(llsd_clone(*ita, filter));
+ }
+ break;
+
+ case LLSD::TypeBinary:
+ {
+ LLSD::Binary bin(value.asBinary().begin(), value.asBinary().end());
+ clone = LLSD::Binary(bin);
+ break;
+ }
+ default:
+ clone = value;
+ }
+
+ return clone;
+}
+
+LLSD llsd_shallow(LLSD value, LLSD filter)
+{
+ LLSD shallow;
+ bool has_filter(filter.isMap());
+
+ if (value.isMap())
+ {
+ shallow = LLSD::emptyMap();
+ for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm)
+ {
+ if (has_filter)
+ {
+ if (filter.has((*itm).first))
+ {
+ if (!filter[(*itm).first].asBoolean())
+ continue;
+ }
+ else if (filter.has("*"))
+ {
+ if (!filter["*"].asBoolean())
+ continue;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ shallow[(*itm).first] = (*itm).second;
+ }
+ }
+ else if (value.isArray())
+ {
+ shallow = LLSD::emptyArray();
+ for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+ {
+ shallow.append(*ita);
+ }
+ }
+ else
+ {
+ return value;
+ }
+
+ return shallow;
+}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 01ab6bcb8d..863be04c8a 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);
@@ -70,6 +71,19 @@ LL_COMMON_API BOOL compare_llsd_with_template(
const LLSD& template_llsd,
LLSD& resultant_llsd);
+// filter_llsd_with_template() is a direct clone (copy-n-paste) of
+// compare_llsd_with_template with the following differences:
+// (1) bool vs BOOL return types
+// (2) A map with the key value "*" is a special value and maps any key in the
+// test llsd that doesn't have an explicitly matching key in the template.
+// (3) The element of an array with exactly one element is taken as a template
+// for *all* the elements of the test array. If the template array is of
+// different size, compare_llsd_with_template() semantics apply.
+bool filter_llsd_with_template(
+ const LLSD & llsd_to_test,
+ const LLSD & template_llsd,
+ LLSD & resultant_llsd);
+
/**
* Recursively determine whether a given LLSD data block "matches" another
* LLSD prototype. The returned string is empty() on success, non-empty() on
@@ -421,4 +435,86 @@ private:
} // namespace llsd
+
+// Creates a deep clone of an LLSD object. Maps, Arrays and binary objects
+// are duplicated, atomic primitives (Boolean, Integer, Real, etc) simply
+// use a shared reference.
+// Optionally a filter may be specified to control what is duplicated. The
+// map takes the form "keyname/boolean".
+// If the value is true the value will be duplicated otherwise it will be skipped
+// when encountered in a map. A key name of "*" can be specified as a wild card
+// and will specify the default behavior. If no wild card is given and the clone
+// encounters a name not in the filter, that value will be skipped.
+LLSD llsd_clone(LLSD value, LLSD filter = LLSD());
+
+// Creates a shallow copy of a map or array. If passed any other type of LLSD
+// object it simply returns that value. See llsd_clone for a description of
+// the filter parameter.
+LLSD llsd_shallow(LLSD value, LLSD filter = 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:
+ default:
+ 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