diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2020-05-06 16:06:26 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2020-05-06 16:06:26 -0400 | 
| commit | ca6f09292925a7bd936338cb598efb3ddc8524bf (patch) | |
| tree | 3f27e75fc8443b84e91fcac400084fd83dfed26a /indra/llcommon | |
| parent | 4768d092f611576b4e4e95574e9b16192e7ced5e (diff) | |
| parent | 4a7fd0117a43dca9e30c58c6417ebdf6862561f6 (diff) | |
DRTVWR-476: Merge branch 'master' of lindenlab/viewer into DRTVWR-476-boost-1.72
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/indra_constants.cpp | 1 | ||||
| -rw-r--r-- | indra/llcommon/indra_constants.h | 1 | ||||
| -rw-r--r-- | indra/llcommon/llassettype.cpp | 19 | ||||
| -rw-r--r-- | indra/llcommon/llassettype.h | 19 | ||||
| -rw-r--r-- | indra/llcommon/llerror.cpp | 53 | ||||
| -rw-r--r-- | indra/llcommon/llmemory.cpp | 6 | ||||
| -rw-r--r-- | indra/llcommon/llprocessor.cpp | 9 | ||||
| -rw-r--r-- | indra/llcommon/llsd.cpp | 26 | ||||
| -rw-r--r-- | indra/llcommon/llsd.h | 5 | ||||
| -rw-r--r-- | indra/llcommon/llsdserialize.cpp | 12 | ||||
| -rw-r--r-- | indra/llcommon/llsdserialize.h | 2 | ||||
| -rw-r--r-- | indra/llcommon/llsdutil.cpp | 275 | ||||
| -rw-r--r-- | indra/llcommon/llsdutil.h | 96 | ||||
| -rw-r--r-- | indra/llcommon/llsingleton.h | 15 | ||||
| -rw-r--r-- | indra/llcommon/llunittype.h | 37 | ||||
| -rw-r--r-- | indra/llcommon/lluuid.h | 20 | 
16 files changed, 529 insertions, 67 deletions
| diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp index e13176e8fa..1b48e4daf3 100644 --- a/indra/llcommon/indra_constants.cpp +++ b/indra/llcommon/indra_constants.cpp @@ -64,7 +64,6 @@ const LLUUID IMG_ALPHA_GRAD				("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEW  const LLUUID IMG_ALPHA_GRAD_2D			("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER  const LLUUID IMG_TRANSPARENT			("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER -const LLUUID IMG_BLOOM1	  			    ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER  const LLUUID TERRAIN_DIRT_DETAIL		("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER  const LLUUID TERRAIN_GRASS_DETAIL		("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER  const LLUUID TERRAIN_MOUNTAIN_DETAIL	("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 0fbf4b966b..e7b0e0ef8e 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -200,7 +200,6 @@ LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD;  LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD_2D;  LL_COMMON_API extern const LLUUID IMG_TRANSPARENT; -LL_COMMON_API extern const LLUUID IMG_BLOOM1;  LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;  LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;  LL_COMMON_API extern const LLUUID TERRAIN_MOUNTAIN_DETAIL; diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 7e5a157cdf..e6cc06e8d0 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -95,11 +95,14 @@ LLAssetDictionary::LLAssetDictionary()  	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",    true,       true,       true));  	addEntry(LLAssetType::AT_UNKNOWN,           new AssetEntry("UNKNOWN",           "invalid",  NULL,               false,      false,      false)); -	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		FALSE,		FALSE,		FALSE)); +    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)  { @@ -118,7 +121,7 @@ const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)  	}  	else  	{ -		return badLookup(); +		return BADLOOKUP;  	}  } @@ -133,7 +136,7 @@ const char *LLAssetType::lookup(LLAssetType::EType asset_type)  	}  	else  	{ -		return badLookup().c_str(); +		return BADLOOKUP.c_str();  	}  } @@ -171,7 +174,7 @@ const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)  	}  	else  	{ -		return badLookup().c_str(); +		return BADLOOKUP.c_str();  	}  } @@ -222,14 +225,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 79ab3d7efe..652c548d59 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/llerror.cpp b/indra/llcommon/llerror.cpp index 0daae96cca..41c4ddc725 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -193,39 +193,46 @@ namespace {              return LLError::getEnabledLogTypesMask() & 0x04;          } +        LL_FORCE_INLINE std::string createANSI(const std::string& color) +        { +            std::string ansi_code; +            ansi_code  += '\033'; +            ansi_code  += "["; +            ansi_code  += color; +            ansi_code += "m"; +            return ansi_code; +        } +  		virtual void recordMessage(LLError::ELevel level,  					   const std::string& message) override  		{ +            static std::string s_ansi_error = createANSI("31"); // red +            static std::string s_ansi_warn  = createANSI("34"); // blue +            static std::string s_ansi_debug = createANSI("35"); // magenta +  			if (mUseANSI)  			{ -				// Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries. -				colorANSI("1"); // bold -				switch (level) { -				case LLError::LEVEL_ERROR: -					colorANSI("31"); // red -					break; -				case LLError::LEVEL_WARN: -					colorANSI("34"); // blue -					break; -				case LLError::LEVEL_DEBUG: -					colorANSI("35"); // magenta -					break; -				default: -					break; -				} +                writeANSI((level == LLError::LEVEL_ERROR) ? s_ansi_error : +                          (level == LLError::LEVEL_WARN)  ? s_ansi_warn : +                                                            s_ansi_debug, message);  			} -			fprintf(stderr, "%s\n", message.c_str()); -			if (mUseANSI) colorANSI("0"); // reset +            else +            { +                 fprintf(stderr, "%s\n", message.c_str()); +            }  		}  	private:  		bool mUseANSI; -		void colorANSI(const std::string color) +        LL_FORCE_INLINE void writeANSI(const std::string& ansi_code, const std::string& message)  		{ -			// ANSI color code escape sequence -			fprintf(stderr, "\033[%sm", color.c_str() ); -		}; +            static std::string s_ansi_bold  = createANSI("1");  // bold +            static std::string s_ansi_reset = createANSI("0");  // reset +			// ANSI color code escape sequence, message, and reset in one fprintf call +            // Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries. +			fprintf(stderr, "%s%s%s\n%s", s_ansi_bold.c_str(), ansi_code.c_str(), message.c_str(), s_ansi_reset.c_str() ); +		}  		static bool checkANSI(void)  		{ @@ -236,8 +243,8 @@ namespace {  			return (0 != isatty(2)) &&  				(NULL == getenv("LL_NO_ANSI_COLOR"));  #endif // LL_LINUX -			return false; -		}; +            return FALSE; // works in a cygwin shell... ;) +		}  	};  	class RecordToFixedBuffer : public LLError::Recorder diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index b3debf3550..1884d6f04f 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -77,7 +77,7 @@ void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)  //static   void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)  { -	sMaxHeapSizeInKB = max_heap_size; +	sMaxHeapSizeInKB = U32Kilobytes::convert(max_heap_size);  	sEnableMemoryFailurePrevention = prevent_heap_failure ;  } @@ -93,9 +93,9 @@ void LLMemory::updateMemoryInfo()  		return ;  	} -	sAllocatedMemInKB = U64Bytes(counters.WorkingSetSize) ; +	sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));  	sample(sAllocatedMem, sAllocatedMemInKB); -	sAllocatedPageSizeInKB = U64Bytes(counters.PagefileUsage) ; +	sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));  	sample(sVirtualMem, sAllocatedPageSizeInKB);  	U32Kilobytes avail_phys, avail_virtual; diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index a618a1cc70..5d16a4b74d 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -195,6 +195,8 @@ namespace  	std::string amd_CPUFamilyName(int composed_family)   	{ +        // https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures +        // https://developer.amd.com/resources/developer-guides-manuals/  		switch(composed_family)  		{  		case 4: return "AMD 80486/5x86"; @@ -202,6 +204,13 @@ namespace  		case 6: return "AMD K7";  		case 0xF: return "AMD K8";  		case 0x10: return "AMD K8L"; +		case 0x12: return "AMD K10"; +		case 0x14: return "AMD Bobcat"; +		case 0x15: return "AMD Bulldozer"; +		case 0x16: return "AMD Jaguar"; +		case 0x17: return "AMD Zen/Zen+/Zen2"; +		case 0x18: return "AMD Hygon Dhyana"; +		case 0x19: return "AMD Zen 3";  		}  		return STRINGIZE("AMD <unknown 0x" << std::hex << composed_family << ">");  	} 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..79934642ae 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; @@ -2241,7 +2251,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,  			return ZR_SIZE_ERROR;  		}  #endif -		catch (std::bad_alloc) +		catch (std::bad_alloc&)  		{  			free(result);  			return ZR_MEM_ERROR; 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 ec883130bd..d44387cc55 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()  *****************************************************************************/ @@ -749,3 +923,104 @@ LLSD drill(const LLSD& blob, const LLSD& path)  }  } // namespace llsd + +// 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 2a8b44ec4e..2ff9ecdf89 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 @@ -516,4 +530,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/llsingleton.h b/indra/llcommon/llsingleton.h index ccd2e48bf2..30a5b21cf8 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -806,6 +806,17 @@ private:                                                                \      DERIVED_CLASS(__VA_ARGS__)  /** + * A slight variance from the above, but includes the "override" keyword + */ +#define LLSINGLETON_C11(DERIVED_CLASS)                                  \ +private:                                                                \ +    /* implement LLSingleton pure virtual method whose sole purpose */  \ +    /* is to remind people to use this macro */                         \ +    virtual void you_must_use_LLSINGLETON_macro() override {}           \ +    friend class LLSingleton<DERIVED_CLASS>;                            \ +    DERIVED_CLASS() + +/**   * Use LLSINGLETON_EMPTY_CTOR(Foo); at the start of an LLSingleton<Foo>   * subclass body when the constructor is trivial:   * @@ -823,4 +834,8 @@ private:                                                                \      /* LLSINGLETON() is carefully implemented to permit exactly this */ \      LLSINGLETON(DERIVED_CLASS) {} +#define LLSINGLETON_EMPTY_CTOR_C11(DERIVED_CLASS)                       \ +    /* LLSINGLETON() is carefully implemented to permit exactly this */ \ +    LLSINGLETON_C11(DERIVED_CLASS) {} +  #endif diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h index ac8504ca61..81f244e422 100644 --- a/indra/llcommon/llunittype.h +++ b/indra/llcommon/llunittype.h @@ -132,23 +132,34 @@ struct LLUnit  		return mValue;  	} -	LL_FORCE_INLINE void value(storage_t value) +	LL_FORCE_INLINE void value(const storage_t& value)  	{  		mValue = value;  	}  	template<typename NEW_UNITS>  -	storage_t valueInUnits() +	storage_t valueInUnits() const  	{  		return LLUnit<storage_t, NEW_UNITS>(*this).value();  	}  	template<typename NEW_UNITS>  -	void valueInUnits(storage_t value) +	void valueInUnits(const storage_t& value) const  	{  		*this = LLUnit<storage_t, NEW_UNITS>(value);  	} +    LL_FORCE_INLINE operator storage_t() const +    { +        return value(); +    } + +    /*LL_FORCE_INLINE self_t& operator= (storage_t v) +	{ +		value(v); +        return *this; +	}*/ +  	LL_FORCE_INLINE void operator += (self_t other)  	{  		mValue += convert(other).mValue; @@ -159,60 +170,60 @@ struct LLUnit  		mValue -= convert(other).mValue;  	} -	LL_FORCE_INLINE void operator *= (storage_t multiplicand) +	LL_FORCE_INLINE void operator *= (const storage_t& multiplicand)  	{  		mValue *= multiplicand;  	} -	LL_FORCE_INLINE void operator *= (self_t multiplicand) +	LL_FORCE_INLINE void operator *= (const self_t& multiplicand)  	{  		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template  		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");  	} -	LL_FORCE_INLINE void operator /= (storage_t divisor) +	LL_FORCE_INLINE void operator /= (const storage_t& divisor)  	{  		mValue /= divisor;  	} -	void operator /= (self_t divisor) +	void operator /= (const self_t& divisor)  	{  		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template  		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");  	}  	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> -	LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	LL_FORCE_INLINE bool operator == (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const  	{  		return mValue == convert(other).value();  	}  	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> -	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	LL_FORCE_INLINE bool operator != (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const  	{  		return mValue != convert(other).value();  	}  	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> -	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	LL_FORCE_INLINE bool operator < (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const  	{  		return mValue < convert(other).value();  	}  	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> -	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	LL_FORCE_INLINE bool operator <= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const  	{  		return mValue <= convert(other).value();  	}  	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> -	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	LL_FORCE_INLINE bool operator > (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const  	{  		return mValue > convert(other).value();  	}  	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> -	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	LL_FORCE_INLINE bool operator >= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const  	{  		return mValue >= convert(other).value();  	} 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 | 
