PListFile.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../Precompiled.h"
  4. #include "../Core/Context.h"
  5. #include "../IO/Deserializer.h"
  6. #include "../IO/Log.h"
  7. #include "../Resource/PListFile.h"
  8. #include "../Resource/XMLFile.h"
  9. #include <cstdio>
  10. #include "../DebugNew.h"
  11. namespace Urho3D
  12. {
  13. static PListValue EMPTY_VALUE;
  14. static PListValueMap EMPTY_VALUEMAP;
  15. static PListValueVector EMPTY_VALUEVECTOR;
  16. PListValue::PListValue() : // NOLINT(hicpp-member-init)
  17. type_(PLVT_NONE)
  18. {
  19. }
  20. PListValue::PListValue(i32 value) : // NOLINT(hicpp-member-init)
  21. type_(PLVT_NONE)
  22. {
  23. SetI32(value);
  24. }
  25. PListValue::PListValue(bool value) : // NOLINT(hicpp-member-init)
  26. type_(PLVT_NONE)
  27. {
  28. SetBool(value);
  29. }
  30. PListValue::PListValue(float value) : // NOLINT(hicpp-member-init)
  31. type_(PLVT_NONE)
  32. {
  33. SetFloat(value);
  34. }
  35. PListValue::PListValue(const String& value) : // NOLINT(hicpp-member-init)
  36. type_(PLVT_NONE)
  37. {
  38. SetString(value);
  39. }
  40. PListValue::PListValue(PListValueMap& valueMap) : // NOLINT(hicpp-member-init)
  41. type_(PLVT_NONE)
  42. {
  43. SetValueMap(valueMap);
  44. }
  45. PListValue::PListValue(PListValueVector& valueVector) : // NOLINT(hicpp-member-init)
  46. type_(PLVT_NONE)
  47. {
  48. SetValueVector(valueVector);
  49. }
  50. PListValue::PListValue(const PListValue& value) : // NOLINT(hicpp-member-init)
  51. type_(PLVT_NONE)
  52. {
  53. *this = value;
  54. }
  55. PListValue::~PListValue()
  56. {
  57. Reset();
  58. }
  59. PListValue& PListValue::operator =(const PListValue& rhs)
  60. {
  61. switch (rhs.type_)
  62. {
  63. case PLVT_NONE:
  64. Reset();
  65. break;
  66. case PLVT_INT:
  67. SetI32(rhs.int_);
  68. break;
  69. case PLVT_BOOL:
  70. SetBool(rhs.bool_);
  71. break;
  72. case PLVT_FLOAT:
  73. SetFloat(rhs.float_);
  74. break;
  75. case PLVT_STRING:
  76. SetString(*rhs.string_);
  77. break;
  78. case PLVT_VALUEMAP:
  79. SetValueMap(*rhs.valueMap_);
  80. break;
  81. case PLVT_VALUEVECTOR:
  82. SetValueVector(*rhs.valueVector_);
  83. break;
  84. }
  85. return *this;
  86. }
  87. void PListValue::SetI32(i32 value)
  88. {
  89. if (type_ != PLVT_INT)
  90. {
  91. Reset();
  92. type_ = PLVT_INT;
  93. }
  94. int_ = value;
  95. }
  96. void PListValue::SetBool(bool value)
  97. {
  98. if (type_ != PLVT_BOOL)
  99. {
  100. Reset();
  101. type_ = PLVT_BOOL;
  102. }
  103. bool_ = value;
  104. }
  105. void PListValue::SetFloat(float value)
  106. {
  107. if (type_ != PLVT_FLOAT)
  108. {
  109. Reset();
  110. type_ = PLVT_FLOAT;
  111. }
  112. float_ = value;
  113. }
  114. void PListValue::SetString(const String& value)
  115. {
  116. if (type_ != PLVT_STRING)
  117. {
  118. Reset();
  119. type_ = PLVT_STRING;
  120. string_ = new String();
  121. }
  122. *string_ = value;
  123. }
  124. void PListValue::SetValueMap(const PListValueMap& valueMap)
  125. {
  126. if (type_ != PLVT_VALUEMAP)
  127. {
  128. Reset();
  129. type_ = PLVT_VALUEMAP;
  130. valueMap_ = new PListValueMap();
  131. }
  132. *valueMap_ = valueMap;
  133. }
  134. void PListValue::SetValueVector(const PListValueVector& valueVector)
  135. {
  136. if (type_ != PLVT_VALUEVECTOR)
  137. {
  138. Reset();
  139. type_ = PLVT_VALUEVECTOR;
  140. valueVector_ = new PListValueVector();
  141. }
  142. *valueVector_ = valueVector;
  143. }
  144. i32 PListValue::GetI32() const
  145. {
  146. return type_ == PLVT_INT ? int_ : 0;
  147. }
  148. bool PListValue::GetBool() const
  149. {
  150. return type_ == PLVT_BOOL ? bool_ : false;
  151. }
  152. float PListValue::GetFloat() const
  153. {
  154. return type_ == PLVT_FLOAT ? float_ : 0.0f;
  155. }
  156. const String& PListValue::GetString() const
  157. {
  158. return type_ == PLVT_STRING ? *string_ : String::EMPTY;
  159. }
  160. IntRect PListValue::GetIntRect() const
  161. {
  162. if (type_ != PLVT_STRING)
  163. return IntRect::ZERO;
  164. int x, y, w, h;
  165. sscanf(string_->CString(), "{{%d,%d},{%d,%d}}", &x, &y, &w, &h); // NOLINT(cert-err34-c)
  166. return {x, y, x + w, y + h};
  167. }
  168. IntVector2 PListValue::GetIntVector2() const
  169. {
  170. if (type_ != PLVT_STRING)
  171. return IntVector2::ZERO;
  172. int x, y;
  173. sscanf(string_->CString(), "{%d,%d}", &x, &y); // NOLINT(cert-err34-c)
  174. return IntVector2(x, y);
  175. }
  176. IntVector3 PListValue::GetIntVector3() const
  177. {
  178. if (type_ != PLVT_STRING)
  179. return IntVector3::ZERO;
  180. int x, y, z;
  181. sscanf(string_->CString(), "{%d,%d,%d}", &x, &y, &z); // NOLINT(cert-err34-c)
  182. return IntVector3(x, y, z);
  183. }
  184. const PListValueMap& PListValue::GetValueMap() const
  185. {
  186. return type_ == PLVT_VALUEMAP ? *valueMap_ : EMPTY_VALUEMAP;
  187. }
  188. const PListValueVector& PListValue::GetValueVector() const
  189. {
  190. return type_ == PLVT_VALUEVECTOR ? *valueVector_ : EMPTY_VALUEVECTOR;
  191. }
  192. PListValueMap& PListValue::ConvertToValueMap()
  193. {
  194. if (type_ != PLVT_VALUEMAP)
  195. {
  196. Reset();
  197. type_ = PLVT_VALUEMAP;
  198. valueMap_ = new PListValueMap();
  199. }
  200. return *valueMap_;
  201. }
  202. PListValueVector& PListValue::ConvertToValueVector()
  203. {
  204. if (type_ != PLVT_VALUEVECTOR)
  205. {
  206. Reset();
  207. type_ = PLVT_VALUEVECTOR;
  208. valueVector_ = new PListValueVector();
  209. }
  210. return *valueVector_;
  211. }
  212. void PListValue::Reset()
  213. {
  214. if (type_ == PLVT_NONE)
  215. return;
  216. switch (type_)
  217. {
  218. case PLVT_STRING:
  219. delete string_;
  220. break;
  221. case PLVT_VALUEMAP:
  222. delete valueMap_;
  223. break;
  224. case PLVT_VALUEVECTOR:
  225. delete valueVector_;
  226. break;
  227. default:
  228. break;
  229. }
  230. type_ = PLVT_NONE;
  231. }
  232. PListFile::PListFile(Context* context) :
  233. Resource(context)
  234. {
  235. }
  236. PListFile::~PListFile() = default;
  237. void PListFile::RegisterObject(Context* context)
  238. {
  239. context->RegisterFactory<PListFile>();
  240. }
  241. bool PListFile::BeginLoad(Deserializer& source)
  242. {
  243. if (GetName().Empty())
  244. SetName(source.GetName());
  245. XMLFile xmlFile(context_);
  246. if (!xmlFile.Load(source))
  247. {
  248. URHO3D_LOGERROR("Could not load property list");
  249. return false;
  250. }
  251. XMLElement plistElem = xmlFile.GetRoot("plist");
  252. if (!plistElem)
  253. {
  254. URHO3D_LOGERROR("Invalid property list file");
  255. return false;
  256. }
  257. root_.Clear();
  258. XMLElement dictElem = plistElem.GetChild("dict");
  259. if (!LoadDict(root_, dictElem))
  260. return false;
  261. SetMemoryUse(source.GetSize());
  262. return true;
  263. }
  264. bool PListFile::LoadDict(PListValueMap& dict, const XMLElement& dictElem)
  265. {
  266. if (!dictElem)
  267. return false;
  268. XMLElement keyElem = dictElem.GetChild("key");
  269. XMLElement valueElem = keyElem.GetNext();
  270. while (keyElem && valueElem)
  271. {
  272. String key = keyElem.GetValue();
  273. valueElem = keyElem.GetNext();
  274. PListValue value;
  275. if (!LoadValue(value, valueElem))
  276. return false;
  277. dict[key] = value;
  278. keyElem = valueElem.GetNext("key");
  279. valueElem = keyElem.GetNext();
  280. }
  281. return true;
  282. }
  283. bool PListFile::LoadArray(PListValueVector& array, const XMLElement& arrayElem)
  284. {
  285. if (!arrayElem)
  286. return false;
  287. for (XMLElement valueElem = arrayElem.GetChild(); valueElem; valueElem = valueElem.GetNext())
  288. {
  289. PListValue value;
  290. if (!LoadValue(value, valueElem))
  291. return false;
  292. array.Push(value);
  293. }
  294. return true;
  295. }
  296. bool PListFile::LoadValue(PListValue& value, const XMLElement& valueElem)
  297. {
  298. String valueType = valueElem.GetName();
  299. if (valueType == "string")
  300. value.SetString(valueElem.GetValue());
  301. else if (valueType == "real")
  302. value.SetFloat(ToFloat(valueElem.GetValue()));
  303. else if (valueType == "integer")
  304. value.SetI32(ToI32(valueElem.GetValue()));
  305. else if (valueType == "true")
  306. value.SetBool(true);
  307. else if (valueType == "false")
  308. value.SetBool(false);
  309. else if (valueType == "dict")
  310. {
  311. if (!LoadDict(value.ConvertToValueMap(), valueElem))
  312. return false;
  313. }
  314. else if (valueType == "array")
  315. {
  316. if (!LoadArray(value.ConvertToValueVector(), valueElem))
  317. return false;
  318. }
  319. else
  320. {
  321. URHO3D_LOGERROR("Supported value type");
  322. return false;
  323. }
  324. return true;
  325. }
  326. }