|
Packit |
01d647 |
/*
|
|
Packit |
01d647 |
Copyright (c) 2013 Johannes Häggqvist
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
01d647 |
of this software and associated documentation files (the "Software"), to deal
|
|
Packit |
01d647 |
in the Software without restriction, including without limitation the rights
|
|
Packit |
01d647 |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
Packit |
01d647 |
copies of the Software, and to permit persons to whom the Software is
|
|
Packit |
01d647 |
furnished to do so, subject to the following conditions:
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
The above copyright notice and this permission notice shall be included in
|
|
Packit |
01d647 |
all copies or substantial portions of the Software.
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
Packit |
01d647 |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
Packit |
01d647 |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
Packit |
01d647 |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
Packit |
01d647 |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
Packit |
01d647 |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
Packit |
01d647 |
THE SOFTWARE.
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef _WINDLL
|
|
Packit |
01d647 |
#define JzonAPI __declspec(dllexport)
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#include "Jzon.h"
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#include <sstream>
|
|
Packit |
01d647 |
#include <fstream>
|
|
Packit |
01d647 |
#include <stack>
|
|
Packit |
01d647 |
#include <algorithm>
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
namespace Jzon
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
class FormatInterpreter
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
FormatInterpreter()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
SetFormat(NoFormat);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
FormatInterpreter(const Format &format)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
SetFormat(format);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void SetFormat(const Format &format)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
this->format = format;
|
|
Packit |
01d647 |
indentationChar = (format.useTabs ? '\t' : ' ');
|
|
Packit |
01d647 |
spacing = (format.spacing ? " " : "");
|
|
Packit |
01d647 |
newline = (format.newline ? "\n" : spacing);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string GetIndentation(unsigned int level) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!format.newline)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return "";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return std::string(format.indentSize * level, indentationChar);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
inline const std::string &GetNewline() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return newline;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
inline const std::string &GetSpacing() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return spacing;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
private:
|
|
Packit |
01d647 |
Format format;
|
|
Packit |
01d647 |
char indentationChar;
|
|
Packit |
01d647 |
std::string newline;
|
|
Packit |
01d647 |
std::string spacing;
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
inline bool IsWhitespace(char c)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return (c == '\n' || c == ' ' || c == '\t' || c == '\r' || c == '\f');
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
inline bool IsNumber(char c)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return ((c >= '0' && c <= '9') || c == '.' || c == '-');
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Node::Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Node::~Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Object &Node::AsObject()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsObject())
|
|
Packit |
01d647 |
return static_cast<Object&>(*this);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
throw TypeException();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
const Object &Node::AsObject() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsObject())
|
|
Packit |
01d647 |
return static_cast<const Object&>(*this);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
throw TypeException();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Array &Node::AsArray()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsArray())
|
|
Packit |
01d647 |
return static_cast<Array&>(*this);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
throw TypeException();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
const Array &Node::AsArray() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsArray())
|
|
Packit |
01d647 |
return static_cast<const Array&>(*this);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
throw TypeException();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value &Node::AsValue()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsValue())
|
|
Packit |
01d647 |
return static_cast<Value&>(*this);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
throw TypeException();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
const Value &Node::AsValue() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsValue())
|
|
Packit |
01d647 |
return static_cast<const Value&>(*this);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
throw TypeException();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Node::Type Node::DetermineType(const std::string &json)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::string::const_iterator jsonIt = json.begin();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
while (jsonIt != json.end() && IsWhitespace(*jsonIt))
|
|
Packit |
01d647 |
++jsonIt;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (jsonIt == json.end())
|
|
Packit |
01d647 |
return T_VALUE;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
switch (*jsonIt)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
case '{' : return T_OBJECT;
|
|
Packit |
01d647 |
case '[' : return T_ARRAY;
|
|
Packit |
01d647 |
default : return T_VALUE;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Value::Value() : Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
SetNull();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::Value(const Value &rhs) : Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(rhs);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::Value(const Node &rhs) : Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const Value &value = rhs.AsValue();
|
|
Packit |
01d647 |
Set(value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::Value(ValueType type, const std::string &value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(type, value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::Value(const std::string &value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::Value(const char *value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::Value(const int value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::Value(const float value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::Value(const double value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::Value(const bool value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::~Value()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Node::Type Value::GetType() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return T_VALUE;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value::ValueType Value::GetValueType() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return type;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Value::ToString() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsNull())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return "null";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return valueStr;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
int Value::ToInt() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsNumber())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::stringstream sstr(valueStr);
|
|
Packit |
01d647 |
int val;
|
|
Packit |
01d647 |
sstr >> val;
|
|
Packit |
01d647 |
return val;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return 0;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
float Value::ToFloat() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsNumber())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::stringstream sstr(valueStr);
|
|
Packit |
01d647 |
float val;
|
|
Packit |
01d647 |
sstr >> val;
|
|
Packit |
01d647 |
return val;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return 0.f;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
double Value::ToDouble() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsNumber())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::stringstream sstr(valueStr);
|
|
Packit |
01d647 |
double val;
|
|
Packit |
01d647 |
sstr >> val;
|
|
Packit |
01d647 |
return val;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return 0.0;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
bool Value::ToBool() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (IsBool())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return (valueStr == "true");
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void Value::SetNull()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
valueStr = "";
|
|
Packit |
01d647 |
type = VT_NULL;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Value::Set(const Value &value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (this != &value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
valueStr = value.valueStr;
|
|
Packit |
01d647 |
type = value.type;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Value::Set(ValueType type, const std::string &value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
valueStr = value;
|
|
Packit |
01d647 |
this->type = type;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Value::Set(const std::string &value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
valueStr = UnescapeString(value);
|
|
Packit |
01d647 |
type = VT_STRING;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Value::Set(const char *value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
valueStr = UnescapeString(std::string(value));
|
|
Packit |
01d647 |
type = VT_STRING;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Value::Set(const int value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::stringstream sstr;
|
|
Packit |
01d647 |
sstr << value;
|
|
Packit |
01d647 |
valueStr = sstr.str();
|
|
Packit |
01d647 |
type = VT_NUMBER;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Value::Set(const float value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::stringstream sstr;
|
|
Packit |
01d647 |
sstr << value;
|
|
Packit |
01d647 |
valueStr = sstr.str();
|
|
Packit |
01d647 |
type = VT_NUMBER;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Value::Set(const double value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::stringstream sstr;
|
|
Packit |
01d647 |
sstr << value;
|
|
Packit |
01d647 |
valueStr = sstr.str();
|
|
Packit |
01d647 |
type = VT_NUMBER;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Value::Set(const bool value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (value)
|
|
Packit |
01d647 |
valueStr = "true";
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
valueStr = "false";
|
|
Packit |
01d647 |
type = VT_BOOL;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Value &Value::operator=(const Value &rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (this != &rhs)
|
|
Packit |
01d647 |
Set(rhs);
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value &Value::operator=(const Node &rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (this != &rhs)
|
|
Packit |
01d647 |
Set(rhs.AsValue());
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value &Value::operator=(const std::string &rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(rhs);
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value &Value::operator=(const char *rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(rhs);
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value &Value::operator=(const int rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(rhs);
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value &Value::operator=(const float rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(rhs);
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value &Value::operator=(const double rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(rhs);
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Value &Value::operator=(const bool rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Set(rhs);
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool Value::operator==(const Value &other) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return ((type == other.type)&&(valueStr == other.valueStr));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
bool Value::operator!=(const Value &other) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return !(*this == other);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Node *Value::GetCopy() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return new Value(*this);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// This is not the most beautiful place for these, but it'll do
|
|
Packit |
01d647 |
static const char charsUnescaped[] = { '\\' , '/' , '\"' , '\n' , '\t' , '\b' , '\f' , '\r' };
|
|
Packit |
01d647 |
static const char *charsEscaped[] = { "\\\\", "\\/", "\\\"", "\\n", "\\t", "\\b", "\\f", "\\r" };
|
|
Packit |
01d647 |
static const unsigned int numEscapeChars = 8;
|
|
Packit |
01d647 |
static const char nullUnescaped = '\0';
|
|
Packit |
01d647 |
static const char *nullEscaped = "\0\0";
|
|
Packit |
01d647 |
const char *&getEscaped(const char &c)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
for (unsigned int i = 0; i < numEscapeChars; ++i)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const char &ue = charsUnescaped[i];
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (c == ue)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const char *&e = charsEscaped[i];
|
|
Packit |
01d647 |
return e;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return nullEscaped;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
const char &getUnescaped(const char &c1, const char &c2)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
for (unsigned int i = 0; i < numEscapeChars; ++i)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const char *&e = charsEscaped[i];
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (c1 == e[0] && c2 == e[1])
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const char &ue = charsUnescaped[i];
|
|
Packit |
01d647 |
return ue;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return nullUnescaped;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Value::EscapeString(const std::string &value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::string escaped;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for (std::string::const_iterator it = value.begin(); it != value.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const char &c = (*it);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char *&a = getEscaped(c);
|
|
Packit |
01d647 |
if (a[0] != '\0')
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
escaped += a[0];
|
|
Packit |
01d647 |
escaped += a[1];
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
escaped += c;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return escaped;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
std::string Value::UnescapeString(const std::string &value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::string unescaped;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for (std::string::const_iterator it = value.begin(); it != value.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const char &c = (*it);
|
|
Packit |
01d647 |
char c2 = '\0';
|
|
Packit |
01d647 |
if (it+1 != value.end())
|
|
Packit |
01d647 |
c2 = *(it+1);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char &a = getUnescaped(c, c2);
|
|
Packit |
01d647 |
if (a != '\0')
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
unescaped += a;
|
|
Packit |
01d647 |
if (it+1 != value.end())
|
|
Packit |
01d647 |
++it;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
unescaped += c;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return unescaped;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Object::Object() : Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Object::Object(const Object &other) : Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
for (ChildList::const_iterator it = other.children.begin(); it != other.children.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const std::string &name = (*it).first;
|
|
Packit |
01d647 |
Node &value = *(*it).second;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
children.push_back(NamedNodePtr(name, value.GetCopy()));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Object::Object(const Node &other) : Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const Object &object = other.AsObject();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for (ChildList::const_iterator it = object.children.begin(); it != object.children.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const std::string &name = (*it).first;
|
|
Packit |
01d647 |
Node &value = *(*it).second;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
children.push_back(NamedNodePtr(name, value.GetCopy()));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Object::~Object()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Clear();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Node::Type Object::GetType() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return T_OBJECT;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void Object::Add(const std::string &name, Node &node)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
children.push_back(NamedNodePtr(name, node.GetCopy()));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Object::Add(const std::string &name, Value node)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
children.push_back(NamedNodePtr(name, new Value(node)));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Object::Remove(const std::string &name)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if ((*it).first == name)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
delete (*it).second;
|
|
Packit |
01d647 |
children.erase(it);
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Object::Clear()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
delete (*it).second;
|
|
Packit |
01d647 |
(*it).second = NULL;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
children.clear();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Object::iterator Object::begin()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!children.empty())
|
|
Packit |
01d647 |
return Object::iterator(&children.front());
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
return Object::iterator(NULL);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Object::const_iterator Object::begin() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!children.empty())
|
|
Packit |
01d647 |
return Object::const_iterator(&children.front());
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
return Object::const_iterator(NULL);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Object::iterator Object::end()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!children.empty())
|
|
Packit |
01d647 |
return Object::iterator(&children.back()+1);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
return Object::iterator(NULL);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Object::const_iterator Object::end() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!children.empty())
|
|
Packit |
01d647 |
return Object::const_iterator(&children.back()+1);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
return Object::const_iterator(NULL);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool Object::Has(const std::string &name) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
for (ChildList::const_iterator it = children.begin(); it != children.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if ((*it).first == name)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return true;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
size_t Object::GetCount() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return children.size();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Node &Object::Get(const std::string &name) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
for (ChildList::const_iterator it = children.begin(); it != children.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if ((*it).first == name)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return *(*it).second;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
throw NotFoundException();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Node *Object::GetCopy() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return new Object(*this);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Array::Array() : Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Array::Array(const Array &other) : Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
for (ChildList::const_iterator it = other.children.begin(); it != other.children.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const Node &value = *(*it);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
children.push_back(value.GetCopy());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Array::Array(const Node &other) : Node()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const Array &array = other.AsArray();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for (ChildList::const_iterator it = array.children.begin(); it != array.children.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const Node &value = *(*it);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
children.push_back(value.GetCopy());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Array::~Array()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Clear();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Node::Type Array::GetType() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return T_ARRAY;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void Array::Add(Node &node)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
children.push_back(node.GetCopy());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Array::Add(Value node)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
children.push_back(new Value(node));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Array::Remove(size_t index)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (index < children.size())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
ChildList::iterator it = children.begin()+index;
|
|
Packit |
01d647 |
delete (*it);
|
|
Packit |
01d647 |
children.erase(it);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Array::Clear()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
delete (*it);
|
|
Packit |
01d647 |
(*it) = NULL;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
children.clear();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Array::iterator Array::begin()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!children.empty())
|
|
Packit |
01d647 |
return Array::iterator(&children.front());
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
return Array::iterator(NULL);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Array::const_iterator Array::begin() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!children.empty())
|
|
Packit |
01d647 |
return Array::const_iterator(&children.front());
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
return Array::const_iterator(NULL);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Array::iterator Array::end()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!children.empty())
|
|
Packit |
01d647 |
return Array::iterator(&children.back()+1);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
return Array::iterator(NULL);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Array::const_iterator Array::end() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!children.empty())
|
|
Packit |
01d647 |
return Array::const_iterator(&children.back()+1);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
return Array::const_iterator(NULL);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
size_t Array::GetCount() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return children.size();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Node &Array::Get(size_t index) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (index < children.size())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return *children.at(index);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
throw NotFoundException();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Node *Array::GetCopy() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return new Array(*this);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
FileWriter::FileWriter(const std::string &filename) : filename(filename)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
FileWriter::~FileWriter()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void FileWriter::WriteFile(const std::string &filename, const Node &root, const Format &format)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
FileWriter writer(filename);
|
|
Packit |
01d647 |
writer.Write(root, format);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void FileWriter::Write(const Node &root, const Format &format)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Writer writer(root, format);
|
|
Packit |
01d647 |
writer.Write();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::fstream file(filename.c_str(), std::ios::out | std::ios::trunc);
|
|
Packit |
01d647 |
file << writer.GetResult();
|
|
Packit |
01d647 |
file.close();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
FileReader::FileReader(const std::string &filename)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!loadFile(filename, json))
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = "Failed to load file";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
FileReader::~FileReader()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool FileReader::ReadFile(const std::string &filename, Node &node)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
FileReader reader(filename);
|
|
Packit |
01d647 |
return reader.Read(node);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool FileReader::Read(Node &node)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!error.empty())
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Parser parser(node, json);
|
|
Packit |
01d647 |
if (!parser.Parse())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = parser.GetError();
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return true;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Node::Type FileReader::DetermineType()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return Node::DetermineType(json);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const std::string &FileReader::GetError() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return error;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool FileReader::loadFile(const std::string &filename, std::string &json)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::fstream file(filename.c_str(), std::ios::in | std::ios::binary);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (!file.is_open())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
file.seekg(0, std::ios::end);
|
|
Packit |
01d647 |
std::ios::pos_type size = file.tellg();
|
|
Packit |
01d647 |
file.seekg(0, std::ios::beg);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
json.resize(static_cast<std::string::size_type>(size), '\0');
|
|
Packit |
01d647 |
file.read(&json[0], size);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return true;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Writer::Writer(const Node &root, const Format &format) : fi(new FormatInterpreter), root(root)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
SetFormat(format);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Writer::~Writer()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
delete fi;
|
|
Packit |
01d647 |
fi = NULL;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void Writer::SetFormat(const Format &format)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
fi->SetFormat(format);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
const std::string &Writer::Write()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
result.clear();
|
|
Packit |
01d647 |
writeNode(root, 0);
|
|
Packit |
01d647 |
return result;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const std::string &Writer::GetResult() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return result;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void Writer::writeNode(const Node &node, unsigned int level)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
switch (node.GetType())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
case Node::T_OBJECT : writeObject(node.AsObject(), level); break;
|
|
Packit |
01d647 |
case Node::T_ARRAY : writeArray(node.AsArray(), level); break;
|
|
Packit |
01d647 |
case Node::T_VALUE : writeValue(node.AsValue()); break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Writer::writeObject(const Object &node, unsigned int level)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
result += "{" + fi->GetNewline();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for (Object::const_iterator it = node.begin(); it != node.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const std::string &name = (*it).first;
|
|
Packit |
01d647 |
// const Node &value = (*it).second;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (it != node.begin())
|
|
Packit |
01d647 |
result += "," + fi->GetNewline();
|
|
Packit |
01d647 |
result += fi->GetIndentation(level+1) + "\""+name+"\"" + ":" + fi->GetSpacing();
|
|
Packit |
01d647 |
writeNode((*it).second, level+1);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
result += fi->GetNewline() + fi->GetIndentation(level) + "}";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Writer::writeArray(const Array &node, unsigned int level)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
result += "[" + fi->GetNewline();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for (Array::const_iterator it = node.begin(); it != node.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const Node &value = (*it);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (it != node.begin())
|
|
Packit |
01d647 |
result += "," + fi->GetNewline();
|
|
Packit |
01d647 |
result += fi->GetIndentation(level+1);
|
|
Packit |
01d647 |
writeNode(value, level+1);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
result += fi->GetNewline() + fi->GetIndentation(level) + "]";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Writer::writeValue(const Value &node)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (node.IsString())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
result += "\""+Value::EscapeString(node.ToString())+"\"";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
result += node.ToString();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Parser::Parser(Node &root) : jsonSize(0), cursor(0), root(root)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Parser::Parser(Node &root, const std::string &json) : jsonSize(0), cursor(0), root(root)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
SetJson(json);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
Parser::~Parser()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void Parser::SetJson(const std::string &json)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
this->json = json;
|
|
Packit |
01d647 |
jsonSize = json.size();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
bool Parser::Parse()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
cursor = 0;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
tokenize();
|
|
Packit |
01d647 |
bool success = assemble();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return success;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const std::string &Parser::GetError() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return error;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void Parser::tokenize()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Token token = T_UNKNOWN;
|
|
Packit |
01d647 |
std::string valueBuffer;
|
|
Packit |
01d647 |
bool saveBuffer;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for (; cursor < jsonSize; ++cursor)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
char c = json.at(cursor);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (IsWhitespace(c))
|
|
Packit |
01d647 |
continue;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
saveBuffer = true;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
switch (c)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
case '{' :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
token = T_OBJ_BEGIN;
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case '}' :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
token = T_OBJ_END;
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case '[' :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
token = T_ARRAY_BEGIN;
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case ']' :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
token = T_ARRAY_END;
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case ',' :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
token = T_SEPARATOR_NODE;
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case ':' :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
token = T_SEPARATOR_NAME;
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case '"' :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
token = T_VALUE;
|
|
Packit |
01d647 |
readString();
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case '/' :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
char p = peek();
|
|
Packit |
01d647 |
if (p == '*')
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
jumpToCommentEnd();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else if (p == '/')
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
jumpToNext('\n');
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
default :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
valueBuffer += c;
|
|
Packit |
01d647 |
saveBuffer = false;
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ((saveBuffer || cursor == jsonSize-1) && (!valueBuffer.empty())) // Always save buffer on the last character
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (interpretValue(valueBuffer))
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
tokens.push(T_VALUE);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
// Store the unknown token, so we can show it to the user
|
|
Packit |
01d647 |
data.push(MakePair(Value::VT_STRING, valueBuffer));
|
|
Packit |
01d647 |
tokens.push(T_UNKNOWN);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
valueBuffer.clear();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// Push the token last so that any
|
|
Packit |
01d647 |
// value token will get pushed first
|
|
Packit |
01d647 |
// from above.
|
|
Packit |
01d647 |
// If saveBuffer is false, it means that
|
|
Packit |
01d647 |
// we are in the middle of a value, so we
|
|
Packit |
01d647 |
// don't want to push any tokens now.
|
|
Packit |
01d647 |
if (saveBuffer)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
tokens.push(token);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
bool Parser::assemble()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::stack<Pair<std::string, Node*> > nodeStack;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string name = "";
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Token token;
|
|
Packit |
01d647 |
while (!tokens.empty())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
token = tokens.front();
|
|
Packit |
01d647 |
tokens.pop();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
switch (token)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
case T_UNKNOWN :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const std::string &unknownToken = data.front().second;
|
|
Packit |
01d647 |
error = "Unknown token: "+unknownToken;
|
|
Packit |
01d647 |
data.pop();
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case T_OBJ_BEGIN :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Node *node = NULL;
|
|
Packit |
01d647 |
if (nodeStack.empty())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!root.IsObject())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = "The given root node is not an object";
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
node = &roo;;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
node = new Object;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
nodeStack.push(MakePair(name, node));
|
|
Packit |
01d647 |
name.clear();
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case T_ARRAY_BEGIN :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Node *node = NULL;
|
|
Packit |
01d647 |
if (nodeStack.empty())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!root.IsArray())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = "The given root node is not an array";
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
node = &roo;;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
node = new Array;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
nodeStack.push(MakePair(name, node));
|
|
Packit |
01d647 |
name.clear();
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case T_OBJ_END :
|
|
Packit |
01d647 |
case T_ARRAY_END :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (nodeStack.empty())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = "Found end of object or array without beginning";
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if (token == T_OBJ_END && !nodeStack.top().second->IsObject())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = "Mismatched end and beginning of object";
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if (token == T_ARRAY_END && !nodeStack.top().second->IsArray())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = "Mismatched end and beginning of array";
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string name = nodeStack.top().first;
|
|
Packit |
01d647 |
Node *node = nodeStack.top().second;
|
|
Packit |
01d647 |
nodeStack.pop();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (!nodeStack.empty())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (nodeStack.top().second->IsObject())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
nodeStack.top().second->AsObject().Add(name, *node);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else if (nodeStack.top().second->IsArray())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
nodeStack.top().second->AsArray().Add(*node);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = "Can only add elements to objects and arrays";
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
delete node;
|
|
Packit |
01d647 |
node = NULL;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case T_VALUE :
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!tokens.empty() && tokens.front() == T_SEPARATOR_NAME)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
tokens.pop();
|
|
Packit |
01d647 |
if (data.front().first != Value::VT_STRING)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = "A name has to be a string";
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
name = data.front().second;
|
|
Packit |
01d647 |
data.pop();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Node *node = NULL;
|
|
Packit |
01d647 |
if (nodeStack.empty())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!root.IsValue())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
error = "The given root node is not a value";
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
node = &roo;;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
node = new Value;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (data.front().first == Value::VT_STRING)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
static_cast<Value*>(node)->Set(data.front().second); // This method calls UnescapeString()
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
static_cast<Value*>(node)->Set(data.front().first, data.front().second);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
data.pop();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (!nodeStack.empty())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (nodeStack.top().second->IsObject())
|
|
Packit |
01d647 |
nodeStack.top().second->AsObject().Add(name, *node);
|
|
Packit |
01d647 |
else if (nodeStack.top().second->IsArray())
|
|
Packit |
01d647 |
nodeStack.top().second->AsArray().Add(*node);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
delete node;
|
|
Packit |
01d647 |
node = NULL;
|
|
Packit |
01d647 |
name.clear();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
nodeStack.push(MakePair(name, node));
|
|
Packit |
01d647 |
name.clear();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
case T_SEPARATOR_NAME :
|
|
Packit |
01d647 |
case T_SEPARATOR_NODE : break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return true;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
char Parser::peek()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (cursor < jsonSize-1)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return json.at(cursor+1);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return '\0';
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Parser::jumpToNext(char c)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
++cursor;
|
|
Packit |
01d647 |
while (cursor < jsonSize && json.at(cursor) != c)
|
|
Packit |
01d647 |
++cursor;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
void Parser::jumpToCommentEnd()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
++cursor;
|
|
Packit |
01d647 |
char c1 = '\0';
|
|
Packit |
01d647 |
for (; cursor < jsonSize; ++cursor)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
char c2 = json.at(cursor);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (c1 == '*' && c2 == '/')
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
c1 = c2;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void Parser::readString()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (json.at(cursor) != '"')
|
|
Packit |
01d647 |
return;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string str;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
++cursor;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
char c1 = '\0';
|
|
Packit |
01d647 |
for (; cursor < jsonSize; ++cursor)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
char c2 = json.at(cursor);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (c1 != '\\' && c2 == '"')
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
str += c2;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
c1 = c2;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
data.push(MakePair(Value::VT_STRING, str));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
bool Parser::interpretValue(const std::string &value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::string upperValue(value.size(), '\0');
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::transform(value.begin(), value.end(), upperValue.begin(), toupper);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (upperValue == "NULL")
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
data.push(MakePair(Value::VT_NULL, std::string("")));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else if (upperValue == "TRUE")
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
data.push(MakePair(Value::VT_BOOL, std::string("true")));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else if (upperValue == "FALSE")
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
data.push(MakePair(Value::VT_BOOL, std::string("false")));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
bool number = true;
|
|
Packit |
01d647 |
for (std::string::const_iterator it = value.begin(); it != value.end(); ++it)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (!IsNumber(*it))
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
number = false;
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (number)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
data.push(MakePair(Value::VT_NUMBER, value));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return true;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|