mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-15 01:24:45 +02:00
Implemented 'strict' json support
This commit is contained in:
@ -405,6 +405,7 @@ set(lib_HEADERS
|
|||||||
filesystem/ResourcePath.h
|
filesystem/ResourcePath.h
|
||||||
|
|
||||||
json/JsonBonus.h
|
json/JsonBonus.h
|
||||||
|
json/JsonFormatException.h
|
||||||
json/JsonNode.h
|
json/JsonNode.h
|
||||||
json/JsonParser.h
|
json/JsonParser.h
|
||||||
json/JsonRandom.h
|
json/JsonRandom.h
|
||||||
|
@ -14,6 +14,11 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct Bonus;
|
||||||
|
class ILimiter;
|
||||||
|
class CSelector;
|
||||||
|
class CAddInfo;
|
||||||
|
|
||||||
namespace JsonUtils
|
namespace JsonUtils
|
||||||
{
|
{
|
||||||
DLL_LINKAGE std::shared_ptr<Bonus> parseBonus(const JsonVector & ability_vec);
|
DLL_LINKAGE std::shared_ptr<Bonus> parseBonus(const JsonVector & ability_vec);
|
||||||
|
20
lib/json/JsonFormatException.h
Normal file
20
lib/json/JsonFormatException.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* JsonFormatException.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class JsonFormatException : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using runtime_error::runtime_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -79,8 +79,12 @@ JsonNode::JsonNode(const std::string & string)
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
JsonNode::JsonNode(const std::byte *data, size_t datasize)
|
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);
|
JsonParser parser(reinterpret_cast<const char*>(data), datasize, parserSettings);
|
||||||
*this = parser.parse("<unknown>");
|
*this = parser.parse("<unknown>");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +92,7 @@ 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);
|
JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second, JsonParsingSettings());
|
||||||
*this = parser.parse(fileURI.getName());
|
*this = parser.parse(fileURI.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +100,7 @@ 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);
|
JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second, JsonParsingSettings());
|
||||||
*this = parser.parse(fileURI.getName());
|
*this = parser.parse(fileURI.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +108,7 @@ 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);
|
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();
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,23 @@ class JsonNode;
|
|||||||
using JsonMap = std::map<std::string, JsonNode>;
|
using JsonMap = std::map<std::string, JsonNode>;
|
||||||
using JsonVector = std::vector<JsonNode>;
|
using JsonVector = std::vector<JsonNode>;
|
||||||
|
|
||||||
struct Bonus;
|
struct JsonParsingSettings
|
||||||
class CSelector;
|
{
|
||||||
class CAddInfo;
|
enum class JsonFormatMode
|
||||||
class ILimiter;
|
{
|
||||||
|
JSON, // strict implementation of json format
|
||||||
|
JSONC, // json format that also allows comments that start from '//'
|
||||||
|
//JSON5 // TODO?
|
||||||
|
};
|
||||||
|
|
||||||
|
JsonFormatMode mode = JsonFormatMode::JSONC;
|
||||||
|
|
||||||
|
/// Maximum depth of elements
|
||||||
|
uint32_t maxDepth = 30;
|
||||||
|
|
||||||
|
/// If set to true, parser will throw on any encountered error
|
||||||
|
bool strict = false;
|
||||||
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE JsonNode
|
class DLL_LINKAGE JsonNode
|
||||||
{
|
{
|
||||||
@ -58,6 +71,7 @@ public:
|
|||||||
|
|
||||||
/// Create tree from Json-formatted input
|
/// Create tree from Json-formatted input
|
||||||
explicit JsonNode(const std::byte * data, size_t datasize);
|
explicit JsonNode(const std::byte * data, size_t datasize);
|
||||||
|
explicit JsonNode(const std::byte * data, size_t datasize, const JsonParsingSettings & parserSettings);
|
||||||
|
|
||||||
/// Create tree from JSON file
|
/// Create tree from JSON file
|
||||||
explicit JsonNode(const JsonPath & fileURI);
|
explicit JsonNode(const JsonPath & fileURI);
|
||||||
|
@ -11,12 +11,14 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "JsonParser.h"
|
#include "JsonParser.h"
|
||||||
|
|
||||||
|
#include "JsonFormatException.h"
|
||||||
#include "../TextOperations.h"
|
#include "../TextOperations.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
JsonParser::JsonParser(const char * inputString, size_t stringSize):
|
JsonParser::JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings):
|
||||||
input(inputString, stringSize),
|
input(inputString, stringSize),
|
||||||
|
settings(settings),
|
||||||
lineCount(1),
|
lineCount(1),
|
||||||
lineStart(0),
|
lineStart(0),
|
||||||
pos(0)
|
pos(0)
|
||||||
@ -105,9 +107,13 @@ bool JsonParser::extractWhitespace(bool verbose)
|
|||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos >= input.size() || input[pos] != '/')
|
if (pos >= input.size() || input[pos] != '/')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (settings.mode == JsonParsingSettings::JsonFormatMode::JSON)
|
||||||
|
error("Comments are not permitted in json!", true);
|
||||||
|
|
||||||
pos++;
|
pos++;
|
||||||
if (pos == input.size())
|
if (pos == input.size())
|
||||||
break;
|
break;
|
||||||
@ -346,9 +352,8 @@ bool JsonParser::extractElement(JsonNode &node, char terminator)
|
|||||||
|
|
||||||
if (input[pos] == terminator)
|
if (input[pos] == terminator)
|
||||||
{
|
{
|
||||||
//FIXME: MOD COMPATIBILITY: Too many of these right now, re-enable later
|
if (comma)
|
||||||
//if (comma)
|
error("Extra comma found!", true);
|
||||||
//error("Extra comma found!", true);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,6 +461,9 @@ bool JsonParser::extractFloat(JsonNode &node)
|
|||||||
|
|
||||||
bool JsonParser::error(const std::string &message, bool warning)
|
bool JsonParser::error(const std::string &message, bool warning)
|
||||||
{
|
{
|
||||||
|
if (settings.strict)
|
||||||
|
throw JsonFormatException(message);
|
||||||
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
std::string type(warning?" warning: ":" error: ");
|
std::string type(warning?" warning: ":" error: ");
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
//Internal class for string -> JsonNode conversion
|
//Internal class for string -> JsonNode conversion
|
||||||
class JsonParser
|
class JsonParser
|
||||||
{
|
{
|
||||||
|
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
|
||||||
ui32 lineCount; // Currently parsed line, starting from 1
|
ui32 lineCount; // Currently parsed line, starting from 1
|
||||||
@ -44,7 +46,7 @@ class JsonParser
|
|||||||
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);
|
JsonParser(const char * inputString, size_t stringSize, const JsonParsingSettings & settings);
|
||||||
|
|
||||||
/// do actual parsing. filename is name of file that will printed to console if any errors were found
|
/// do actual parsing. filename is name of file that will printed to console if any errors were found
|
||||||
JsonNode parse(const std::string & fileName);
|
JsonNode parse(const std::string & fileName);
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct Bonus;
|
||||||
|
|
||||||
namespace spells
|
namespace spells
|
||||||
{
|
{
|
||||||
namespace effects
|
namespace effects
|
||||||
|
Reference in New Issue
Block a user