llsdutil.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. /**
  2. * @file llsdutil.h
  3. * @author Phoenix
  4. * @date 2006-05-24
  5. * @brief Utility classes, functions, etc, for using structured data.
  6. *
  7. * $LicenseInfo:firstyear=2006&license=viewergpl$
  8. *
  9. * Copyright (c) 2006-2009, Linden Research, Inc.
  10. *
  11. * Second Life Viewer Source Code
  12. * The source code in this file ("Source Code") is provided by Linden Lab
  13. * to you under the terms of the GNU General Public License, version 2.0
  14. * ("GPL"), unless you have obtained a separate licensing agreement
  15. * ("Other License"), formally executed by you and Linden Lab. Terms of
  16. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18. *
  19. * There are special exceptions to the terms and conditions of the GPL as
  20. * it is applied to this Source Code. View the full text of the exception
  21. * in the file doc/FLOSS-exception.txt in this software distribution, or
  22. * online at
  23. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24. *
  25. * By copying, modifying or distributing this software, you acknowledge
  26. * that you have read and understood your obligations described above,
  27. * and agree to abide by those obligations.
  28. *
  29. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31. * COMPLETENESS OR PERFORMANCE.
  32. * $/LicenseInfo$
  33. */
  34. #ifndef LL_LLSDUTIL_H
  35. #define LL_LLSDUTIL_H
  36. #include <memory> // For std::make_shared
  37. #include <utility> // For std::forward
  38. #include <type_traits> // For std::decay_t
  39. #include "llsd.h"
  40. // U32
  41. LLSD ll_sd_from_U32(U32);
  42. U32 ll_U32_from_sd(const LLSD& sd);
  43. // U64
  44. LLSD ll_sd_from_U64(U64);
  45. U64 ll_U64_from_sd(const LLSD& sd);
  46. // IP Address
  47. LLSD ll_sd_from_ipaddr(U32);
  48. U32 ll_ipaddr_from_sd(const LLSD& sd);
  49. // Binary to string
  50. LLSD ll_string_from_binary(const LLSD& sd);
  51. //String to binary
  52. LLSD ll_binary_from_string(const LLSD& sd);
  53. // Serializes sd to static buffer and returns pointer, useful for gdb debugging.
  54. char* ll_print_sd(const LLSD& sd);
  55. // Serializes sd to static buffer and returns pointer, using "pretty printing"
  56. // mode.
  57. char* ll_pretty_print_sd_ptr(const LLSD* sd);
  58. char* ll_pretty_print_sd(const LLSD& sd);
  59. // Compares the structure of an LLSD to a template LLSD and stores the "valid"
  60. // values in a 3rd LLSD. Default values are pulled from the template. Extra
  61. // keys/values in the test are ignored in the resultant LLSD. Ordering of
  62. // arrays matters. Returns false if the test is of same type but values differ
  63. // in type. Otherwise, returns true.
  64. bool compare_llsd_with_template(const LLSD& llsd_to_test,
  65. const LLSD& template_llsd,
  66. LLSD& resultant_llsd);
  67. // filter_llsd_with_template() is a direct clone (copy-n-paste) of
  68. // compare_llsd_with_template with the following differences:
  69. // (1) bool vs BOOL return types
  70. // (2) A map with the key value "*" is a special value and maps any key in the
  71. // test llsd that doesn't have an explicitly matching key in the template.
  72. // (3) The element of an array with exactly one element is taken as a template
  73. // for *all* the elements of the test array. If the template array is of
  74. // different size, compare_llsd_with_template() semantics apply.
  75. bool filter_llsd_with_template(const LLSD& llsd_to_test,
  76. const LLSD& template_llsd,
  77. LLSD& result_llsd);
  78. // Recursively determine whether a given LLSD data block "matches" another
  79. // LLSD prototype. The returned string is empty() on success, non-empty() on
  80. // mismatch.
  81. //
  82. // This function tests structure (types) rather than data values. It is
  83. // intended for when a consumer expects an LLSD block with a particular
  84. // structure, and must succinctly detect whether the arriving block is
  85. // well-formed. For instance, a test of the form:
  86. // if (!(data.has("request") && data.has("target") && ...))
  87. // could instead be expressed by initializing a prototype LLSD map with the
  88. // required keys and writing:
  89. // if (!llsd_matches(prototype, data).empty())
  90. //
  91. // A non-empty return value is an error-message fragment intended to indicate
  92. // to (English-speaking) developers where in the prototype structure the
  93. // mismatch occurred.
  94. //
  95. // * If a slot in the prototype isUndefined(), then anything is valid at that
  96. // place in the real object. (Passing prototype == LLSD() matches anything
  97. // at all.)
  98. // * An array in the prototype must match a data array at least that large.
  99. // (Additional entries in the data array are ignored.) Every isDefined()
  100. // entry in the prototype array must match the corresponding entry in the
  101. // data array.
  102. // * A map in the prototype must match a map in the data. Every key in the
  103. // prototype map must match a corresponding key in the data map. (Additional
  104. // keys in the data map are ignored.) Every isDefined() value in the
  105. // prototype map must match the corresponding key's value in the data map.
  106. // * Scalar values in the prototype are tested for @em type rather than value.
  107. // For instance, a String in the prototype matches any String at all. In
  108. // effect, storing an Integer at a particular place in the prototype asserts
  109. // that the caller intends to apply asInteger() to the corresponding slot in
  110. // the data.
  111. // * A String in the prototype matches String, Boolean, Integer, Real, UUID,
  112. // Date and URI, because asString() applied to any of these produces a
  113. // meaningful result.
  114. // * Similarly, a Boolean, Integer or Real in the prototype can match any of
  115. // Boolean, Integer or Real in the data -- or even String.
  116. // * UUID matches UUID or String.
  117. // * Date matches Date or String.
  118. // * URI matches URI or String.
  119. // * Binary in the prototype matches only Binary in the data.
  120. //
  121. // *TODO: when a Boolean, Integer or Real in the prototype matches a String in
  122. // the data, we should examine the String @em value to ensure it can be
  123. // meaningfully converted to the requested type. The same goes for UUID, Date
  124. // and URI.
  125. std::string llsd_matches(const LLSD& prototype, const LLSD& data,
  126. const std::string& pfx = "");
  127. // Deep equality. If you want to compare LLSD::Real values for approximate
  128. // equality rather than bitwise equality, pass @a bits as for
  129. // is_approx_equal_fraction().
  130. bool llsd_equals(const LLSD& lhs, const LLSD& rhs, S32 bits = -1);
  131. // Simple function to copy data out of input & output iterators if there is no
  132. // need for casting.
  133. template<typename Input> LLSD llsd_copy_array(Input iter, Input end)
  134. {
  135. LLSD dest;
  136. for ( ; iter != end; ++iter)
  137. {
  138. dest.append(*iter);
  139. }
  140. return dest;
  141. }
  142. namespace llsd
  143. {
  144. LLSD& drill_ref(LLSD& blob, const LLSD& path);
  145. LL_INLINE LLSD drill(const LLSD& blob, const LLSD& path)
  146. {
  147. // Non-const drill_ref() does exactly what we want. Temporarily cast
  148. // away constness and use that.
  149. return drill_ref(const_cast<LLSD&>(blob), path);
  150. }
  151. }
  152. ///////////////////////////////////////////////////////////////////////////////
  153. // LLSDMap
  154. ///////////////////////////////////////////////////////////////////////////////
  155. // Constructs an LLSD::Map inline, with implicit conversion to LLSD. Usage:
  156. //
  157. // void somefunc(const LLSD&);
  158. // ...
  159. // somefunc(LLSDMap("alpha", "abc")("number", 17)("pi", 3.14));
  160. //
  161. // For completeness, LLSDMap() with no args constructs an empty map, so
  162. // LLSDMap()("alpha", "abc")("number", 17)("pi", 3.14)</tt> produces a map
  163. // equivalent to the above. But for most purposes, LLSD() is already equivalent
  164. // to an empty map, and if you explicitly want an empty isMap(), there is
  165. // LLSD::emptyMap(). However, supporting a no-args LLSDMap() constructor
  166. // follows the principle of least astonishment.
  167. class LLSDMap
  168. {
  169. public:
  170. LLSDMap()
  171. : mData_(LLSD::emptyMap())
  172. {
  173. }
  174. LLSDMap(const LLSD::String& key, const LLSD& value)
  175. : mData_(LLSD::emptyMap())
  176. {
  177. mData_[key] = value;
  178. }
  179. LLSDMap& operator()(const LLSD::String& key, const LLSD& value)
  180. {
  181. mData_[key] = value;
  182. return *this;
  183. }
  184. LL_INLINE operator LLSD() const { return mData_; }
  185. LL_INLINE LLSD get() const { return mData_; }
  186. private:
  187. LLSD mData_;
  188. };
  189. ///////////////////////////////////////////////////////////////////////////////
  190. // llsd::map(): constructs an LLSD::Map inline, using modern C++ variadic
  191. // arguments.
  192. ///////////////////////////////////////////////////////////////////////////////
  193. namespace llsd
  194. {
  195. // Recursion tail
  196. LL_INLINE void map_(LLSD&) {}
  197. // Recursion call
  198. template<typename T0, typename... Ts>
  199. void map_(LLSD& data, const LLSD::String& k0, T0&& v0, Ts&&... vs)
  200. {
  201. data[k0] = v0;
  202. map_(data, std::forward<Ts>(vs)...);
  203. }
  204. // Public interface
  205. template<typename... Ts>
  206. LLSD map(Ts&&... vs)
  207. {
  208. LLSD data;
  209. map_(data, std::forward<Ts>(vs)...);
  210. return data;
  211. }
  212. } // namespace llsd
  213. ///////////////////////////////////////////////////////////////////////////////
  214. // LLSDParam
  215. ///////////////////////////////////////////////////////////////////////////////
  216. class LLSDParamBase
  217. {
  218. public:
  219. virtual ~LLSDParamBase() = default;
  220. };
  221. // LLSDParam is a customization point for passing LLSD values to function
  222. // parameters of more or less arbitrary type. LLSD provides a small set of
  223. // native conversions; but if a generic algorithm explicitly constructs an
  224. // LLSDParam object in the function's argument list, a consumer can provide
  225. // LLSDParam specializations to support more different parameter types than
  226. // LLSD's native conversions.
  227. //
  228. // Usage:
  229. // void somefunc(const paramtype&);
  230. // ...
  231. // somefunc(..., LLSDParam<paramtype>(someLLSD), ...);
  232. template<typename T>
  233. class LLSDParam : public LLSDParamBase
  234. {
  235. public:
  236. /**
  237. * Default implementation converts to T on construction, saves converted
  238. * value for later retrieval
  239. */
  240. LL_INLINE LLSDParam(const LLSD& value)
  241. : mValue_(value)
  242. {
  243. }
  244. LL_INLINE operator T() const { return mValue_; }
  245. private:
  246. T mValue_;
  247. };
  248. // LLSDParam<LLSD> is for when you do not already have the target parameter
  249. // type in hand. Instantiate LLSDParam<LLSD>(your LLSD object), and the
  250. // templated conversion operator will try to select a more specific LLSDParam
  251. // specialization.
  252. template<>
  253. class LLSDParam<LLSD> : public LLSDParamBase
  254. {
  255. public:
  256. LL_INLINE LLSDParam(const LLSD& value)
  257. : mValue_(value)
  258. {
  259. }
  260. // If we are literally being asked for an LLSD parameter, avoid infinite
  261. // recursion.
  262. LL_INLINE operator LLSD() const { return mValue_; }
  263. // Otherwise, instantiate a more specific LLSDParam<T> to convert; this
  264. // preserves the existing customization mechanism.
  265. template<typename T>
  266. operator T() const
  267. {
  268. // Capture 'ptr' with the specific subclass type because mConverters_
  269. // only stores LLSDParamBase pointers.
  270. auto ptr{ std::make_shared<LLSDParam<std::decay_t<T> > >(mValue_) };
  271. // Keep the new converter alive until we ourselves are destroyed.
  272. mConverters_.emplace_back(ptr);
  273. return *ptr;
  274. }
  275. private:
  276. // LLSDParam<LLSD>::operator T() works by instantiating an LLSDParam<T> on
  277. // demand. Returning that engages LLSDParam<T>::operator T(), producing the
  278. // desired result. But LLSDParam<const char*> owns a std::string whose
  279. // c_str() is returned by its operator const char*(). If we return a temp
  280. // LLSDParam<const char*>, the compiler can destroy it right away, as soon
  281. // as we have called operator const char*(). That is a problem since it
  282. // invalidates the const char* we have just passed to the subject function.
  283. // This LLSDParam<LLSD> is presumably guaranteed to survive until the
  284. // subject function has returned, so we must ensure that any constructed
  285. // LLSDParam<T> lives just as long as this LLSDParam<LLSD> does. Putting
  286. // each LLSDParam<T> on the heap and capturing a smart pointer in a vector
  287. // works. We would have liked to use std::unique_ptr, but vector entries
  288. // must be copyable.
  289. typedef std::vector<std::shared_ptr<LLSDParamBase> > converters_vec_t;
  290. mutable converters_vec_t mConverters_;
  291. LLSD mValue_;
  292. };
  293. // It turns out that several target types could accept an LLSD param using any
  294. // of a few different conversions, e.g. LLUUID's constructor can accept LLUUID
  295. // or std::string. Therefore, the compiler can't decide which LLSD conversion
  296. // operator to choose, even though to us it seems obvious. But this is okay, we
  297. // can specialize LLSDParam for such target types, explicitly specifying the
  298. // desired conversion; this is part of what LLSDParam is all about. We have to
  299. // do that enough to make it worthwhile generalizing. Using a macro because we
  300. // need to specify one of the asReal, etc., explicit conversion methods as well
  301. // as a type.
  302. #define LLSDParam_for(T, AS) \
  303. template<> \
  304. class LLSDParam<T> : public LLSDParamBase \
  305. { \
  306. public: \
  307. LLSDParam(const LLSD& value) \
  308. : mValue_((T)value.AS()) \
  309. { \
  310. } \
  311. \
  312. operator T() const { return mValue_; } \
  313. \
  314. private: \
  315. T mValue_; \
  316. }
  317. LLSDParam_for(F32, asReal);
  318. LLSDParam_for(LLUUID, asUUID);
  319. LLSDParam_for(LLDate, asDate);
  320. LLSDParam_for(LLURI, asURI);
  321. LLSDParam_for(LLSD::Binary, asBinary);
  322. // LLSDParam<const char*> is an example of the kind of conversion you can
  323. // support with LLSDParam beyond native LLSD conversions. Normally you cannot
  324. // pass an LLSD object to a function accepting const char*, but you can safely
  325. // pass an LLSDParam<const char*>(yourLLSD).
  326. template<>
  327. class LLSDParam<const char*> : public LLSDParamBase
  328. {
  329. public:
  330. LLSDParam(const LLSD& value)
  331. : mValue_(value),
  332. mUndefined_(value.isUndefined())
  333. {
  334. }
  335. // The const char* we retrieve is for storage owned by our _value member.
  336. // That's how we guarantee that the const char* is valid for the lifetime
  337. // of this LLSDParam object. Constructing your LLSDParam in the argument
  338. // list should ensure that the LLSDParam object will persist for the
  339. // duration of the function call.
  340. operator const char*() const
  341. {
  342. if (mUndefined_)
  343. {
  344. // By default, an isUndefined() LLSD object's asString() method
  345. // will produce an empty string. But for a function accepting
  346. // const char*, it is often important to be able to pass NULL, and
  347. // isUndefined() seems like the best way. If you want to pass an
  348. // empty string, you can still pass LLSD(""). Without this special
  349. // case, though, no LLSD value could pass NULL.
  350. return NULL;
  351. }
  352. return mValue_.c_str();
  353. }
  354. private:
  355. // The difference here is that we store a std::string rather than a const
  356. // char*. It is important that the LLSDParam object own the std::string.
  357. std::string mValue_;
  358. // We do not bother storing the incoming LLSD object, but we do have to
  359. // distinguish whether _value is an empty string because the LLSD object
  360. // contains an empty string or because it's isUndefined().
  361. bool mUndefined_;
  362. };
  363. ///////////////////////////////////////////////////////////////////////////////
  364. // llsd::array(): constructs an LLSD::Array inline, using modern C++ variadic
  365. // arguments.
  366. ///////////////////////////////////////////////////////////////////////////////
  367. namespace llsd
  368. {
  369. // Recursion tail
  370. LL_INLINE void array_(LLSD&) {}
  371. // Recursion call
  372. template<typename T0, typename... Ts>
  373. void array_(LLSD& data, T0&& v0, Ts&&... vs)
  374. {
  375. data.append(std::forward<T0>(v0));
  376. array_(data, std::forward<Ts>(vs)...);
  377. }
  378. // Public interface
  379. template<typename... Ts>
  380. LLSD array(Ts&&... vs)
  381. {
  382. LLSD data;
  383. array_(data, std::forward<Ts>(vs)...);
  384. return data;
  385. }
  386. } // namespace llsd
  387. // Creates a deep clone of an LLSD object. Maps, Arrays and binary objects are
  388. // duplicated, atomic primitives (Boolean, Integer, Real, etc) simply use a
  389. // shared reference.
  390. // Optionally a filter may be specified to control what is duplicated. The map
  391. // takes the form "keyname/boolean".
  392. // If the value is true the value will be duplicated otherwise it will be
  393. // skipped when encountered in a map. A key name of "*" can be specified as a
  394. // wild card and will specify the default behavior. If no wild card is given
  395. // and the clone encounters a name not in the filter, that value will be
  396. // skipped.
  397. LLSD llsd_clone(LLSD value, LLSD filter = LLSD());
  398. // Creates a shallow copy of a map or array. If passed any other type of LLSD
  399. // object it simply returns that value. See llsd_clone for a description of
  400. // the filter parameter.
  401. LLSD llsd_shallow(LLSD value, LLSD filter = LLSD());
  402. // Specialization for generating a hash value from an LLSD block.
  403. size_t hash_value(const LLSD& s) noexcept;
  404. // std::hash implementation for LLSD
  405. namespace std
  406. {
  407. template<> struct hash<LLSD>
  408. {
  409. LL_INLINE size_t operator()(const LLSD& s) const noexcept
  410. {
  411. return hash_value(s);
  412. }
  413. };
  414. }
  415. #endif // LL_LLSDUTIL_H