llsdutil.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:20k
源码类别:

游戏引擎

开发平台:

C++ Builder

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