1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9 #include "Variant.h"
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include <utility>
14
15 #ifndef strtoll
16 #ifdef TARGET_WINDOWS
17 #define strtoll _strtoi64
18 #define strtoull _strtoui64
19 #define wcstoll _wcstoi64
20 #define wcstoull _wcstoui64
21 #else // TARGET_WINDOWS
22 #if !defined(TARGET_DARWIN)
23 #define strtoll(str, endptr, base) (int64_t)strtod(str, endptr)
24 #define strtoull(str, endptr, base) (uint64_t)strtod(str, endptr)
25 #define wcstoll(str, endptr, base) (int64_t)wcstod(str, endptr)
26 #define wcstoull(str, endptr, base) (uint64_t)wcstod(str, endptr)
27 #endif
28 #endif // TARGET_WINDOWS
29 #endif // strtoll
30
trimRight(const std::string & str)31 std::string trimRight(const std::string &str)
32 {
33 std::string tmp = str;
34 // find_last_not_of will return string::npos (which is defined as -1)
35 // or a value between 0 and size() - 1 => find_last_not_of() + 1 will
36 // always result in a valid index between 0 and size()
37 tmp.erase(tmp.find_last_not_of(" \n\r\t") + 1);
38
39 return tmp;
40 }
41
trimRight(const std::wstring & str)42 std::wstring trimRight(const std::wstring &str)
43 {
44 std::wstring tmp = str;
45 // find_last_not_of will return string::npos (which is defined as -1)
46 // or a value between 0 and size() - 1 => find_last_not_of() + 1 will
47 // always result in a valid index between 0 and size()
48 tmp.erase(tmp.find_last_not_of(L" \n\r\t") + 1);
49
50 return tmp;
51 }
52
str2int64(const std::string & str,int64_t fallback)53 int64_t str2int64(const std::string &str, int64_t fallback /* = 0 */)
54 {
55 char *end = NULL;
56 std::string tmp = trimRight(str);
57 int64_t result = strtoll(tmp.c_str(), &end, 0);
58 if (end == NULL || *end == '\0')
59 return result;
60
61 return fallback;
62 }
63
str2int64(const std::wstring & str,int64_t fallback)64 int64_t str2int64(const std::wstring &str, int64_t fallback /* = 0 */)
65 {
66 wchar_t *end = NULL;
67 std::wstring tmp = trimRight(str);
68 int64_t result = wcstoll(tmp.c_str(), &end, 0);
69 if (end == NULL || *end == '\0')
70 return result;
71
72 return fallback;
73 }
74
str2uint64(const std::string & str,uint64_t fallback)75 uint64_t str2uint64(const std::string &str, uint64_t fallback /* = 0 */)
76 {
77 char *end = NULL;
78 std::string tmp = trimRight(str);
79 uint64_t result = strtoull(tmp.c_str(), &end, 0);
80 if (end == NULL || *end == '\0')
81 return result;
82
83 return fallback;
84 }
85
str2uint64(const std::wstring & str,uint64_t fallback)86 uint64_t str2uint64(const std::wstring &str, uint64_t fallback /* = 0 */)
87 {
88 wchar_t *end = NULL;
89 std::wstring tmp = trimRight(str);
90 uint64_t result = wcstoull(tmp.c_str(), &end, 0);
91 if (end == NULL || *end == '\0')
92 return result;
93
94 return fallback;
95 }
96
str2double(const std::string & str,double fallback)97 double str2double(const std::string &str, double fallback /* = 0.0 */)
98 {
99 char *end = NULL;
100 std::string tmp = trimRight(str);
101 double result = strtod(tmp.c_str(), &end);
102 if (end == NULL || *end == '\0')
103 return result;
104
105 return fallback;
106 }
107
str2double(const std::wstring & str,double fallback)108 double str2double(const std::wstring &str, double fallback /* = 0.0 */)
109 {
110 wchar_t *end = NULL;
111 std::wstring tmp = trimRight(str);
112 double result = wcstod(tmp.c_str(), &end);
113 if (end == NULL || *end == '\0')
114 return result;
115
116 return fallback;
117 }
118
CVariant()119 CVariant::CVariant()
120 : CVariant(VariantTypeNull)
121 {
122 }
123
124 CVariant CVariant::ConstNullVariant = CVariant::VariantTypeConstNull;
125 CVariant::VariantArray CVariant::EMPTY_ARRAY;
126 CVariant::VariantMap CVariant::EMPTY_MAP;
127
CVariant(VariantType type)128 CVariant::CVariant(VariantType type)
129 {
130 m_type = type;
131
132 switch (type)
133 {
134 case VariantTypeInteger:
135 m_data.integer = 0;
136 break;
137 case VariantTypeUnsignedInteger:
138 m_data.unsignedinteger = 0;
139 break;
140 case VariantTypeBoolean:
141 m_data.boolean = false;
142 break;
143 case VariantTypeDouble:
144 m_data.dvalue = 0.0;
145 break;
146 case VariantTypeString:
147 m_data.string = new std::string();
148 break;
149 case VariantTypeWideString:
150 m_data.wstring = new std::wstring();
151 break;
152 case VariantTypeArray:
153 m_data.array = new VariantArray();
154 break;
155 case VariantTypeObject:
156 m_data.map = new VariantMap();
157 break;
158 default:
159 #ifndef TARGET_WINDOWS_STORE // this corrupts the heap in Win10 UWP version
160 memset(&m_data, 0, sizeof(m_data));
161 #endif
162 break;
163 }
164 }
165
CVariant(int integer)166 CVariant::CVariant(int integer)
167 {
168 m_type = VariantTypeInteger;
169 m_data.integer = integer;
170 }
171
CVariant(int64_t integer)172 CVariant::CVariant(int64_t integer)
173 {
174 m_type = VariantTypeInteger;
175 m_data.integer = integer;
176 }
177
CVariant(unsigned int unsignedinteger)178 CVariant::CVariant(unsigned int unsignedinteger)
179 {
180 m_type = VariantTypeUnsignedInteger;
181 m_data.unsignedinteger = unsignedinteger;
182 }
183
CVariant(uint64_t unsignedinteger)184 CVariant::CVariant(uint64_t unsignedinteger)
185 {
186 m_type = VariantTypeUnsignedInteger;
187 m_data.unsignedinteger = unsignedinteger;
188 }
189
CVariant(double value)190 CVariant::CVariant(double value)
191 {
192 m_type = VariantTypeDouble;
193 m_data.dvalue = value;
194 }
195
CVariant(float value)196 CVariant::CVariant(float value)
197 {
198 m_type = VariantTypeDouble;
199 m_data.dvalue = (double)value;
200 }
201
CVariant(bool boolean)202 CVariant::CVariant(bool boolean)
203 {
204 m_type = VariantTypeBoolean;
205 m_data.boolean = boolean;
206 }
207
CVariant(const char * str)208 CVariant::CVariant(const char *str)
209 {
210 m_type = VariantTypeString;
211 m_data.string = new std::string(str);
212 }
213
CVariant(const char * str,unsigned int length)214 CVariant::CVariant(const char *str, unsigned int length)
215 {
216 m_type = VariantTypeString;
217 m_data.string = new std::string(str, length);
218 }
219
CVariant(const std::string & str)220 CVariant::CVariant(const std::string &str)
221 {
222 m_type = VariantTypeString;
223 m_data.string = new std::string(str);
224 }
225
CVariant(std::string && str)226 CVariant::CVariant(std::string &&str)
227 {
228 m_type = VariantTypeString;
229 m_data.string = new std::string(std::move(str));
230 }
231
CVariant(const wchar_t * str)232 CVariant::CVariant(const wchar_t *str)
233 {
234 m_type = VariantTypeWideString;
235 m_data.wstring = new std::wstring(str);
236 }
237
CVariant(const wchar_t * str,unsigned int length)238 CVariant::CVariant(const wchar_t *str, unsigned int length)
239 {
240 m_type = VariantTypeWideString;
241 m_data.wstring = new std::wstring(str, length);
242 }
243
CVariant(const std::wstring & str)244 CVariant::CVariant(const std::wstring &str)
245 {
246 m_type = VariantTypeWideString;
247 m_data.wstring = new std::wstring(str);
248 }
249
CVariant(std::wstring && str)250 CVariant::CVariant(std::wstring &&str)
251 {
252 m_type = VariantTypeWideString;
253 m_data.wstring = new std::wstring(std::move(str));
254 }
255
CVariant(const std::vector<std::string> & strArray)256 CVariant::CVariant(const std::vector<std::string> &strArray)
257 {
258 m_type = VariantTypeArray;
259 m_data.array = new VariantArray;
260 m_data.array->reserve(strArray.size());
261 for (const auto& item : strArray)
262 m_data.array->push_back(CVariant(item));
263 }
264
CVariant(const std::map<std::string,std::string> & strMap)265 CVariant::CVariant(const std::map<std::string, std::string> &strMap)
266 {
267 m_type = VariantTypeObject;
268 m_data.map = new VariantMap;
269 for (std::map<std::string, std::string>::const_iterator it = strMap.begin(); it != strMap.end(); ++it)
270 m_data.map->insert(make_pair(it->first, CVariant(it->second)));
271 }
272
CVariant(const std::map<std::string,CVariant> & variantMap)273 CVariant::CVariant(const std::map<std::string, CVariant> &variantMap)
274 {
275 m_type = VariantTypeObject;
276 m_data.map = new VariantMap(variantMap.begin(), variantMap.end());
277 }
278
CVariant(const CVariant & variant)279 CVariant::CVariant(const CVariant &variant)
280 {
281 m_type = VariantTypeNull;
282 *this = variant;
283 }
284
CVariant(CVariant && rhs)285 CVariant::CVariant(CVariant&& rhs) noexcept
286 {
287 //Set this so that operator= don't try and run cleanup
288 //when we're not initialized.
289 m_type = VariantTypeNull;
290
291 *this = std::move(rhs);
292 }
293
~CVariant()294 CVariant::~CVariant()
295 {
296 cleanup();
297 }
298
cleanup()299 void CVariant::cleanup()
300 {
301 switch (m_type)
302 {
303 case VariantTypeString:
304 delete m_data.string;
305 m_data.string = nullptr;
306 break;
307
308 case VariantTypeWideString:
309 delete m_data.wstring;
310 m_data.wstring = nullptr;
311 break;
312
313 case VariantTypeArray:
314 delete m_data.array;
315 m_data.array = nullptr;
316 break;
317
318 case VariantTypeObject:
319 delete m_data.map;
320 m_data.map = nullptr;
321 break;
322 default:
323 break;
324 }
325 m_type = VariantTypeNull;
326 }
327
isInteger() const328 bool CVariant::isInteger() const
329 {
330 return isSignedInteger() || isUnsignedInteger();
331 }
332
isSignedInteger() const333 bool CVariant::isSignedInteger() const
334 {
335 return m_type == VariantTypeInteger;
336 }
337
isUnsignedInteger() const338 bool CVariant::isUnsignedInteger() const
339 {
340 return m_type == VariantTypeUnsignedInteger;
341 }
342
isBoolean() const343 bool CVariant::isBoolean() const
344 {
345 return m_type == VariantTypeBoolean;
346 }
347
isDouble() const348 bool CVariant::isDouble() const
349 {
350 return m_type == VariantTypeDouble;
351 }
352
isString() const353 bool CVariant::isString() const
354 {
355 return m_type == VariantTypeString;
356 }
357
isWideString() const358 bool CVariant::isWideString() const
359 {
360 return m_type == VariantTypeWideString;
361 }
362
isArray() const363 bool CVariant::isArray() const
364 {
365 return m_type == VariantTypeArray;
366 }
367
isObject() const368 bool CVariant::isObject() const
369 {
370 return m_type == VariantTypeObject;
371 }
372
isNull() const373 bool CVariant::isNull() const
374 {
375 return m_type == VariantTypeNull || m_type == VariantTypeConstNull;
376 }
377
type() const378 CVariant::VariantType CVariant::type() const
379 {
380 return m_type;
381 }
382
asInteger(int64_t fallback) const383 int64_t CVariant::asInteger(int64_t fallback) const
384 {
385 switch (m_type)
386 {
387 case VariantTypeInteger:
388 return m_data.integer;
389 case VariantTypeUnsignedInteger:
390 return (int64_t)m_data.unsignedinteger;
391 case VariantTypeDouble:
392 return (int64_t)m_data.dvalue;
393 case VariantTypeString:
394 return str2int64(*m_data.string, fallback);
395 case VariantTypeWideString:
396 return str2int64(*m_data.wstring, fallback);
397 default:
398 return fallback;
399 }
400
401 return fallback;
402 }
403
asInteger32(int32_t fallback) const404 int32_t CVariant::asInteger32(int32_t fallback) const
405 {
406 return static_cast<int32_t>(asInteger(fallback));
407 }
408
asUnsignedInteger(uint64_t fallback) const409 uint64_t CVariant::asUnsignedInteger(uint64_t fallback) const
410 {
411 switch (m_type)
412 {
413 case VariantTypeUnsignedInteger:
414 return m_data.unsignedinteger;
415 case VariantTypeInteger:
416 return (uint64_t)m_data.integer;
417 case VariantTypeDouble:
418 return (uint64_t)m_data.dvalue;
419 case VariantTypeString:
420 return str2uint64(*m_data.string, fallback);
421 case VariantTypeWideString:
422 return str2uint64(*m_data.wstring, fallback);
423 default:
424 return fallback;
425 }
426
427 return fallback;
428 }
429
asUnsignedInteger32(uint32_t fallback) const430 uint32_t CVariant::asUnsignedInteger32(uint32_t fallback) const
431 {
432 return static_cast<uint32_t>(asUnsignedInteger(fallback));
433 }
434
asDouble(double fallback) const435 double CVariant::asDouble(double fallback) const
436 {
437 switch (m_type)
438 {
439 case VariantTypeDouble:
440 return m_data.dvalue;
441 case VariantTypeInteger:
442 return (double)m_data.integer;
443 case VariantTypeUnsignedInteger:
444 return (double)m_data.unsignedinteger;
445 case VariantTypeString:
446 return str2double(*m_data.string, fallback);
447 case VariantTypeWideString:
448 return str2double(*m_data.wstring, fallback);
449 default:
450 return fallback;
451 }
452
453 return fallback;
454 }
455
asFloat(float fallback) const456 float CVariant::asFloat(float fallback) const
457 {
458 switch (m_type)
459 {
460 case VariantTypeDouble:
461 return (float)m_data.dvalue;
462 case VariantTypeInteger:
463 return (float)m_data.integer;
464 case VariantTypeUnsignedInteger:
465 return (float)m_data.unsignedinteger;
466 case VariantTypeString:
467 return (float)str2double(*m_data.string, fallback);
468 case VariantTypeWideString:
469 return (float)str2double(*m_data.wstring, fallback);
470 default:
471 return fallback;
472 }
473
474 return fallback;
475 }
476
asBoolean(bool fallback) const477 bool CVariant::asBoolean(bool fallback) const
478 {
479 switch (m_type)
480 {
481 case VariantTypeBoolean:
482 return m_data.boolean;
483 case VariantTypeInteger:
484 return (m_data.integer != 0);
485 case VariantTypeUnsignedInteger:
486 return (m_data.unsignedinteger != 0);
487 case VariantTypeDouble:
488 return (m_data.dvalue != 0);
489 case VariantTypeString:
490 if (m_data.string->empty() || m_data.string->compare("0") == 0 || m_data.string->compare("false") == 0)
491 return false;
492 return true;
493 case VariantTypeWideString:
494 if (m_data.wstring->empty() || m_data.wstring->compare(L"0") == 0 || m_data.wstring->compare(L"false") == 0)
495 return false;
496 return true;
497 default:
498 return fallback;
499 }
500
501 return fallback;
502 }
503
asString(const std::string & fallback) const504 std::string CVariant::asString(const std::string &fallback /* = "" */) const
505 {
506 switch (m_type)
507 {
508 case VariantTypeString:
509 return *m_data.string;
510 case VariantTypeBoolean:
511 return m_data.boolean ? "true" : "false";
512 case VariantTypeInteger:
513 return std::to_string(m_data.integer);
514 case VariantTypeUnsignedInteger:
515 return std::to_string(m_data.unsignedinteger);
516 case VariantTypeDouble:
517 return std::to_string(m_data.dvalue);
518 default:
519 return fallback;
520 }
521
522 return fallback;
523 }
524
asWideString(const std::wstring & fallback) const525 std::wstring CVariant::asWideString(const std::wstring &fallback /* = L"" */) const
526 {
527 switch (m_type)
528 {
529 case VariantTypeWideString:
530 return *m_data.wstring;
531 case VariantTypeBoolean:
532 return m_data.boolean ? L"true" : L"false";
533 case VariantTypeInteger:
534 return std::to_wstring(m_data.integer);
535 case VariantTypeUnsignedInteger:
536 return std::to_wstring(m_data.unsignedinteger);
537 case VariantTypeDouble:
538 return std::to_wstring(m_data.dvalue);
539 default:
540 return fallback;
541 }
542
543 return fallback;
544 }
545
operator [](const std::string & key)546 CVariant &CVariant::operator[](const std::string &key)
547 {
548 if (m_type == VariantTypeNull)
549 {
550 m_type = VariantTypeObject;
551 m_data.map = new VariantMap;
552 }
553
554 if (m_type == VariantTypeObject)
555 return (*m_data.map)[key];
556 else
557 return ConstNullVariant;
558 }
559
operator [](const std::string & key) const560 const CVariant &CVariant::operator[](const std::string &key) const
561 {
562 VariantMap::const_iterator it;
563 if (m_type == VariantTypeObject && (it = m_data.map->find(key)) != m_data.map->end())
564 return it->second;
565 else
566 return ConstNullVariant;
567 }
568
operator [](unsigned int position)569 CVariant &CVariant::operator[](unsigned int position)
570 {
571 if (m_type == VariantTypeArray && size() > position)
572 return m_data.array->at(position);
573 else
574 return ConstNullVariant;
575 }
576
operator [](unsigned int position) const577 const CVariant &CVariant::operator[](unsigned int position) const
578 {
579 if (m_type == VariantTypeArray && size() > position)
580 return m_data.array->at(position);
581 else
582 return ConstNullVariant;
583 }
584
operator =(const CVariant & rhs)585 CVariant &CVariant::operator=(const CVariant &rhs)
586 {
587 if (m_type == VariantTypeConstNull || this == &rhs)
588 return *this;
589
590 cleanup();
591
592 m_type = rhs.m_type;
593
594 switch (m_type)
595 {
596 case VariantTypeInteger:
597 m_data.integer = rhs.m_data.integer;
598 break;
599 case VariantTypeUnsignedInteger:
600 m_data.unsignedinteger = rhs.m_data.unsignedinteger;
601 break;
602 case VariantTypeBoolean:
603 m_data.boolean = rhs.m_data.boolean;
604 break;
605 case VariantTypeDouble:
606 m_data.dvalue = rhs.m_data.dvalue;
607 break;
608 case VariantTypeString:
609 m_data.string = new std::string(*rhs.m_data.string);
610 break;
611 case VariantTypeWideString:
612 m_data.wstring = new std::wstring(*rhs.m_data.wstring);
613 break;
614 case VariantTypeArray:
615 m_data.array = new VariantArray(rhs.m_data.array->begin(), rhs.m_data.array->end());
616 break;
617 case VariantTypeObject:
618 m_data.map = new VariantMap(rhs.m_data.map->begin(), rhs.m_data.map->end());
619 break;
620 default:
621 break;
622 }
623
624 return *this;
625 }
626
operator =(CVariant && rhs)627 CVariant& CVariant::operator=(CVariant&& rhs) noexcept
628 {
629 if (m_type == VariantTypeConstNull || this == &rhs)
630 return *this;
631
632 //Make sure that if we're moved into we don't leak any pointers
633 if (m_type != VariantTypeNull)
634 cleanup();
635
636 m_type = rhs.m_type;
637 m_data = rhs.m_data;
638
639 //Should be enough to just set m_type here
640 //but better safe than sorry, could probably lead to coverity warnings
641 if (rhs.m_type == VariantTypeString)
642 rhs.m_data.string = nullptr;
643 else if (rhs.m_type == VariantTypeWideString)
644 rhs.m_data.wstring = nullptr;
645 else if (rhs.m_type == VariantTypeArray)
646 rhs.m_data.array = nullptr;
647 else if (rhs.m_type == VariantTypeObject)
648 rhs.m_data.map = nullptr;
649
650 rhs.m_type = VariantTypeNull;
651
652 return *this;
653 }
654
operator ==(const CVariant & rhs) const655 bool CVariant::operator==(const CVariant &rhs) const
656 {
657 if (m_type == rhs.m_type)
658 {
659 switch (m_type)
660 {
661 case VariantTypeInteger:
662 return m_data.integer == rhs.m_data.integer;
663 case VariantTypeUnsignedInteger:
664 return m_data.unsignedinteger == rhs.m_data.unsignedinteger;
665 case VariantTypeBoolean:
666 return m_data.boolean == rhs.m_data.boolean;
667 case VariantTypeDouble:
668 return m_data.dvalue == rhs.m_data.dvalue;
669 case VariantTypeString:
670 return *m_data.string == *rhs.m_data.string;
671 case VariantTypeWideString:
672 return *m_data.wstring == *rhs.m_data.wstring;
673 case VariantTypeArray:
674 return *m_data.array == *rhs.m_data.array;
675 case VariantTypeObject:
676 return *m_data.map == *rhs.m_data.map;
677 default:
678 break;
679 }
680 }
681
682 return false;
683 }
684
reserve(size_t length)685 void CVariant::reserve(size_t length)
686 {
687 if (m_type == VariantTypeNull)
688 {
689 m_type = VariantTypeArray;
690 m_data.array = new VariantArray;
691 }
692 if (m_type == VariantTypeArray)
693 m_data.array->reserve(length);
694 }
695
push_back(const CVariant & variant)696 void CVariant::push_back(const CVariant &variant)
697 {
698 if (m_type == VariantTypeNull)
699 {
700 m_type = VariantTypeArray;
701 m_data.array = new VariantArray;
702 }
703
704 if (m_type == VariantTypeArray)
705 m_data.array->push_back(variant);
706 }
707
push_back(CVariant && variant)708 void CVariant::push_back(CVariant &&variant)
709 {
710 if (m_type == VariantTypeNull)
711 {
712 m_type = VariantTypeArray;
713 m_data.array = new VariantArray;
714 }
715
716 if (m_type == VariantTypeArray)
717 m_data.array->push_back(std::move(variant));
718 }
719
append(const CVariant & variant)720 void CVariant::append(const CVariant &variant)
721 {
722 push_back(variant);
723 }
724
append(CVariant && variant)725 void CVariant::append(CVariant&& variant)
726 {
727 push_back(std::move(variant));
728 }
729
c_str() const730 const char *CVariant::c_str() const
731 {
732 if (m_type == VariantTypeString)
733 return m_data.string->c_str();
734 else
735 return NULL;
736 }
737
swap(CVariant & rhs)738 void CVariant::swap(CVariant &rhs)
739 {
740 VariantType temp_type = m_type;
741 VariantUnion temp_data = m_data;
742
743 m_type = rhs.m_type;
744 m_data = rhs.m_data;
745
746 rhs.m_type = temp_type;
747 rhs.m_data = temp_data;
748 }
749
begin_array()750 CVariant::iterator_array CVariant::begin_array()
751 {
752 if (m_type == VariantTypeArray)
753 return m_data.array->begin();
754 else
755 return EMPTY_ARRAY.begin();
756 }
757
begin_array() const758 CVariant::const_iterator_array CVariant::begin_array() const
759 {
760 if (m_type == VariantTypeArray)
761 return m_data.array->begin();
762 else
763 return EMPTY_ARRAY.begin();
764 }
765
end_array()766 CVariant::iterator_array CVariant::end_array()
767 {
768 if (m_type == VariantTypeArray)
769 return m_data.array->end();
770 else
771 return EMPTY_ARRAY.end();
772 }
773
end_array() const774 CVariant::const_iterator_array CVariant::end_array() const
775 {
776 if (m_type == VariantTypeArray)
777 return m_data.array->end();
778 else
779 return EMPTY_ARRAY.end();
780 }
781
begin_map()782 CVariant::iterator_map CVariant::begin_map()
783 {
784 if (m_type == VariantTypeObject)
785 return m_data.map->begin();
786 else
787 return EMPTY_MAP.begin();
788 }
789
begin_map() const790 CVariant::const_iterator_map CVariant::begin_map() const
791 {
792 if (m_type == VariantTypeObject)
793 return m_data.map->begin();
794 else
795 return EMPTY_MAP.begin();
796 }
797
end_map()798 CVariant::iterator_map CVariant::end_map()
799 {
800 if (m_type == VariantTypeObject)
801 return m_data.map->end();
802 else
803 return EMPTY_MAP.end();
804 }
805
end_map() const806 CVariant::const_iterator_map CVariant::end_map() const
807 {
808 if (m_type == VariantTypeObject)
809 return m_data.map->end();
810 else
811 return EMPTY_MAP.end();
812 }
813
size() const814 unsigned int CVariant::size() const
815 {
816 if (m_type == VariantTypeObject)
817 return m_data.map->size();
818 else if (m_type == VariantTypeArray)
819 return m_data.array->size();
820 else if (m_type == VariantTypeString)
821 return m_data.string->size();
822 else if (m_type == VariantTypeWideString)
823 return m_data.wstring->size();
824 else
825 return 0;
826 }
827
empty() const828 bool CVariant::empty() const
829 {
830 if (m_type == VariantTypeObject)
831 return m_data.map->empty();
832 else if (m_type == VariantTypeArray)
833 return m_data.array->empty();
834 else if (m_type == VariantTypeString)
835 return m_data.string->empty();
836 else if (m_type == VariantTypeWideString)
837 return m_data.wstring->empty();
838 else if (m_type == VariantTypeNull)
839 return true;
840
841 return false;
842 }
843
clear()844 void CVariant::clear()
845 {
846 if (m_type == VariantTypeObject)
847 m_data.map->clear();
848 else if (m_type == VariantTypeArray)
849 m_data.array->clear();
850 else if (m_type == VariantTypeString)
851 m_data.string->clear();
852 else if (m_type == VariantTypeWideString)
853 m_data.wstring->clear();
854 }
855
erase(const std::string & key)856 void CVariant::erase(const std::string &key)
857 {
858 if (m_type == VariantTypeNull)
859 {
860 m_type = VariantTypeObject;
861 m_data.map = new VariantMap;
862 }
863 else if (m_type == VariantTypeObject)
864 m_data.map->erase(key);
865 }
866
erase(unsigned int position)867 void CVariant::erase(unsigned int position)
868 {
869 if (m_type == VariantTypeNull)
870 {
871 m_type = VariantTypeArray;
872 m_data.array = new VariantArray;
873 }
874
875 if (m_type == VariantTypeArray && position < size())
876 m_data.array->erase(m_data.array->begin() + position);
877 }
878
isMember(const std::string & key) const879 bool CVariant::isMember(const std::string &key) const
880 {
881 if (m_type == VariantTypeObject)
882 return m_data.map->find(key) != m_data.map->end();
883
884 return false;
885 }
886