2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
29 #define strtoll _strtoi64
30 #define strtoull _strtoui64
31 #define wcstoll _wcstoi64
32 #define wcstoull _wcstoui64
33 #else // TARGET_WINDOWS
34 #define strtoll(str, endptr, base) (int64_t)strtod(str, endptr)
35 #define strtoull(str, endptr, base) (uint64_t)strtod(str, endptr)
36 #define wcstoll(str, endptr, base) (int64_t)wcstod(str, endptr)
37 #define wcstoull(str, endptr, base) (uint64_t)wcstod(str, endptr)
38 #endif // TARGET_WINDOWS
43 string trimRight(const string &str)
46 // find_last_not_of will return string::npos (which is defined as -1)
47 // or a value between 0 and size() - 1 => find_last_not_of() + 1 will
48 // always result in a valid index between 0 and size()
49 tmp.erase(tmp.find_last_not_of(" \n\r\t") + 1);
54 wstring trimRight(const wstring &str)
57 // find_last_not_of will return string::npos (which is defined as -1)
58 // or a value between 0 and size() - 1 => find_last_not_of() + 1 will
59 // always result in a valid index between 0 and size()
60 tmp.erase(tmp.find_last_not_of(L" \n\r\t") + 1);
65 int64_t str2int64(const string &str, int64_t fallback /* = 0 */)
68 string tmp = trimRight(str);
69 int64_t result = strtoll(tmp.c_str(), &end, 0);
70 if (end == NULL || *end == '\0')
76 int64_t str2int64(const wstring &str, int64_t fallback /* = 0 */)
79 wstring tmp = trimRight(str);
80 int64_t result = wcstoll(tmp.c_str(), &end, 0);
81 if (end == NULL || *end == '\0')
87 uint64_t str2uint64(const string &str, uint64_t fallback /* = 0 */)
90 string tmp = trimRight(str);
91 uint64_t result = strtoull(tmp.c_str(), &end, 0);
92 if (end == NULL || *end == '\0')
98 uint64_t str2uint64(const wstring &str, uint64_t fallback /* = 0 */)
101 wstring tmp = trimRight(str);
102 uint64_t result = wcstoull(tmp.c_str(), &end, 0);
103 if (end == NULL || *end == '\0')
109 double str2double(const string &str, double fallback /* = 0.0 */)
112 string tmp = trimRight(str);
113 double result = strtod(tmp.c_str(), &end);
114 if (end == NULL || *end == '\0')
120 double str2double(const wstring &str, double fallback /* = 0.0 */)
123 wstring tmp = trimRight(str);
124 double result = wcstod(tmp.c_str(), &end);
125 if (end == NULL || *end == '\0')
131 CVariant CVariant::ConstNullVariant = CVariant::VariantTypeConstNull;
133 CVariant::CVariant(VariantType type)
139 case VariantTypeInteger:
142 case VariantTypeUnsignedInteger:
143 m_data.unsignedinteger = 0;
145 case VariantTypeBoolean:
146 m_data.boolean = false;
148 case VariantTypeDouble:
151 case VariantTypeString:
152 m_data.string = new string();
154 case VariantTypeWideString:
155 m_data.wstring = new wstring();
157 case VariantTypeArray:
158 m_data.array = new VariantArray();
160 case VariantTypeObject:
161 m_data.map = new VariantMap();
164 memset(&m_data, 0, sizeof(m_data));
169 CVariant::CVariant(int integer)
171 m_type = VariantTypeInteger;
172 m_data.integer = integer;
175 CVariant::CVariant(int64_t integer)
177 m_type = VariantTypeInteger;
178 m_data.integer = integer;
181 CVariant::CVariant(unsigned int unsignedinteger)
183 m_type = VariantTypeUnsignedInteger;
184 m_data.unsignedinteger = unsignedinteger;
187 CVariant::CVariant(uint64_t unsignedinteger)
189 m_type = VariantTypeUnsignedInteger;
190 m_data.unsignedinteger = unsignedinteger;
193 CVariant::CVariant(double value)
195 m_type = VariantTypeDouble;
196 m_data.dvalue = value;
199 CVariant::CVariant(float value)
201 m_type = VariantTypeDouble;
202 m_data.dvalue = (double)value;
205 CVariant::CVariant(bool boolean)
207 m_type = VariantTypeBoolean;
208 m_data.boolean = boolean;
211 CVariant::CVariant(const char *str)
213 m_type = VariantTypeString;
214 m_data.string = new string(str);
217 CVariant::CVariant(const char *str, unsigned int length)
219 m_type = VariantTypeString;
220 m_data.string = new string(str, length);
223 CVariant::CVariant(const string &str)
225 m_type = VariantTypeString;
226 m_data.string = new string(str);
229 CVariant::CVariant(const wchar_t *str)
231 m_type = VariantTypeWideString;
232 m_data.wstring = new wstring(str);
235 CVariant::CVariant(const wchar_t *str, unsigned int length)
237 m_type = VariantTypeWideString;
238 m_data.wstring = new wstring(str, length);
241 CVariant::CVariant(const wstring &str)
243 m_type = VariantTypeWideString;
244 m_data.wstring = new wstring(str);
247 CVariant::CVariant(const std::vector<std::string> &strArray)
249 m_type = VariantTypeArray;
250 m_data.array = new VariantArray;
251 m_data.array->reserve(strArray.size());
252 for (unsigned int index = 0; index < strArray.size(); index++)
253 m_data.array->push_back(strArray.at(index));
256 CVariant::CVariant(const std::map<std::string, std::string> &strMap)
258 m_type = VariantTypeObject;
259 m_data.map = new VariantMap;
260 for (std::map<std::string, std::string>::const_iterator it = strMap.begin(); it != strMap.end(); it++)
261 m_data.map->insert(make_pair(it->first, CVariant(it->second)));
264 CVariant::CVariant(const std::map<std::string, CVariant> &variantMap)
266 m_type = VariantTypeObject;
267 m_data.map = new VariantMap(variantMap.begin(), variantMap.end());
270 CVariant::CVariant(const CVariant &variant)
272 m_type = VariantTypeNull;
276 CVariant::~CVariant()
281 void CVariant::cleanup()
283 if (m_type == VariantTypeString)
284 delete m_data.string;
285 else if (m_type == VariantTypeWideString)
286 delete m_data.wstring;
287 else if (m_type == VariantTypeArray)
289 else if (m_type == VariantTypeObject)
291 m_type = VariantTypeNull;
294 bool CVariant::isInteger() const
296 return m_type == VariantTypeInteger;
299 bool CVariant::isUnsignedInteger() const
301 return m_type == VariantTypeUnsignedInteger;
304 bool CVariant::isBoolean() const
306 return m_type == VariantTypeBoolean;
309 bool CVariant::isDouble() const
311 return m_type == VariantTypeDouble;
314 bool CVariant::isString() const
316 return m_type == VariantTypeString;
319 bool CVariant::isWideString() const
321 return m_type == VariantTypeWideString;
324 bool CVariant::isArray() const
326 return m_type == VariantTypeArray;
329 bool CVariant::isObject() const
331 return m_type == VariantTypeObject;
334 bool CVariant::isNull() const
336 return m_type == VariantTypeNull || m_type == VariantTypeConstNull;
339 CVariant::VariantType CVariant::type() const
344 int64_t CVariant::asInteger(int64_t fallback) const
348 case VariantTypeInteger:
349 return m_data.integer;
350 case VariantTypeUnsignedInteger:
351 return (int64_t)m_data.unsignedinteger;
352 case VariantTypeDouble:
353 return (int64_t)m_data.dvalue;
354 case VariantTypeString:
355 return str2int64(*m_data.string, fallback);
356 case VariantTypeWideString:
357 return str2int64(*m_data.wstring, fallback);
365 uint64_t CVariant::asUnsignedInteger(uint64_t fallback) const
369 case VariantTypeUnsignedInteger:
370 return m_data.unsignedinteger;
371 case VariantTypeInteger:
372 return (uint64_t)m_data.integer;
373 case VariantTypeDouble:
374 return (uint64_t)m_data.dvalue;
375 case VariantTypeString:
376 return str2uint64(*m_data.string, fallback);
377 case VariantTypeWideString:
378 return str2uint64(*m_data.wstring, fallback);
386 double CVariant::asDouble(double fallback) const
390 case VariantTypeDouble:
391 return m_data.dvalue;
392 case VariantTypeInteger:
393 return (double)m_data.integer;
394 case VariantTypeUnsignedInteger:
395 return (double)m_data.unsignedinteger;
396 case VariantTypeString:
397 return str2double(*m_data.string, fallback);
398 case VariantTypeWideString:
399 return str2double(*m_data.wstring, fallback);
407 float CVariant::asFloat(float fallback) const
411 case VariantTypeDouble:
412 return (float)m_data.dvalue;
413 case VariantTypeInteger:
414 return (float)m_data.integer;
415 case VariantTypeUnsignedInteger:
416 return (float)m_data.unsignedinteger;
417 case VariantTypeString:
418 return (float)str2double(*m_data.string, fallback);
419 case VariantTypeWideString:
420 return (float)str2double(*m_data.wstring, fallback);
428 bool CVariant::asBoolean(bool fallback) const
432 case VariantTypeBoolean:
433 return m_data.boolean;
434 case VariantTypeInteger:
435 return (m_data.integer != 0);
436 case VariantTypeUnsignedInteger:
437 return (m_data.unsignedinteger != 0);
438 case VariantTypeDouble:
439 return (m_data.dvalue != 0);
440 case VariantTypeString:
441 if (m_data.string->empty() || m_data.string->compare("0") == 0 || m_data.string->compare("false") == 0)
444 case VariantTypeWideString:
445 if (m_data.wstring->empty() || m_data.wstring->compare(L"0") == 0 || m_data.wstring->compare(L"false") == 0)
455 std::string CVariant::asString(const std::string &fallback /* = "" */) const
459 case VariantTypeString:
460 return *m_data.string;
461 case VariantTypeBoolean:
462 return m_data.boolean ? "true" : "false";
463 case VariantTypeInteger:
464 case VariantTypeUnsignedInteger:
465 case VariantTypeDouble:
467 std::ostringstream strStream;
468 if (m_type == VariantTypeInteger)
469 strStream << m_data.integer;
470 else if (m_type == VariantTypeUnsignedInteger)
471 strStream << m_data.unsignedinteger;
473 strStream << m_data.dvalue;
474 return strStream.str();
483 std::wstring CVariant::asWideString(const std::wstring &fallback /* = L"" */) const
487 case VariantTypeWideString:
488 return *m_data.wstring;
489 case VariantTypeBoolean:
490 return m_data.boolean ? L"true" : L"false";
491 case VariantTypeInteger:
492 case VariantTypeUnsignedInteger:
493 case VariantTypeDouble:
495 std::wostringstream strStream;
496 if (m_type == VariantTypeInteger)
497 strStream << m_data.integer;
498 else if (m_type == VariantTypeUnsignedInteger)
499 strStream << m_data.unsignedinteger;
501 strStream << m_data.dvalue;
502 return strStream.str();
512 CVariant &CVariant::operator[](const std::string &key)
514 if (m_type == VariantTypeNull)
516 m_type = VariantTypeObject;
517 m_data.map = new VariantMap;
520 if (m_type == VariantTypeObject)
521 return (*m_data.map)[key];
523 return ConstNullVariant;
526 const CVariant &CVariant::operator[](const std::string &key) const
528 VariantMap::const_iterator it;
529 if (m_type == VariantTypeObject && (it = m_data.map->find(key)) != m_data.map->end())
532 return ConstNullVariant;
535 CVariant &CVariant::operator[](unsigned int position)
537 if (m_type == VariantTypeArray && size() > position)
538 return m_data.array->at(position);
540 return ConstNullVariant;
543 const CVariant &CVariant::operator[](unsigned int position) const
545 if (m_type == VariantTypeArray && size() > position)
546 return m_data.array->at(position);
548 return ConstNullVariant;
551 CVariant &CVariant::operator=(const CVariant &rhs)
553 if (m_type == VariantTypeConstNull)
562 case VariantTypeInteger:
563 m_data.integer = rhs.m_data.integer;
565 case VariantTypeUnsignedInteger:
566 m_data.integer = rhs.m_data.unsignedinteger;
568 case VariantTypeBoolean:
569 m_data.boolean = rhs.m_data.boolean;
571 case VariantTypeDouble:
572 m_data.dvalue = rhs.m_data.dvalue;
574 case VariantTypeString:
575 m_data.string = new string(*rhs.m_data.string);
577 case VariantTypeWideString:
578 m_data.wstring = new wstring(*rhs.m_data.wstring);
580 case VariantTypeArray:
581 m_data.array = new VariantArray(rhs.m_data.array->begin(), rhs.m_data.array->end());
583 case VariantTypeObject:
584 m_data.map = new VariantMap(rhs.m_data.map->begin(), rhs.m_data.map->end());
593 bool CVariant::operator==(const CVariant &rhs) const
595 if (m_type == rhs.m_type)
599 case VariantTypeInteger:
600 return m_data.integer == rhs.m_data.integer;
601 case VariantTypeUnsignedInteger:
602 return m_data.unsignedinteger == rhs.m_data.unsignedinteger;
603 case VariantTypeBoolean:
604 return m_data.boolean == rhs.m_data.boolean;
605 case VariantTypeDouble:
606 return m_data.dvalue == rhs.m_data.dvalue;
607 case VariantTypeString:
608 return *m_data.string == *rhs.m_data.string;
609 case VariantTypeWideString:
610 return *m_data.wstring == *rhs.m_data.wstring;
611 case VariantTypeArray:
612 return *m_data.array == *rhs.m_data.array;
613 case VariantTypeObject:
614 return *m_data.map == *rhs.m_data.map;
623 void CVariant::push_back(const CVariant &variant)
625 if (m_type == VariantTypeNull)
627 m_type = VariantTypeArray;
628 m_data.array = new VariantArray;
631 if (m_type == VariantTypeArray)
632 m_data.array->push_back(variant);
635 void CVariant::append(const CVariant &variant)
640 const char *CVariant::c_str() const
642 if (m_type == VariantTypeString)
643 return m_data.string->c_str();
648 void CVariant::swap(CVariant &rhs)
650 VariantType temp_type = m_type;
651 VariantUnion temp_data = m_data;
656 rhs.m_type = temp_type;
657 rhs.m_data = temp_data;
660 CVariant::iterator_array CVariant::begin_array()
662 if (m_type == VariantTypeArray)
663 return m_data.array->begin();
665 return iterator_array();
668 CVariant::const_iterator_array CVariant::begin_array() const
670 if (m_type == VariantTypeArray)
671 return m_data.array->begin();
673 return const_iterator_array();
676 CVariant::iterator_array CVariant::end_array()
678 if (m_type == VariantTypeArray)
679 return m_data.array->end();
681 return iterator_array();
684 CVariant::const_iterator_array CVariant::end_array() const
686 if (m_type == VariantTypeArray)
687 return m_data.array->end();
689 return const_iterator_array();
692 CVariant::iterator_map CVariant::begin_map()
694 if (m_type == VariantTypeObject)
695 return m_data.map->begin();
697 return iterator_map();
700 CVariant::const_iterator_map CVariant::begin_map() const
702 if (m_type == VariantTypeObject)
703 return m_data.map->begin();
705 return const_iterator_map();
708 CVariant::iterator_map CVariant::end_map()
710 if (m_type == VariantTypeObject)
711 return m_data.map->end();
713 return iterator_map();
716 CVariant::const_iterator_map CVariant::end_map() const
718 if (m_type == VariantTypeObject)
719 return m_data.map->end();
721 return const_iterator_map();
724 unsigned int CVariant::size() const
726 if (m_type == VariantTypeObject)
727 return m_data.map->size();
728 else if (m_type == VariantTypeArray)
729 return m_data.array->size();
730 else if (m_type == VariantTypeString)
731 return m_data.string->size();
732 else if (m_type == VariantTypeWideString)
733 return m_data.wstring->size();
738 bool CVariant::empty() const
740 if (m_type == VariantTypeObject)
741 return m_data.map->empty();
742 else if (m_type == VariantTypeArray)
743 return m_data.array->empty();
744 else if (m_type == VariantTypeString)
745 return m_data.string->empty();
746 else if (m_type == VariantTypeWideString)
747 return m_data.wstring->empty();
748 else if (m_type == VariantTypeNull)
754 void CVariant::clear()
756 if (m_type == VariantTypeObject)
758 else if (m_type == VariantTypeArray)
759 m_data.array->clear();
760 else if (m_type == VariantTypeString)
761 m_data.string->clear();
762 else if (m_type == VariantTypeWideString)
763 m_data.wstring->clear();
766 void CVariant::erase(const std::string &key)
768 if (m_type == VariantTypeNull)
770 m_type = VariantTypeObject;
771 m_data.map = new VariantMap;
773 else if (m_type == VariantTypeObject)
774 m_data.map->erase(key);
777 void CVariant::erase(unsigned int position)
779 if (m_type == VariantTypeNull)
781 m_type = VariantTypeArray;
782 m_data.array = new VariantArray;
785 if (m_type == VariantTypeArray && position < size())
786 m_data.array->erase(m_data.array->begin() + position);
789 bool CVariant::isMember(const std::string &key) const
791 if (m_type == VariantTypeObject)
792 return m_data.map->find(key) != m_data.map->end();