llsdutil.cpp 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  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=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. #include "linden_common.h"
  35. #include "boost/functional/hash.hpp"
  36. #include "boost/range.hpp"
  37. #include "llsdutil.h"
  38. #if LL_WINDOWS
  39. # define WIN32_LEAN_AND_MEAN
  40. # include <winsock2.h> // For htonl()
  41. #elif LL_LINUX
  42. # include <netinet/in.h>
  43. #elif LL_DARWIN
  44. # include <arpa/inet.h>
  45. #endif
  46. #include "llcommonmath.h"
  47. #include "llsdserialize.h"
  48. // U32
  49. LLSD ll_sd_from_U32(U32 val)
  50. {
  51. LLSD::Binary v;
  52. v.resize(4);
  53. U32 net_order = htonl(val);
  54. memcpy(&(v[0]), &net_order, 4);
  55. return LLSD(v);
  56. }
  57. U32 ll_U32_from_sd(const LLSD& sd)
  58. {
  59. const LLSD::Binary& v = sd.asBinary();
  60. if (v.size() < 4)
  61. {
  62. return 0;
  63. }
  64. U32 ret;
  65. memcpy(&ret, v.data(), 4);
  66. return ntohl(ret);
  67. }
  68. // U64
  69. LLSD ll_sd_from_U64(U64 val)
  70. {
  71. LLSD::Binary v;
  72. v.resize(8);
  73. U32 high = htonl((U32)(val >> 32));
  74. U32 low = htonl((U32)val);
  75. memcpy(&(v[0]), &high, 4);
  76. memcpy(&(v[4]), &low, 4);
  77. return LLSD(v);
  78. }
  79. U64 ll_U64_from_sd(const LLSD& sd)
  80. {
  81. const LLSD::Binary& v = sd.asBinary();
  82. if (v.size() < 8)
  83. {
  84. return 0;
  85. }
  86. U32 high, low;
  87. memcpy(&high, &(v[0]), 4);
  88. memcpy(&low, &(v[4]), 4);
  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(U32 val)
  95. {
  96. LLSD::Binary v;
  97. v.resize(4);
  98. memcpy(&(v[0]), &val, 4);
  99. return LLSD(v);
  100. }
  101. U32 ll_ipaddr_from_sd(const LLSD& sd)
  102. {
  103. const LLSD::Binary& v = sd.asBinary();
  104. if (v.size() < 4)
  105. {
  106. return 0;
  107. }
  108. U32 ret;
  109. memcpy(&ret, &(v[0]), 4);
  110. return ret;
  111. }
  112. // Converts an LLSD binary to an LLSD string
  113. LLSD ll_string_from_binary(const LLSD& sd)
  114. {
  115. const LLSD::Binary& 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. LLSD::Binary 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. constexpr size_t BUFFER_SIZE = 100 * 1024;
  137. static char buffer[BUFFER_SIZE + 1];
  138. std::ostringstream stream;
  139. //stream.rdbuf()->pubsetbuf(buffer, BUFFER_SIZE);
  140. stream << LLSDOStreamer<LLSDXMLFormatter>(sd);
  141. stream << std::ends;
  142. strncpy(buffer, stream.str().c_str(), BUFFER_SIZE);
  143. buffer[BUFFER_SIZE] = '\0';
  144. return buffer;
  145. }
  146. char* ll_pretty_print_sd_ptr(const LLSD* sd)
  147. {
  148. return sd ? ll_pretty_print_sd(*sd) : NULL;
  149. }
  150. char* ll_pretty_print_sd(const LLSD& sd)
  151. {
  152. constexpr size_t BUFFER_SIZE = 100 * 1024;
  153. static char buffer[BUFFER_SIZE + 1];
  154. std::ostringstream stream;
  155. //stream.rdbuf()->pubsetbuf(buffer, BUFFER_SIZE);
  156. stream << LLSDOStreamer<LLSDXMLFormatter>(sd, LLSDFormatter::OPTIONS_PRETTY);
  157. stream << std::ends;
  158. strncpy(buffer, stream.str().c_str(), BUFFER_SIZE);
  159. buffer[BUFFER_SIZE] = '\0';
  160. return buffer;
  161. }
  162. // Compares the structure of an LLSD to a template LLSD and stores the "valid"
  163. // values in a 3rd LLSD. Default values are pulled from the template. Extra
  164. // keys/values in the test are ignored in the resultant LLSD. Ordering of
  165. // arrays matters.
  166. // Returns false if the test is of same type but values differ in type.
  167. // Otherwise, returns true.
  168. bool compare_llsd_with_template(const LLSD& llsd_to_test,
  169. const LLSD& template_llsd,
  170. LLSD& result_llsd)
  171. {
  172. if (llsd_to_test.isUndefined() && template_llsd.isDefined())
  173. {
  174. result_llsd = template_llsd;
  175. return true;
  176. }
  177. if (llsd_to_test.type() != template_llsd.type())
  178. {
  179. result_llsd = LLSD();
  180. return false;
  181. }
  182. if (llsd_to_test.isArray())
  183. {
  184. // They are both arrays. We loop over all the items in the template,
  185. // verifying that the to_test has a subset (in the same order) any
  186. // shortcoming in the testing_llsd are just taken to be the rest of the
  187. // template
  188. LLSD data;
  189. LLSD::array_const_iterator test_iter;
  190. LLSD::array_const_iterator template_iter;
  191. result_llsd = LLSD::emptyArray();
  192. test_iter = llsd_to_test.beginArray();
  193. for (template_iter = template_llsd.beginArray();
  194. template_iter != template_llsd.endArray() &&
  195. test_iter != llsd_to_test.endArray(); ++template_iter)
  196. {
  197. if (!compare_llsd_with_template(*test_iter, *template_iter, data))
  198. {
  199. result_llsd = LLSD();
  200. return false;
  201. }
  202. else
  203. {
  204. result_llsd.append(data);
  205. }
  206. ++test_iter;
  207. }
  208. // So either the test or the template ended. We do another loop now to
  209. // the end of the template grabbing the default values
  210. for ( ; template_iter != template_llsd.endArray(); ++template_iter)
  211. {
  212. result_llsd.append(*template_iter);
  213. }
  214. }
  215. else if (llsd_to_test.isMap())
  216. {
  217. // Now we loop over the keys of the two maps. Any excess is taken from
  218. // the template. Excess is ignored in the test.
  219. LLSD value;
  220. LLSD::map_const_iterator template_iter;
  221. result_llsd = LLSD::emptyMap();
  222. for (template_iter = template_llsd.beginMap();
  223. template_iter != template_llsd.endMap(); ++template_iter)
  224. {
  225. if (llsd_to_test.has(template_iter->first))
  226. {
  227. // The test LLSD has the same key
  228. if (!compare_llsd_with_template(llsd_to_test[template_iter->first],
  229. template_iter->second, value))
  230. {
  231. result_llsd = LLSD();
  232. return false;
  233. }
  234. else
  235. {
  236. result_llsd[template_iter->first] = value;
  237. }
  238. }
  239. else
  240. {
  241. // Test llsd does not have it... Take the template as default
  242. // value
  243. result_llsd[template_iter->first] = template_iter->second;
  244. }
  245. }
  246. }
  247. else
  248. {
  249. // Of same type... Take the test LLSD's value
  250. result_llsd = llsd_to_test;
  251. }
  252. return true;
  253. }
  254. // filter_llsd_with_template() is a direct clone (copy-n-paste) of
  255. // compare_llsd_with_template with the following differences:
  256. // (1) bool vs BOOL return types
  257. // (2) A map with the key value "*" is a special value and maps any key in the
  258. // test llsd that doesn't have an explicitly matching key in the template.
  259. // (3) The element of an array with exactly one element is taken as a template
  260. // for *all* the elements of the test array. If the template array is of
  261. // different size, compare_llsd_with_template() semantics apply.
  262. bool filter_llsd_with_template(const LLSD& llsd_to_test,
  263. const LLSD& template_llsd, LLSD& result_llsd)
  264. {
  265. if (llsd_to_test.isUndefined() && template_llsd.isDefined())
  266. {
  267. result_llsd = template_llsd;
  268. return true;
  269. }
  270. if (llsd_to_test.type() != template_llsd.type())
  271. {
  272. result_llsd = LLSD();
  273. return false;
  274. }
  275. if (llsd_to_test.isArray())
  276. {
  277. // They are both arrays; we loop over all the items in the template
  278. // verifying that the to_test has a subset (in the same order) any
  279. // shortcoming in the testing_llsd are just taken to be the rest of the
  280. // template
  281. LLSD data;
  282. result_llsd = LLSD::emptyArray();
  283. LLSD::array_const_iterator test_iter = llsd_to_test.beginArray();
  284. LLSD::array_const_iterator template_iter = template_llsd.beginArray();
  285. if (template_llsd.size() == 1)
  286. {
  287. // If the template has a single item, treat it as the template for
  288. // *all* items in the test LLSD.
  289. while (test_iter != llsd_to_test.endArray())
  290. {
  291. if (!filter_llsd_with_template(*test_iter, *template_iter,
  292. data))
  293. {
  294. result_llsd = LLSD();
  295. return false;
  296. }
  297. else
  298. {
  299. result_llsd.append(data);
  300. }
  301. ++test_iter;
  302. }
  303. }
  304. else
  305. {
  306. // Traditional compare_llsd_with_template matching
  307. while (template_iter != template_llsd.endArray() &&
  308. test_iter != llsd_to_test.endArray())
  309. {
  310. if (!filter_llsd_with_template(*test_iter, *template_iter,
  311. data))
  312. {
  313. result_llsd = LLSD();
  314. return false;
  315. }
  316. else
  317. {
  318. result_llsd.append(data);
  319. }
  320. ++template_iter;
  321. ++test_iter;
  322. }
  323. // So either the test or the template ended. We do another loop now
  324. // to the end of the template grabbing the default values.
  325. while (template_iter != template_llsd.endArray())
  326. {
  327. result_llsd.append(*template_iter++);
  328. }
  329. }
  330. }
  331. else if (llsd_to_test.isMap())
  332. {
  333. result_llsd = LLSD::emptyMap();
  334. // Now we loop over the keys of the two maps any excess is taken from
  335. // the template excess is ignored in the test
  336. // Special tag for wildcarded LLSD map key templates
  337. const LLSD::String wildcard_tag("*");
  338. bool template_has_wildcard = template_llsd.has(wildcard_tag);
  339. LLSD wildcard_value;
  340. LLSD value;
  341. const LLSD::map_const_iterator template_iter_end(template_llsd.endMap());
  342. for (LLSD::map_const_iterator template_iter(template_llsd.beginMap());
  343. template_iter_end != template_iter; ++template_iter)
  344. {
  345. if (wildcard_tag == template_iter->first)
  346. {
  347. wildcard_value = template_iter->second;
  348. }
  349. else if (llsd_to_test.has(template_iter->first))
  350. {
  351. // The test LLSD has the same key
  352. if (!filter_llsd_with_template(llsd_to_test[template_iter->first],
  353. template_iter->second,
  354. value))
  355. {
  356. result_llsd = LLSD();
  357. return false;
  358. }
  359. else
  360. {
  361. result_llsd[template_iter->first] = value;
  362. }
  363. }
  364. else if (!template_has_wildcard)
  365. {
  366. // Test llsd does not have it... Take the template as default
  367. // value
  368. result_llsd[template_iter->first] = template_iter->second;
  369. }
  370. }
  371. if (template_has_wildcard)
  372. {
  373. LLSD sub_value;
  374. for (LLSD::map_const_iterator test_iter = llsd_to_test.beginMap();
  375. test_iter != llsd_to_test.endMap(); ++test_iter)
  376. {
  377. if (result_llsd.has(test_iter->first))
  378. {
  379. // Final value has test key, assume more specific template
  380. // matched and we shouldn't modify it again.
  381. continue;
  382. }
  383. else if (!filter_llsd_with_template(test_iter->second,
  384. wildcard_value, sub_value))
  385. {
  386. // Test value does not match wildcarded template
  387. result_llsd = LLSD();
  388. return false;
  389. }
  390. else
  391. {
  392. // Test value matches template, add the actuals.
  393. result_llsd[test_iter->first] = sub_value;
  394. }
  395. }
  396. }
  397. }
  398. else
  399. {
  400. // Of same type... Take the test LLSD's value
  401. result_llsd = llsd_to_test;
  402. }
  403. return true;
  404. }
  405. ///////////////////////////////////////////////////////////////////////////////
  406. // Helpers for llsd_matches()
  407. ///////////////////////////////////////////////////////////////////////////////
  408. // Raw data used for LLSD::Type lookup
  409. struct Data
  410. {
  411. LLSD::Type type;
  412. const char* name;
  413. } typedata[] =
  414. {
  415. #define def(type) { LLSD::type, &#type[4] }
  416. def(TypeUndefined),
  417. def(TypeBoolean),
  418. def(TypeInteger),
  419. def(TypeReal),
  420. def(TypeString),
  421. def(TypeUUID),
  422. def(TypeDate),
  423. def(TypeURI),
  424. def(TypeBinary),
  425. def(TypeMap),
  426. def(TypeArray)
  427. #undef def
  428. };
  429. // LLSD::Type lookup class into which we load the above static data
  430. class TypeLookup
  431. {
  432. typedef std::map<LLSD::Type, std::string> MapType;
  433. public:
  434. TypeLookup()
  435. {
  436. for (const Data *di(boost::begin(typedata)),
  437. *dend(boost::end(typedata)); di != dend; ++di)
  438. {
  439. mMap[di->type] = di->name;
  440. }
  441. }
  442. std::string lookup(LLSD::Type type) const
  443. {
  444. MapType::const_iterator found = mMap.find(type);
  445. if (found == mMap.end())
  446. {
  447. return llformat("<unknown LLSD type %d>", type);
  448. }
  449. return found->second;
  450. }
  451. private:
  452. MapType mMap;
  453. };
  454. // Static instance of the lookup class
  455. static const TypeLookup sTypes;
  456. // Describes a mismatch; phrasing may want tweaking
  457. static const char op[] = " required instead of ";
  458. // llsd_matches() wants to identify specifically where in a complex prototype
  459. // structure the mismatch occurred. This entails passing a prefix string,
  460. // empty for the top-level call. If the prototype contains an array of maps,
  461. // and the mismatch occurs in the second map in a key 'foo', we want to
  462. // decorate the returned string with: "[1]['foo']: etc." On the other hand, we
  463. // want to omit the entire prefix -- including colon -- if the mismatch is at
  464. // top level. This helper accepts the (possibly empty) recursively-accumulated
  465. // prefix string, returning either empty or the original string with colon
  466. // appended.
  467. static const char* colon(const std::string& pfx)
  468. {
  469. thread_local std::string buffer;
  470. if (pfx.empty())
  471. {
  472. return pfx.c_str();
  473. }
  474. buffer = pfx + ": ";
  475. return buffer.c_str();
  476. }
  477. // Param type for match_types
  478. typedef std::vector<LLSD::Type> TypeVector;
  479. // The scalar cases in llsd_matches() use this helper. In most cases, we can
  480. // accept not only the exact type specified in the prototype, but also other
  481. // types convertible to the expected type. That implies looping over an array
  482. // of such types. If the actual type doesn't match any of them, we want to
  483. // provide a list of acceptable conversions as well as the exact type, e.g.:
  484. // "Integer (or Boolean, Real, String) required instead of UUID". Both the
  485. // implementation and the calling logic are simplified by separating out the
  486. // expected type from the convertible types.
  487. static std::string match_types(LLSD::Type expect, // prototype.type()
  488. const TypeVector& accept, // types convertible to that type
  489. LLSD::Type actual, // type we're checking
  490. const std::string& pfx) // as for llsd_matches
  491. {
  492. // Trivial case: if the actual type is exactly what we expect, we're good.
  493. if (actual == expect)
  494. {
  495. return "";
  496. }
  497. // For the rest of the logic, build up a suitable error string as we go so
  498. // we only have to make a single pass over the list of acceptable types.
  499. // If we detect success along the way, we'll simply discard the partial
  500. // error string.
  501. std::ostringstream out;
  502. out << colon(pfx) << sTypes.lookup(expect);
  503. // If there are any convertible types, append that list.
  504. if (!accept.empty())
  505. {
  506. out << " (";
  507. const char* sep = "or ";
  508. for (TypeVector::const_iterator ai(accept.begin()), aend(accept.end());
  509. ai != aend; ++ai, sep = ", ")
  510. {
  511. // Do not forget to return success if we match any of those types
  512. if (actual == *ai)
  513. {
  514. return "";
  515. }
  516. out << sep << sTypes.lookup(*ai);
  517. }
  518. out << ')';
  519. }
  520. // If we got this far, it is because 'actual' was not one of the acceptable
  521. // types, so we must return an error. 'out' already contains colon(pfx)
  522. // and the formatted list of acceptable types, so just append the mismatch
  523. // phrase and the actual type.
  524. out << op << sTypes.lookup(actual);
  525. return out.str();
  526. }
  527. // See docstring in .h file
  528. std::string llsd_matches(const LLSD& prototype, const LLSD& data,
  529. const std::string& pfx)
  530. {
  531. // An undefined prototype means that any data is valid. An undefined slot
  532. // in an array or map prototype means that any data may fill that slot.
  533. if (prototype.isUndefined())
  534. {
  535. return "";
  536. }
  537. // A prototype array must match a data array with at least as many entries.
  538. // Moreover, every prototype entry must match the corresponding data entry.
  539. if (prototype.isArray())
  540. {
  541. if (!data.isArray())
  542. {
  543. return llformat("%sArray%s%s", colon(pfx), op,
  544. sTypes.lookup(data.type()).c_str());
  545. }
  546. if (data.size() < prototype.size())
  547. {
  548. return llformat("%sArray size %d%sArray size %d", colon(pfx),
  549. prototype.size(), op, data.size());
  550. }
  551. for (size_t i = 0; i < prototype.size(); ++i)
  552. {
  553. std::string match(llsd_matches(prototype[i], data[i],
  554. llformat("[%d]", i)));
  555. if (!match.empty())
  556. {
  557. return match;
  558. }
  559. }
  560. return "";
  561. }
  562. // A prototype map must match a data map. Every key in the prototype must
  563. // have a corresponding key in the data map; every value in the prototype
  564. // must match the corresponding key's value in the data.
  565. if (prototype.isMap())
  566. {
  567. if (!data.isMap())
  568. {
  569. return llformat("%sMap%s%s", colon(pfx), op,
  570. sTypes.lookup(data.type()).c_str());
  571. }
  572. // If there are a number of keys missing from the data, it would be
  573. // frustrating to a coder to discover them one at a time, with a big
  574. // build each time. Enumerate all missing keys.
  575. std::ostringstream out;
  576. out << colon(pfx);
  577. const char* init = "Map missing keys: ";
  578. const char* sep = init;
  579. for (LLSD::map_const_iterator mi = prototype.beginMap();
  580. mi != prototype.endMap(); ++mi)
  581. {
  582. if (!data.has(mi->first))
  583. {
  584. out << sep << mi->first;
  585. sep = ", ";
  586. }
  587. }
  588. // So... are we missing any keys ?
  589. if (sep != init)
  590. {
  591. return out.str();
  592. }
  593. std::string key, match;
  594. // Good, the data block contains all the keys required by the
  595. // prototype. Now match the prototype entries.
  596. for (LLSD::map_const_iterator mi2 = prototype.beginMap();
  597. mi2 != prototype.endMap(); ++mi2)
  598. {
  599. key = mi2->first;
  600. match = llsd_matches(mi2->second, data[key],
  601. llformat("['%s']", key.c_str()));
  602. if (!match.empty())
  603. {
  604. return match;
  605. }
  606. }
  607. return "";
  608. }
  609. // A String prototype can match String, Boolean, Integer, Real, UUID, Date
  610. // and URI, because any of these can be converted to String.
  611. if (prototype.isString())
  612. {
  613. static LLSD::Type accept[] =
  614. {
  615. LLSD::TypeBoolean,
  616. LLSD::TypeInteger,
  617. LLSD::TypeReal,
  618. LLSD::TypeUUID,
  619. LLSD::TypeDate,
  620. LLSD::TypeURI
  621. };
  622. return match_types(prototype.type(),
  623. TypeVector(boost::begin(accept),
  624. boost::end(accept)),
  625. data.type(),
  626. pfx);
  627. }
  628. // Boolean, Integer, Real match each other or String. TBD: ensure that
  629. // a String value is numeric.
  630. if (prototype.isBoolean() || prototype.isInteger() || prototype.isReal())
  631. {
  632. static LLSD::Type all[] =
  633. {
  634. LLSD::TypeBoolean,
  635. LLSD::TypeInteger,
  636. LLSD::TypeReal,
  637. LLSD::TypeString
  638. };
  639. // Funny business: shuffle the set of acceptable types to include all
  640. // but the prototype's type. Get the acceptable types in a set.
  641. std::set<LLSD::Type> rest(boost::begin(all), boost::end(all));
  642. // Remove the prototype's type because we pass that separately.
  643. rest.erase(prototype.type());
  644. return match_types(prototype.type(),
  645. TypeVector(rest.begin(), rest.end()),
  646. data.type(), pfx);
  647. }
  648. // UUID, Date and URI match themselves or String.
  649. if (prototype.isUUID() || prototype.isDate() || prototype.isURI())
  650. {
  651. static LLSD::Type accept[] =
  652. {
  653. LLSD::TypeString
  654. };
  655. return match_types(prototype.type(),
  656. TypeVector(boost::begin(accept),
  657. boost::end(accept)),
  658. data.type(), pfx);
  659. }
  660. // We do not yet know the conversion semantics associated with any new LLSD
  661. // data type that might be added, so until we have been extended to handle
  662. // them, assume it is strict: the new type matches only itself (this is
  663. // true of Binary, which is why we do not handle that case separately). Too
  664. // bad LLSD doesn't define isConvertible(Type to, Type from).
  665. return match_types(prototype.type(), TypeVector(), data.type(), pfx);
  666. }
  667. bool llsd_equals(const LLSD& lhs, const LLSD& rhs, S32 bits)
  668. {
  669. // We are comparing strict equality of LLSD representation rather than
  670. // performing any conversions. So if the types aren't equal, the LLSD
  671. // values aren't equal.
  672. if (lhs.type() != rhs.type())
  673. {
  674. return false;
  675. }
  676. // Here we know both types are equal. Now compare values.
  677. switch (lhs.type())
  678. {
  679. case LLSD::TypeUndefined:
  680. // Both are TypeUndefined. There is nothing more to know.
  681. return true;
  682. case LLSD::TypeReal:
  683. // This is where the 'bits' argument comes in handy. If passed
  684. // explicitly, it means to use is_approx_equal_fraction() to compare.
  685. if (bits >= 0)
  686. {
  687. return is_approx_equal_fraction(lhs.asReal(), rhs.asReal(),
  688. bits);
  689. }
  690. // Otherwise we compare bit representations, and the usual caveats
  691. // about comparing floating-point numbers apply. Omitting 'bits'
  692. // when comparing Real values is only useful when we expect
  693. // identical bit representation for a given Real value, e.g. for
  694. // integer-valued Reals.
  695. return lhs.asReal() == rhs.asReal();
  696. #define COMPARE_SCALAR(type) \
  697. case LLSD::Type##type: \
  698. /* LLSD::URI has operator!=() but not operator==() */ \
  699. /* rely on the optimizer for all others */ \
  700. return (!(lhs.as##type() != rhs.as##type()))
  701. COMPARE_SCALAR(Boolean);
  702. COMPARE_SCALAR(Integer);
  703. COMPARE_SCALAR(String);
  704. COMPARE_SCALAR(UUID);
  705. COMPARE_SCALAR(Date);
  706. COMPARE_SCALAR(URI);
  707. COMPARE_SCALAR(Binary);
  708. #undef COMPARE_SCALAR
  709. case LLSD::TypeArray:
  710. {
  711. LLSD::array_const_iterator lai(lhs.beginArray()),
  712. laend(lhs.endArray()),
  713. rai(rhs.beginArray()),
  714. raend(rhs.endArray());
  715. // Compare array elements, walking the two arrays in parallel.
  716. for ( ; lai != laend && rai != raend; ++lai, ++rai)
  717. {
  718. // If any one array element is unequal, the arrays are unequal.
  719. if (!llsd_equals(*lai, *rai, bits))
  720. {
  721. return false;
  722. }
  723. }
  724. // Here we have reached the end of one or the other array. They are
  725. // equal only if they are BOTH at end: that is, if they have equal
  726. // length too.
  727. return lai == laend && rai == raend;
  728. }
  729. case LLSD::TypeMap:
  730. {
  731. // Build a set of all rhs keys.
  732. std::set<LLSD::String> rhskeys;
  733. for (LLSD::map_const_iterator rmi(rhs.beginMap()),
  734. rmend(rhs.endMap());
  735. rmi != rmend; ++rmi)
  736. {
  737. rhskeys.insert(rmi->first);
  738. }
  739. // Now walk all the lhs keys.
  740. for (LLSD::map_const_iterator lmi(lhs.beginMap()),
  741. lmend(lhs.endMap());
  742. lmi != lmend; ++lmi)
  743. {
  744. // Try to erase this lhs key from the set of rhs keys. If rhs
  745. // has no such key, the maps are unequal. erase(key) returns
  746. // count of items erased.
  747. if (rhskeys.erase(lmi->first) != 1)
  748. {
  749. return false;
  750. }
  751. // Both maps have the current key. Compare values.
  752. if (!llsd_equals(lmi->second, rhs[lmi->first], bits))
  753. {
  754. return false;
  755. }
  756. }
  757. // We've now established that all the lhs keys have equal values in
  758. // both maps. The maps are equal unless rhs contains a superset of
  759. // those keys.
  760. return rhskeys.empty();
  761. }
  762. default:
  763. // We expect that every possible type() value is specifically
  764. // handled above. Failing to extend this switch to support a new
  765. // LLSD type is an error that must be brought to the coder's
  766. // attention.
  767. llerrs << "llsd_equals(" << lhs << ", " << rhs << ", " << bits
  768. << "): unknown type " << lhs.type() << llendl;
  769. }
  770. return false;
  771. }
  772. LLSD llsd_clone(LLSD value, LLSD filter)
  773. {
  774. bool has_filter = filter.isMap();
  775. LLSD clone;
  776. switch (value.type())
  777. {
  778. case LLSD::TypeMap:
  779. {
  780. clone = LLSD::emptyMap();
  781. for (LLSD::map_const_iterator it = value.beginMap(),
  782. end = value.endMap();
  783. it != end; ++it)
  784. {
  785. if (has_filter)
  786. {
  787. if (filter.has(it->first))
  788. {
  789. if (!filter[it->first].asBoolean())
  790. {
  791. continue;
  792. }
  793. }
  794. else if (filter.has("*"))
  795. {
  796. if (!filter["*"].asBoolean())
  797. {
  798. continue;
  799. }
  800. }
  801. else
  802. {
  803. continue;
  804. }
  805. }
  806. clone[it->first] = llsd_clone(it->second, filter);
  807. }
  808. break;
  809. }
  810. case LLSD::TypeArray:
  811. {
  812. clone = LLSD::emptyArray();
  813. for (LLSD::array_const_iterator it = value.beginArray(),
  814. end = value.endArray();
  815. it != end; ++it)
  816. {
  817. clone.append(llsd_clone(*it, filter));
  818. }
  819. break;
  820. }
  821. case LLSD::TypeBinary:
  822. {
  823. clone = LLSD::Binary(value.asBinary().begin(),
  824. value.asBinary().end());
  825. break;
  826. }
  827. default:
  828. {
  829. clone = value;
  830. }
  831. }
  832. return clone;
  833. }
  834. LLSD llsd_shallow(LLSD value, LLSD filter)
  835. {
  836. bool has_filter = filter.isMap();
  837. LLSD shallow;
  838. if (value.isMap())
  839. {
  840. shallow = LLSD::emptyMap();
  841. for (LLSD::map_const_iterator it = value.beginMap(),
  842. end = value.endMap();
  843. it != end; ++it)
  844. {
  845. if (has_filter)
  846. {
  847. if (filter.has(it->first))
  848. {
  849. if (!filter[it->first].asBoolean())
  850. {
  851. continue;
  852. }
  853. }
  854. else if (filter.has("*"))
  855. {
  856. if (!filter["*"].asBoolean())
  857. {
  858. continue;
  859. }
  860. }
  861. else
  862. {
  863. continue;
  864. }
  865. }
  866. shallow[it->first] = it->second;
  867. }
  868. }
  869. else if (value.isArray())
  870. {
  871. shallow = LLSD::emptyArray();
  872. for (LLSD::array_const_iterator it = value.beginArray(),
  873. end = value.endArray();
  874. it != end; ++it)
  875. {
  876. shallow.append(*it);
  877. }
  878. }
  879. else
  880. {
  881. return value;
  882. }
  883. return shallow;
  884. }
  885. size_t hash_value(const LLSD& s) noexcept
  886. {
  887. size_t seed = 0;
  888. LLSD::Type stype = s.type();
  889. boost::hash_combine(seed, (S32)stype);
  890. switch (stype)
  891. {
  892. case LLSD::TypeBoolean:
  893. boost::hash_combine(seed, s.asBoolean());
  894. break;
  895. case LLSD::TypeInteger:
  896. boost::hash_combine(seed, s.asInteger());
  897. break;
  898. case LLSD::TypeReal:
  899. boost::hash_combine(seed, s.asReal());
  900. break;
  901. case LLSD::TypeURI:
  902. case LLSD::TypeString:
  903. boost::hash_combine(seed, s.asString());
  904. break;
  905. case LLSD::TypeUUID:
  906. boost::hash_combine(seed, s.asUUID());
  907. break;
  908. case LLSD::TypeDate:
  909. boost::hash_combine(seed, s.asDate().secondsSinceEpoch());
  910. break;
  911. case LLSD::TypeBinary:
  912. {
  913. const LLSD::Binary& b(s.asBinary());
  914. boost::hash_range(seed, b.begin(), b.end());
  915. break;
  916. }
  917. case LLSD::TypeMap:
  918. for (LLSD::map_const_iterator it = s.beginMap(),
  919. end = s.endMap();
  920. it != end; ++it)
  921. {
  922. boost::hash_combine(seed, it->first);
  923. boost::hash_combine(seed, it->second);
  924. }
  925. break;
  926. case LLSD::TypeArray:
  927. for (LLSD::array_const_iterator it = s.beginArray(),
  928. end = s.endArray();
  929. it != end; ++it)
  930. {
  931. boost::hash_combine(seed, *it);
  932. }
  933. break;
  934. case LLSD::TypeUndefined:
  935. default:
  936. break;
  937. }
  938. return seed;
  939. }
  940. ///////////////////////////////////////////////////////////////////////////////
  941. // llsd::drill_ref()
  942. ///////////////////////////////////////////////////////////////////////////////
  943. namespace llsd
  944. {
  945. LLSD& drill_ref(LLSD& blob, const LLSD& raw_path)
  946. {
  947. // Treat raw_path uniformly as an array. If it is not already an array,
  948. // store it as the only entry in one.
  949. LLSD path;
  950. if (raw_path.isArray())
  951. {
  952. path = raw_path;
  953. }
  954. else
  955. {
  956. path.append(raw_path);
  957. }
  958. // Need to indicate a current destination, but that current destination
  959. // needs to change as we step through the path array. Where normally we
  960. // would use an LLSD& to capture a subscripted LLSD lvalue, this time we
  961. // must instead use a pointer, since it must be reassigned.
  962. LLSD* located = &blob;
  963. // Now loop through that array
  964. for (size_t i = 0; i < path.size(); ++i)
  965. {
  966. const LLSD& key = path[i];
  967. if (key.isString())
  968. {
  969. // *located is an LLSD map
  970. located = &((*located)[key.asString()]);
  971. }
  972. else if (key.isInteger())
  973. {
  974. // *located is an LLSD array
  975. located = &((*located)[key.asInteger()]);
  976. }
  977. else
  978. {
  979. // What do we do with Real or Array or Map or ... ?
  980. // As it is a coder error, not a user error, so rub the coder's
  981. // face in it so it gets fixed.
  982. llerrs << "drill_ref(" << blob << ", " << raw_path << "): path["
  983. << i << "] bad type " << sTypes.lookup(key.type())
  984. << llendl;
  985. }
  986. }
  987. // Dereference the pointer to return a reference to the element we found
  988. return *located;
  989. }
  990. } // namespace llsd