PListFile.cpp 8.5 KB

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