diff options
Diffstat (limited to 'indra/llcommon/llsd.h')
-rw-r--r-- | indra/llcommon/llsd.h | 850 |
1 files changed, 425 insertions, 425 deletions
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index 8ed254919c..a5e735b561 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -1,25 +1,25 @@ -/** +/** * @file llsd.h * @brief LLSD flexible data system. * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,450 +38,450 @@ #include "lluuid.h" /** - LLSD provides a flexible data system similar to the data facilities of - dynamic languages like Perl and Python. It is created to support exchange - of structured data between loosely coupled systems. (Here, "loosely coupled" - means not compiled together into the same module.) - - Data in such exchanges must be highly tolerant of changes on either side - such as: - - recompilation - - implementation in a different langauge - - addition of extra parameters - - execution of older versions (with fewer parameters) - - To this aim, the C++ API of LLSD strives to be very easy to use, and to - default to "the right thing" wherever possible. It is extremely tolerant - of errors and unexpected situations. - - The fundamental class is LLSD. LLSD is a value holding object. It holds - one value that is either undefined, one of the scalar types, or a map or an - array. LLSD objects have value semantics (copying them copies the value, - though it can be considered efficient, due to sharing), and mutable. - - Undefined is the singular value given to LLSD objects that are not - initialized with any data. It is also used as the return value for - operations that return an LLSD. - - The scalar data types are: - - Boolean - true or false - - Integer - a 32 bit signed integer - - Real - a 64 IEEE 754 floating point value - - UUID - a 128 unique value - - String - a sequence of zero or more Unicode chracters - - Date - an absolute point in time, UTC, - with resolution to the second - - URI - a String that is a URI - - Binary - a sequence of zero or more octets (unsigned bytes) - - A map is a dictionary mapping String keys to LLSD values. The keys are - unique within a map, and have only one value (though that value could be - 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 - classes. Implementations prior to this one were unsafe even when - completely unrelated LLSD trees were in two threads due to reference - sharing of special 'undefined' values that participated in the reference - counting mechanism. - - The dereference-before-refcount and aggressive tree sharing also make - it impractical to share an LLSD across threads. A strategy of passing - ownership or a copy to another thread is still difficult due to a lack - of a cloning interface but it can be done with some care. - - One way of transferring ownership is as follows: - - void method(const LLSD input) { - ... - LLSD * xfer_tree = new LLSD(); - { - // Top-level values - (* xfer_tree)['label'] = "Some text"; - (* xfer_tree)['mode'] = APP_MODE_CONSTANT; - - // There will be a second-level - LLSD subtree(LLSD::emptyMap()); - (* xfer_tree)['subtree'] = subtree; - - // Do *not* copy from LLSD objects via LLSD - // intermediaries. Only use plain-old-data - // types as intermediaries to prevent reference - // sharing. - subtree['value1'] = input['value1'].asInteger(); - subtree['value2'] = input['value2'].asString(); - - // Close scope and drop 'subtree's reference. - // Only xfer_tree has a reference to the second - // level data. - } - ... - // Transfer the LLSD pointer to another thread. Ownership - // transfers, this thread no longer has a reference to any - // part of the xfer_tree and there's nothing to free or - // release here. Receiving thread does need to delete the - // pointer when it is done with the LLSD. Transfer - // mechanism must perform correct data ordering operations - // as dictated by architecture. - other_thread.sendMessageAndPointer("Take This", xfer_tree); - xfer_tree = NULL; - - - Avoid this pattern which provides half of a race condition: - - void method(const LLSD input) { - ... - LLSD xfer_tree(LLSD::emptyMap()); - xfer_tree['label'] = "Some text"; - xfer_tree['mode'] = APP_MODE_CONSTANT; - ... - other_thread.sendMessageAndPointer("Take This", xfer_tree); - - - @nosubgrouping + LLSD provides a flexible data system similar to the data facilities of + dynamic languages like Perl and Python. It is created to support exchange + of structured data between loosely coupled systems. (Here, "loosely coupled" + means not compiled together into the same module.) + + Data in such exchanges must be highly tolerant of changes on either side + such as: + - recompilation + - implementation in a different langauge + - addition of extra parameters + - execution of older versions (with fewer parameters) + + To this aim, the C++ API of LLSD strives to be very easy to use, and to + default to "the right thing" wherever possible. It is extremely tolerant + of errors and unexpected situations. + + The fundamental class is LLSD. LLSD is a value holding object. It holds + one value that is either undefined, one of the scalar types, or a map or an + array. LLSD objects have value semantics (copying them copies the value, + though it can be considered efficient, due to sharing), and mutable. + + Undefined is the singular value given to LLSD objects that are not + initialized with any data. It is also used as the return value for + operations that return an LLSD. + + The scalar data types are: + - Boolean - true or false + - Integer - a 32 bit signed integer + - Real - a 64 IEEE 754 floating point value + - UUID - a 128 unique value + - String - a sequence of zero or more Unicode chracters + - Date - an absolute point in time, UTC, + with resolution to the second + - URI - a String that is a URI + - Binary - a sequence of zero or more octets (unsigned bytes) + + A map is a dictionary mapping String keys to LLSD values. The keys are + unique within a map, and have only one value (though that value could be + 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 + classes. Implementations prior to this one were unsafe even when + completely unrelated LLSD trees were in two threads due to reference + sharing of special 'undefined' values that participated in the reference + counting mechanism. + + The dereference-before-refcount and aggressive tree sharing also make + it impractical to share an LLSD across threads. A strategy of passing + ownership or a copy to another thread is still difficult due to a lack + of a cloning interface but it can be done with some care. + + One way of transferring ownership is as follows: + + void method(const LLSD input) { + ... + LLSD * xfer_tree = new LLSD(); + { + // Top-level values + (* xfer_tree)['label'] = "Some text"; + (* xfer_tree)['mode'] = APP_MODE_CONSTANT; + + // There will be a second-level + LLSD subtree(LLSD::emptyMap()); + (* xfer_tree)['subtree'] = subtree; + + // Do *not* copy from LLSD objects via LLSD + // intermediaries. Only use plain-old-data + // types as intermediaries to prevent reference + // sharing. + subtree['value1'] = input['value1'].asInteger(); + subtree['value2'] = input['value2'].asString(); + + // Close scope and drop 'subtree's reference. + // Only xfer_tree has a reference to the second + // level data. + } + ... + // Transfer the LLSD pointer to another thread. Ownership + // transfers, this thread no longer has a reference to any + // part of the xfer_tree and there's nothing to free or + // release here. Receiving thread does need to delete the + // pointer when it is done with the LLSD. Transfer + // mechanism must perform correct data ordering operations + // as dictated by architecture. + other_thread.sendMessageAndPointer("Take This", xfer_tree); + xfer_tree = NULL; + + + Avoid this pattern which provides half of a race condition: + + void method(const LLSD input) { + ... + LLSD xfer_tree(LLSD::emptyMap()); + xfer_tree['label'] = "Some text"; + xfer_tree['mode'] = APP_MODE_CONSTANT; + ... + other_thread.sendMessageAndPointer("Take This", xfer_tree); + + + @nosubgrouping */ // Normally undefined, used for diagnostics -//#define LLSD_DEBUG_INFO 1 +//#define LLSD_DEBUG_INFO 1 class LL_COMMON_API LLSD { public: - LLSD(); ///< initially Undefined - ~LLSD(); ///< this class may NOT be subclassed - - /** @name Copyable and Assignable */ - //@{ - LLSD(const LLSD&); - void assign(const LLSD& other); - LLSD& operator=(const LLSD& other) { assign(other); return *this; } - - //@} - - void clear(); ///< resets to Undefined - - - /** @name Scalar Types - The scalar types, and how they map onto C++ - */ - //@{ - typedef bool Boolean; - typedef S32 Integer; - typedef F64 Real; - typedef std::string String; - typedef LLUUID UUID; - typedef LLDate Date; - typedef LLURI URI; - typedef std::vector<U8> Binary; - //@} - - /** @name Scalar Constructors */ - //@{ - LLSD(Boolean); - LLSD(Integer); - LLSD(Real); - LLSD(const String&); - LLSD(const UUID&); - LLSD(const Date&); - LLSD(const URI&); - LLSD(const Binary&); - //@} - - /** @name Convenience Constructors */ - //@{ - // support construction from size_t et al. - template <typename VALUE, - typename std::enable_if<std::is_integral<VALUE>::value && - ! std::is_same<VALUE, Boolean>::value, - bool>::type = true> - LLSD(VALUE v): LLSD(Integer(narrow<VALUE>(v))) {} - // support construction from F32 et al. - template <typename VALUE, - typename std::enable_if<std::is_floating_point<VALUE>::value, - bool>::type = true> - LLSD(VALUE v): LLSD(Real(narrow<VALUE>(v))) {} - //@} - - /** @name Scalar Assignment */ - //@{ - void assign(Boolean); - void assign(Integer); - void assign(Real); - void assign(const String&); - void assign(const UUID&); - void assign(const Date&); - void assign(const URI&); - void assign(const Binary&); - - LLSD& operator=(Boolean v) { assign(v); return *this; } - LLSD& operator=(Integer v) { assign(v); return *this; } - LLSD& operator=(Real v) { assign(v); return *this; } - LLSD& operator=(const String& v) { assign(v); return *this; } - LLSD& operator=(const UUID& v) { assign(v); return *this; } - LLSD& operator=(const Date& v) { assign(v); return *this; } - LLSD& operator=(const URI& v) { assign(v); return *this; } - LLSD& operator=(const Binary& v) { assign(v); return *this; } - //@} - - /** - @name Scalar Accessors - @brief Fetch a scalar value, converting if needed and possible - - Conversion among the basic types, Boolean, Integer, Real and String, is - fully defined. Each type can be converted to another with a reasonable - interpretation. These conversions can be used as a convenience even - when you know the data is in one format, but you want it in another. Of - course, many of these conversions lose information. - - Note: These conversions are not the same as Perl's. In particular, when - converting a String to a Boolean, only the empty string converts to - false. Converting the String "0" to Boolean results in true. - - Conversion to and from UUID, Date, and URI is only defined to and from - String. Conversion is defined to be information preserving for valid - values of those types. These conversions can be used when one needs to - convert data to or from another system that cannot handle these types - natively, but can handle strings. - - Conversion to and from Binary isn't defined. - - Conversion of the Undefined value to any scalar type results in a - reasonable null or zero value for the type. - */ - //@{ - Boolean asBoolean() const; - Integer asInteger() const; - Real asReal() const; - String asString() const; - UUID asUUID() const; - Date asDate() const; - URI asURI() const; - const Binary& asBinary() const; - - // asStringRef on any non-string type will return a ref to an empty string. - const String& asStringRef() const; - - operator Boolean() const { return asBoolean(); } - operator Integer() const { return asInteger(); } - operator Real() const { return asReal(); } - operator String() const { return asString(); } - operator UUID() const { return asUUID(); } - operator Date() const { return asDate(); } - operator URI() const { return asURI(); } - operator Binary() const { return asBinary(); } - - // This is needed because most platforms do not automatically - // convert the boolean negation as a bool in an if statement. - bool operator!() const {return !asBoolean();} - //@} - - /** @name Character Pointer Helpers - These are helper routines to make working with char* as easy as - working with strings. - */ - //@{ - LLSD(const char*); - void assign(const char*); - LLSD& operator=(const char* v) { assign(v); return *this; } - //@} - - /** @name Map Values */ - //@{ - static LLSD emptyMap(); - - 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&); - - LLSD& operator[](const String&); - LLSD& operator[](const char* c) + LLSD(); ///< initially Undefined + ~LLSD(); ///< this class may NOT be subclassed + + /** @name Copyable and Assignable */ + //@{ + LLSD(const LLSD&); + void assign(const LLSD& other); + LLSD& operator=(const LLSD& other) { assign(other); return *this; } + + //@} + + void clear(); ///< resets to Undefined + + + /** @name Scalar Types + The scalar types, and how they map onto C++ + */ + //@{ + typedef bool Boolean; + typedef S32 Integer; + typedef F64 Real; + typedef std::string String; + typedef LLUUID UUID; + typedef LLDate Date; + typedef LLURI URI; + typedef std::vector<U8> Binary; + //@} + + /** @name Scalar Constructors */ + //@{ + LLSD(Boolean); + LLSD(Integer); + LLSD(Real); + LLSD(const String&); + LLSD(const UUID&); + LLSD(const Date&); + LLSD(const URI&); + LLSD(const Binary&); + //@} + + /** @name Convenience Constructors */ + //@{ + // support construction from size_t et al. + template <typename VALUE, + typename std::enable_if<std::is_integral<VALUE>::value && + ! std::is_same<VALUE, Boolean>::value, + bool>::type = true> + LLSD(VALUE v): LLSD(Integer(narrow<VALUE>(v))) {} + // support construction from F32 et al. + template <typename VALUE, + typename std::enable_if<std::is_floating_point<VALUE>::value, + bool>::type = true> + LLSD(VALUE v): LLSD(Real(narrow<VALUE>(v))) {} + //@} + + /** @name Scalar Assignment */ + //@{ + void assign(Boolean); + void assign(Integer); + void assign(Real); + void assign(const String&); + void assign(const UUID&); + void assign(const Date&); + void assign(const URI&); + void assign(const Binary&); + + LLSD& operator=(Boolean v) { assign(v); return *this; } + LLSD& operator=(Integer v) { assign(v); return *this; } + LLSD& operator=(Real v) { assign(v); return *this; } + LLSD& operator=(const String& v) { assign(v); return *this; } + LLSD& operator=(const UUID& v) { assign(v); return *this; } + LLSD& operator=(const Date& v) { assign(v); return *this; } + LLSD& operator=(const URI& v) { assign(v); return *this; } + LLSD& operator=(const Binary& v) { assign(v); return *this; } + //@} + + /** + @name Scalar Accessors + @brief Fetch a scalar value, converting if needed and possible + + Conversion among the basic types, Boolean, Integer, Real and String, is + fully defined. Each type can be converted to another with a reasonable + interpretation. These conversions can be used as a convenience even + when you know the data is in one format, but you want it in another. Of + course, many of these conversions lose information. + + Note: These conversions are not the same as Perl's. In particular, when + converting a String to a Boolean, only the empty string converts to + false. Converting the String "0" to Boolean results in true. + + Conversion to and from UUID, Date, and URI is only defined to and from + String. Conversion is defined to be information preserving for valid + values of those types. These conversions can be used when one needs to + convert data to or from another system that cannot handle these types + natively, but can handle strings. + + Conversion to and from Binary isn't defined. + + Conversion of the Undefined value to any scalar type results in a + reasonable null or zero value for the type. + */ + //@{ + Boolean asBoolean() const; + Integer asInteger() const; + Real asReal() const; + String asString() const; + UUID asUUID() const; + Date asDate() const; + URI asURI() const; + const Binary& asBinary() const; + + // asStringRef on any non-string type will return a ref to an empty string. + const String& asStringRef() const; + + operator Boolean() const { return asBoolean(); } + operator Integer() const { return asInteger(); } + operator Real() const { return asReal(); } + operator String() const { return asString(); } + operator UUID() const { return asUUID(); } + operator Date() const { return asDate(); } + operator URI() const { return asURI(); } + operator Binary() const { return asBinary(); } + + // This is needed because most platforms do not automatically + // convert the boolean negation as a bool in an if statement. + bool operator!() const {return !asBoolean();} + //@} + + /** @name Character Pointer Helpers + These are helper routines to make working with char* as easy as + working with strings. + */ + //@{ + LLSD(const char*); + void assign(const char*); + LLSD& operator=(const char* v) { assign(v); return *this; } + //@} + + /** @name Map Values */ + //@{ + static LLSD emptyMap(); + + 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&); + + LLSD& operator[](const String&); + LLSD& operator[](const char* c) { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; return (*this)[String(c)]; } - const LLSD& operator[](const String&) const; - const LLSD& operator[](const char* c) const + const LLSD& operator[](const String&) const; + const LLSD& operator[](const char* c) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; return (*this)[String(c)]; } - //@} - - /** @name Array Values */ - //@{ - static LLSD emptyArray(); - - LLSD get(Integer) const; - void set(Integer, const LLSD&); - void insert(Integer, const LLSD&); - LLSD& append(const LLSD&); - void erase(Integer); - LLSD& with(Integer, const LLSD&); - - // accept size_t so we can index relative to size() - const LLSD& operator[](size_t) const; - LLSD& operator[](size_t); - // template overloads to support int literals, U32 et al. - template <typename IDX, - typename std::enable_if<std::is_convertible<IDX, size_t>::value, - bool>::type = true> - const LLSD& operator[](IDX i) const { return (*this)[size_t(i)]; } - template <typename IDX, - typename std::enable_if<std::is_convertible<IDX, size_t>::value, - bool>::type = true> - LLSD& operator[](IDX i) { return (*this)[size_t(i)]; } - //@} - - /** @name Iterators */ - //@{ - size_t size() const; - - typedef std::map<String, LLSD>::iterator map_iterator; - typedef std::map<String, LLSD>::const_iterator map_const_iterator; - - map_iterator beginMap(); - map_iterator endMap(); - map_const_iterator beginMap() const; - map_const_iterator endMap() const; - - typedef std::vector<LLSD>::iterator array_iterator; - typedef std::vector<LLSD>::const_iterator array_const_iterator; - typedef std::vector<LLSD>::reverse_iterator reverse_array_iterator; - - array_iterator beginArray(); - array_iterator endArray(); - array_const_iterator beginArray() const; - array_const_iterator endArray() const; - - reverse_array_iterator rbeginArray(); - reverse_array_iterator rendArray(); - //@} - - /** @name Type Testing */ - //@{ - enum Type { - TypeUndefined = 0, - TypeBoolean, - TypeInteger, - TypeReal, - TypeString, - TypeUUID, - TypeDate, - TypeURI, - TypeBinary, - TypeMap, - TypeArray, - TypeLLSDTypeEnd, - TypeLLSDTypeBegin = TypeUndefined, - TypeLLSDNumTypes = (TypeLLSDTypeEnd - TypeLLSDTypeBegin) - }; - - Type type() const; - - bool isUndefined() const { return type() == TypeUndefined; } - bool isDefined() const { return type() != TypeUndefined; } - bool isBoolean() const { return type() == TypeBoolean; } - bool isInteger() const { return type() == TypeInteger; } - bool isReal() const { return type() == TypeReal; } - bool isString() const { return type() == TypeString; } - bool isUUID() const { return type() == TypeUUID; } - bool isDate() const { return type() == TypeDate; } - bool isURI() const { return type() == TypeURI; } - bool isBinary() const { return type() == TypeBinary; } - bool isMap() const { return type() == TypeMap; } - bool isArray() const { return type() == TypeArray; } - //@} - - /** @name Automatic Cast Protection - These are not implemented on purpose. Without them, C++ can perform - some conversions that are clearly not what the programmer intended. - - If you get a linker error about these being missing, you have made - mistake in your code. DO NOT IMPLEMENT THESE FUNCTIONS as a fix. - - All of these problems stem from trying to support char* in LLSD or in - std::string. There are too many automatic casts that will lead to - using an arbitrary pointer or scalar type to std::string. - */ - //@{ - LLSD(const void*); ///< construct from aribrary pointers - void assign(const void*); ///< assign from arbitrary pointers - LLSD& operator=(const void*); ///< assign from arbitrary pointers - - bool has(Integer) const; ///< has() only works for Maps - //@} - - /** @name Implementation */ - //@{ + //@} + + /** @name Array Values */ + //@{ + static LLSD emptyArray(); + + LLSD get(Integer) const; + void set(Integer, const LLSD&); + void insert(Integer, const LLSD&); + LLSD& append(const LLSD&); + void erase(Integer); + LLSD& with(Integer, const LLSD&); + + // accept size_t so we can index relative to size() + const LLSD& operator[](size_t) const; + LLSD& operator[](size_t); + // template overloads to support int literals, U32 et al. + template <typename IDX, + typename std::enable_if<std::is_convertible<IDX, size_t>::value, + bool>::type = true> + const LLSD& operator[](IDX i) const { return (*this)[size_t(i)]; } + template <typename IDX, + typename std::enable_if<std::is_convertible<IDX, size_t>::value, + bool>::type = true> + LLSD& operator[](IDX i) { return (*this)[size_t(i)]; } + //@} + + /** @name Iterators */ + //@{ + size_t size() const; + + typedef std::map<String, LLSD>::iterator map_iterator; + typedef std::map<String, LLSD>::const_iterator map_const_iterator; + + map_iterator beginMap(); + map_iterator endMap(); + map_const_iterator beginMap() const; + map_const_iterator endMap() const; + + typedef std::vector<LLSD>::iterator array_iterator; + typedef std::vector<LLSD>::const_iterator array_const_iterator; + typedef std::vector<LLSD>::reverse_iterator reverse_array_iterator; + + array_iterator beginArray(); + array_iterator endArray(); + array_const_iterator beginArray() const; + array_const_iterator endArray() const; + + reverse_array_iterator rbeginArray(); + reverse_array_iterator rendArray(); + //@} + + /** @name Type Testing */ + //@{ + enum Type { + TypeUndefined = 0, + TypeBoolean, + TypeInteger, + TypeReal, + TypeString, + TypeUUID, + TypeDate, + TypeURI, + TypeBinary, + TypeMap, + TypeArray, + TypeLLSDTypeEnd, + TypeLLSDTypeBegin = TypeUndefined, + TypeLLSDNumTypes = (TypeLLSDTypeEnd - TypeLLSDTypeBegin) + }; + + Type type() const; + + bool isUndefined() const { return type() == TypeUndefined; } + bool isDefined() const { return type() != TypeUndefined; } + bool isBoolean() const { return type() == TypeBoolean; } + bool isInteger() const { return type() == TypeInteger; } + bool isReal() const { return type() == TypeReal; } + bool isString() const { return type() == TypeString; } + bool isUUID() const { return type() == TypeUUID; } + bool isDate() const { return type() == TypeDate; } + bool isURI() const { return type() == TypeURI; } + bool isBinary() const { return type() == TypeBinary; } + bool isMap() const { return type() == TypeMap; } + bool isArray() const { return type() == TypeArray; } + //@} + + /** @name Automatic Cast Protection + These are not implemented on purpose. Without them, C++ can perform + some conversions that are clearly not what the programmer intended. + + If you get a linker error about these being missing, you have made + mistake in your code. DO NOT IMPLEMENT THESE FUNCTIONS as a fix. + + All of these problems stem from trying to support char* in LLSD or in + std::string. There are too many automatic casts that will lead to + using an arbitrary pointer or scalar type to std::string. + */ + //@{ + LLSD(const void*); ///< construct from aribrary pointers + void assign(const void*); ///< assign from arbitrary pointers + LLSD& operator=(const void*); ///< assign from arbitrary pointers + + bool has(Integer) const; ///< has() only works for Maps + //@} + + /** @name Implementation */ + //@{ public: - class Impl; + class Impl; private: - Impl* impl; - friend class LLSD::Impl; - //@} + Impl* impl; + friend class LLSD::Impl; + //@} private: - /** @name Debugging Interface */ - //@{ - /// Returns XML version of llsd -- only to be called from debugger - static const char *dumpXML(const LLSD &llsd); + /** @name Debugging Interface */ + //@{ + /// Returns XML version of llsd -- only to be called from debugger + static const char *dumpXML(const LLSD &llsd); - /// Returns Notation version of llsd -- only to be called from debugger - static const char *dump(const LLSD &llsd); - //@} + /// Returns Notation version of llsd -- only to be called from debugger + static const char *dump(const LLSD &llsd); + //@} public: - static std::string typeString(Type type); // Return human-readable type as a string + static std::string typeString(Type type); // Return human-readable type as a string }; struct llsd_select_bool { - LLSD::Boolean operator()(const LLSD& sd) const - { - return sd.asBoolean(); - } + LLSD::Boolean operator()(const LLSD& sd) const + { + return sd.asBoolean(); + } }; struct llsd_select_integer { - LLSD::Integer operator()(const LLSD& sd) const - { - return sd.asInteger(); - } + LLSD::Integer operator()(const LLSD& sd) const + { + return sd.asInteger(); + } }; struct llsd_select_real { - LLSD::Real operator()(const LLSD& sd) const - { - return sd.asReal(); - } + LLSD::Real operator()(const LLSD& sd) const + { + return sd.asReal(); + } }; struct llsd_select_float { - F32 operator()(const LLSD& sd) const - { - return (F32)sd.asReal(); - } + F32 operator()(const LLSD& sd) const + { + return (F32)sd.asReal(); + } }; struct llsd_select_uuid { - LLSD::UUID operator()(const LLSD& sd) const - { - return sd.asUUID(); - } + LLSD::UUID operator()(const LLSD& sd) const + { + return sd.asUUID(); + } }; struct llsd_select_string { - LLSD::String operator()(const LLSD& sd) const - { - return sd.asString(); - } + LLSD::String operator()(const LLSD& sd) const + { + return sd.asString(); + } }; LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLSD& llsd); @@ -492,30 +492,30 @@ namespace llsd #ifdef LLSD_DEBUG_INFO /** @name Unit Testing Interface */ //@{ - LL_COMMON_API void dumpStats(const LLSD&); ///< Output information on object and usage - - /// @warn THE FOLLOWING COUNTS WILL NOT BE ACCURATE IN A MULTI-THREADED - /// ENVIRONMENT. - /// - /// These counts track LLSD::Impl (hidden) objects. - LL_COMMON_API U32 allocationCount(); ///< how many Impls have been made - LL_COMMON_API U32 outstandingCount(); ///< how many Impls are still alive - - /// These counts track LLSD (public) objects. - LL_COMMON_API extern S32 sLLSDAllocationCount; ///< Number of LLSD objects ever created - LL_COMMON_API extern S32 sLLSDNetObjects; ///< Number of LLSD objects that exist + LL_COMMON_API void dumpStats(const LLSD&); ///< Output information on object and usage + + /// @warn THE FOLLOWING COUNTS WILL NOT BE ACCURATE IN A MULTI-THREADED + /// ENVIRONMENT. + /// + /// These counts track LLSD::Impl (hidden) objects. + LL_COMMON_API U32 allocationCount(); ///< how many Impls have been made + LL_COMMON_API U32 outstandingCount(); ///< how many Impls are still alive + + /// These counts track LLSD (public) objects. + LL_COMMON_API extern S32 sLLSDAllocationCount; ///< Number of LLSD objects ever created + LL_COMMON_API extern S32 sLLSDNetObjects; ///< Number of LLSD objects that exist #endif //@} } // namespace llsd /** QUESTIONS & TO DOS - - Would Binary be more convenient as unsigned char* buffer semantics? - - Should Binary be convertible to/from String, and if so how? - - as UTF8 encoded strings (making not like UUID<->String) - - as Base64 or Base96 encoded (making like UUID<->String) - - Conversions to std::string and LLUUID do not result in easy assignment - to std::string, std::string or LLUUID due to non-unique conversion paths + - Would Binary be more convenient as unsigned char* buffer semantics? + - Should Binary be convertible to/from String, and if so how? + - as UTF8 encoded strings (making not like UUID<->String) + - as Base64 or Base96 encoded (making like UUID<->String) + - Conversions to std::string and LLUUID do not result in easy assignment + to std::string, std::string or LLUUID due to non-unique conversion paths */ #endif // LL_LLSD_NEW_H |