summaryrefslogtreecommitdiff
path: root/indra/llcommon/llsd.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llsd.h')
-rw-r--r--indra/llcommon/llsd.h850
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