mirror of
https://github.com/pocoproject/poco.git
synced 2025-11-26 00:40:05 +01:00
new trunk (base for 1.5)
windows build only
This commit is contained in:
486
Foundation/src/Var.cpp
Normal file
486
Foundation/src/Var.cpp
Normal file
@@ -0,0 +1,486 @@
|
||||
//
|
||||
// Var.cpp
|
||||
//
|
||||
// $Id: //poco/svn/Foundation/src/Var.cpp#3 $
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Core
|
||||
// Module: Var
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/Dynamic/Struct.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Dynamic {
|
||||
|
||||
|
||||
Var::Var(): _pHolder(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Var::Var(const char* pVal):
|
||||
_pHolder(new VarHolderImpl<std::string>(pVal))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Var::Var(const Var& other):
|
||||
_pHolder(0)
|
||||
{
|
||||
if (other._pHolder)
|
||||
_pHolder = other._pHolder->clone();
|
||||
}
|
||||
|
||||
|
||||
Var::~Var()
|
||||
{
|
||||
delete _pHolder;
|
||||
}
|
||||
|
||||
|
||||
Var& Var::operator = (const Var& other)
|
||||
{
|
||||
Var tmp(other);
|
||||
swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
const Var Var::operator + (const Var& other) const
|
||||
{
|
||||
if (isInteger())
|
||||
{
|
||||
if(isSigned())
|
||||
return add<Poco::Int64>(other);
|
||||
else
|
||||
return add<Poco::UInt64>(other);
|
||||
}
|
||||
else if (isNumeric())
|
||||
return add<double>(other);
|
||||
else if (isString())
|
||||
return add<std::string>(other);
|
||||
else
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
}
|
||||
|
||||
|
||||
Var& Var::operator += (const Var& other)
|
||||
{
|
||||
if (isInteger())
|
||||
{
|
||||
if(isSigned())
|
||||
return *this = add<Poco::Int64>(other);
|
||||
else
|
||||
return *this = add<Poco::UInt64>(other);
|
||||
}
|
||||
else if (isNumeric())
|
||||
return *this = add<double>(other);
|
||||
else if (isString())
|
||||
return *this = add<std::string>(other);
|
||||
else
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
}
|
||||
|
||||
|
||||
const Var Var::operator - (const Var& other) const
|
||||
{
|
||||
if (isInteger())
|
||||
{
|
||||
if(isSigned())
|
||||
return subtract<Poco::Int64>(other);
|
||||
else
|
||||
return subtract<Poco::UInt64>(other);
|
||||
}
|
||||
else if (isNumeric())
|
||||
return subtract<double>(other);
|
||||
else
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
}
|
||||
|
||||
|
||||
Var& Var::operator -= (const Var& other)
|
||||
{
|
||||
if (isInteger())
|
||||
{
|
||||
if(isSigned())
|
||||
return *this = subtract<Poco::Int64>(other);
|
||||
else
|
||||
return *this = subtract<Poco::UInt64>(other);
|
||||
}
|
||||
else if (isNumeric())
|
||||
return *this = subtract<double>(other);
|
||||
else
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
}
|
||||
|
||||
|
||||
const Var Var::operator * (const Var& other) const
|
||||
{
|
||||
if (isInteger())
|
||||
{
|
||||
if(isSigned())
|
||||
return multiply<Poco::Int64>(other);
|
||||
else
|
||||
return multiply<Poco::UInt64>(other);
|
||||
}
|
||||
else if (isNumeric())
|
||||
return multiply<double>(other);
|
||||
else
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
}
|
||||
|
||||
|
||||
Var& Var::operator *= (const Var& other)
|
||||
{
|
||||
if (isInteger())
|
||||
{
|
||||
if(isSigned())
|
||||
return *this = multiply<Poco::Int64>(other);
|
||||
else
|
||||
return *this = multiply<Poco::UInt64>(other);
|
||||
}
|
||||
else if (isNumeric())
|
||||
return *this = multiply<double>(other);
|
||||
else
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
}
|
||||
|
||||
|
||||
const Var Var::operator / (const Var& other) const
|
||||
{
|
||||
if (isInteger())
|
||||
{
|
||||
if(isSigned())
|
||||
return divide<Poco::Int64>(other);
|
||||
else
|
||||
return divide<Poco::UInt64>(other);
|
||||
}
|
||||
else if (isNumeric())
|
||||
return divide<double>(other);
|
||||
else
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
}
|
||||
|
||||
|
||||
Var& Var::operator /= (const Var& other)
|
||||
{
|
||||
if (isInteger())
|
||||
{
|
||||
if(isSigned())
|
||||
return *this = divide<Poco::Int64>(other);
|
||||
else
|
||||
return *this = divide<Poco::UInt64>(other);
|
||||
}
|
||||
else if (isNumeric())
|
||||
return *this = divide<double>(other);
|
||||
else
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
}
|
||||
|
||||
|
||||
Var& Var::operator ++ ()
|
||||
{
|
||||
if (!isInteger())
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
|
||||
return *this = *this + 1;
|
||||
}
|
||||
|
||||
const Var Var::operator ++ (int)
|
||||
{
|
||||
if (!isInteger())
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
|
||||
Var tmp(*this);
|
||||
*this += 1;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Var& Var::operator -- ()
|
||||
{
|
||||
if (!isInteger())
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
|
||||
return *this = *this - 1;
|
||||
}
|
||||
|
||||
const Var Var::operator -- (int)
|
||||
{
|
||||
if (!isInteger())
|
||||
throw InvalidArgumentException("Invalid operation for this data type.");
|
||||
|
||||
Var tmp(*this);
|
||||
*this -= 1;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator == (const Var& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<std::string>() == other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator == (const char* other) const
|
||||
{
|
||||
if (isEmpty()) return false;
|
||||
return convert<std::string>() == other;
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator != (const Var& other) const
|
||||
{
|
||||
if (isEmpty() && other.isEmpty()) return false;
|
||||
else if (isEmpty() || other.isEmpty()) return true;
|
||||
|
||||
return convert<std::string>() != other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator != (const char* other) const
|
||||
{
|
||||
if (isEmpty()) return true;
|
||||
return convert<std::string>() != other;
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator < (const Var& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<std::string>() < other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator <= (const Var& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<std::string>() <= other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator > (const Var& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<std::string>() > other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator >= (const Var& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<std::string>() >= other.convert<std::string>();
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator || (const Var& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<bool>() || other.convert<bool>();
|
||||
}
|
||||
|
||||
|
||||
bool Var::operator && (const Var& other) const
|
||||
{
|
||||
if (isEmpty() || other.isEmpty()) return false;
|
||||
return convert<bool>() && other.convert<bool>();
|
||||
}
|
||||
|
||||
|
||||
void Var::empty()
|
||||
{
|
||||
delete _pHolder;
|
||||
_pHolder = 0;
|
||||
}
|
||||
|
||||
|
||||
Var& Var::operator [] (const std::string& name)
|
||||
{
|
||||
return holderImpl<DynamicStruct, InvalidAccessException>("Not an array.")->operator[](name);
|
||||
}
|
||||
|
||||
|
||||
const Var& Var::operator [] (const std::string& name) const
|
||||
{
|
||||
return const_cast<const Var&>(holderImpl<DynamicStruct,
|
||||
InvalidAccessException>("Not an array.")->operator[](name));
|
||||
}
|
||||
|
||||
|
||||
Var Var::parse(const std::string& val)
|
||||
{
|
||||
std::string::size_type t = 0;
|
||||
return parse(val, t);
|
||||
}
|
||||
|
||||
|
||||
Var Var::parse(const std::string& val, std::string::size_type& pos)
|
||||
{
|
||||
// { -> an Object==DynamicStruct
|
||||
// [ -> an array
|
||||
// '/" -> a string (strip '/")
|
||||
// other: also treat as string
|
||||
skipWhiteSpace(val, pos);
|
||||
if (pos < val.size())
|
||||
{
|
||||
switch (val[pos])
|
||||
{
|
||||
case '{':
|
||||
return parseObject(val, pos);
|
||||
case '[':
|
||||
return parseArray(val, pos);
|
||||
default:
|
||||
return parseString(val, pos);
|
||||
}
|
||||
}
|
||||
std::string empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
Var Var::parseObject(const std::string& val, std::string::size_type& pos)
|
||||
{
|
||||
poco_assert_dbg (val[pos] == '{');
|
||||
++pos;
|
||||
skipWhiteSpace(val, pos);
|
||||
DynamicStruct aStruct;
|
||||
while (val[pos] != '}' && pos < val.size())
|
||||
{
|
||||
std::string key = parseString(val, pos);
|
||||
skipWhiteSpace(val, pos);
|
||||
if (val[pos] != ':')
|
||||
throw DataFormatException("Incorrect object, must contain: key : value pairs");
|
||||
++pos; // skip past :
|
||||
Var value = parse(val, pos);
|
||||
aStruct.insert(key, value);
|
||||
skipWhiteSpace(val, pos);
|
||||
if (val[pos] == ',')
|
||||
{
|
||||
++pos;
|
||||
skipWhiteSpace(val, pos);
|
||||
}
|
||||
}
|
||||
if (val[pos] != '}')
|
||||
throw DataFormatException("Unterminated object");
|
||||
++pos;
|
||||
return aStruct;
|
||||
}
|
||||
|
||||
|
||||
Var Var::parseArray(const std::string& val, std::string::size_type& pos)
|
||||
{
|
||||
poco_assert_dbg (val[pos] == '[');
|
||||
++pos;
|
||||
skipWhiteSpace(val, pos);
|
||||
std::vector<Var> result;
|
||||
while (val[pos] != ']' && pos < val.size())
|
||||
{
|
||||
result.push_back(parse(val, pos));
|
||||
skipWhiteSpace(val, pos);
|
||||
if (val[pos] == ',')
|
||||
{
|
||||
++pos;
|
||||
skipWhiteSpace(val, pos);
|
||||
}
|
||||
}
|
||||
if (val[pos] != ']')
|
||||
throw DataFormatException("Unterminated array");
|
||||
++pos;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::string Var::parseString(const std::string& val, std::string::size_type& pos)
|
||||
{
|
||||
static const std::string STR_STOP("\"");
|
||||
static const std::string OTHER_STOP(" ,]}"); // we stop at space, ',', ']' or '}'
|
||||
|
||||
bool inString = false;
|
||||
//skip optional ' "
|
||||
if (val[pos] == '"')
|
||||
{
|
||||
inString = true;
|
||||
++pos;
|
||||
}
|
||||
|
||||
std::string::size_type stop = std::string::npos;
|
||||
if (inString)
|
||||
{
|
||||
stop = val.find_first_of(STR_STOP, pos);
|
||||
if (stop == std::string::npos)
|
||||
throw DataFormatException("Unterminated string");
|
||||
}
|
||||
else
|
||||
{
|
||||
// we stop at space, ',', ']' or '}' or end of string
|
||||
stop = val.find_first_of(OTHER_STOP, pos);
|
||||
if (stop == std::string::npos)
|
||||
stop = val.size();
|
||||
|
||||
std::string::size_type safeCheck = val.find_first_of(STR_STOP, pos);
|
||||
if (safeCheck != std::string::npos && safeCheck < stop)
|
||||
throw DataFormatException("Misplaced string termination char found");
|
||||
|
||||
}
|
||||
|
||||
// stop now points to the last char to be not included
|
||||
std::string result = val.substr(pos, stop - pos);
|
||||
++stop; // point past '/"
|
||||
pos = stop;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Var::skipWhiteSpace(const std::string& val, std::string::size_type& pos)
|
||||
{
|
||||
while (std::isspace(val[pos]))
|
||||
++pos;
|
||||
}
|
||||
|
||||
|
||||
std::string Var::toString(const Var& any)
|
||||
{
|
||||
std::string res;
|
||||
appendJSONString(res, any);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
Var& Var::structIndexOperator(VarHolderImpl<Struct<int> >* pStr, int n) const
|
||||
{
|
||||
return pStr->operator[](n);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Dynamic
|
||||
Reference in New Issue
Block a user