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