File: JsonDetail.h

package info (click to toggle)
vcmi 1.1.0%2Bdfsg-1
  • links: PTS, VCS
  • area: contrib
  • in suites: bookworm
  • size: 14,672 kB
  • sloc: cpp: 181,738; sh: 220; python: 178; ansic: 69; objc: 66; xml: 59; makefile: 34
file content (133 lines) | stat: -rw-r--r-- 4,134 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * JsonDetail.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

#include "JsonNode.h"

VCMI_LIB_NAMESPACE_BEGIN

class JsonWriter
{
	//prefix for each line (tabulation)
	std::string prefix;
	std::ostream & out;
	//sets whether compact nodes are written in single-line format
	bool compact;
	//tracks whether we are currently using single-line format
	bool compactMode = false;
public:
	template<typename Iterator>
	void writeContainer(Iterator begin, Iterator end);
	void writeEntry(JsonMap::const_iterator entry);
	void writeEntry(JsonVector::const_iterator entry);
	void writeString(const std::string & string);
	void writeNode(const JsonNode & node);
	JsonWriter(std::ostream & output, bool compact = false);
};

//Tiny string class that uses const char* as data for speed, members are private
//for ease of debugging and some compatibility with std::string
class constString
{
	const char *data;
	const size_t datasize;

public:
	constString(const char * inputString, size_t stringSize):
		data(inputString),
		datasize(stringSize)
	{
	}

	inline size_t size() const
	{
		return datasize;
	};

	inline const char& operator[] (size_t position)
	{
		assert (position < datasize);
		return data[position];
	}
};

//Internal class for string -> JsonNode conversion
class DLL_LINKAGE JsonParser
{
	std::string errors;     // Contains description of all encountered errors
	constString input;      // Input data
	ui32 lineCount; // Currently parsed line, starting from 1
	size_t lineStart;       // Position of current line start
	size_t pos;             // Current position of parser

	//Helpers
	bool extractEscaping(std::string &str);
	bool extractLiteral(const std::string &literal);
	bool extractString(std::string &string);
	bool extractWhitespace(bool verbose = true);
	bool extractSeparator();
	bool extractElement(JsonNode &node, char terminator);

	//Methods for extracting JSON data
	bool extractArray(JsonNode &node);
	bool extractFalse(JsonNode &node);
	bool extractFloat(JsonNode &node);
	bool extractNull(JsonNode &node);
	bool extractString(JsonNode &node);
	bool extractStruct(JsonNode &node);
	bool extractTrue(JsonNode &node);
	bool extractValue(JsonNode &node);

	//Add error\warning message to list
	bool error(const std::string &message, bool warning=false);

public:
	JsonParser(const char * inputString, size_t stringSize);

	/// do actual parsing. filename is name of file that will printed to console if any errors were found
	JsonNode parse(std::string fileName);

	/// returns true if parsing was successful
	bool isValid();
};

//Internal class for Json validation. Mostly compilant with json-schema v4 draft
namespace Validation
{
	/// struct used to pass data around during validation
	struct ValidationData
	{
		/// path from root node to current one.
		/// JsonNode is used as variant - either string (name of node) or as float (index in list)
		std::vector<JsonNode> currentPath;

		/// Stack of used schemas. Last schema is the one used currently.
		/// May contain multiple items in case if remote references were found
		std::vector<std::string> usedSchemas;

		/// generates error message
		std::string makeErrorMessage(const std::string &message);
	};

	typedef std::function<std::string(const JsonNode &)> TFormatValidator;
	typedef std::unordered_map<std::string, TFormatValidator> TFormatMap;
	typedef std::function<std::string(ValidationData &, const JsonNode &, const JsonNode &, const JsonNode &)> TFieldValidator;
	typedef std::unordered_map<std::string, TFieldValidator> TValidatorMap;

	/// map of known fields in schema
	const TValidatorMap & getKnownFieldsFor(JsonNode::JsonType type);
	const TFormatMap & getKnownFormats();

	std::string check(std::string schemaName, const JsonNode & data);
	std::string check(std::string schemaName, const JsonNode & data, ValidationData & validator);
	std::string check(const JsonNode & schema, const JsonNode & data, ValidationData & validator);
}

VCMI_LIB_NAMESPACE_END