JSONValue.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../Precompiled.h"
  4. #include "../Core/Context.h"
  5. #include "../Core/StringUtils.h"
  6. #include "../IO/Log.h"
  7. #include "../Resource/JSONValue.h"
  8. #include "../DebugNew.h"
  9. namespace Urho3D
  10. {
  11. static const char* valueTypeNames[] =
  12. {
  13. "Null",
  14. "Bool",
  15. "Number",
  16. "String",
  17. "Array",
  18. "Object",
  19. nullptr
  20. };
  21. static const char* numberTypeNames[] =
  22. {
  23. "NaN",
  24. "Int",
  25. "Unsigned",
  26. "Real",
  27. nullptr
  28. };
  29. const JSONValue JSONValue::EMPTY;
  30. const JSONArray JSONValue::emptyArray { };
  31. const JSONObject JSONValue::emptyObject;
  32. JSONValue& JSONValue::operator =(bool rhs)
  33. {
  34. SetType(JSON_BOOL);
  35. boolValue_ = rhs;
  36. return *this;
  37. }
  38. JSONValue& JSONValue::operator =(int rhs)
  39. {
  40. SetType(JSON_NUMBER, JSONNT_INT);
  41. numberValue_ = rhs;
  42. return *this;
  43. }
  44. JSONValue& JSONValue::operator =(unsigned rhs)
  45. {
  46. SetType(JSON_NUMBER, JSONNT_UINT);
  47. numberValue_ = rhs;
  48. return *this;
  49. }
  50. JSONValue& JSONValue::operator =(float rhs)
  51. {
  52. SetType(JSON_NUMBER, JSONNT_FLOAT_DOUBLE);
  53. numberValue_ = rhs;
  54. return *this;
  55. }
  56. JSONValue& JSONValue::operator =(double rhs)
  57. {
  58. SetType(JSON_NUMBER, JSONNT_FLOAT_DOUBLE);
  59. numberValue_ = rhs;
  60. return *this;
  61. }
  62. JSONValue& JSONValue::operator =(const String& rhs)
  63. {
  64. SetType(JSON_STRING);
  65. *stringValue_ = rhs;
  66. return *this;
  67. }
  68. JSONValue& JSONValue::operator =(const char* rhs)
  69. {
  70. SetType(JSON_STRING);
  71. *stringValue_ = rhs;
  72. return *this;
  73. }
  74. JSONValue& JSONValue::operator =(const JSONArray& rhs)
  75. {
  76. SetType(JSON_ARRAY);
  77. *arrayValue_ = rhs;
  78. return *this;
  79. }
  80. JSONValue& JSONValue::operator =(const JSONObject& rhs)
  81. {
  82. SetType(JSON_OBJECT);
  83. *objectValue_ = rhs;
  84. return *this;
  85. }
  86. JSONValue& JSONValue::operator =(const JSONValue& rhs)
  87. {
  88. if (this == &rhs)
  89. return *this;
  90. SetType(rhs.GetValueType(), rhs.GetNumberType());
  91. switch (GetValueType())
  92. {
  93. case JSON_BOOL:
  94. boolValue_ = rhs.boolValue_;
  95. break;
  96. case JSON_NUMBER:
  97. numberValue_ = rhs.numberValue_;
  98. break;
  99. case JSON_STRING:
  100. *stringValue_ = *rhs.stringValue_;
  101. break;
  102. case JSON_ARRAY:
  103. *arrayValue_ = *rhs.arrayValue_;
  104. break;
  105. case JSON_OBJECT:
  106. *objectValue_ = *rhs.objectValue_;
  107. break;
  108. default:
  109. break;
  110. }
  111. return *this;
  112. }
  113. JSONValueType JSONValue::GetValueType() const
  114. {
  115. return (JSONValueType)(type_ >> 16u);
  116. }
  117. JSONNumberType JSONValue::GetNumberType() const
  118. {
  119. return (JSONNumberType)(type_ & 0xffffu);
  120. }
  121. String JSONValue::GetValueTypeName() const
  122. {
  123. return GetValueTypeName(GetValueType());
  124. }
  125. String JSONValue::GetNumberTypeName() const
  126. {
  127. return GetNumberTypeName(GetNumberType());
  128. }
  129. JSONValue& JSONValue::operator [](unsigned index)
  130. {
  131. // Convert to array type
  132. SetType(JSON_ARRAY);
  133. return (*arrayValue_)[index];
  134. }
  135. const JSONValue& JSONValue::operator [](unsigned index) const
  136. {
  137. if (GetValueType() != JSON_ARRAY)
  138. return EMPTY;
  139. return (*arrayValue_)[index];
  140. }
  141. void JSONValue::Push(const JSONValue& value)
  142. {
  143. // Convert to array type
  144. SetType(JSON_ARRAY);
  145. arrayValue_->Push(value);
  146. }
  147. void JSONValue::Pop()
  148. {
  149. if (GetValueType() != JSON_ARRAY)
  150. return;
  151. arrayValue_->Pop();
  152. }
  153. void JSONValue::Insert(unsigned pos, const JSONValue& value)
  154. {
  155. if (GetValueType() != JSON_ARRAY)
  156. return;
  157. arrayValue_->Insert(pos, value);
  158. }
  159. void JSONValue::Erase(unsigned pos, unsigned length)
  160. {
  161. if (GetValueType() != JSON_ARRAY)
  162. return;
  163. arrayValue_->Erase(pos, length);
  164. }
  165. void JSONValue::Resize(unsigned newSize)
  166. {
  167. // Convert to array type
  168. SetType(JSON_ARRAY);
  169. arrayValue_->Resize(newSize);
  170. }
  171. unsigned JSONValue::Size() const
  172. {
  173. if (GetValueType() == JSON_ARRAY)
  174. return arrayValue_->Size();
  175. else if (GetValueType() == JSON_OBJECT)
  176. return objectValue_->Size();
  177. return 0;
  178. }
  179. JSONValue& JSONValue::operator [](const String& key)
  180. {
  181. // Convert to object type
  182. SetType(JSON_OBJECT);
  183. return (*objectValue_)[key];
  184. }
  185. const JSONValue& JSONValue::operator [](const String& key) const
  186. {
  187. if (GetValueType() != JSON_OBJECT)
  188. return EMPTY;
  189. return (*objectValue_)[key];
  190. }
  191. void JSONValue::Set(const String& key, const JSONValue& value)
  192. {
  193. // Convert to object type
  194. SetType(JSON_OBJECT);
  195. (*objectValue_)[key] = value;
  196. }
  197. const JSONValue& JSONValue::Get(const String& key) const
  198. {
  199. if (GetValueType() != JSON_OBJECT)
  200. return EMPTY;
  201. JSONObject::ConstIterator i = objectValue_->Find(key);
  202. if (i == objectValue_->End())
  203. return EMPTY;
  204. return i->second_;
  205. }
  206. bool JSONValue::Erase(const String& key)
  207. {
  208. if (GetValueType() != JSON_OBJECT)
  209. return false;
  210. return objectValue_->Erase(key);
  211. }
  212. bool JSONValue::Contains(const String& key) const
  213. {
  214. if (GetValueType() != JSON_OBJECT)
  215. return false;
  216. return objectValue_->Contains(key);
  217. }
  218. JSONObjectIterator JSONValue::Begin()
  219. {
  220. // Convert to object type.
  221. SetType(JSON_OBJECT);
  222. return objectValue_->Begin();
  223. }
  224. ConstJSONObjectIterator JSONValue::Begin() const
  225. {
  226. if (GetValueType() != JSON_OBJECT)
  227. return emptyObject.Begin();
  228. return objectValue_->Begin();
  229. }
  230. JSONObjectIterator JSONValue::End()
  231. {
  232. // Convert to object type.
  233. SetType(JSON_OBJECT);
  234. return objectValue_->End();
  235. }
  236. ConstJSONObjectIterator JSONValue::End() const
  237. {
  238. if (GetValueType() != JSON_OBJECT)
  239. return emptyObject.End();
  240. return objectValue_->End();
  241. }
  242. void JSONValue::Clear()
  243. {
  244. if (GetValueType() == JSON_ARRAY)
  245. arrayValue_->Clear();
  246. else if (GetValueType() == JSON_OBJECT)
  247. objectValue_->Clear();
  248. }
  249. void JSONValue::SetType(JSONValueType valueType, JSONNumberType numberType)
  250. {
  251. int type = valueType << 16u | numberType;
  252. if (type == type_)
  253. return;
  254. switch (GetValueType())
  255. {
  256. case JSON_STRING:
  257. delete stringValue_;
  258. break;
  259. case JSON_ARRAY:
  260. delete arrayValue_;
  261. break;
  262. case JSON_OBJECT:
  263. delete objectValue_;
  264. break;
  265. default:
  266. break;
  267. }
  268. type_ = type;
  269. switch (GetValueType())
  270. {
  271. case JSON_STRING:
  272. stringValue_ = new String();
  273. break;
  274. case JSON_ARRAY:
  275. arrayValue_ = new JSONArray();
  276. break;
  277. case JSON_OBJECT:
  278. objectValue_ = new JSONObject();
  279. break;
  280. default:
  281. break;
  282. }
  283. }
  284. void JSONValue::SetVariant(const Variant& variant, Context* context)
  285. {
  286. if (!IsNull())
  287. {
  288. URHO3D_LOGWARNING("JsonValue is not null");
  289. }
  290. (*this)["type"] = variant.GetTypeName();
  291. (*this)["value"].SetVariantValue(variant, context);
  292. }
  293. Variant JSONValue::GetVariant() const
  294. {
  295. VariantType type = Variant::GetTypeFromName((*this)["type"].GetString());
  296. return (*this)["value"].GetVariantValue(type);
  297. }
  298. void JSONValue::SetVariantValue(const Variant& variant, Context* context)
  299. {
  300. if (!IsNull())
  301. {
  302. URHO3D_LOGWARNING("JsonValue is not null");
  303. }
  304. switch (variant.GetType())
  305. {
  306. case VAR_BOOL:
  307. *this = variant.GetBool();
  308. return;
  309. case VAR_INT:
  310. *this = variant.GetI32();
  311. return;
  312. case VAR_FLOAT:
  313. *this = variant.GetFloat();
  314. return;
  315. case VAR_DOUBLE:
  316. *this = variant.GetDouble();
  317. return;
  318. case VAR_STRING:
  319. *this = variant.GetString();
  320. return;
  321. case VAR_VARIANTVECTOR:
  322. SetVariantVector(variant.GetVariantVector(), context);
  323. return;
  324. case VAR_VARIANTMAP:
  325. SetVariantMap(variant.GetVariantMap(), context);
  326. return;
  327. case VAR_RESOURCEREF:
  328. {
  329. if (!context)
  330. {
  331. URHO3D_LOGERROR("Context must not be null for ResourceRef");
  332. return;
  333. }
  334. const ResourceRef& ref = variant.GetResourceRef();
  335. *this = String(context->GetTypeName(ref.type_)) + ";" + ref.name_;
  336. }
  337. return;
  338. case VAR_RESOURCEREFLIST:
  339. {
  340. if (!context)
  341. {
  342. URHO3D_LOGERROR("Context must not be null for ResourceRefList");
  343. return;
  344. }
  345. const ResourceRefList& refList = variant.GetResourceRefList();
  346. String str(context->GetTypeName(refList.type_));
  347. for (const String& name : refList.names_)
  348. {
  349. str += ";";
  350. str += name;
  351. }
  352. *this = str;
  353. }
  354. return;
  355. case VAR_STRINGVECTOR:
  356. {
  357. const StringVector& vector = variant.GetStringVector();
  358. Resize(vector.Size());
  359. for (i32 i = 0; i < vector.Size(); ++i)
  360. (*this)[i] = vector[i];
  361. }
  362. return;
  363. default:
  364. *this = variant.ToString();
  365. }
  366. }
  367. Variant JSONValue::GetVariantValue(VariantType type) const
  368. {
  369. Variant variant;
  370. switch (type)
  371. {
  372. case VAR_BOOL:
  373. variant = GetBool();
  374. break;
  375. case VAR_INT:
  376. variant = GetI32();
  377. break;
  378. case VAR_FLOAT:
  379. variant = GetFloat();
  380. break;
  381. case VAR_DOUBLE:
  382. variant = GetDouble();
  383. break;
  384. case VAR_STRING:
  385. variant = GetString();
  386. break;
  387. case VAR_VARIANTVECTOR:
  388. variant = GetVariantVector();
  389. break;
  390. case VAR_VARIANTMAP:
  391. variant = GetVariantMap();
  392. break;
  393. case VAR_RESOURCEREF:
  394. {
  395. ResourceRef ref;
  396. Vector<String> values = GetString().Split(';');
  397. if (values.Size() == 2)
  398. {
  399. ref.type_ = values[0];
  400. ref.name_ = values[1];
  401. }
  402. variant = ref;
  403. }
  404. break;
  405. case VAR_RESOURCEREFLIST:
  406. {
  407. ResourceRefList refList;
  408. Vector<String> values = GetString().Split(';', true);
  409. if (values.Size() >= 1)
  410. {
  411. refList.type_ = values[0];
  412. refList.names_.Resize(values.Size() - 1);
  413. for (i32 i = 1; i < values.Size(); ++i)
  414. refList.names_[i - 1] = values[i];
  415. }
  416. variant = refList;
  417. }
  418. break;
  419. case VAR_STRINGVECTOR:
  420. {
  421. StringVector vector;
  422. for (unsigned i = 0; i < Size(); ++i)
  423. vector.Push((*this)[i].GetString());
  424. variant = vector;
  425. }
  426. break;
  427. default:
  428. variant.FromString(type, GetString());
  429. }
  430. return variant;
  431. }
  432. void JSONValue::SetVariantMap(const VariantMap& variantMap, Context* context)
  433. {
  434. SetType(JSON_OBJECT);
  435. for (VariantMap::ConstIterator i = variantMap.Begin(); i != variantMap.End(); ++i)
  436. (*this)[i->first_.ToString()].SetVariant(i->second_);
  437. }
  438. VariantMap JSONValue::GetVariantMap() const
  439. {
  440. VariantMap variantMap;
  441. if (!IsObject())
  442. {
  443. URHO3D_LOGERROR("JSONValue is not a object");
  444. return variantMap;
  445. }
  446. for (ConstJSONObjectIterator i = Begin(); i != End(); ++i)
  447. {
  448. /// \todo Ideally this should allow any strings, but for now the convention is that the keys need to be hexadecimal StringHashes
  449. StringHash key(ToU32(i->first_, 16));
  450. Variant variant = i->second_.GetVariant();
  451. variantMap[key] = variant;
  452. }
  453. return variantMap;
  454. }
  455. void JSONValue::SetVariantVector(const VariantVector& variantVector, Context* context)
  456. {
  457. SetType(JSON_ARRAY);
  458. arrayValue_->Reserve(variantVector.Size());
  459. for (const Variant& var : variantVector)
  460. {
  461. JSONValue val;
  462. val.SetVariant(var, context);
  463. arrayValue_->Push(val);
  464. }
  465. }
  466. VariantVector JSONValue::GetVariantVector() const
  467. {
  468. VariantVector variantVector;
  469. if (!IsArray())
  470. {
  471. URHO3D_LOGERROR("JSONValue is not a array");
  472. return variantVector;
  473. }
  474. for (unsigned i = 0; i < Size(); ++i)
  475. {
  476. Variant variant = (*this)[i].GetVariant();
  477. variantVector.Push(variant);
  478. }
  479. return variantVector;
  480. }
  481. String JSONValue::GetValueTypeName(JSONValueType type)
  482. {
  483. return valueTypeNames[type];
  484. }
  485. String JSONValue::GetNumberTypeName(JSONNumberType type)
  486. {
  487. return numberTypeNames[type];
  488. }
  489. JSONValueType JSONValue::GetValueTypeFromName(const String& typeName)
  490. {
  491. return GetValueTypeFromName(typeName.CString());
  492. }
  493. JSONValueType JSONValue::GetValueTypeFromName(const char* typeName)
  494. {
  495. return (JSONValueType)GetStringListIndex(typeName, valueTypeNames, JSON_NULL);
  496. }
  497. JSONNumberType JSONValue::GetNumberTypeFromName(const String& typeName)
  498. {
  499. return GetNumberTypeFromName(typeName.CString());
  500. }
  501. JSONNumberType JSONValue::GetNumberTypeFromName(const char* typeName)
  502. {
  503. return (JSONNumberType)GetStringListIndex(typeName, numberTypeNames, JSONNT_NAN);
  504. }
  505. }