mirror of
https://github.com/Team-Resurgent/XBMC4Xbox.git
synced 2026-08-15 11:18:13 -07:00
If ever adding the XBMC4Xbox source to GitHub use "git add -f -A" or it wont add all the files.
760 lines
17 KiB
C++
760 lines
17 KiB
C++
/*
|
|
* Copyright (C) 2005-2013 Team XBMC
|
|
* http://xbmc.org
|
|
*
|
|
* This Program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This Program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with XBMC; see the file COPYING. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sstream>
|
|
|
|
#include "Variant.h"
|
|
|
|
using namespace std;
|
|
|
|
string trimRight(const string &str)
|
|
{
|
|
string tmp = str;
|
|
// find_last_not_of will return string::npos (which is defined as -1)
|
|
// or a value between 0 and size() - 1 => find_last_not_of() + 1 will
|
|
// always result in a valid index between 0 and size()
|
|
tmp.erase(tmp.find_last_not_of(" \n\r\t") + 1);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
wstring trimRight(const wstring &str)
|
|
{
|
|
wstring tmp = str;
|
|
// find_last_not_of will return string::npos (which is defined as -1)
|
|
// or a value between 0 and size() - 1 => find_last_not_of() + 1 will
|
|
// always result in a valid index between 0 and size()
|
|
tmp.erase(tmp.find_last_not_of(L" \n\r\t") + 1);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
int64_t str2int64(const string &str, int64_t fallback /* = 0 */)
|
|
{
|
|
char *end = NULL;
|
|
int64_t result = strtol(trimRight(str).c_str(), &end, 0);
|
|
if (end == NULL || *end == '\0')
|
|
return result;
|
|
|
|
return fallback;
|
|
}
|
|
|
|
int64_t str2int64(const wstring &str, int64_t fallback /* = 0 */)
|
|
{
|
|
wchar_t *end = NULL;
|
|
int64_t result = wcstol(trimRight(str).c_str(), &end, 0);
|
|
if (end == NULL || *end == '\0')
|
|
return result;
|
|
|
|
return fallback;
|
|
}
|
|
|
|
uint64_t str2uint64(const string &str, uint64_t fallback /* = 0 */)
|
|
{
|
|
char *end = NULL;
|
|
uint64_t result = strtoul(trimRight(str).c_str(), &end, 0);
|
|
if (end == NULL || *end == '\0')
|
|
return result;
|
|
|
|
return fallback;
|
|
}
|
|
|
|
uint64_t str2uint64(const wstring &str, uint64_t fallback /* = 0 */)
|
|
{
|
|
wchar_t *end = NULL;
|
|
uint64_t result = wcstoul(trimRight(str).c_str(), &end, 0);
|
|
if (end == NULL || *end == '\0')
|
|
return result;
|
|
|
|
return fallback;
|
|
}
|
|
|
|
double str2double(const string &str, double fallback /* = 0.0 */)
|
|
{
|
|
char *end = NULL;
|
|
double result = strtod(trimRight(str).c_str(), &end);
|
|
if (end == NULL || *end == '\0')
|
|
return result;
|
|
|
|
return fallback;
|
|
}
|
|
|
|
double str2double(const wstring &str, double fallback /* = 0.0 */)
|
|
{
|
|
wchar_t *end = NULL;
|
|
double result = wcstod(trimRight(str).c_str(), &end);
|
|
if (end == NULL || *end == '\0')
|
|
return result;
|
|
|
|
return fallback;
|
|
}
|
|
|
|
CVariant CVariant::ConstNullVariant = CVariant::VariantTypeConstNull;
|
|
|
|
CVariant::CVariant(VariantType type)
|
|
{
|
|
m_type = type;
|
|
|
|
switch (type)
|
|
{
|
|
case VariantTypeInteger:
|
|
m_data.integer = 0;
|
|
break;
|
|
case VariantTypeUnsignedInteger:
|
|
m_data.unsignedinteger = 0;
|
|
break;
|
|
case VariantTypeBoolean:
|
|
m_data.boolean = false;
|
|
break;
|
|
case VariantTypeDouble:
|
|
m_data.dvalue = 0.0;
|
|
break;
|
|
case VariantTypeString:
|
|
m_data.string = new string();
|
|
break;
|
|
case VariantTypeWideString:
|
|
m_data.wstring = new wstring();
|
|
break;
|
|
case VariantTypeArray:
|
|
m_data.array = new VariantArray();
|
|
break;
|
|
case VariantTypeObject:
|
|
m_data.map = new VariantMap();
|
|
break;
|
|
default:
|
|
memset(&m_data, 0, sizeof(m_data));
|
|
break;
|
|
}
|
|
}
|
|
|
|
CVariant::CVariant(int integer)
|
|
{
|
|
m_type = VariantTypeInteger;
|
|
m_data.integer = integer;
|
|
}
|
|
|
|
CVariant::CVariant(int64_t integer)
|
|
{
|
|
m_type = VariantTypeInteger;
|
|
m_data.integer = integer;
|
|
}
|
|
|
|
CVariant::CVariant(unsigned int unsignedinteger)
|
|
{
|
|
m_type = VariantTypeUnsignedInteger;
|
|
m_data.unsignedinteger = unsignedinteger;
|
|
}
|
|
|
|
CVariant::CVariant(uint64_t unsignedinteger)
|
|
{
|
|
m_type = VariantTypeUnsignedInteger;
|
|
m_data.unsignedinteger = unsignedinteger;
|
|
}
|
|
|
|
CVariant::CVariant(double value)
|
|
{
|
|
m_type = VariantTypeDouble;
|
|
m_data.dvalue = value;
|
|
}
|
|
|
|
CVariant::CVariant(float value)
|
|
{
|
|
m_type = VariantTypeDouble;
|
|
m_data.dvalue = (double)value;
|
|
}
|
|
|
|
CVariant::CVariant(bool boolean)
|
|
{
|
|
m_type = VariantTypeBoolean;
|
|
m_data.boolean = boolean;
|
|
}
|
|
|
|
CVariant::CVariant(const char *str)
|
|
{
|
|
m_type = VariantTypeString;
|
|
m_data.string = new string(str);
|
|
}
|
|
|
|
CVariant::CVariant(const char *str, unsigned int length)
|
|
{
|
|
m_type = VariantTypeString;
|
|
m_data.string = new string(str, length);
|
|
}
|
|
|
|
CVariant::CVariant(const string &str)
|
|
{
|
|
m_type = VariantTypeString;
|
|
m_data.string = new string(str);
|
|
}
|
|
|
|
CVariant::CVariant(const wchar_t *str)
|
|
{
|
|
m_type = VariantTypeWideString;
|
|
m_data.wstring = new wstring(str);
|
|
}
|
|
|
|
CVariant::CVariant(const wchar_t *str, unsigned int length)
|
|
{
|
|
m_type = VariantTypeWideString;
|
|
m_data.wstring = new wstring(str, length);
|
|
}
|
|
|
|
CVariant::CVariant(const wstring &str)
|
|
{
|
|
m_type = VariantTypeWideString;
|
|
m_data.wstring = new wstring(str);
|
|
}
|
|
|
|
CVariant::CVariant(const std::vector<std::string> &strArray)
|
|
{
|
|
m_type = VariantTypeArray;
|
|
m_data.array = new VariantArray;
|
|
m_data.array->reserve(strArray.size());
|
|
for (unsigned int index = 0; index < strArray.size(); index++)
|
|
m_data.array->push_back(strArray.at(index));
|
|
}
|
|
|
|
CVariant::CVariant(const CVariant &variant)
|
|
{
|
|
m_type = VariantTypeNull;
|
|
*this = variant;
|
|
}
|
|
|
|
CVariant::~CVariant()
|
|
{
|
|
cleanup();
|
|
}
|
|
|
|
void CVariant::cleanup()
|
|
{
|
|
if (m_type == VariantTypeString)
|
|
delete m_data.string;
|
|
else if (m_type == VariantTypeWideString)
|
|
delete m_data.wstring;
|
|
else if (m_type == VariantTypeArray)
|
|
delete m_data.array;
|
|
else if (m_type == VariantTypeObject)
|
|
delete m_data.map;
|
|
m_type = VariantTypeNull;
|
|
}
|
|
|
|
bool CVariant::isInteger() const
|
|
{
|
|
return m_type == VariantTypeInteger;
|
|
}
|
|
|
|
bool CVariant::isUnsignedInteger() const
|
|
{
|
|
return m_type == VariantTypeUnsignedInteger;
|
|
}
|
|
|
|
bool CVariant::isBoolean() const
|
|
{
|
|
return m_type == VariantTypeBoolean;
|
|
}
|
|
|
|
bool CVariant::isDouble() const
|
|
{
|
|
return m_type == VariantTypeDouble;
|
|
}
|
|
|
|
bool CVariant::isString() const
|
|
{
|
|
return m_type == VariantTypeString;
|
|
}
|
|
|
|
bool CVariant::isWideString() const
|
|
{
|
|
return m_type == VariantTypeWideString;
|
|
}
|
|
|
|
bool CVariant::isArray() const
|
|
{
|
|
return m_type == VariantTypeArray;
|
|
}
|
|
|
|
bool CVariant::isObject() const
|
|
{
|
|
return m_type == VariantTypeObject;
|
|
}
|
|
|
|
bool CVariant::isNull() const
|
|
{
|
|
return m_type == VariantTypeNull || m_type == VariantTypeConstNull;
|
|
}
|
|
|
|
CVariant::VariantType CVariant::type() const
|
|
{
|
|
return m_type;
|
|
}
|
|
|
|
int64_t CVariant::asInteger(int64_t fallback) const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case VariantTypeInteger:
|
|
return m_data.integer;
|
|
case VariantTypeUnsignedInteger:
|
|
return (int64_t)m_data.unsignedinteger;
|
|
case VariantTypeDouble:
|
|
return (int64_t)m_data.dvalue;
|
|
case VariantTypeString:
|
|
return str2int64(*m_data.string, fallback);
|
|
case VariantTypeWideString:
|
|
return str2int64(*m_data.wstring, fallback);
|
|
default:
|
|
return fallback;
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
uint64_t CVariant::asUnsignedInteger(uint64_t fallback) const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case VariantTypeUnsignedInteger:
|
|
return m_data.unsignedinteger;
|
|
case VariantTypeInteger:
|
|
return (uint64_t)m_data.integer;
|
|
case VariantTypeDouble:
|
|
return (uint64_t)m_data.dvalue;
|
|
case VariantTypeString:
|
|
return str2uint64(*m_data.string, fallback);
|
|
case VariantTypeWideString:
|
|
return str2uint64(*m_data.wstring, fallback);
|
|
default:
|
|
return fallback;
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
double CVariant::asDouble(double fallback) const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case VariantTypeDouble:
|
|
return m_data.dvalue;
|
|
case VariantTypeInteger:
|
|
return (double)m_data.integer;
|
|
case VariantTypeUnsignedInteger:
|
|
return (double)m_data.unsignedinteger;
|
|
case VariantTypeString:
|
|
return str2double(*m_data.string, fallback);
|
|
case VariantTypeWideString:
|
|
return str2double(*m_data.wstring, fallback);
|
|
default:
|
|
return fallback;
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
float CVariant::asFloat(float fallback) const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case VariantTypeDouble:
|
|
return (float)m_data.dvalue;
|
|
case VariantTypeInteger:
|
|
return (float)m_data.integer;
|
|
case VariantTypeUnsignedInteger:
|
|
return (float)m_data.unsignedinteger;
|
|
case VariantTypeString:
|
|
return (float)str2double(*m_data.string, fallback);
|
|
case VariantTypeWideString:
|
|
return (float)str2double(*m_data.wstring, fallback);
|
|
default:
|
|
return fallback;
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
bool CVariant::asBoolean(bool fallback) const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case VariantTypeBoolean:
|
|
return m_data.boolean;
|
|
case VariantTypeInteger:
|
|
return (m_data.integer != 0);
|
|
case VariantTypeUnsignedInteger:
|
|
return (m_data.unsignedinteger != 0);
|
|
case VariantTypeDouble:
|
|
return (m_data.dvalue != 0);
|
|
case VariantTypeString:
|
|
if (m_data.string->empty() || m_data.string->compare("0") == 0 || m_data.string->compare("false") == 0)
|
|
return false;
|
|
return true;
|
|
case VariantTypeWideString:
|
|
if (m_data.wstring->empty() || m_data.wstring->compare(L"0") == 0 || m_data.wstring->compare(L"false") == 0)
|
|
return false;
|
|
return true;
|
|
default:
|
|
return fallback;
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
std::string CVariant::asString(const std::string &fallback /* = "" */) const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case VariantTypeString:
|
|
return *m_data.string;
|
|
case VariantTypeBoolean:
|
|
return m_data.boolean ? "true" : "false";
|
|
case VariantTypeInteger:
|
|
case VariantTypeUnsignedInteger:
|
|
case VariantTypeDouble:
|
|
{
|
|
std::ostringstream strStream;
|
|
if (m_type == VariantTypeInteger)
|
|
strStream << m_data.integer;
|
|
else if (m_type == VariantTypeUnsignedInteger)
|
|
strStream << m_data.unsignedinteger;
|
|
else
|
|
strStream << m_data.dvalue;
|
|
return strStream.str();
|
|
}
|
|
default:
|
|
return fallback;
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
std::wstring CVariant::asWideString(const std::wstring &fallback /* = L"" */) const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case VariantTypeWideString:
|
|
return *m_data.wstring;
|
|
case VariantTypeBoolean:
|
|
return m_data.boolean ? L"true" : L"false";
|
|
case VariantTypeInteger:
|
|
case VariantTypeUnsignedInteger:
|
|
case VariantTypeDouble:
|
|
{
|
|
std::wostringstream strStream;
|
|
if (m_type == VariantTypeInteger)
|
|
strStream << m_data.integer;
|
|
else if (m_type == VariantTypeUnsignedInteger)
|
|
strStream << m_data.unsignedinteger;
|
|
else
|
|
strStream << m_data.dvalue;
|
|
return strStream.str();
|
|
break;
|
|
}
|
|
default:
|
|
return fallback;
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
CVariant &CVariant::operator[](const std::string &key)
|
|
{
|
|
if (m_type == VariantTypeNull)
|
|
{
|
|
m_type = VariantTypeObject;
|
|
m_data.map = new VariantMap;
|
|
}
|
|
|
|
if (m_type == VariantTypeObject)
|
|
return (*m_data.map)[key];
|
|
else
|
|
return ConstNullVariant;
|
|
}
|
|
|
|
const CVariant &CVariant::operator[](const std::string &key) const
|
|
{
|
|
VariantMap::const_iterator it;
|
|
if (m_type == VariantTypeObject && (it = m_data.map->find(key)) != m_data.map->end())
|
|
return it->second;
|
|
else
|
|
return ConstNullVariant;
|
|
}
|
|
|
|
CVariant &CVariant::operator[](unsigned int position)
|
|
{
|
|
if (m_type == VariantTypeArray && size() > position)
|
|
return m_data.array->at(position);
|
|
else
|
|
return ConstNullVariant;
|
|
}
|
|
|
|
const CVariant &CVariant::operator[](unsigned int position) const
|
|
{
|
|
if (m_type == VariantTypeArray && size() > position)
|
|
return m_data.array->at(position);
|
|
else
|
|
return ConstNullVariant;
|
|
}
|
|
|
|
CVariant &CVariant::operator=(const CVariant &rhs)
|
|
{
|
|
if (m_type == VariantTypeConstNull)
|
|
return *this;
|
|
|
|
cleanup();
|
|
|
|
m_type = rhs.m_type;
|
|
|
|
switch (m_type)
|
|
{
|
|
case VariantTypeInteger:
|
|
m_data.integer = rhs.m_data.integer;
|
|
break;
|
|
case VariantTypeUnsignedInteger:
|
|
m_data.integer = rhs.m_data.unsignedinteger;
|
|
break;
|
|
case VariantTypeBoolean:
|
|
m_data.boolean = rhs.m_data.boolean;
|
|
break;
|
|
case VariantTypeDouble:
|
|
m_data.dvalue = rhs.m_data.dvalue;
|
|
break;
|
|
case VariantTypeString:
|
|
m_data.string = new string(*rhs.m_data.string);
|
|
break;
|
|
case VariantTypeWideString:
|
|
m_data.wstring = new wstring(*rhs.m_data.wstring);
|
|
break;
|
|
case VariantTypeArray:
|
|
m_data.array = new VariantArray(rhs.m_data.array->begin(), rhs.m_data.array->end());
|
|
break;
|
|
case VariantTypeObject:
|
|
m_data.map = new VariantMap(rhs.m_data.map->begin(), rhs.m_data.map->end());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
bool CVariant::operator==(const CVariant &rhs) const
|
|
{
|
|
if (m_type == rhs.m_type)
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case VariantTypeInteger:
|
|
return m_data.integer == rhs.m_data.integer;
|
|
case VariantTypeUnsignedInteger:
|
|
return m_data.unsignedinteger == rhs.m_data.unsignedinteger;
|
|
case VariantTypeBoolean:
|
|
return m_data.boolean == rhs.m_data.boolean;
|
|
case VariantTypeDouble:
|
|
return m_data.dvalue == rhs.m_data.dvalue;
|
|
case VariantTypeString:
|
|
return *m_data.string == *rhs.m_data.string;
|
|
case VariantTypeWideString:
|
|
return *m_data.wstring == *rhs.m_data.wstring;
|
|
case VariantTypeArray:
|
|
return *m_data.array == *rhs.m_data.array;
|
|
case VariantTypeObject:
|
|
return *m_data.map == *rhs.m_data.map;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CVariant::push_back(const CVariant &variant)
|
|
{
|
|
if (m_type == VariantTypeNull)
|
|
{
|
|
m_type = VariantTypeArray;
|
|
m_data.array = new VariantArray;
|
|
}
|
|
|
|
if (m_type == VariantTypeArray)
|
|
m_data.array->push_back(variant);
|
|
}
|
|
|
|
void CVariant::append(const CVariant &variant)
|
|
{
|
|
push_back(variant);
|
|
}
|
|
|
|
const char *CVariant::c_str() const
|
|
{
|
|
if (m_type == VariantTypeString)
|
|
return m_data.string->c_str();
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
void CVariant::swap(CVariant &rhs)
|
|
{
|
|
VariantType temp_type = m_type;
|
|
VariantUnion temp_data = m_data;
|
|
|
|
m_type = rhs.m_type;
|
|
m_data = rhs.m_data;
|
|
|
|
rhs.m_type = temp_type;
|
|
rhs.m_data = temp_data;
|
|
}
|
|
|
|
CVariant::iterator_array CVariant::begin_array()
|
|
{
|
|
if (m_type == VariantTypeArray)
|
|
return m_data.array->begin();
|
|
else
|
|
return iterator_array();
|
|
}
|
|
|
|
CVariant::const_iterator_array CVariant::begin_array() const
|
|
{
|
|
if (m_type == VariantTypeArray)
|
|
return m_data.array->begin();
|
|
else
|
|
return const_iterator_array();
|
|
}
|
|
|
|
CVariant::iterator_array CVariant::end_array()
|
|
{
|
|
if (m_type == VariantTypeArray)
|
|
return m_data.array->end();
|
|
else
|
|
return iterator_array();
|
|
}
|
|
|
|
CVariant::const_iterator_array CVariant::end_array() const
|
|
{
|
|
if (m_type == VariantTypeArray)
|
|
return m_data.array->end();
|
|
else
|
|
return const_iterator_array();
|
|
}
|
|
|
|
CVariant::iterator_map CVariant::begin_map()
|
|
{
|
|
if (m_type == VariantTypeObject)
|
|
return m_data.map->begin();
|
|
else
|
|
return iterator_map();
|
|
}
|
|
|
|
CVariant::const_iterator_map CVariant::begin_map() const
|
|
{
|
|
if (m_type == VariantTypeObject)
|
|
return m_data.map->begin();
|
|
else
|
|
return const_iterator_map();
|
|
}
|
|
|
|
CVariant::iterator_map CVariant::end_map()
|
|
{
|
|
if (m_type == VariantTypeObject)
|
|
return m_data.map->end();
|
|
else
|
|
return iterator_map();
|
|
}
|
|
|
|
CVariant::const_iterator_map CVariant::end_map() const
|
|
{
|
|
if (m_type == VariantTypeObject)
|
|
return m_data.map->end();
|
|
else
|
|
return const_iterator_map();
|
|
}
|
|
|
|
unsigned int CVariant::size() const
|
|
{
|
|
if (m_type == VariantTypeObject)
|
|
return m_data.map->size();
|
|
else if (m_type == VariantTypeArray)
|
|
return m_data.array->size();
|
|
else if (m_type == VariantTypeString)
|
|
return m_data.string->size();
|
|
else if (m_type == VariantTypeWideString)
|
|
return m_data.wstring->size();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
bool CVariant::empty() const
|
|
{
|
|
if (m_type == VariantTypeObject)
|
|
return m_data.map->empty();
|
|
else if (m_type == VariantTypeArray)
|
|
return m_data.array->empty();
|
|
else if (m_type == VariantTypeString)
|
|
return m_data.string->empty();
|
|
else if (m_type == VariantTypeWideString)
|
|
return m_data.wstring->empty();
|
|
else
|
|
return true;
|
|
}
|
|
|
|
void CVariant::clear()
|
|
{
|
|
if (m_type == VariantTypeObject)
|
|
m_data.map->clear();
|
|
else if (m_type == VariantTypeArray)
|
|
m_data.array->clear();
|
|
else if (m_type == VariantTypeString)
|
|
m_data.string->clear();
|
|
else if (m_type == VariantTypeWideString)
|
|
m_data.wstring->clear();
|
|
}
|
|
|
|
void CVariant::erase(const std::string &key)
|
|
{
|
|
if (m_type == VariantTypeNull)
|
|
{
|
|
m_type = VariantTypeObject;
|
|
m_data.map = new VariantMap;
|
|
}
|
|
else if (m_type == VariantTypeObject)
|
|
m_data.map->erase(key);
|
|
}
|
|
|
|
void CVariant::erase(unsigned int position)
|
|
{
|
|
if (m_type == VariantTypeNull)
|
|
{
|
|
m_type = VariantTypeArray;
|
|
m_data.array = new VariantArray;
|
|
}
|
|
|
|
if (m_type == VariantTypeArray && position < size())
|
|
m_data.array->erase(m_data.array->begin() + position);
|
|
}
|
|
|
|
bool CVariant::isMember(const std::string &key) const
|
|
{
|
|
if (m_type == VariantTypeObject)
|
|
return m_data.map->find(key) != m_data.map->end();
|
|
|
|
return false;
|
|
}
|