mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-02 00:10:22 +02:00
Unify formatting
This commit is contained in:
parent
2632ab04f5
commit
18bbccd167
@ -11,9 +11,9 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "JsonNode.h"
|
#include "JsonNode.h"
|
||||||
|
|
||||||
#include "filesystem/Filesystem.h"
|
|
||||||
#include "JsonParser.h"
|
#include "JsonParser.h"
|
||||||
#include "JsonWriter.h"
|
#include "JsonWriter.h"
|
||||||
|
#include "filesystem/Filesystem.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -40,7 +40,7 @@ Node & resolvePointer(Node & in, const std::string & pointer)
|
|||||||
|
|
||||||
auto index = boost::lexical_cast<size_t>(entry);
|
auto index = boost::lexical_cast<size_t>(entry);
|
||||||
|
|
||||||
if (in.Vector().size() > index)
|
if(in.Vector().size() > index)
|
||||||
return in.Vector()[index].resolvePointer(remainer);
|
return in.Vector()[index].resolvePointer(remainer);
|
||||||
}
|
}
|
||||||
return in[entry].resolvePointer(remainer);
|
return in[entry].resolvePointer(remainer);
|
||||||
@ -55,36 +55,43 @@ class CModHandler;
|
|||||||
static const JsonNode nullNode;
|
static const JsonNode nullNode;
|
||||||
|
|
||||||
JsonNode::JsonNode(bool boolean)
|
JsonNode::JsonNode(bool boolean)
|
||||||
:data(boolean)
|
: data(boolean)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
JsonNode::JsonNode(int32_t number)
|
JsonNode::JsonNode(int32_t number)
|
||||||
:data(static_cast<int64_t>(number))
|
: data(static_cast<int64_t>(number))
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
JsonNode::JsonNode(uint32_t number)
|
JsonNode::JsonNode(uint32_t number)
|
||||||
:data(static_cast<int64_t>(number))
|
: data(static_cast<int64_t>(number))
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
JsonNode::JsonNode(int64_t number)
|
JsonNode::JsonNode(int64_t number)
|
||||||
:data(number)
|
: data(number)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
JsonNode::JsonNode(double number)
|
JsonNode::JsonNode(double number)
|
||||||
:data(number)
|
: data(number)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
JsonNode::JsonNode(const std::string & string)
|
JsonNode::JsonNode(const std::string & string)
|
||||||
:data(string)
|
: data(string)
|
||||||
{}
|
|
||||||
|
|
||||||
JsonNode::JsonNode(const std::byte *data, size_t datasize)
|
|
||||||
:JsonNode(data, datasize, JsonParsingSettings())
|
|
||||||
{}
|
|
||||||
|
|
||||||
JsonNode::JsonNode(const std::byte *data, size_t datasize, const JsonParsingSettings & parserSettings)
|
|
||||||
{
|
{
|
||||||
JsonParser parser(reinterpret_cast<const char*>(data), datasize, parserSettings);
|
}
|
||||||
|
|
||||||
|
JsonNode::JsonNode(const std::byte * data, size_t datasize)
|
||||||
|
: JsonNode(data, datasize, JsonParsingSettings())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode::JsonNode(const std::byte * data, size_t datasize, const JsonParsingSettings & parserSettings)
|
||||||
|
{
|
||||||
|
JsonParser parser(reinterpret_cast<const char *>(data), datasize, parserSettings);
|
||||||
*this = parser.parse("<unknown>");
|
*this = parser.parse("<unknown>");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,33 +99,33 @@ JsonNode::JsonNode(const JsonPath & fileURI)
|
|||||||
{
|
{
|
||||||
auto file = CResourceHandler::get()->load(fileURI)->readAll();
|
auto file = CResourceHandler::get()->load(fileURI)->readAll();
|
||||||
|
|
||||||
JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second, JsonParsingSettings());
|
JsonParser parser(reinterpret_cast<char *>(file.first.get()), file.second, JsonParsingSettings());
|
||||||
*this = parser.parse(fileURI.getName());
|
*this = parser.parse(fileURI.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode::JsonNode(const JsonPath & fileURI, const std::string & idx)
|
JsonNode::JsonNode(const JsonPath & fileURI, const std::string & idx)
|
||||||
{
|
{
|
||||||
auto file = CResourceHandler::get(idx)->load(fileURI)->readAll();
|
auto file = CResourceHandler::get(idx)->load(fileURI)->readAll();
|
||||||
|
|
||||||
JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second, JsonParsingSettings());
|
JsonParser parser(reinterpret_cast<char *>(file.first.get()), file.second, JsonParsingSettings());
|
||||||
*this = parser.parse(fileURI.getName());
|
*this = parser.parse(fileURI.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode::JsonNode(const JsonPath & fileURI, bool &isValidSyntax)
|
JsonNode::JsonNode(const JsonPath & fileURI, bool & isValidSyntax)
|
||||||
{
|
{
|
||||||
auto file = CResourceHandler::get()->load(fileURI)->readAll();
|
auto file = CResourceHandler::get()->load(fileURI)->readAll();
|
||||||
|
|
||||||
JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second, JsonParsingSettings());
|
JsonParser parser(reinterpret_cast<char *>(file.first.get()), file.second, JsonParsingSettings());
|
||||||
*this = parser.parse(fileURI.getName());
|
*this = parser.parse(fileURI.getName());
|
||||||
isValidSyntax = parser.isValid();
|
isValidSyntax = parser.isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonNode::operator == (const JsonNode &other) const
|
bool JsonNode::operator==(const JsonNode & other) const
|
||||||
{
|
{
|
||||||
return data == other.data;
|
return data == other.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonNode::operator != (const JsonNode &other) const
|
bool JsonNode::operator!=(const JsonNode & other) const
|
||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
@ -146,18 +153,20 @@ bool JsonNode::getOverrideFlag() const
|
|||||||
void JsonNode::setModScope(const std::string & metadata, bool recursive)
|
void JsonNode::setModScope(const std::string & metadata, bool recursive)
|
||||||
{
|
{
|
||||||
modScope = metadata;
|
modScope = metadata;
|
||||||
if (recursive)
|
if(recursive)
|
||||||
{
|
{
|
||||||
switch (getType())
|
switch(getType())
|
||||||
{
|
{
|
||||||
break; case JsonType::DATA_VECTOR:
|
break;
|
||||||
|
case JsonType::DATA_VECTOR:
|
||||||
{
|
{
|
||||||
for(auto & node : Vector())
|
for(auto & node : Vector())
|
||||||
{
|
{
|
||||||
node.setModScope(metadata);
|
node.setModScope(metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break; case JsonType::DATA_STRUCT:
|
break;
|
||||||
|
case JsonType::DATA_STRUCT:
|
||||||
{
|
{
|
||||||
for(auto & node : Struct())
|
for(auto & node : Struct())
|
||||||
{
|
{
|
||||||
@ -170,7 +179,7 @@ void JsonNode::setModScope(const std::string & metadata, bool recursive)
|
|||||||
|
|
||||||
void JsonNode::setType(JsonType Type)
|
void JsonNode::setType(JsonType Type)
|
||||||
{
|
{
|
||||||
if (getType() == Type)
|
if(getType() == Type)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//float<->int conversion
|
//float<->int conversion
|
||||||
@ -190,13 +199,27 @@ void JsonNode::setType(JsonType Type)
|
|||||||
//Set new node type
|
//Set new node type
|
||||||
switch(Type)
|
switch(Type)
|
||||||
{
|
{
|
||||||
break; case JsonType::DATA_NULL: data = JsonData();
|
case JsonType::DATA_NULL:
|
||||||
break; case JsonType::DATA_BOOL: data = JsonData(false);
|
data = JsonData();
|
||||||
break; case JsonType::DATA_FLOAT: data = JsonData(static_cast<double>(0.0));
|
break;
|
||||||
break; case JsonType::DATA_STRING: data = JsonData(std::string());
|
case JsonType::DATA_BOOL:
|
||||||
break; case JsonType::DATA_VECTOR: data = JsonData(JsonVector());
|
data = JsonData(false);
|
||||||
break; case JsonType::DATA_STRUCT: data = JsonData(JsonMap());
|
break;
|
||||||
break; case JsonType::DATA_INTEGER: data = JsonData(static_cast<si64>(0));
|
case JsonType::DATA_FLOAT:
|
||||||
|
data = JsonData(static_cast<double>(0.0));
|
||||||
|
break;
|
||||||
|
case JsonType::DATA_STRING:
|
||||||
|
data = JsonData(std::string());
|
||||||
|
break;
|
||||||
|
case JsonType::DATA_VECTOR:
|
||||||
|
data = JsonData(JsonVector());
|
||||||
|
break;
|
||||||
|
case JsonType::DATA_STRUCT:
|
||||||
|
data = JsonData(JsonMap());
|
||||||
|
break;
|
||||||
|
case JsonType::DATA_INTEGER:
|
||||||
|
data = JsonData(static_cast<si64>(0));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,18 +252,18 @@ bool JsonNode::containsBaseData() const
|
|||||||
{
|
{
|
||||||
switch(getType())
|
switch(getType())
|
||||||
{
|
{
|
||||||
case JsonType::DATA_NULL:
|
case JsonType::DATA_NULL:
|
||||||
return false;
|
return false;
|
||||||
case JsonType::DATA_STRUCT:
|
case JsonType::DATA_STRUCT:
|
||||||
for(const auto & elem : Struct())
|
for(const auto & elem : Struct())
|
||||||
{
|
{
|
||||||
if(elem.second.containsBaseData())
|
if(elem.second.containsBaseData())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
//other types (including vector) cannot be extended via merge
|
//other types (including vector) cannot be extended via merge
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,14 +271,14 @@ bool JsonNode::isCompact() const
|
|||||||
{
|
{
|
||||||
switch(getType())
|
switch(getType())
|
||||||
{
|
{
|
||||||
case JsonType::DATA_VECTOR:
|
case JsonType::DATA_VECTOR:
|
||||||
for(const JsonNode & elem : Vector())
|
for(const JsonNode & elem : Vector())
|
||||||
{
|
{
|
||||||
if(!elem.isCompact())
|
if(!elem.isCompact())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case JsonType::DATA_STRUCT:
|
case JsonType::DATA_STRUCT:
|
||||||
{
|
{
|
||||||
auto propertyCount = Struct().size();
|
auto propertyCount = Struct().size();
|
||||||
if(propertyCount == 0)
|
if(propertyCount == 0)
|
||||||
@ -263,9 +286,9 @@ bool JsonNode::isCompact() const
|
|||||||
else if(propertyCount == 1)
|
else if(propertyCount == 1)
|
||||||
return Struct().begin()->second.isCompact();
|
return Struct().begin()->second.isCompact();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +308,7 @@ bool JsonNode::TryBoolFromString(bool & success) const
|
|||||||
|
|
||||||
if(success)
|
if(success)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
success = boolParamStr == "false";
|
success = boolParamStr == "false";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -337,7 +360,7 @@ bool JsonNode::Bool() const
|
|||||||
{
|
{
|
||||||
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_BOOL);
|
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_BOOL);
|
||||||
|
|
||||||
if (getType() == JsonType::DATA_BOOL)
|
if(getType() == JsonType::DATA_BOOL)
|
||||||
return std::get<bool>(data);
|
return std::get<bool>(data);
|
||||||
|
|
||||||
return boolDefault;
|
return boolDefault;
|
||||||
@ -376,7 +399,7 @@ const std::string & JsonNode::String() const
|
|||||||
{
|
{
|
||||||
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRING);
|
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRING);
|
||||||
|
|
||||||
if (getType() == JsonType::DATA_STRING)
|
if(getType() == JsonType::DATA_STRING)
|
||||||
return std::get<std::string>(data);
|
return std::get<std::string>(data);
|
||||||
|
|
||||||
return stringDefault;
|
return stringDefault;
|
||||||
@ -387,7 +410,7 @@ const JsonVector & JsonNode::Vector() const
|
|||||||
{
|
{
|
||||||
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_VECTOR);
|
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_VECTOR);
|
||||||
|
|
||||||
if (getType() == JsonType::DATA_VECTOR)
|
if(getType() == JsonType::DATA_VECTOR)
|
||||||
return std::get<JsonVector>(data);
|
return std::get<JsonVector>(data);
|
||||||
|
|
||||||
return vectorDefault;
|
return vectorDefault;
|
||||||
@ -398,7 +421,7 @@ const JsonMap & JsonNode::Struct() const
|
|||||||
{
|
{
|
||||||
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRUCT);
|
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRUCT);
|
||||||
|
|
||||||
if (getType() == JsonType::DATA_STRUCT)
|
if(getType() == JsonType::DATA_STRUCT)
|
||||||
return std::get<JsonMap>(data);
|
return std::get<JsonMap>(data);
|
||||||
|
|
||||||
return mapDefault;
|
return mapDefault;
|
||||||
@ -412,32 +435,32 @@ JsonNode & JsonNode::operator[](const std::string & child)
|
|||||||
const JsonNode & JsonNode::operator[](const std::string & child) const
|
const JsonNode & JsonNode::operator[](const std::string & child) const
|
||||||
{
|
{
|
||||||
auto it = Struct().find(child);
|
auto it = Struct().find(child);
|
||||||
if (it != Struct().end())
|
if(it != Struct().end())
|
||||||
return it->second;
|
return it->second;
|
||||||
return nullNode;
|
return nullNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode & JsonNode::operator[](size_t child)
|
JsonNode & JsonNode::operator[](size_t child)
|
||||||
{
|
{
|
||||||
if (child >= Vector().size() )
|
if(child >= Vector().size())
|
||||||
Vector().resize(child + 1);
|
Vector().resize(child + 1);
|
||||||
return Vector()[child];
|
return Vector()[child];
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonNode & JsonNode::operator[](size_t child) const
|
const JsonNode & JsonNode::operator[](size_t child) const
|
||||||
{
|
{
|
||||||
if (child < Vector().size() )
|
if(child < Vector().size())
|
||||||
return Vector()[child];
|
return Vector()[child];
|
||||||
|
|
||||||
return nullNode;
|
return nullNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer) const
|
const JsonNode & JsonNode::resolvePointer(const std::string & jsonPointer) const
|
||||||
{
|
{
|
||||||
return ::resolvePointer(*this, jsonPointer);
|
return ::resolvePointer(*this, jsonPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer)
|
JsonNode & JsonNode::resolvePointer(const std::string & jsonPointer)
|
||||||
{
|
{
|
||||||
return ::resolvePointer(*this, jsonPointer);
|
return ::resolvePointer(*this, jsonPointer);
|
||||||
}
|
}
|
||||||
@ -445,7 +468,7 @@ JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer)
|
|||||||
std::vector<std::byte> JsonNode::toBytes() const
|
std::vector<std::byte> JsonNode::toBytes() const
|
||||||
{
|
{
|
||||||
std::string jsonString = toString();
|
std::string jsonString = toString();
|
||||||
auto dataBegin = reinterpret_cast<const std::byte*>(jsonString.data());
|
auto dataBegin = reinterpret_cast<const std::byte *>(jsonString.data());
|
||||||
auto dataEnd = dataBegin + jsonString.size();
|
auto dataEnd = dataBegin + jsonString.size();
|
||||||
std::vector<std::byte> result(dataBegin, dataEnd);
|
std::vector<std::byte> result(dataBegin, dataEnd);
|
||||||
return result;
|
return result;
|
||||||
|
@ -58,6 +58,7 @@ private:
|
|||||||
std::string modScope;
|
std::string modScope;
|
||||||
|
|
||||||
bool overrideFlag = false;
|
bool overrideFlag = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonNode() = default;
|
JsonNode() = default;
|
||||||
|
|
||||||
@ -78,8 +79,8 @@ public:
|
|||||||
explicit JsonNode(const JsonPath & fileURI, const std::string & modName);
|
explicit JsonNode(const JsonPath & fileURI, const std::string & modName);
|
||||||
explicit JsonNode(const JsonPath & fileURI, bool & isValidSyntax);
|
explicit JsonNode(const JsonPath & fileURI, bool & isValidSyntax);
|
||||||
|
|
||||||
bool operator == (const JsonNode &other) const;
|
bool operator==(const JsonNode & other) const;
|
||||||
bool operator != (const JsonNode &other) const;
|
bool operator!=(const JsonNode & other) const;
|
||||||
|
|
||||||
const std::string & getModScope() const;
|
const std::string & getModScope() const;
|
||||||
void setModScope(const std::string & metadata, bool recursive = true);
|
void setModScope(const std::string & metadata, bool recursive = true);
|
||||||
@ -139,17 +140,18 @@ public:
|
|||||||
const JsonNode & operator[](const std::string & child) const;
|
const JsonNode & operator[](const std::string & child) const;
|
||||||
|
|
||||||
JsonNode & operator[](size_t child);
|
JsonNode & operator[](size_t child);
|
||||||
const JsonNode & operator[](size_t child) const;
|
const JsonNode & operator[](size_t child) const;
|
||||||
|
|
||||||
std::string toCompactString() const;
|
std::string toCompactString() const;
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
std::vector<std::byte> toBytes() const;
|
std::vector<std::byte> toBytes() const;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h)
|
template<typename Handler>
|
||||||
|
void serialize(Handler & h)
|
||||||
{
|
{
|
||||||
h & modScope;
|
h & modScope;
|
||||||
|
|
||||||
if (h.version >= Handler::Version::JSON_FLAGS)
|
if(h.version >= Handler::Version::JSON_FLAGS)
|
||||||
{
|
{
|
||||||
h & overrideFlag;
|
h & overrideFlag;
|
||||||
}
|
}
|
||||||
@ -187,15 +189,15 @@ inline void convert(std::string & value, const JsonNode & node)
|
|||||||
value = node.String();
|
value = node.String();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template<typename Type>
|
||||||
void convert(std::map<std::string,Type> & value, const JsonNode & node)
|
void convert(std::map<std::string, Type> & value, const JsonNode & node)
|
||||||
{
|
{
|
||||||
value.clear();
|
value.clear();
|
||||||
for (const JsonMap::value_type & entry : node.Struct())
|
for(const JsonMap::value_type & entry : node.Struct())
|
||||||
value.insert(entry.first, entry.second.convertTo<Type>());
|
value.insert(entry.first, entry.second.convertTo<Type>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template<typename Type>
|
||||||
void convert(std::set<Type> & value, const JsonNode & node)
|
void convert(std::set<Type> & value, const JsonNode & node)
|
||||||
{
|
{
|
||||||
value.clear();
|
value.clear();
|
||||||
@ -205,7 +207,7 @@ void convert(std::set<Type> & value, const JsonNode & node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template<typename Type>
|
||||||
void convert(std::vector<Type> & value, const JsonNode & node)
|
void convert(std::vector<Type> & value, const JsonNode & node)
|
||||||
{
|
{
|
||||||
value.clear();
|
value.clear();
|
||||||
|
@ -11,18 +11,18 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "JsonParser.h"
|
#include "JsonParser.h"
|
||||||
|
|
||||||
#include "JsonFormatException.h"
|
|
||||||
#include "../TextOperations.h"
|
#include "../TextOperations.h"
|
||||||
|
#include "JsonFormatException.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
JsonParser::JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings):
|
JsonParser::JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings)
|
||||||
input(inputString, stringSize),
|
: input(inputString, stringSize)
|
||||||
settings(settings),
|
, settings(settings)
|
||||||
currentDepth(0),
|
, currentDepth(0)
|
||||||
lineCount(1),
|
, lineCount(1)
|
||||||
lineStart(0),
|
, lineStart(0)
|
||||||
pos(0)
|
, pos(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,24 +30,24 @@ JsonNode JsonParser::parse(const std::string & fileName)
|
|||||||
{
|
{
|
||||||
JsonNode root;
|
JsonNode root;
|
||||||
|
|
||||||
if (input.empty())
|
if(input.empty())
|
||||||
{
|
{
|
||||||
error("File is empty", false);
|
error("File is empty", false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!TextOperations::isValidUnicodeString(input.data(), input.size()))
|
if(!TextOperations::isValidUnicodeString(input.data(), input.size()))
|
||||||
error("Not a valid UTF-8 file", false);
|
error("Not a valid UTF-8 file", false);
|
||||||
|
|
||||||
extractValue(root);
|
extractValue(root);
|
||||||
extractWhitespace(false);
|
extractWhitespace(false);
|
||||||
|
|
||||||
//Warn if there are any non-whitespace symbols left
|
//Warn if there are any non-whitespace symbols left
|
||||||
if (pos < input.size())
|
if(pos < input.size())
|
||||||
error("Not all file was parsed!", true);
|
error("Not all file was parsed!", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!errors.empty())
|
if(!errors.empty())
|
||||||
{
|
{
|
||||||
logMod->warn("File %s is not a valid JSON file!", fileName);
|
logMod->warn("File %s is not a valid JSON file!", fileName);
|
||||||
logMod->warn(errors);
|
logMod->warn(errors);
|
||||||
@ -62,33 +62,40 @@ bool JsonParser::isValid()
|
|||||||
|
|
||||||
bool JsonParser::extractSeparator()
|
bool JsonParser::extractSeparator()
|
||||||
{
|
{
|
||||||
if (!extractWhitespace())
|
if(!extractWhitespace())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( input[pos] !=':')
|
if(input[pos] != ':')
|
||||||
return error("Separator expected");
|
return error("Separator expected");
|
||||||
|
|
||||||
pos++;
|
pos++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractValue(JsonNode &node)
|
bool JsonParser::extractValue(JsonNode & node)
|
||||||
{
|
{
|
||||||
if (!extractWhitespace())
|
if(!extractWhitespace())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (input[pos])
|
switch(input[pos])
|
||||||
{
|
{
|
||||||
case '\"': return extractString(node);
|
case '\"':
|
||||||
case 'n' : return extractNull(node);
|
return extractString(node);
|
||||||
case 't' : return extractTrue(node);
|
case 'n':
|
||||||
case 'f' : return extractFalse(node);
|
return extractNull(node);
|
||||||
case '{' : return extractStruct(node);
|
case 't':
|
||||||
case '[' : return extractArray(node);
|
return extractTrue(node);
|
||||||
case '-' : return extractFloat(node);
|
case 'f':
|
||||||
|
return extractFalse(node);
|
||||||
|
case '{':
|
||||||
|
return extractStruct(node);
|
||||||
|
case '[':
|
||||||
|
return extractArray(node);
|
||||||
|
case '-':
|
||||||
|
return extractFloat(node);
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (input[pos] >= '0' && input[pos] <= '9')
|
if(input[pos] >= '0' && input[pos] <= '9')
|
||||||
return extractFloat(node);
|
return extractFloat(node);
|
||||||
return error("Value expected!");
|
return error("Value expected!");
|
||||||
}
|
}
|
||||||
@ -100,73 +107,90 @@ bool JsonParser::extractWhitespace(bool verbose)
|
|||||||
//TODO: JSON5 - C-style multi-line comments
|
//TODO: JSON5 - C-style multi-line comments
|
||||||
//TODO: JSON5 - Additional white space characters are allowed
|
//TODO: JSON5 - Additional white space characters are allowed
|
||||||
|
|
||||||
while (true)
|
while(true)
|
||||||
{
|
{
|
||||||
while(pos < input.size() && static_cast<ui8>(input[pos]) <= ' ')
|
while(pos < input.size() && static_cast<ui8>(input[pos]) <= ' ')
|
||||||
{
|
{
|
||||||
if (input[pos] == '\n')
|
if(input[pos] == '\n')
|
||||||
{
|
{
|
||||||
lineCount++;
|
lineCount++;
|
||||||
lineStart = pos+1;
|
lineStart = pos + 1;
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos >= input.size() || input[pos] != '/')
|
if(pos >= input.size() || input[pos] != '/')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (settings.mode == JsonParsingSettings::JsonFormatMode::JSON)
|
if(settings.mode == JsonParsingSettings::JsonFormatMode::JSON)
|
||||||
error("Comments are not permitted in json!", true);
|
error("Comments are not permitted in json!", true);
|
||||||
|
|
||||||
pos++;
|
pos++;
|
||||||
if (pos == input.size())
|
if(pos == input.size())
|
||||||
break;
|
break;
|
||||||
if (input[pos] == '/')
|
if(input[pos] == '/')
|
||||||
pos++;
|
pos++;
|
||||||
else
|
else
|
||||||
error("Comments must consist of two slashes!", true);
|
error("Comments must consist of two slashes!", true);
|
||||||
|
|
||||||
while (pos < input.size() && input[pos] != '\n')
|
while(pos < input.size() && input[pos] != '\n')
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos >= input.size() && verbose)
|
if(pos >= input.size() && verbose)
|
||||||
return error("Unexpected end of file!");
|
return error("Unexpected end of file!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractEscaping(std::string &str)
|
bool JsonParser::extractEscaping(std::string & str)
|
||||||
{
|
{
|
||||||
// TODO: support unicode escaping:
|
// TODO: support unicode escaping:
|
||||||
// \u1234
|
// \u1234
|
||||||
|
|
||||||
switch(input[pos])
|
switch(input[pos])
|
||||||
{
|
{
|
||||||
break; case '\"': str += '\"';
|
case '\"':
|
||||||
break; case '\\': str += '\\';
|
str += '\"';
|
||||||
break; case 'b': str += '\b';
|
break;
|
||||||
break; case 'f': str += '\f';
|
case '\\':
|
||||||
break; case 'n': str += '\n';
|
str += '\\';
|
||||||
break; case 'r': str += '\r';
|
break;
|
||||||
break; case 't': str += '\t';
|
case 'b':
|
||||||
break; case '/': str += '/';
|
str += '\b';
|
||||||
break; default: return error("Unknown escape sequence!", true);
|
break;
|
||||||
|
case 'f':
|
||||||
|
str += '\f';
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
str += '\n';
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
str += '\r';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
str += '\t';
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
str += '/';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return error("Unknown escape sequence!", true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractString(std::string &str)
|
bool JsonParser::extractString(std::string & str)
|
||||||
{
|
{
|
||||||
//TODO: JSON5 - line breaks escaping
|
//TODO: JSON5 - line breaks escaping
|
||||||
|
|
||||||
if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
||||||
{
|
{
|
||||||
if (input[pos] != '\"')
|
if(input[pos] != '\"')
|
||||||
return error("String expected!");
|
return error("String expected!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (input[pos] != '\"' && input[pos] != '\'')
|
if(input[pos] != '\"' && input[pos] != '\'')
|
||||||
return error("String expected!");
|
return error("String expected!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,32 +199,32 @@ bool JsonParser::extractString(std::string &str)
|
|||||||
|
|
||||||
size_t first = pos;
|
size_t first = pos;
|
||||||
|
|
||||||
while (pos != input.size())
|
while(pos != input.size())
|
||||||
{
|
{
|
||||||
if (input[pos] == lineTerminator) // Correct end of string
|
if(input[pos] == lineTerminator) // Correct end of string
|
||||||
{
|
{
|
||||||
str.append( &input[first], pos-first);
|
str.append(&input[first], pos - first);
|
||||||
pos++;
|
pos++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (input[pos] == '\\') // Escaping
|
if(input[pos] == '\\') // Escaping
|
||||||
{
|
{
|
||||||
str.append( &input[first], pos-first);
|
str.append(&input[first], pos - first);
|
||||||
pos++;
|
pos++;
|
||||||
if (pos == input.size())
|
if(pos == input.size())
|
||||||
break;
|
break;
|
||||||
extractEscaping(str);
|
extractEscaping(str);
|
||||||
first = pos + 1;
|
first = pos + 1;
|
||||||
}
|
}
|
||||||
if (input[pos] == '\n') // end-of-line
|
if(input[pos] == '\n') // end-of-line
|
||||||
{
|
{
|
||||||
str.append( &input[first], pos-first);
|
str.append(&input[first], pos - first);
|
||||||
return error("Closing quote not found!", true);
|
return error("Closing quote not found!", true);
|
||||||
}
|
}
|
||||||
if(static_cast<unsigned char>(input[pos]) < ' ') // control character
|
if(static_cast<unsigned char>(input[pos]) < ' ') // control character
|
||||||
{
|
{
|
||||||
str.append( &input[first], pos-first);
|
str.append(&input[first], pos - first);
|
||||||
first = pos+1;
|
first = pos + 1;
|
||||||
error("Illegal character in the string!", true);
|
error("Illegal character in the string!", true);
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
@ -208,10 +232,10 @@ bool JsonParser::extractString(std::string &str)
|
|||||||
return error("Unterminated string!");
|
return error("Unterminated string!");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractString(JsonNode &node)
|
bool JsonParser::extractString(JsonNode & node)
|
||||||
{
|
{
|
||||||
std::string str;
|
std::string str;
|
||||||
if (!extractString(str))
|
if(!extractString(str))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
node.setType(JsonNode::JsonType::DATA_STRING);
|
node.setType(JsonNode::JsonType::DATA_STRING);
|
||||||
@ -221,13 +245,13 @@ bool JsonParser::extractString(JsonNode &node)
|
|||||||
|
|
||||||
bool JsonParser::extractLiteral(std::string & literal)
|
bool JsonParser::extractLiteral(std::string & literal)
|
||||||
{
|
{
|
||||||
while (pos < input.size() )
|
while(pos < input.size())
|
||||||
{
|
{
|
||||||
bool isUpperCase = input[pos]>='A' && input[pos]<='Z';
|
bool isUpperCase = input[pos] >= 'A' && input[pos] <= 'Z';
|
||||||
bool isLowerCase = input[pos]>='a' && input[pos]<='z';
|
bool isLowerCase = input[pos] >= 'a' && input[pos] <= 'z';
|
||||||
bool isNumber = input[pos]>='0' && input[pos]<='9';
|
bool isNumber = input[pos] >= '0' && input[pos] <= '9';
|
||||||
|
|
||||||
if (!isUpperCase && !isLowerCase && !isNumber)
|
if(!isUpperCase && !isLowerCase && !isNumber)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
literal += input[pos];
|
literal += input[pos];
|
||||||
@ -238,13 +262,13 @@ bool JsonParser::extractLiteral(std::string & literal)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractAndCompareLiteral(const std::string &expectedLiteral)
|
bool JsonParser::extractAndCompareLiteral(const std::string & expectedLiteral)
|
||||||
{
|
{
|
||||||
std::string literal;
|
std::string literal;
|
||||||
if (!extractLiteral(literal))
|
if(!extractLiteral(literal))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (literal != expectedLiteral)
|
if(literal != expectedLiteral)
|
||||||
{
|
{
|
||||||
return error("Expected " + expectedLiteral + ", but unknown literal found", true);
|
return error("Expected " + expectedLiteral + ", but unknown literal found", true);
|
||||||
return false;
|
return false;
|
||||||
@ -253,81 +277,81 @@ bool JsonParser::extractAndCompareLiteral(const std::string &expectedLiteral)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractNull(JsonNode &node)
|
bool JsonParser::extractNull(JsonNode & node)
|
||||||
{
|
{
|
||||||
if (!extractAndCompareLiteral("null"))
|
if(!extractAndCompareLiteral("null"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
node.clear();
|
node.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractTrue(JsonNode &node)
|
bool JsonParser::extractTrue(JsonNode & node)
|
||||||
{
|
{
|
||||||
if (!extractAndCompareLiteral("true"))
|
if(!extractAndCompareLiteral("true"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
node.Bool() = true;
|
node.Bool() = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractFalse(JsonNode &node)
|
bool JsonParser::extractFalse(JsonNode & node)
|
||||||
{
|
{
|
||||||
if (!extractAndCompareLiteral("false"))
|
if(!extractAndCompareLiteral("false"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
node.Bool() = false;
|
node.Bool() = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractStruct(JsonNode &node)
|
bool JsonParser::extractStruct(JsonNode & node)
|
||||||
{
|
{
|
||||||
node.setType(JsonNode::JsonType::DATA_STRUCT);
|
node.setType(JsonNode::JsonType::DATA_STRUCT);
|
||||||
|
|
||||||
if (currentDepth > settings.maxDepth)
|
if(currentDepth > settings.maxDepth)
|
||||||
error("Macimum allowed depth of json structure has been reached", true);
|
error("Macimum allowed depth of json structure has been reached", true);
|
||||||
|
|
||||||
currentDepth++;
|
currentDepth++;
|
||||||
pos++;
|
pos++;
|
||||||
|
|
||||||
if (!extractWhitespace())
|
if(!extractWhitespace())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//Empty struct found
|
//Empty struct found
|
||||||
if (input[pos] == '}')
|
if(input[pos] == '}')
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while(true)
|
||||||
{
|
{
|
||||||
if (!extractWhitespace())
|
if(!extractWhitespace())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool overrideFlag = false;
|
bool overrideFlag = false;
|
||||||
std::string key;
|
std::string key;
|
||||||
|
|
||||||
if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
||||||
{
|
{
|
||||||
if (!extractString(key))
|
if(!extractString(key))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (input[pos] == '\'' || input[pos] == '\"')
|
if(input[pos] == '\'' || input[pos] == '\"')
|
||||||
{
|
{
|
||||||
if (!extractString(key))
|
if(!extractString(key))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!extractLiteral(key))
|
if(!extractLiteral(key))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.find('#') != std::string::npos)
|
if(key.find('#') != std::string::npos)
|
||||||
{
|
{
|
||||||
// split key string into actual key and meta-flags
|
// split key string into actual key and meta-flags
|
||||||
std::vector<std::string> keyAndFlags;
|
std::vector<std::string> keyAndFlags;
|
||||||
@ -337,25 +361,25 @@ bool JsonParser::extractStruct(JsonNode &node)
|
|||||||
|
|
||||||
for(int i = 1; i < keyAndFlags.size(); i++)
|
for(int i = 1; i < keyAndFlags.size(); i++)
|
||||||
{
|
{
|
||||||
if (keyAndFlags[i] == "override")
|
if(keyAndFlags[i] == "override")
|
||||||
overrideFlag = true;
|
overrideFlag = true;
|
||||||
else
|
else
|
||||||
error("Encountered unknown flag #" + keyAndFlags[i], true);
|
error("Encountered unknown flag #" + keyAndFlags[i], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.Struct().find(key) != node.Struct().end())
|
if(node.Struct().find(key) != node.Struct().end())
|
||||||
error("Duplicate element encountered!", true);
|
error("Duplicate element encountered!", true);
|
||||||
|
|
||||||
if (!extractSeparator())
|
if(!extractSeparator())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!extractElement(node.Struct()[key], '}'))
|
if(!extractElement(node.Struct()[key], '}'))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
node.Struct()[key].setOverrideFlag(overrideFlag);
|
node.Struct()[key].setOverrideFlag(overrideFlag);
|
||||||
|
|
||||||
if (input[pos] == '}')
|
if(input[pos] == '}')
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
return true;
|
return true;
|
||||||
@ -363,35 +387,35 @@ bool JsonParser::extractStruct(JsonNode &node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractArray(JsonNode &node)
|
bool JsonParser::extractArray(JsonNode & node)
|
||||||
{
|
{
|
||||||
if (currentDepth > settings.maxDepth)
|
if(currentDepth > settings.maxDepth)
|
||||||
error("Macimum allowed depth of json structure has been reached", true);
|
error("Macimum allowed depth of json structure has been reached", true);
|
||||||
|
|
||||||
currentDepth++;
|
currentDepth++;
|
||||||
pos++;
|
pos++;
|
||||||
node.setType(JsonNode::JsonType::DATA_VECTOR);
|
node.setType(JsonNode::JsonType::DATA_VECTOR);
|
||||||
|
|
||||||
if (!extractWhitespace())
|
if(!extractWhitespace())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//Empty array found
|
//Empty array found
|
||||||
if (input[pos] == ']')
|
if(input[pos] == ']')
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while(true)
|
||||||
{
|
{
|
||||||
//NOTE: currently 50% of time is this vector resizing.
|
//NOTE: currently 50% of time is this vector resizing.
|
||||||
//May be useful to use list during parsing and then swap() all items to vector
|
//May be useful to use list during parsing and then swap() all items to vector
|
||||||
node.Vector().resize(node.Vector().size()+1);
|
node.Vector().resize(node.Vector().size() + 1);
|
||||||
|
|
||||||
if (!extractElement(node.Vector().back(), ']'))
|
if(!extractElement(node.Vector().back(), ']'))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (input[pos] == ']')
|
if(input[pos] == ']')
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
return true;
|
return true;
|
||||||
@ -399,92 +423,92 @@ bool JsonParser::extractArray(JsonNode &node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractElement(JsonNode &node, char terminator)
|
bool JsonParser::extractElement(JsonNode & node, char terminator)
|
||||||
{
|
{
|
||||||
if (!extractValue(node))
|
if(!extractValue(node))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!extractWhitespace())
|
if(!extractWhitespace())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool comma = (input[pos] == ',');
|
bool comma = (input[pos] == ',');
|
||||||
if (comma )
|
if(comma)
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
if (!extractWhitespace())
|
if(!extractWhitespace())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input[pos] == terminator)
|
if(input[pos] == terminator)
|
||||||
{
|
{
|
||||||
if (comma)
|
if(comma)
|
||||||
{
|
{
|
||||||
if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
||||||
error("Extra comma found!", true);
|
error("Extra comma found!", true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!comma)
|
if(!comma)
|
||||||
error("Comma expected!", true);
|
error("Comma expected!", true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::extractFloat(JsonNode &node)
|
bool JsonParser::extractFloat(JsonNode & node)
|
||||||
{
|
{
|
||||||
//TODO: JSON5 - hexacedimal support
|
//TODO: JSON5 - hexacedimal support
|
||||||
//TODO: JSON5 - Numbers may be IEEE 754 positive infinity, negative infinity, and NaN (why?)
|
//TODO: JSON5 - Numbers may be IEEE 754 positive infinity, negative infinity, and NaN (why?)
|
||||||
|
|
||||||
assert(input[pos] == '-' || (input[pos] >= '0' && input[pos] <= '9'));
|
assert(input[pos] == '-' || (input[pos] >= '0' && input[pos] <= '9'));
|
||||||
bool negative=false;
|
bool negative = false;
|
||||||
double result=0;
|
double result = 0;
|
||||||
si64 integerPart = 0;
|
si64 integerPart = 0;
|
||||||
bool isFloat = false;
|
bool isFloat = false;
|
||||||
|
|
||||||
if (input[pos] == '+')
|
if(input[pos] == '+')
|
||||||
{
|
{
|
||||||
if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
||||||
error("Positive numbers should not have plus sign!", true);
|
error("Positive numbers should not have plus sign!", true);
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
else if (input[pos] == '-')
|
else if(input[pos] == '-')
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
negative = true;
|
negative = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input[pos] < '0' || input[pos] > '9')
|
if(input[pos] < '0' || input[pos] > '9')
|
||||||
{
|
{
|
||||||
if (input[pos] != '.' && settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
if(input[pos] != '.' && settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
||||||
return error("Number expected!");
|
return error("Number expected!");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Extract integer part
|
//Extract integer part
|
||||||
while (input[pos] >= '0' && input[pos] <= '9')
|
while(input[pos] >= '0' && input[pos] <= '9')
|
||||||
{
|
{
|
||||||
integerPart = integerPart*10+(input[pos]-'0');
|
integerPart = integerPart * 10 + (input[pos] - '0');
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = static_cast<double>(integerPart);
|
result = static_cast<double>(integerPart);
|
||||||
|
|
||||||
if (input[pos] == '.')
|
if(input[pos] == '.')
|
||||||
{
|
{
|
||||||
//extract fractional part
|
//extract fractional part
|
||||||
isFloat = true;
|
isFloat = true;
|
||||||
pos++;
|
pos++;
|
||||||
double fractMult = 0.1;
|
double fractMult = 0.1;
|
||||||
|
|
||||||
if (settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
if(settings.mode < JsonParsingSettings::JsonFormatMode::JSON5)
|
||||||
{
|
{
|
||||||
if (input[pos] < '0' || input[pos] > '9')
|
if(input[pos] < '0' || input[pos] > '9')
|
||||||
return error("Decimal part expected!");
|
return error("Decimal part expected!");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (input[pos] >= '0' && input[pos] <= '9')
|
while(input[pos] >= '0' && input[pos] <= '9')
|
||||||
{
|
{
|
||||||
result = result + fractMult*(input[pos]-'0');
|
result = result + fractMult * (input[pos] - '0');
|
||||||
fractMult /= 10;
|
fractMult /= 10;
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
@ -508,12 +532,12 @@ bool JsonParser::extractFloat(JsonNode &node)
|
|||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input[pos] < '0' || input[pos] > '9')
|
if(input[pos] < '0' || input[pos] > '9')
|
||||||
return error("Exponential part expected!");
|
return error("Exponential part expected!");
|
||||||
|
|
||||||
while (input[pos] >= '0' && input[pos] <= '9')
|
while(input[pos] >= '0' && input[pos] <= '9')
|
||||||
{
|
{
|
||||||
power = power*10 + (input[pos]-'0');
|
power = power * 10 + (input[pos] - '0');
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,16 +567,15 @@ bool JsonParser::extractFloat(JsonNode &node)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonParser::error(const std::string &message, bool warning)
|
bool JsonParser::error(const std::string & message, bool warning)
|
||||||
{
|
{
|
||||||
if (settings.strict)
|
if(settings.strict)
|
||||||
throw JsonFormatException(message);
|
throw JsonFormatException(message);
|
||||||
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
std::string type(warning?" warning: ":" error: ");
|
std::string type(warning ? " warning: " : " error: ");
|
||||||
|
|
||||||
stream << "At line " << lineCount << ", position "<<pos-lineStart
|
stream << "At line " << lineCount << ", position " << pos - lineStart << type << message << "\n";
|
||||||
<< type << message <<"\n";
|
|
||||||
errors += stream.str();
|
errors += stream.str();
|
||||||
|
|
||||||
return warning;
|
return warning;
|
||||||
|
@ -18,34 +18,34 @@ class JsonParser
|
|||||||
{
|
{
|
||||||
const JsonParsingSettings settings;
|
const JsonParsingSettings settings;
|
||||||
|
|
||||||
std::string errors; // Contains description of all encountered errors
|
std::string errors; // Contains description of all encountered errors
|
||||||
std::string_view input; // Input data
|
std::string_view input; // Input data
|
||||||
uint32_t lineCount; // Currently parsed line, starting from 1
|
uint32_t lineCount; // Currently parsed line, starting from 1
|
||||||
uint32_t currentDepth;
|
uint32_t currentDepth;
|
||||||
size_t lineStart; // Position of current line start
|
size_t lineStart; // Position of current line start
|
||||||
size_t pos; // Current position of parser
|
size_t pos; // Current position of parser
|
||||||
|
|
||||||
//Helpers
|
//Helpers
|
||||||
bool extractEscaping(std::string &str);
|
bool extractEscaping(std::string & str);
|
||||||
bool extractLiteral(std::string &literal);
|
bool extractLiteral(std::string & literal);
|
||||||
bool extractAndCompareLiteral(const std::string &expectedLiteral);
|
bool extractAndCompareLiteral(const std::string & expectedLiteral);
|
||||||
bool extractString(std::string &string);
|
bool extractString(std::string & string);
|
||||||
bool extractWhitespace(bool verbose = true);
|
bool extractWhitespace(bool verbose = true);
|
||||||
bool extractSeparator();
|
bool extractSeparator();
|
||||||
bool extractElement(JsonNode &node, char terminator);
|
bool extractElement(JsonNode & node, char terminator);
|
||||||
|
|
||||||
//Methods for extracting JSON data
|
//Methods for extracting JSON data
|
||||||
bool extractArray(JsonNode &node);
|
bool extractArray(JsonNode & node);
|
||||||
bool extractFalse(JsonNode &node);
|
bool extractFalse(JsonNode & node);
|
||||||
bool extractFloat(JsonNode &node);
|
bool extractFloat(JsonNode & node);
|
||||||
bool extractNull(JsonNode &node);
|
bool extractNull(JsonNode & node);
|
||||||
bool extractString(JsonNode &node);
|
bool extractString(JsonNode & node);
|
||||||
bool extractStruct(JsonNode &node);
|
bool extractStruct(JsonNode & node);
|
||||||
bool extractTrue(JsonNode &node);
|
bool extractTrue(JsonNode & node);
|
||||||
bool extractValue(JsonNode &node);
|
bool extractValue(JsonNode & node);
|
||||||
|
|
||||||
//Add error\warning message to list
|
//Add error\warning message to list
|
||||||
bool error(const std::string &message, bool warning=false);
|
bool error(const std::string & message, bool warning = false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings);
|
JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings);
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "GameCallbackHolder.h"
|
||||||
#include "GameConstants.h"
|
#include "GameConstants.h"
|
||||||
#include "ResourceSet.h"
|
#include "ResourceSet.h"
|
||||||
#include "GameCallbackHolder.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -16,28 +16,28 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
void JsonWriter::writeContainer(Iterator begin, Iterator end)
|
void JsonWriter::writeContainer(Iterator begin, Iterator end)
|
||||||
{
|
{
|
||||||
if (begin == end)
|
if(begin == end)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
prefix += '\t';
|
prefix += '\t';
|
||||||
|
|
||||||
writeEntry(begin++);
|
writeEntry(begin++);
|
||||||
|
|
||||||
while (begin != end)
|
while(begin != end)
|
||||||
{
|
{
|
||||||
out << (compactMode ? ", " : ",\n");
|
out << (compactMode ? ", " : ",\n");
|
||||||
writeEntry(begin++);
|
writeEntry(begin++);
|
||||||
}
|
}
|
||||||
|
|
||||||
out << (compactMode ? "" : "\n");
|
out << (compactMode ? "" : "\n");
|
||||||
prefix.resize(prefix.size()-1);
|
prefix.resize(prefix.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeEntry(JsonMap::const_iterator entry)
|
void JsonWriter::writeEntry(JsonMap::const_iterator entry)
|
||||||
{
|
{
|
||||||
if(!compactMode)
|
if(!compactMode)
|
||||||
{
|
{
|
||||||
if (!entry->second.getModScope().empty())
|
if(!entry->second.getModScope().empty())
|
||||||
out << prefix << " // " << entry->second.getModScope() << "\n";
|
out << prefix << " // " << entry->second.getModScope() << "\n";
|
||||||
out << prefix;
|
out << prefix;
|
||||||
}
|
}
|
||||||
@ -50,27 +50,25 @@ void JsonWriter::writeEntry(JsonVector::const_iterator entry)
|
|||||||
{
|
{
|
||||||
if(!compactMode)
|
if(!compactMode)
|
||||||
{
|
{
|
||||||
if (!entry->getModScope().empty())
|
if(!entry->getModScope().empty())
|
||||||
out << prefix << " // " << entry->getModScope() << "\n";
|
out << prefix << " // " << entry->getModScope() << "\n";
|
||||||
out << prefix;
|
out << prefix;
|
||||||
}
|
}
|
||||||
writeNode(*entry);
|
writeNode(*entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeString(const std::string &string)
|
void JsonWriter::writeString(const std::string & string)
|
||||||
{
|
{
|
||||||
static const std::string escaped = "\"\\\b\f\n\r\t";
|
static const std::string escaped = "\"\\\b\f\n\r\t";
|
||||||
static const std::array escaped_code = {'\"', '\\', 'b', 'f', 'n', 'r', 't'};
|
static const std::array escaped_code = {'\"', '\\', 'b', 'f', 'n', 'r', 't'};
|
||||||
|
|
||||||
out <<'\"';
|
out << '\"';
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
size_t start = 0;
|
size_t start = 0;
|
||||||
for (; pos<string.size(); pos++)
|
for(; pos < string.size(); pos++)
|
||||||
{
|
{
|
||||||
//we need to check if special character was been already escaped
|
//we need to check if special character was been already escaped
|
||||||
if((string[pos] == '\\')
|
if((string[pos] == '\\') && (pos + 1 < string.size()) && (std::find(escaped_code.begin(), escaped_code.end(), string[pos + 1]) != escaped_code.end()))
|
||||||
&& (pos+1 < string.size())
|
|
||||||
&& (std::find(escaped_code.begin(), escaped_code.end(), string[pos+1]) != escaped_code.end()) )
|
|
||||||
{
|
{
|
||||||
pos++; //write unchanged, next simbol also checked
|
pos++; //write unchanged, next simbol also checked
|
||||||
}
|
}
|
||||||
@ -78,20 +76,19 @@ void JsonWriter::writeString(const std::string &string)
|
|||||||
{
|
{
|
||||||
size_t escapedPos = escaped.find(string[pos]);
|
size_t escapedPos = escaped.find(string[pos]);
|
||||||
|
|
||||||
if (escapedPos != std::string::npos)
|
if(escapedPos != std::string::npos)
|
||||||
{
|
{
|
||||||
out.write(string.data()+start, pos - start);
|
out.write(string.data() + start, pos - start);
|
||||||
out << '\\' << escaped_code[escapedPos];
|
out << '\\' << escaped_code[escapedPos];
|
||||||
start = pos+1;
|
start = pos + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
out.write(string.data()+start, pos - start);
|
out.write(string.data() + start, pos - start);
|
||||||
out <<'\"';
|
out << '\"';
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonWriter::writeNode(const JsonNode &node)
|
void JsonWriter::writeNode(const JsonNode & node)
|
||||||
{
|
{
|
||||||
bool originalMode = compactMode;
|
bool originalMode = compactMode;
|
||||||
if(compact && !compactMode && node.isCompact())
|
if(compact && !compactMode && node.isCompact())
|
||||||
@ -99,40 +96,48 @@ void JsonWriter::writeNode(const JsonNode &node)
|
|||||||
|
|
||||||
switch(node.getType())
|
switch(node.getType())
|
||||||
{
|
{
|
||||||
break; case JsonNode::JsonType::DATA_NULL:
|
case JsonNode::JsonType::DATA_NULL:
|
||||||
out << "null";
|
out << "null";
|
||||||
|
break;
|
||||||
|
|
||||||
break; case JsonNode::JsonType::DATA_BOOL:
|
case JsonNode::JsonType::DATA_BOOL:
|
||||||
if (node.Bool())
|
if(node.Bool())
|
||||||
out << "true";
|
out << "true";
|
||||||
else
|
else
|
||||||
out << "false";
|
out << "false";
|
||||||
|
break;
|
||||||
|
|
||||||
break; case JsonNode::JsonType::DATA_FLOAT:
|
case JsonNode::JsonType::DATA_FLOAT:
|
||||||
out << node.Float();
|
out << node.Float();
|
||||||
|
break;
|
||||||
|
|
||||||
break; case JsonNode::JsonType::DATA_STRING:
|
case JsonNode::JsonType::DATA_STRING:
|
||||||
writeString(node.String());
|
writeString(node.String());
|
||||||
|
break;
|
||||||
|
|
||||||
break; case JsonNode::JsonType::DATA_VECTOR:
|
case JsonNode::JsonType::DATA_VECTOR:
|
||||||
out << "[" << (compactMode ? " " : "\n");
|
out << "[" << (compactMode ? " " : "\n");
|
||||||
writeContainer(node.Vector().begin(), node.Vector().end());
|
writeContainer(node.Vector().begin(), node.Vector().end());
|
||||||
out << (compactMode ? " " : prefix) << "]";
|
out << (compactMode ? " " : prefix) << "]";
|
||||||
|
break;
|
||||||
|
|
||||||
break; case JsonNode::JsonType::DATA_STRUCT:
|
case JsonNode::JsonType::DATA_STRUCT:
|
||||||
out << "{" << (compactMode ? " " : "\n");
|
out << "{" << (compactMode ? " " : "\n");
|
||||||
writeContainer(node.Struct().begin(), node.Struct().end());
|
writeContainer(node.Struct().begin(), node.Struct().end());
|
||||||
out << (compactMode ? " " : prefix) << "}";
|
out << (compactMode ? " " : prefix) << "}";
|
||||||
|
break;
|
||||||
|
|
||||||
break; case JsonNode::JsonType::DATA_INTEGER:
|
case JsonNode::JsonType::DATA_INTEGER:
|
||||||
out << node.Integer();
|
out << node.Integer();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
compactMode = originalMode;
|
compactMode = originalMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonWriter::JsonWriter(std::ostream & output, bool compact)
|
JsonWriter::JsonWriter(std::ostream & output, bool compact)
|
||||||
: out(output), compact(compact)
|
: out(output)
|
||||||
|
, compact(compact)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ class JsonWriter
|
|||||||
bool compact;
|
bool compact;
|
||||||
//tracks whether we are currently using single-line format
|
//tracks whether we are currently using single-line format
|
||||||
bool compactMode = false;
|
bool compactMode = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
void writeContainer(Iterator begin, Iterator end);
|
void writeContainer(Iterator begin, Iterator end);
|
||||||
|
Loading…
Reference in New Issue
Block a user