llsd.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /**
  2. * @file llsd.h
  3. * @brief LLSD flexible data system.
  4. *
  5. * $LicenseInfo:firstyear=2005&license=viewergpl$
  6. *
  7. * Copyright (c) 2005-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_LLSD_H
  33. #define LL_LLSD_H
  34. #include <map>
  35. #include <ostream>
  36. #include <type_traits>
  37. #include "lldate.h"
  38. #include "lluri.h"
  39. #include "lluuid.h"
  40. // LLSD provides a flexible data system similar to the data facilities of
  41. // dynamic languages like Perl and Python. It is created to support exchange
  42. // of structured data between loosly coupled systems. (Here, "loosly coupled"
  43. // means not compiled together into the same module.)
  44. //
  45. // Data in such exchanges must be highly tollerant of changes on either side
  46. // such as:
  47. // - recompilation
  48. // - implementation in a different langauge
  49. // - addition of extra parameters
  50. // - execution of older versions (with fewer parameters)
  51. //
  52. // To this aim, the C++ API of LLSD strives to be very easy to use, and to
  53. // default to "the right thing" whereever possible. It is extremely tollerant
  54. // of errors and unexpected situations.
  55. //
  56. // The fundimental class is LLSD. LLSD is a value holding object. It holds one
  57. // value that is either undefined, one of the scalar types, or a map or an
  58. // array. LLSD objects have value semantics (copying them copies the value,
  59. // though it can be considered efficient, due to shareing.), and mutable.
  60. //
  61. // Undefined is the singular value given to LLSD objects that are not
  62. // initialized with any data. It is also used as the return value for
  63. // operations that return an LLSD,
  64. //
  65. // The sclar data types are:
  66. // - Boolean - true or false
  67. // - Integer - a 32 bit signed integer
  68. // - Real - a 64 IEEE 754 floating point value
  69. // - UUID - a 128 unique value
  70. // - String - a sequence of zero or more Unicode chracters
  71. // - Date - an absolute point in time, UTC, with resolution to the second
  72. // - URI - a String that is a URI
  73. // - Binary - a sequence of zero or more octets (unsigned bytes)
  74. //
  75. // A map is a dictionary mapping String keys to LLSD values. The keys are
  76. // unique within a map, and have only one value (though that value could be an
  77. // LLSD array).
  78. //
  79. // An array is a sequence of zero or more LLSD values.
  80. class LLSD final // This class may NOT be subclassed
  81. {
  82. public:
  83. LLSD(); // Initially undefined
  84. ~LLSD();
  85. // Copyable and assignable (*TODO: C++11 movable)
  86. LLSD(const LLSD& other);
  87. void assign(const LLSD& other);
  88. LL_INLINE LLSD& operator=(const LLSD& other)
  89. {
  90. assign(other);
  91. return *this;
  92. }
  93. void clear(); // Resets to Undefined
  94. // The scalar types, and how they map onto C++
  95. typedef bool Boolean;
  96. typedef S32 Integer;
  97. typedef F64 Real;
  98. typedef std::string String;
  99. typedef LLUUID UUID;
  100. typedef LLDate Date;
  101. typedef LLURI URI;
  102. typedef std::vector<U8> Binary;
  103. // Scalar constructors
  104. LLSD(Boolean);
  105. LLSD(Integer);
  106. LLSD(Real);
  107. LLSD(const String&);
  108. LLSD(const UUID&);
  109. LLSD(const Date&);
  110. LLSD(const URI&);
  111. LLSD(const Binary&);
  112. // Support construction from size_t et al.
  113. template <typename VALUE,
  114. typename std::enable_if<std::is_integral<VALUE>::value &&
  115. !std::is_same<VALUE, Boolean>::value,
  116. bool>::type = true>
  117. LL_INLINE LLSD(VALUE v) : LLSD((Integer)v) {}
  118. // Scalar assignments
  119. void assign(Boolean);
  120. void assign(Integer);
  121. void assign(Real);
  122. void assign(const String&);
  123. void assign(const UUID&);
  124. void assign(const Date&);
  125. void assign(const URI&);
  126. void assign(const Binary&);
  127. // Support assignment from size_t et al.
  128. template <typename VALUE,
  129. typename std::enable_if<std::is_integral<VALUE>::value &&
  130. !std::is_same<VALUE, Boolean>::value,
  131. bool>::type = true>
  132. LL_INLINE void assign(VALUE v) { assign((Integer)v); }
  133. // Support assignment from F32 et al.
  134. template <typename VALUE,
  135. typename std::enable_if<std::is_floating_point<VALUE>::value,
  136. bool>::type = true>
  137. LL_INLINE void assign(VALUE v) { assign((Real)v); }
  138. template <typename VALUE>
  139. LL_INLINE LLSD& operator=(VALUE v) { assign(v); return *this; }
  140. // Scalar accessors: fetch a scalar value, converting if needed and
  141. // possible
  142. // Conversion among the basic types, Boolean, Integer, Real and String, is
  143. // fully defined. Each type can be converted to another with a reasonable
  144. // interpretation. These conversions can be used as a convenience even
  145. // when you know the data is in one format, but you want it in another. Of
  146. // course, many of these conversions lose information.
  147. //
  148. // Note: These conversions are not the same as Perl's. In particular, when
  149. // converting a String to a Boolean, only the empty string converts to
  150. // false. Converting the String "0" to Boolean results in true.
  151. //
  152. // Conversion to and from UUID, Date, and URI is only defined to and from
  153. // String. Conversion is defined to be information preserving for valid
  154. // values of those types. These conversions can be used when one needs to
  155. // convert data to or from another system that cannot handle these types
  156. // natively, but can handle strings.
  157. //
  158. // Conversion to and from Binary is not defined.
  159. // Conversion of the Undefined value to any scalar type results in a
  160. // reasonable null or zero value for the type.
  161. Boolean asBoolean() const;
  162. Integer asInteger() const;
  163. Real asReal() const;
  164. String asString() const;
  165. UUID asUUID() const;
  166. Date asDate() const;
  167. URI asURI() const;
  168. const Binary& asBinary() const;
  169. // Applied to any non-string type will return a ref to an empty string.
  170. const String& asStringRef() const;
  171. // Returns:
  172. // "<value><((type))>((scalar value or recursive calls))</((type))></value>"
  173. // See: http://xmlrpc.com/spec.md
  174. String asXMLRPCValue() const;
  175. LL_INLINE operator Boolean() const { return asBoolean(); }
  176. LL_INLINE operator Integer() const { return asInteger(); }
  177. LL_INLINE operator Real() const { return asReal(); }
  178. LL_INLINE operator String() const { return asString(); }
  179. LL_INLINE operator UUID() const { return asUUID(); }
  180. LL_INLINE operator Date() const { return asDate(); }
  181. LL_INLINE operator URI() const { return asURI(); }
  182. LL_INLINE operator Binary() const { return asBinary(); }
  183. // This is needed because most platforms do not automatically convert the
  184. // boolean negation as a bool in an if statement.
  185. LL_INLINE bool operator!() const { return !asBoolean(); }
  186. // Character pointer helpers. These are helper methods to make working with
  187. // char* the same as easy as working with strings.
  188. LLSD(const char* v);
  189. void assign(const char* v);
  190. LL_INLINE LLSD& operator=(const char* v) { assign(v); return *this; }
  191. // Map values
  192. static LLSD emptyMap();
  193. bool has(const String& k) const;
  194. LLSD get(const String& k) const;
  195. bool has(const char* k) const;
  196. LLSD get(const char* k) const;
  197. // Returns an LLSD array with keys as strings
  198. LLSD getKeys() const;
  199. void insert(const String& k, const LLSD& v);
  200. void erase(const String& k);
  201. LLSD& with(const char* k, const LLSD& v);
  202. LL_INLINE LLSD& with(const String& k, const LLSD& v)
  203. {
  204. return with(k.c_str(), v);
  205. }
  206. LLSD& operator[](const String& k);
  207. LL_INLINE LLSD& operator[](const char* k) { return (*this)[String(k)]; }
  208. const LLSD& operator[](const String& k) const;
  209. LL_INLINE const LLSD& operator[](const char* k) const
  210. {
  211. return (*this)[String(k)];
  212. }
  213. // Array values
  214. static LLSD emptyArray();
  215. LLSD get(size_t i) const;
  216. void set(size_t i, const LLSD& v);
  217. void insert(size_t i, const LLSD& v);
  218. void erase(size_t i);
  219. LLSD& with(size_t i, const LLSD& v);
  220. LLSD& append(const LLSD& v);
  221. // Accept size_t so we can index relative to size()
  222. const LLSD& operator[](size_t i) const;
  223. LLSD& operator[](size_t i);
  224. // Template overloads to support int literals, U32 et al.
  225. template <typename IDX,
  226. typename std::enable_if<std::is_convertible<IDX, size_t>::value,
  227. bool>::type = true>
  228. LL_INLINE const LLSD& operator[](IDX i) const
  229. {
  230. return (*this)[size_t(i)];
  231. }
  232. template <typename IDX,
  233. typename std::enable_if<std::is_convertible<IDX, size_t>::value,
  234. bool>::type = true>
  235. LL_INLINE LLSD& operator[](IDX i) { return (*this)[size_t(i)]; }
  236. // Iterators
  237. size_t size() const;
  238. typedef std::map<String, LLSD>::iterator map_iterator;
  239. map_iterator beginMap();
  240. map_iterator endMap();
  241. typedef std::map<String, LLSD>::const_iterator map_const_iterator;
  242. map_const_iterator beginMap() const;
  243. map_const_iterator endMap() const;
  244. typedef std::vector<LLSD>::iterator array_iterator;
  245. array_iterator beginArray();
  246. array_iterator endArray();
  247. typedef std::vector<LLSD>::const_iterator array_const_iterator;
  248. array_const_iterator beginArray() const;
  249. array_const_iterator endArray() const;
  250. typedef std::vector<LLSD>::reverse_iterator reverse_array_iterator;
  251. reverse_array_iterator rbeginArray();
  252. reverse_array_iterator rendArray();
  253. map_const_iterator find(const String& k) const;
  254. map_const_iterator find(const char* k) const;
  255. // Type testing
  256. enum Type {
  257. TypeUndefined,
  258. TypeBoolean,
  259. TypeInteger,
  260. TypeReal,
  261. TypeString,
  262. TypeUUID,
  263. TypeDate,
  264. TypeURI,
  265. TypeBinary,
  266. TypeMap,
  267. TypeArray
  268. };
  269. Type type() const;
  270. LL_INLINE bool isUndefined() const { return type() == TypeUndefined; }
  271. LL_INLINE bool isDefined() const { return type() != TypeUndefined; }
  272. LL_INLINE bool isBoolean() const { return type() == TypeBoolean; }
  273. LL_INLINE bool isInteger() const { return type() == TypeInteger; }
  274. LL_INLINE bool isReal() const { return type() == TypeReal; }
  275. LL_INLINE bool isString() const { return type() == TypeString; }
  276. LL_INLINE bool isUUID() const { return type() == TypeUUID; }
  277. LL_INLINE bool isDate() const { return type() == TypeDate; }
  278. LL_INLINE bool isURI() const { return type() == TypeURI; }
  279. LL_INLINE bool isBinary() const { return type() == TypeBinary; }
  280. LL_INLINE bool isMap() const { return type() == TypeMap; }
  281. LL_INLINE bool isArray() const { return type() == TypeArray; }
  282. // Automatic cast protection. Without them, C++ can perform some
  283. // conversions that are clearly not what the programmer intended.
  284. // If you get a compiler error about them, you have made mistake in your
  285. // code. DO NOT IMPLEMENT THESE FUNCTIONS as a fix.
  286. // All of thse problems stem from trying to support char* in LLSD or in
  287. // std::string. There are too many automatic casts that will lead to using
  288. // an arbitrary pointer or scalar type to std::string.
  289. LLSD(const void*) = delete; // Constructs from aribrary pointers
  290. void assign(const void*) = delete; // Assigns from arbitrary pointers
  291. LLSD& operator=(const void*) = delete; // Assigns from arbitrary pointers
  292. bool has(Integer) const = delete; // has() only works for maps
  293. public:
  294. class Impl;
  295. private:
  296. Impl* impl;
  297. };
  298. // Declared here for convenience, but implemented in llsdserialize.cpp
  299. std::ostream& operator<<(std::ostream& s, const LLSD& llsd);
  300. /* QUESTIONS & TO DO
  301. - Would Binary be more convenient as unsigned char* buffer semantics ?
  302. - Should Binary be convertable to/from String, and if so how ?
  303. - as UTF8 encoded strings (making not like UUID<->String)
  304. - as Base64 or Base96 encoded (making like UUID<->String)
  305. - Conversions to std::string and LLUUID do not result in easy assignment
  306. to std::string, std::string or LLUUID due to non-unique conversion paths
  307. */
  308. #endif // LL_LLSD_H