PageRenderTime 36ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcommon/llsdutil.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 675 lines | 465 code | 60 blank | 150 comment | 80 complexity | 2e14142a9b6e9fbd5b57a04fc75b5164 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llsdutil.cpp
  3. * @author Phoenix
  4. * @date 2006-05-24
  5. * @brief Implementation of classes, functions, etc, for using structured data.
  6. *
  7. * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #include "linden_common.h"
  29. #include "llsdutil.h"
  30. #if LL_WINDOWS
  31. # define WIN32_LEAN_AND_MEAN
  32. # include <winsock2.h> // for htonl
  33. #elif LL_LINUX || LL_SOLARIS
  34. # include <netinet/in.h>
  35. #elif LL_DARWIN
  36. # include <arpa/inet.h>
  37. #endif
  38. #include "llsdserialize.h"
  39. #include "stringize.h"
  40. #include "is_approx_equal_fraction.h"
  41. #include <map>
  42. #include <set>
  43. #include <boost/range.hpp>
  44. // U32
  45. LLSD ll_sd_from_U32(const U32 val)
  46. {
  47. std::vector<U8> v;
  48. U32 net_order = htonl(val);
  49. v.resize(4);
  50. memcpy(&(v[0]), &net_order, 4); /* Flawfinder: ignore */
  51. return LLSD(v);
  52. }
  53. U32 ll_U32_from_sd(const LLSD& sd)
  54. {
  55. U32 ret;
  56. std::vector<U8> v = sd.asBinary();
  57. if (v.size() < 4)
  58. {
  59. return 0;
  60. }
  61. memcpy(&ret, &(v[0]), 4); /* Flawfinder: ignore */
  62. ret = ntohl(ret);
  63. return ret;
  64. }
  65. //U64
  66. LLSD ll_sd_from_U64(const U64 val)
  67. {
  68. std::vector<U8> v;
  69. U32 high, low;
  70. high = (U32)(val >> 32);
  71. low = (U32)val;
  72. high = htonl(high);
  73. low = htonl(low);
  74. v.resize(8);
  75. memcpy(&(v[0]), &high, 4); /* Flawfinder: ignore */
  76. memcpy(&(v[4]), &low, 4); /* Flawfinder: ignore */
  77. return LLSD(v);
  78. }
  79. U64 ll_U64_from_sd(const LLSD& sd)
  80. {
  81. U32 high, low;
  82. std::vector<U8> v = sd.asBinary();
  83. if (v.size() < 8)
  84. {
  85. return 0;
  86. }
  87. memcpy(&high, &(v[0]), 4); /* Flawfinder: ignore */
  88. memcpy(&low, &(v[4]), 4); /* Flawfinder: ignore */
  89. high = ntohl(high);
  90. low = ntohl(low);
  91. return ((U64)high) << 32 | low;
  92. }
  93. // IP Address (stored in net order in a U32, so don't need swizzling)
  94. LLSD ll_sd_from_ipaddr(const U32 val)
  95. {
  96. std::vector<U8> v;
  97. v.resize(4);
  98. memcpy(&(v[0]), &val, 4); /* Flawfinder: ignore */
  99. return LLSD(v);
  100. }
  101. U32 ll_ipaddr_from_sd(const LLSD& sd)
  102. {
  103. U32 ret;
  104. std::vector<U8> v = sd.asBinary();
  105. if (v.size() < 4)
  106. {
  107. return 0;
  108. }
  109. memcpy(&ret, &(v[0]), 4); /* Flawfinder: ignore */
  110. return ret;
  111. }
  112. // Converts an LLSD binary to an LLSD string
  113. LLSD ll_string_from_binary(const LLSD& sd)
  114. {
  115. std::vector<U8> value = sd.asBinary();
  116. std::string str;
  117. str.resize(value.size());
  118. memcpy(&str[0], &value[0], value.size());
  119. return str;
  120. }
  121. // Converts an LLSD string to an LLSD binary
  122. LLSD ll_binary_from_string(const LLSD& sd)
  123. {
  124. std::vector<U8> binary_value;
  125. std::string string_value = sd.asString();
  126. for (std::string::iterator iter = string_value.begin();
  127. iter != string_value.end(); ++iter)
  128. {
  129. binary_value.push_back(*iter);
  130. }
  131. binary_value.push_back('\0');
  132. return binary_value;
  133. }
  134. char* ll_print_sd(const LLSD& sd)
  135. {
  136. const U32 bufferSize = 10 * 1024;
  137. static char buffer[bufferSize];
  138. std::ostringstream stream;
  139. //stream.rdbuf()->pubsetbuf(buffer, bufferSize);
  140. stream << LLSDOStreamer<LLSDXMLFormatter>(sd);
  141. stream << std::ends;
  142. strncpy(buffer, stream.str().c_str(), bufferSize);
  143. buffer[bufferSize - 1] = '\0';
  144. return buffer;
  145. }
  146. char* ll_pretty_print_sd_ptr(const LLSD* sd)
  147. {
  148. if (sd)
  149. {
  150. return ll_pretty_print_sd(*sd);
  151. }
  152. return NULL;
  153. }
  154. char* ll_pretty_print_sd(const LLSD& sd)
  155. {
  156. const U32 bufferSize = 10 * 1024;
  157. static char buffer[bufferSize];
  158. std::ostringstream stream;
  159. //stream.rdbuf()->pubsetbuf(buffer, bufferSize);
  160. stream << LLSDOStreamer<LLSDXMLFormatter>(sd, LLSDFormatter::OPTIONS_PRETTY);
  161. stream << std::ends;
  162. strncpy(buffer, stream.str().c_str(), bufferSize);
  163. buffer[bufferSize - 1] = '\0';
  164. return buffer;
  165. }
  166. //compares the structure of an LLSD to a template LLSD and stores the
  167. //"valid" values in a 3rd LLSD. Default values pulled from the template
  168. //if the tested LLSD does not contain the key/value pair.
  169. //Excess values in the test LLSD are ignored in the resultant_llsd.
  170. //If the llsd to test has a specific key to a map and the values
  171. //are not of the same type, false is returned or if the LLSDs are not
  172. //of the same value. Ordering of arrays matters
  173. //Otherwise, returns true
  174. BOOL compare_llsd_with_template(
  175. const LLSD& llsd_to_test,
  176. const LLSD& template_llsd,
  177. LLSD& resultant_llsd)
  178. {
  179. if (
  180. llsd_to_test.isUndefined() &&
  181. template_llsd.isDefined() )
  182. {
  183. resultant_llsd = template_llsd;
  184. return TRUE;
  185. }
  186. else if ( llsd_to_test.type() != template_llsd.type() )
  187. {
  188. resultant_llsd = LLSD();
  189. return FALSE;
  190. }
  191. if ( llsd_to_test.isArray() )
  192. {
  193. //they are both arrays
  194. //we loop over all the items in the template
  195. //verifying that the to_test has a subset (in the same order)
  196. //any shortcoming in the testing_llsd are just taken
  197. //to be the rest of the template
  198. LLSD data;
  199. LLSD::array_const_iterator test_iter;
  200. LLSD::array_const_iterator template_iter;
  201. resultant_llsd = LLSD::emptyArray();
  202. test_iter = llsd_to_test.beginArray();
  203. for (
  204. template_iter = template_llsd.beginArray();
  205. (template_iter != template_llsd.endArray() &&
  206. test_iter != llsd_to_test.endArray());
  207. ++template_iter)
  208. {
  209. if ( !compare_llsd_with_template(
  210. *test_iter,
  211. *template_iter,
  212. data) )
  213. {
  214. resultant_llsd = LLSD();
  215. return FALSE;
  216. }
  217. else
  218. {
  219. resultant_llsd.append(data);
  220. }
  221. ++test_iter;
  222. }
  223. //so either the test or the template ended
  224. //we do another loop now to the end of the template
  225. //grabbing the default values
  226. for (;
  227. template_iter != template_llsd.endArray();
  228. ++template_iter)
  229. {
  230. resultant_llsd.append(*template_iter);
  231. }
  232. }
  233. else if ( llsd_to_test.isMap() )
  234. {
  235. //now we loop over the keys of the two maps
  236. //any excess is taken from the template
  237. //excess is ignored in the test
  238. LLSD value;
  239. LLSD::map_const_iterator template_iter;
  240. resultant_llsd = LLSD::emptyMap();
  241. for (
  242. template_iter = template_llsd.beginMap();
  243. template_iter != template_llsd.endMap();
  244. ++template_iter)
  245. {
  246. if ( llsd_to_test.has(template_iter->first) )
  247. {
  248. //the test LLSD has the same key
  249. if ( !compare_llsd_with_template(
  250. llsd_to_test[template_iter->first],
  251. template_iter->second,
  252. value) )
  253. {
  254. resultant_llsd = LLSD();
  255. return FALSE;
  256. }
  257. else
  258. {
  259. resultant_llsd[template_iter->first] = value;
  260. }
  261. }
  262. else
  263. {
  264. //test llsd doesn't have it...take the
  265. //template as default value
  266. resultant_llsd[template_iter->first] =
  267. template_iter->second;
  268. }
  269. }
  270. }
  271. else
  272. {
  273. //of same type...take the test llsd's value
  274. resultant_llsd = llsd_to_test;
  275. }
  276. return TRUE;
  277. }
  278. /*****************************************************************************
  279. * Helpers for llsd_matches()
  280. *****************************************************************************/
  281. // raw data used for LLSD::Type lookup
  282. struct Data
  283. {
  284. LLSD::Type type;
  285. const char* name;
  286. } typedata[] =
  287. {
  288. #define def(type) { LLSD::type, #type + 4 }
  289. def(TypeUndefined),
  290. def(TypeBoolean),
  291. def(TypeInteger),
  292. def(TypeReal),
  293. def(TypeString),
  294. def(TypeUUID),
  295. def(TypeDate),
  296. def(TypeURI),
  297. def(TypeBinary),
  298. def(TypeMap),
  299. def(TypeArray)
  300. #undef def
  301. };
  302. // LLSD::Type lookup class into which we load the above static data
  303. class TypeLookup
  304. {
  305. typedef std::map<LLSD::Type, std::string> MapType;
  306. public:
  307. TypeLookup()
  308. {
  309. for (const Data *di(boost::begin(typedata)), *dend(boost::end(typedata)); di != dend; ++di)
  310. {
  311. mMap[di->type] = di->name;
  312. }
  313. }
  314. std::string lookup(LLSD::Type type) const
  315. {
  316. MapType::const_iterator found = mMap.find(type);
  317. if (found != mMap.end())
  318. {
  319. return found->second;
  320. }
  321. return STRINGIZE("<unknown LLSD type " << type << ">");
  322. }
  323. private:
  324. MapType mMap;
  325. };
  326. // static instance of the lookup class
  327. static const TypeLookup sTypes;
  328. // describe a mismatch; phrasing may want tweaking
  329. const std::string op(" required instead of ");
  330. // llsd_matches() wants to identify specifically where in a complex prototype
  331. // structure the mismatch occurred. This entails passing a prefix string,
  332. // empty for the top-level call. If the prototype contains an array of maps,
  333. // and the mismatch occurs in the second map in a key 'foo', we want to
  334. // decorate the returned string with: "[1]['foo']: etc." On the other hand, we
  335. // want to omit the entire prefix -- including colon -- if the mismatch is at
  336. // top level. This helper accepts the (possibly empty) recursively-accumulated
  337. // prefix string, returning either empty or the original string with colon
  338. // appended.
  339. static std::string colon(const std::string& pfx)
  340. {
  341. if (pfx.empty())
  342. return pfx;
  343. return pfx + ": ";
  344. }
  345. // param type for match_types
  346. typedef std::vector<LLSD::Type> TypeVector;
  347. // The scalar cases in llsd_matches() use this helper. In most cases, we can
  348. // accept not only the exact type specified in the prototype, but also other
  349. // types convertible to the expected type. That implies looping over an array
  350. // of such types. If the actual type doesn't match any of them, we want to
  351. // provide a list of acceptable conversions as well as the exact type, e.g.:
  352. // "Integer (or Boolean, Real, String) required instead of UUID". Both the
  353. // implementation and the calling logic are simplified by separating out the
  354. // expected type from the convertible types.
  355. static std::string match_types(LLSD::Type expect, // prototype.type()
  356. const TypeVector& accept, // types convertible to that type
  357. LLSD::Type actual, // type we're checking
  358. const std::string& pfx) // as for llsd_matches
  359. {
  360. // Trivial case: if the actual type is exactly what we expect, we're good.
  361. if (actual == expect)
  362. return "";
  363. // For the rest of the logic, build up a suitable error string as we go so
  364. // we only have to make a single pass over the list of acceptable types.
  365. // If we detect success along the way, we'll simply discard the partial
  366. // error string.
  367. std::ostringstream out;
  368. out << colon(pfx) << sTypes.lookup(expect);
  369. // If there are any convertible types, append that list.
  370. if (! accept.empty())
  371. {
  372. out << " (";
  373. const char* sep = "or ";
  374. for (TypeVector::const_iterator ai(accept.begin()), aend(accept.end());
  375. ai != aend; ++ai, sep = ", ")
  376. {
  377. // Don't forget to return success if we match any of those types...
  378. if (actual == *ai)
  379. return "";
  380. out << sep << sTypes.lookup(*ai);
  381. }
  382. out << ')';
  383. }
  384. // If we got this far, it's because 'actual' was not one of the acceptable
  385. // types, so we must return an error. 'out' already contains colon(pfx)
  386. // and the formatted list of acceptable types, so just append the mismatch
  387. // phrase and the actual type.
  388. out << op << sTypes.lookup(actual);
  389. return out.str();
  390. }
  391. // see docstring in .h file
  392. std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx)
  393. {
  394. // An undefined prototype means that any data is valid.
  395. // An undefined slot in an array or map prototype means that any data
  396. // may fill that slot.
  397. if (prototype.isUndefined())
  398. return "";
  399. // A prototype array must match a data array with at least as many
  400. // entries. Moreover, every prototype entry must match the
  401. // corresponding data entry.
  402. if (prototype.isArray())
  403. {
  404. if (! data.isArray())
  405. {
  406. return STRINGIZE(colon(pfx) << "Array" << op << sTypes.lookup(data.type()));
  407. }
  408. if (data.size() < prototype.size())
  409. {
  410. return STRINGIZE(colon(pfx) << "Array size " << prototype.size() << op
  411. << "Array size " << data.size());
  412. }
  413. for (LLSD::Integer i = 0; i < prototype.size(); ++i)
  414. {
  415. std::string match(llsd_matches(prototype[i], data[i], STRINGIZE('[' << i << ']')));
  416. if (! match.empty())
  417. {
  418. return match;
  419. }
  420. }
  421. return "";
  422. }
  423. // A prototype map must match a data map. Every key in the prototype
  424. // must have a corresponding key in the data map; every value in the
  425. // prototype must match the corresponding key's value in the data.
  426. if (prototype.isMap())
  427. {
  428. if (! data.isMap())
  429. {
  430. return STRINGIZE(colon(pfx) << "Map" << op << sTypes.lookup(data.type()));
  431. }
  432. // If there are a number of keys missing from the data, it would be
  433. // frustrating to a coder to discover them one at a time, with a big
  434. // build each time. Enumerate all missing keys.
  435. std::ostringstream out;
  436. out << colon(pfx);
  437. const char* init = "Map missing keys: ";
  438. const char* sep = init;
  439. for (LLSD::map_const_iterator mi = prototype.beginMap(); mi != prototype.endMap(); ++mi)
  440. {
  441. if (! data.has(mi->first))
  442. {
  443. out << sep << mi->first;
  444. sep = ", ";
  445. }
  446. }
  447. // So... are we missing any keys?
  448. if (sep != init)
  449. {
  450. return out.str();
  451. }
  452. // Good, the data block contains all the keys required by the
  453. // prototype. Now match the prototype entries.
  454. for (LLSD::map_const_iterator mi2 = prototype.beginMap(); mi2 != prototype.endMap(); ++mi2)
  455. {
  456. std::string match(llsd_matches(mi2->second, data[mi2->first],
  457. STRINGIZE("['" << mi2->first << "']")));
  458. if (! match.empty())
  459. {
  460. return match;
  461. }
  462. }
  463. return "";
  464. }
  465. // A String prototype can match String, Boolean, Integer, Real, UUID,
  466. // Date and URI, because any of these can be converted to String.
  467. if (prototype.isString())
  468. {
  469. static LLSD::Type accept[] =
  470. {
  471. LLSD::TypeBoolean,
  472. LLSD::TypeInteger,
  473. LLSD::TypeReal,
  474. LLSD::TypeUUID,
  475. LLSD::TypeDate,
  476. LLSD::TypeURI
  477. };
  478. return match_types(prototype.type(),
  479. TypeVector(boost::begin(accept), boost::end(accept)),
  480. data.type(),
  481. pfx);
  482. }
  483. // Boolean, Integer, Real match each other or String. TBD: ensure that
  484. // a String value is numeric.
  485. if (prototype.isBoolean() || prototype.isInteger() || prototype.isReal())
  486. {
  487. static LLSD::Type all[] =
  488. {
  489. LLSD::TypeBoolean,
  490. LLSD::TypeInteger,
  491. LLSD::TypeReal,
  492. LLSD::TypeString
  493. };
  494. // Funny business: shuffle the set of acceptable types to include all
  495. // but the prototype's type. Get the acceptable types in a set.
  496. std::set<LLSD::Type> rest(boost::begin(all), boost::end(all));
  497. // Remove the prototype's type because we pass that separately.
  498. rest.erase(prototype.type());
  499. return match_types(prototype.type(),
  500. TypeVector(rest.begin(), rest.end()),
  501. data.type(),
  502. pfx);
  503. }
  504. // UUID, Date and URI match themselves or String.
  505. if (prototype.isUUID() || prototype.isDate() || prototype.isURI())
  506. {
  507. static LLSD::Type accept[] =
  508. {
  509. LLSD::TypeString
  510. };
  511. return match_types(prototype.type(),
  512. TypeVector(boost::begin(accept), boost::end(accept)),
  513. data.type(),
  514. pfx);
  515. }
  516. // We don't yet know the conversion semantics associated with any new LLSD
  517. // data type that might be added, so until we've been extended to handle
  518. // them, assume it's strict: the new type matches only itself. (This is
  519. // true of Binary, which is why we don't handle that case separately.) Too
  520. // bad LLSD doesn't define isConvertible(Type to, Type from).
  521. return match_types(prototype.type(), TypeVector(), data.type(), pfx);
  522. }
  523. bool llsd_equals(const LLSD& lhs, const LLSD& rhs, unsigned bits)
  524. {
  525. // We're comparing strict equality of LLSD representation rather than
  526. // performing any conversions. So if the types aren't equal, the LLSD
  527. // values aren't equal.
  528. if (lhs.type() != rhs.type())
  529. {
  530. return false;
  531. }
  532. // Here we know both types are equal. Now compare values.
  533. switch (lhs.type())
  534. {
  535. case LLSD::TypeUndefined:
  536. // Both are TypeUndefined. There's nothing more to know.
  537. return true;
  538. case LLSD::TypeReal:
  539. // This is where the 'bits' argument comes in handy. If passed
  540. // explicitly, it means to use is_approx_equal_fraction() to compare.
  541. if (bits >= 0)
  542. {
  543. return is_approx_equal_fraction(lhs.asReal(), rhs.asReal(), bits);
  544. }
  545. // Otherwise we compare bit representations, and the usual caveats
  546. // about comparing floating-point numbers apply. Omitting 'bits' when
  547. // comparing Real values is only useful when we expect identical bit
  548. // representation for a given Real value, e.g. for integer-valued
  549. // Reals.
  550. return (lhs.asReal() == rhs.asReal());
  551. #define COMPARE_SCALAR(type) \
  552. case LLSD::Type##type: \
  553. /* LLSD::URI has operator!=() but not operator==() */ \
  554. /* rely on the optimizer for all others */ \
  555. return (! (lhs.as##type() != rhs.as##type()))
  556. COMPARE_SCALAR(Boolean);
  557. COMPARE_SCALAR(Integer);
  558. COMPARE_SCALAR(String);
  559. COMPARE_SCALAR(UUID);
  560. COMPARE_SCALAR(Date);
  561. COMPARE_SCALAR(URI);
  562. COMPARE_SCALAR(Binary);
  563. #undef COMPARE_SCALAR
  564. case LLSD::TypeArray:
  565. {
  566. LLSD::array_const_iterator
  567. lai(lhs.beginArray()), laend(lhs.endArray()),
  568. rai(rhs.beginArray()), raend(rhs.endArray());
  569. // Compare array elements, walking the two arrays in parallel.
  570. for ( ; lai != laend && rai != raend; ++lai, ++rai)
  571. {
  572. // If any one array element is unequal, the arrays are unequal.
  573. if (! llsd_equals(*lai, *rai, bits))
  574. return false;
  575. }
  576. // Here we've reached the end of one or the other array. They're equal
  577. // only if they're BOTH at end: that is, if they have equal length too.
  578. return (lai == laend && rai == raend);
  579. }
  580. case LLSD::TypeMap:
  581. {
  582. // Build a set of all rhs keys.
  583. std::set<LLSD::String> rhskeys;
  584. for (LLSD::map_const_iterator rmi(rhs.beginMap()), rmend(rhs.endMap());
  585. rmi != rmend; ++rmi)
  586. {
  587. rhskeys.insert(rmi->first);
  588. }
  589. // Now walk all the lhs keys.
  590. for (LLSD::map_const_iterator lmi(lhs.beginMap()), lmend(lhs.endMap());
  591. lmi != lmend; ++lmi)
  592. {
  593. // Try to erase this lhs key from the set of rhs keys. If rhs has
  594. // no such key, the maps are unequal. erase(key) returns count of
  595. // items erased.
  596. if (rhskeys.erase(lmi->first) != 1)
  597. return false;
  598. // Both maps have the current key. Compare values.
  599. if (! llsd_equals(lmi->second, rhs[lmi->first], bits))
  600. return false;
  601. }
  602. // We've now established that all the lhs keys have equal values in
  603. // both maps. The maps are equal unless rhs contains a superset of
  604. // those keys.
  605. return rhskeys.empty();
  606. }
  607. default:
  608. // We expect that every possible type() value is specifically handled
  609. // above. Failing to extend this switch to support a new LLSD type is
  610. // an error that must be brought to the coder's attention.
  611. LL_ERRS("llsd_equals") << "llsd_equals(" << lhs << ", " << rhs << ", " << bits << "): "
  612. "unknown type " << lhs.type() << LL_ENDL;
  613. return false; // pacify the compiler
  614. }
  615. }