PListFile.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Precompiled.h"
  23. #include "../Core/Context.h"
  24. #include "../IO/Deserializer.h"
  25. #include "../IO/Log.h"
  26. #include "../Resource/PListFile.h"
  27. #include "../Resource/XMLFile.h"
  28. #include <cstdio>
  29. #include "../DebugNew.h"
  30. namespace Urho3D
  31. {
  32. static PListValue EMPTY_VALUE;
  33. static PListValueMap EMPTY_VALUEMAP;
  34. static PListValueVector EMPTY_VALUEVECTOR;
  35. PListValue::PListValue() : // NOLINT(hicpp-member-init)
  36. type_(PLVT_NONE)
  37. {
  38. }
  39. PListValue::PListValue(int value) : // NOLINT(hicpp-member-init)
  40. type_(PLVT_NONE)
  41. {
  42. SetInt(value);
  43. }
  44. PListValue::PListValue(bool value) : // NOLINT(hicpp-member-init)
  45. type_(PLVT_NONE)
  46. {
  47. SetBool(value);
  48. }
  49. PListValue::PListValue(float value) : // NOLINT(hicpp-member-init)
  50. type_(PLVT_NONE)
  51. {
  52. SetFloat(value);
  53. }
  54. PListValue::PListValue(const String& value) : // NOLINT(hicpp-member-init)
  55. type_(PLVT_NONE)
  56. {
  57. SetString(value);
  58. }
  59. PListValue::PListValue(PListValueMap& valueMap) : // NOLINT(hicpp-member-init)
  60. type_(PLVT_NONE)
  61. {
  62. SetValueMap(valueMap);
  63. }
  64. PListValue::PListValue(PListValueVector& valueVector) : // NOLINT(hicpp-member-init)
  65. type_(PLVT_NONE)
  66. {
  67. SetValueVector(valueVector);
  68. }
  69. PListValue::PListValue(const PListValue& value) : // NOLINT(hicpp-member-init)
  70. type_(PLVT_NONE)
  71. {
  72. *this = value;
  73. }
  74. PListValue::~PListValue()
  75. {
  76. Reset();
  77. }
  78. PListValue& PListValue::operator =(const PListValue& rhs)
  79. {
  80. switch (rhs.type_)
  81. {
  82. case PLVT_NONE:
  83. Reset();
  84. break;
  85. case PLVT_INT:
  86. SetInt(rhs.int_);
  87. break;
  88. case PLVT_BOOL:
  89. SetBool(rhs.bool_);
  90. break;
  91. case PLVT_FLOAT:
  92. SetFloat(rhs.float_);
  93. break;
  94. case PLVT_STRING:
  95. SetString(*rhs.string_);
  96. break;
  97. case PLVT_VALUEMAP:
  98. SetValueMap(*rhs.valueMap_);
  99. break;
  100. case PLVT_VALUEVECTOR:
  101. SetValueVector(*rhs.valueVector_);
  102. break;
  103. }
  104. return *this;
  105. }
  106. void PListValue::SetInt(int value)
  107. {
  108. if (type_ != PLVT_INT)
  109. {
  110. Reset();
  111. type_ = PLVT_INT;
  112. }
  113. int_ = value;
  114. }
  115. void PListValue::SetBool(bool value)
  116. {
  117. if (type_ != PLVT_BOOL)
  118. {
  119. Reset();
  120. type_ = PLVT_BOOL;
  121. }
  122. bool_ = value;
  123. }
  124. void PListValue::SetFloat(float value)
  125. {
  126. if (type_ != PLVT_FLOAT)
  127. {
  128. Reset();
  129. type_ = PLVT_FLOAT;
  130. }
  131. float_ = value;
  132. }
  133. void PListValue::SetString(const String& value)
  134. {
  135. if (type_ != PLVT_STRING)
  136. {
  137. Reset();
  138. type_ = PLVT_STRING;
  139. string_ = new String();
  140. }
  141. *string_ = value;
  142. }
  143. void PListValue::SetValueMap(const PListValueMap& valueMap)
  144. {
  145. if (type_ != PLVT_VALUEMAP)
  146. {
  147. Reset();
  148. type_ = PLVT_VALUEMAP;
  149. valueMap_ = new PListValueMap();
  150. }
  151. *valueMap_ = valueMap;
  152. }
  153. void PListValue::SetValueVector(const PListValueVector& valueVector)
  154. {
  155. if (type_ != PLVT_VALUEVECTOR)
  156. {
  157. Reset();
  158. type_ = PLVT_VALUEVECTOR;
  159. valueVector_ = new PListValueVector();
  160. }
  161. *valueVector_ = valueVector;
  162. }
  163. int PListValue::GetInt() const
  164. {
  165. return type_ == PLVT_INT ? int_ : 0;
  166. }
  167. bool PListValue::GetBool() const
  168. {
  169. return type_ == PLVT_BOOL ? bool_ : false;
  170. }
  171. float PListValue::GetFloat() const
  172. {
  173. return type_ == PLVT_FLOAT ? float_ : 0.0f;
  174. }
  175. const String& PListValue::GetString() const
  176. {
  177. return type_ == PLVT_STRING ? *string_ : String::EMPTY;
  178. }
  179. IntRect PListValue::GetIntRect() const
  180. {
  181. if (type_ != PLVT_STRING)
  182. return IntRect::ZERO;
  183. int x, y, w, h;
  184. sscanf(string_->CString(), "{{%d,%d},{%d,%d}}", &x, &y, &w, &h); // NOLINT(cert-err34-c)
  185. return {x, y, x + w, y + h};
  186. }
  187. IntVector2 PListValue::GetIntVector2() const
  188. {
  189. if (type_ != PLVT_STRING)
  190. return IntVector2::ZERO;
  191. int x, y;
  192. sscanf(string_->CString(), "{%d,%d}", &x, &y); // NOLINT(cert-err34-c)
  193. return IntVector2(x, y);
  194. }
  195. IntVector3 PListValue::GetIntVector3() const
  196. {
  197. if (type_ != PLVT_STRING)
  198. return IntVector3::ZERO;
  199. int x, y, z;
  200. sscanf(string_->CString(), "{%d,%d,%d}", &x, &y, &z); // NOLINT(cert-err34-c)
  201. return IntVector3(x, y, z);
  202. }
  203. const PListValueMap& PListValue::GetValueMap() const
  204. {
  205. return type_ == PLVT_VALUEMAP ? *valueMap_ : EMPTY_VALUEMAP;
  206. }
  207. const PListValueVector& PListValue::GetValueVector() const
  208. {
  209. return type_ == PLVT_VALUEVECTOR ? *valueVector_ : EMPTY_VALUEVECTOR;
  210. }
  211. PListValueMap& PListValue::ConvertToValueMap()
  212. {
  213. if (type_ != PLVT_VALUEMAP)
  214. {
  215. Reset();
  216. type_ = PLVT_VALUEMAP;
  217. valueMap_ = new PListValueMap();
  218. }
  219. return *valueMap_;
  220. }
  221. PListValueVector& PListValue::ConvertToValueVector()
  222. {
  223. if (type_ != PLVT_VALUEVECTOR)
  224. {
  225. Reset();
  226. type_ = PLVT_VALUEVECTOR;
  227. valueVector_ = new PListValueVector();
  228. }
  229. return *valueVector_;
  230. }
  231. void PListValue::Reset()
  232. {
  233. if (type_ == PLVT_NONE)
  234. return;
  235. switch (type_)
  236. {
  237. case PLVT_STRING:
  238. delete string_;
  239. break;
  240. case PLVT_VALUEMAP:
  241. delete valueMap_;
  242. break;
  243. case PLVT_VALUEVECTOR:
  244. delete valueVector_;
  245. break;
  246. default:
  247. break;
  248. }
  249. type_ = PLVT_NONE;
  250. }
  251. PListFile::PListFile(Context* context) :
  252. Resource(context)
  253. {
  254. }
  255. PListFile::~PListFile() = default;
  256. void PListFile::RegisterObject(Context* context)
  257. {
  258. context->RegisterFactory<PListFile>();
  259. }
  260. bool PListFile::BeginLoad(Deserializer& source)
  261. {
  262. if (GetName().Empty())
  263. SetName(source.GetName());
  264. XMLFile xmlFile(context_);
  265. if (!xmlFile.Load(source))
  266. {
  267. URHO3D_LOGERROR("Could not load property list");
  268. return false;
  269. }
  270. XMLElement plistElem = xmlFile.GetRoot("plist");
  271. if (!plistElem)
  272. {
  273. URHO3D_LOGERROR("Invalid property list file");
  274. return false;
  275. }
  276. root_.Clear();
  277. XMLElement dictElem = plistElem.GetChild("dict");
  278. if (!LoadDict(root_, dictElem))
  279. return false;
  280. SetMemoryUse(source.GetSize());
  281. return true;
  282. }
  283. bool PListFile::LoadDict(PListValueMap& dict, const XMLElement& dictElem)
  284. {
  285. if (!dictElem)
  286. return false;
  287. XMLElement keyElem = dictElem.GetChild("key");
  288. XMLElement valueElem = keyElem.GetNext();
  289. while (keyElem && valueElem)
  290. {
  291. String key = keyElem.GetValue();
  292. valueElem = keyElem.GetNext();
  293. PListValue value;
  294. if (!LoadValue(value, valueElem))
  295. return false;
  296. dict[key] = value;
  297. keyElem = valueElem.GetNext("key");
  298. valueElem = keyElem.GetNext();
  299. }
  300. return true;
  301. }
  302. bool PListFile::LoadArray(PListValueVector& array, const XMLElement& arrayElem)
  303. {
  304. if (!arrayElem)
  305. return false;
  306. for (XMLElement valueElem = arrayElem.GetChild(); valueElem; valueElem = valueElem.GetNext())
  307. {
  308. PListValue value;
  309. if (!LoadValue(value, valueElem))
  310. return false;
  311. array.Push(value);
  312. }
  313. return true;
  314. }
  315. bool PListFile::LoadValue(PListValue& value, const XMLElement& valueElem)
  316. {
  317. String valueType = valueElem.GetName();
  318. if (valueType == "string")
  319. value.SetString(valueElem.GetValue());
  320. else if (valueType == "real")
  321. value.SetFloat(ToFloat(valueElem.GetValue()));
  322. else if (valueType == "integer")
  323. value.SetInt(ToInt(valueElem.GetValue()));
  324. else if (valueType == "true")
  325. value.SetBool(true);
  326. else if (valueType == "false")
  327. value.SetBool(false);
  328. else if (valueType == "dict")
  329. {
  330. if (!LoadDict(value.ConvertToValueMap(), valueElem))
  331. return false;
  332. }
  333. else if (valueType == "array")
  334. {
  335. if (!LoadArray(value.ConvertToValueVector(), valueElem))
  336. return false;
  337. }
  338. else
  339. {
  340. URHO3D_LOGERROR("Supported value type");
  341. return false;
  342. }
  343. return true;
  344. }
  345. }