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