add exception, gtest and some parse function
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "googletest"]
|
||||||
|
path = googletest
|
||||||
|
url = https://github.com/google/googletest.git
|
||||||
Generated
+7
-1
@@ -1,2 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
<module classpath="CMake" type="CPP_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="Python" name="Python facet">
|
||||||
|
<configuration sdkName="D:\Apps\Anaconda3" />
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
Generated
-7
@@ -9,13 +9,6 @@
|
|||||||
</mappings>
|
</mappings>
|
||||||
</serverdata>
|
</serverdata>
|
||||||
</paths>
|
</paths>
|
||||||
<paths name="WSL (a4a5868f-4653-4e3e-a1e4-92d5c2007084)">
|
|
||||||
<serverdata>
|
|
||||||
<mappings>
|
|
||||||
<mapping local="$PROJECT_DIR$" web="/" />
|
|
||||||
</mappings>
|
|
||||||
</serverdata>
|
|
||||||
</paths>
|
|
||||||
<paths name="WSL (ab0fb59d-77f8-4703-9979-f3a81cca500e)">
|
<paths name="WSL (ab0fb59d-77f8-4703-9979-f3a81cca500e)">
|
||||||
<serverdata>
|
<serverdata>
|
||||||
<mappings>
|
<mappings>
|
||||||
|
|||||||
Generated
+3
@@ -1,4 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="D:\Apps\Anaconda3" />
|
||||||
|
</component>
|
||||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
</project>
|
</project>
|
||||||
+9
-3
@@ -1,8 +1,14 @@
|
|||||||
cmake_minimum_required(VERSION 3.26)
|
cmake_minimum_required(VERSION 3.26)
|
||||||
project(SimpleJson)
|
project(SimpleJson)
|
||||||
|
set(GOOGLETEST_VERSION 1.14.0)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
|
add_subdirectory(./googletest/googletest)
|
||||||
|
enable_testing()
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src ./googletest/googletest/include)
|
||||||
|
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/googletest/googletest/lib)
|
||||||
add_executable(SimpleJson main.cpp
|
add_executable(SimpleJson main.cpp
|
||||||
src/json.cpp
|
src/json.cpp
|
||||||
src/json.h)
|
src/json.h
|
||||||
|
src/exception.h)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} gtest)
|
||||||
|
|||||||
Submodule
+1
Submodule googletest added at dddb219c3e
@@ -1,6 +1,44 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/json.h"
|
||||||
|
|
||||||
int main() {
|
TEST(TestCase, testJsonNodeSetDoule) {
|
||||||
std::cout << "Hello, World!" << std::endl;
|
simpleJson::JsonNode node(simpleJson::JSON_TYPE_DOUBLE, "key");
|
||||||
return 0;
|
node.set_value(1.0);
|
||||||
|
EXPECT_EQ(node.as_int(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestCase, testJsonNodeSetString) {
|
||||||
|
simpleJson::JsonNode node(simpleJson::JSON_TYPE_STRING, "key");
|
||||||
|
node.set_value("1.0");
|
||||||
|
const char* s = node.as_string().c_str();
|
||||||
|
EXPECT_STREQ(s,"1.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestCase, testJsonNodeSetError) {
|
||||||
|
simpleJson::JsonNode node(simpleJson::JSON_TYPE_INT, "key");
|
||||||
|
EXPECT_THROW(node.set_value("1.0"), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestCase, testJsonNodeSetKey) {
|
||||||
|
simpleJson::JsonNode node(simpleJson::JSON_TYPE_INT, "key");
|
||||||
|
node.set_key("key1");
|
||||||
|
EXPECT_STREQ(node.get_key().c_str(), "key1");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestCase,testJsonNodeSetBool) {
|
||||||
|
simpleJson::JsonNode node(simpleJson::JSON_TYPE_BOOL, "key");
|
||||||
|
node.set_value(true);
|
||||||
|
EXPECT_EQ(node.as_bool(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestCase, testParseStr) {
|
||||||
|
std::string json_str = "{\"key\":\"1\"}";
|
||||||
|
simpleJson::JsonParser parser(json_str);
|
||||||
|
EXPECT_EQ(parser.get_root().obj_get("key").as_string(), "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// Created by jun on 2023/12/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SIMPLEJSON_EXCEPTION_H
|
||||||
|
#define SIMPLEJSON_EXCEPTION_H
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace simpleJson {
|
||||||
|
const std::string_view SYNTAX_ERROR = "Syntax Error";
|
||||||
|
const std::string_view INVALID_TYPE = "Invalid Type";
|
||||||
|
|
||||||
|
class JsonException : public std::exception {
|
||||||
|
protected:
|
||||||
|
std::string message;
|
||||||
|
public:
|
||||||
|
explicit JsonException(std::string_view str = "JsonException") : message{str} {}
|
||||||
|
|
||||||
|
virtual ~JsonException() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonTypeError : public JsonException {
|
||||||
|
protected:
|
||||||
|
std::string function_name;
|
||||||
|
JsonValueTypeEnum expected_type;
|
||||||
|
JsonValueTypeEnum actual_type;
|
||||||
|
public:
|
||||||
|
JsonTypeError(std::string_view str, const char *function_name, JsonValueTypeEnum expected,
|
||||||
|
JsonValueTypeEnum actual) : JsonException{str}, function_name(function_name),
|
||||||
|
expected_type(expected), actual_type(actual) {}
|
||||||
|
|
||||||
|
const char *what() {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "[JsonTypeError]" << message << ":" << function_name << " expect " << JSON_TYPE_STR[expected_type]
|
||||||
|
<< " but found " << JSON_TYPE_STR[actual_type];
|
||||||
|
return ss.str().c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonParseError : public JsonException {
|
||||||
|
protected:
|
||||||
|
int line, column;
|
||||||
|
public:
|
||||||
|
JsonParseError(int line, int column, std::string_view str) : JsonException{str}, line{line}, column{column} {}
|
||||||
|
|
||||||
|
JsonParseError(std::string_view str) : JsonException{str} {}
|
||||||
|
|
||||||
|
const char *what() {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "[JsonParseError]" << message << " at line " << line << " column " << column;
|
||||||
|
return ss.str().c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonInvalidSym : public JsonParseError {
|
||||||
|
protected:
|
||||||
|
char detail;
|
||||||
|
public:
|
||||||
|
JsonInvalidSym(int line, int column, char detail) : JsonParseError{line, column, SYNTAX_ERROR},
|
||||||
|
detail(detail) {}
|
||||||
|
|
||||||
|
const char *what() {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "[JsonParseError]" << message << " :invalid symbol " << detail << " at line " << line << " column "
|
||||||
|
<< column << " detail " << detail;
|
||||||
|
return ss.str().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonInvalidEscapedSym : public JsonInvalidSym {
|
||||||
|
public:
|
||||||
|
JsonInvalidEscapedSym(int line, int column, char detail) : JsonInvalidSym{line, column, detail} {}
|
||||||
|
|
||||||
|
const char *what() {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "[JsonParseError]" << message << " :invalid escaped symbol " << detail << " at line " << line
|
||||||
|
<< " column " << column << " detail " << detail;
|
||||||
|
return ss.str().c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SIMPLEJSON_EXCEPTION_H
|
||||||
+232
-15
@@ -3,6 +3,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
#include "exception.h"
|
||||||
|
|
||||||
namespace simpleJson {
|
namespace simpleJson {
|
||||||
|
|
||||||
@@ -149,7 +150,8 @@ namespace simpleJson {
|
|||||||
setValueType(JSON_TYPE_LIST);
|
setValueType(JSON_TYPE_LIST);
|
||||||
}
|
}
|
||||||
if (type != JSON_TYPE_LIST) {
|
if (type != JSON_TYPE_LIST) {
|
||||||
throw std::runtime_error("JsonNode::set_list() error: type is not list");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_LIST, type);
|
||||||
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
clear();
|
clear();
|
||||||
@@ -166,7 +168,7 @@ namespace simpleJson {
|
|||||||
|
|
||||||
JsonNode &JsonNode::list_get(int index) {
|
JsonNode &JsonNode::list_get(int index) {
|
||||||
if (type != JSON_TYPE_LIST) {
|
if (type != JSON_TYPE_LIST) {
|
||||||
throw std::runtime_error("JsonNode::list_get() error: type is not list");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_LIST, type);
|
||||||
} else if (index < 0 || index >= children_size) {
|
} else if (index < 0 || index >= children_size) {
|
||||||
throw std::runtime_error("JsonNode::list_get() error: index out of range");
|
throw std::runtime_error("JsonNode::list_get() error: index out of range");
|
||||||
} else {
|
} else {
|
||||||
@@ -180,7 +182,7 @@ namespace simpleJson {
|
|||||||
|
|
||||||
void JsonNode::list_insert(int index, simpleJson::JsonNodePtr node) {
|
void JsonNode::list_insert(int index, simpleJson::JsonNodePtr node) {
|
||||||
if (type != JSON_TYPE_LIST) {
|
if (type != JSON_TYPE_LIST) {
|
||||||
throw std::runtime_error("JsonNode::list_insert() error: type is not list");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_LIST, type);
|
||||||
} else if (index < 0 || index > children_size) {
|
} else if (index < 0 || index > children_size) {
|
||||||
throw std::runtime_error("JsonNode::list_insert() error: index out of range");
|
throw std::runtime_error("JsonNode::list_insert() error: index out of range");
|
||||||
} else {
|
} else {
|
||||||
@@ -204,7 +206,8 @@ namespace simpleJson {
|
|||||||
|
|
||||||
void JsonNode::list_erase(int index) {
|
void JsonNode::list_erase(int index) {
|
||||||
if (type != JSON_TYPE_LIST) {
|
if (type != JSON_TYPE_LIST) {
|
||||||
throw std::runtime_error("JsonNode::list_erase() error: type is not list");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_LIST, type);
|
||||||
|
|
||||||
} else if (index < 0 || index >= children_size) {
|
} else if (index < 0 || index >= children_size) {
|
||||||
throw std::runtime_error("JsonNode::list_erase() error: index out of range");
|
throw std::runtime_error("JsonNode::list_erase() error: index out of range");
|
||||||
} else {
|
} else {
|
||||||
@@ -231,7 +234,7 @@ namespace simpleJson {
|
|||||||
|
|
||||||
bool JsonNode::obj_has_item(const std::string &key) {
|
bool JsonNode::obj_has_item(const std::string &key) {
|
||||||
if (type != JSON_TYPE_OBJECT) {
|
if (type != JSON_TYPE_OBJECT) {
|
||||||
throw std::runtime_error("JsonNode::obj_has_item() error: type is not object");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_OBJECT, type);
|
||||||
} else {
|
} else {
|
||||||
JsonNodePtr p = child_head;
|
JsonNodePtr p = child_head;
|
||||||
while (p != nullptr) {
|
while (p != nullptr) {
|
||||||
@@ -246,7 +249,7 @@ namespace simpleJson {
|
|||||||
|
|
||||||
JsonNode &JsonNode::obj_get(const std::string &key) {
|
JsonNode &JsonNode::obj_get(const std::string &key) {
|
||||||
if (type != JSON_TYPE_OBJECT) {
|
if (type != JSON_TYPE_OBJECT) {
|
||||||
throw std::runtime_error("JsonNode::obj_get() error: type is not object");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_OBJECT, type);
|
||||||
} else {
|
} else {
|
||||||
JsonNodePtr p = child_head;
|
JsonNodePtr p = child_head;
|
||||||
while (p != nullptr) {
|
while (p != nullptr) {
|
||||||
@@ -261,7 +264,7 @@ namespace simpleJson {
|
|||||||
|
|
||||||
void JsonNode::obj_set(simpleJson::JsonNodePtr node) {
|
void JsonNode::obj_set(simpleJson::JsonNodePtr node) {
|
||||||
if (type != JSON_TYPE_OBJECT) {
|
if (type != JSON_TYPE_OBJECT) {
|
||||||
throw std::runtime_error("JsonNode::obj_set() error: type is not object");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_OBJECT, type);
|
||||||
} else {
|
} else {
|
||||||
if (obj_has_item(node->key)) {
|
if (obj_has_item(node->key)) {
|
||||||
obj_get(node->key) = *node;
|
obj_get(node->key) = *node;
|
||||||
@@ -351,7 +354,7 @@ namespace simpleJson {
|
|||||||
setValueType(JSON_TYPE_OBJECT);
|
setValueType(JSON_TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
if (type != JSON_TYPE_OBJECT) {
|
if (type != JSON_TYPE_OBJECT) {
|
||||||
throw std::runtime_error("JsonNode::operator[]() error: type is not object");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_OBJECT, type);
|
||||||
} else {
|
} else {
|
||||||
if (obj_has_item(key)) {
|
if (obj_has_item(key)) {
|
||||||
return obj_get(key);
|
return obj_get(key);
|
||||||
@@ -368,7 +371,7 @@ namespace simpleJson {
|
|||||||
setValueType(JSON_TYPE_LIST);
|
setValueType(JSON_TYPE_LIST);
|
||||||
}
|
}
|
||||||
if (type != JSON_TYPE_LIST) {
|
if (type != JSON_TYPE_LIST) {
|
||||||
throw std::runtime_error("JsonNode::operator[]() error: type is not list");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_LIST, type);
|
||||||
} else {
|
} else {
|
||||||
if (index < 0 || index >= children_size) {
|
if (index < 0 || index >= children_size) {
|
||||||
throw std::runtime_error("JsonNode::operator[]() error: index out of range");
|
throw std::runtime_error("JsonNode::operator[]() error: index out of range");
|
||||||
@@ -392,7 +395,7 @@ namespace simpleJson {
|
|||||||
value.bool_value = _value > 0;
|
value.bool_value = _value > 0;
|
||||||
return _value;
|
return _value;
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("JsonNode::operator=(double) error: type is not number");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_INT, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,7 +414,7 @@ namespace simpleJson {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw std::runtime_error("JsonNode::as_int() error: type is not number");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_INT, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -431,7 +434,7 @@ namespace simpleJson {
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw std::runtime_error("JsonNode::as_double() error: type is not number");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_DOUBLE, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,7 +457,7 @@ namespace simpleJson {
|
|||||||
return "NULL";
|
return "NULL";
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw std::runtime_error("JsonNode::as_string() error: type is not string");
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_STRING, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -472,6 +475,22 @@ namespace simpleJson {
|
|||||||
void JsonNode::setValueType(simpleJson::JsonValueTypeEnum _type) {
|
void JsonNode::setValueType(simpleJson::JsonValueTypeEnum _type) {
|
||||||
type = _type;
|
type = _type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JsonNode::as_bool() const {
|
||||||
|
switch (type) {
|
||||||
|
case JSON_TYPE_INT:
|
||||||
|
return static_cast<bool>(value.int_value);
|
||||||
|
case JSON_TYPE_DOUBLE:
|
||||||
|
return static_cast<bool>(value.double_value);
|
||||||
|
case JSON_TYPE_BOOL:
|
||||||
|
return value.bool_value;
|
||||||
|
case JSON_TYPE_NULL:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
throw JsonTypeError(INVALID_TYPE, __func__, JSON_TYPE_BOOL, type);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/*****************************************************************************************************************/
|
/*****************************************************************************************************************/
|
||||||
|
|
||||||
/***********************************************JsonReader*******************************************************/
|
/***********************************************JsonReader*******************************************************/
|
||||||
@@ -535,7 +554,6 @@ namespace simpleJson {
|
|||||||
if (eof) {
|
if (eof) {
|
||||||
throw std::runtime_error("JsonReader::get_char() error: end of file");
|
throw std::runtime_error("JsonReader::get_char() error: end of file");
|
||||||
} else {
|
} else {
|
||||||
curr_ptr++;
|
|
||||||
if (curr_ptr >= src_str_len) {
|
if (curr_ptr >= src_str_len) {
|
||||||
eof = 1;
|
eof = 1;
|
||||||
return '\0';
|
return '\0';
|
||||||
@@ -582,7 +600,9 @@ namespace simpleJson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JsonReader::skip_space() {
|
void JsonReader::skip_space() {
|
||||||
while (curr_ptr < src_str_len && (src_str[curr_ptr] == ' ' || src_str[curr_ptr] == '\t' || src_str[curr_ptr] == '\n' || src_str[curr_ptr] == '\r')) {
|
while (curr_ptr < src_str_len &&
|
||||||
|
(src_str[curr_ptr] == ' ' || src_str[curr_ptr] == '\t' || src_str[curr_ptr] == '\n' ||
|
||||||
|
src_str[curr_ptr] == '\r')) {
|
||||||
get_char();
|
get_char();
|
||||||
}
|
}
|
||||||
if (curr_ptr >= src_str_len) {
|
if (curr_ptr >= src_str_len) {
|
||||||
@@ -594,5 +614,202 @@ namespace simpleJson {
|
|||||||
return eof;
|
return eof;
|
||||||
}
|
}
|
||||||
/****************************************************************************************************************/
|
/****************************************************************************************************************/
|
||||||
|
/**********************************************JsonParser********************************************************/
|
||||||
|
|
||||||
|
JsonParser::JsonParser() {
|
||||||
|
root = JsonNodePtr(new JsonNode(JSON_TYPE_OBJECT));
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonParser::JsonParser(const std::string &_src_str) {
|
||||||
|
root = JsonNodePtr(new JsonNode(JSON_TYPE_OBJECT));
|
||||||
|
try {
|
||||||
|
JsonReader reader(_src_str);
|
||||||
|
parseValue(reader, root);
|
||||||
|
is_parse_success = true;
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
is_parse_success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonParser::JsonParser(std::ifstream &_input_file_stream) {
|
||||||
|
root = JsonNodePtr(new JsonNode(JSON_TYPE_OBJECT));
|
||||||
|
try {
|
||||||
|
JsonReader reader(_input_file_stream);
|
||||||
|
parseValue(reader, root);
|
||||||
|
is_parse_success = true;
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
is_parse_success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode &JsonParser::get_root() {
|
||||||
|
return *root;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonParser::is_success() const {
|
||||||
|
return is_parse_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonParser::fail() const {
|
||||||
|
return !is_parse_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonParser::parseValue(simpleJson::JsonReader &reader, simpleJson::JsonNodePtr &node) {
|
||||||
|
reader.skip_space();
|
||||||
|
|
||||||
|
char ch = reader.curr_char();
|
||||||
|
if (ch == '{') {
|
||||||
|
parseObject(reader, node);
|
||||||
|
} else if (ch == '\"') {
|
||||||
|
parseString(reader, node);
|
||||||
|
} else if (ch == '[') {
|
||||||
|
parseList(reader, node);
|
||||||
|
} else if (ch == '-' || isdigit(ch)) {
|
||||||
|
parseNumber(reader, node);
|
||||||
|
} else {
|
||||||
|
if (reader.str_ahead(4) == "true") {
|
||||||
|
node->setValueType(JSON_TYPE_BOOL);
|
||||||
|
node->set_value(1);
|
||||||
|
reader.get_str(4);
|
||||||
|
} else if (reader.str_ahead(5) == "false") {
|
||||||
|
node->setValueType(JSON_TYPE_BOOL);
|
||||||
|
node->set_value(0);
|
||||||
|
reader.get_str(5);
|
||||||
|
} else if (reader.str_ahead(4) == "null" || reader.str_ahead(4) == "NULL") {
|
||||||
|
node->setValueType(JSON_TYPE_NULL);
|
||||||
|
reader.get_str(4);
|
||||||
|
} else {
|
||||||
|
throw JsonParseError(reader.get_curr_line(), reader.get_curr_col(), SYNTAX_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonParser::parseObject(simpleJson::JsonReader &reader, simpleJson::JsonNodePtr &node) {
|
||||||
|
node->setValueType(JSON_TYPE_OBJECT);
|
||||||
|
auto ch = reader.curr_char();
|
||||||
|
if (ch != '{') {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
} else {
|
||||||
|
reader.get_char();
|
||||||
|
reader.skip_space();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ch != '}') {
|
||||||
|
if (ch != '\"') {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
} else {
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
std::string key;
|
||||||
|
while (ch != '\"') {
|
||||||
|
key += reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
reader.get_char();
|
||||||
|
reader.skip_space();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
|
||||||
|
if (ch != ':') {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
} else {
|
||||||
|
reader.get_char();
|
||||||
|
reader.skip_space();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
JsonNodePtr child(new JsonNode(JSON_TYPE_NULL, key));
|
||||||
|
parseValue(reader, child);
|
||||||
|
|
||||||
|
node->push_back(child);
|
||||||
|
|
||||||
|
reader.skip_space();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
|
||||||
|
if (ch == ',') {
|
||||||
|
reader.get_char();
|
||||||
|
reader.skip_space();
|
||||||
|
} else if (ch != '}') {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
} else {
|
||||||
|
reader.get_char();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
reader.get_char();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonParser::parseList(simpleJson::JsonReader &reader, simpleJson::JsonNodePtr &node) {
|
||||||
|
node->setValueType(JSON_TYPE_LIST);
|
||||||
|
char ch = reader.curr_char();
|
||||||
|
if (ch != '[') {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
} else {
|
||||||
|
reader.get_char();
|
||||||
|
reader.skip_space();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
while (ch != ']') {
|
||||||
|
JsonNodePtr child(new JsonNode(JSON_TYPE_NULL));
|
||||||
|
parseValue(reader, child);
|
||||||
|
node->push_back(child);
|
||||||
|
|
||||||
|
reader.skip_space();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
|
||||||
|
if (ch == ',') {
|
||||||
|
reader.get_char();
|
||||||
|
reader.skip_space();
|
||||||
|
} else if (ch != ']') {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
} else {
|
||||||
|
reader.get_char();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
reader.get_char();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonParser::parseString(simpleJson::JsonReader &reader, simpleJson::JsonNodePtr &node) {
|
||||||
|
node->setValueType(JSON_TYPE_STRING);
|
||||||
|
std::string str;
|
||||||
|
char ch = reader.curr_char();
|
||||||
|
if (ch != '\"') {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
|
||||||
|
while (ch != '\"') {
|
||||||
|
if (ch == '\\') {
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
if (ch == '\"' || ch == '\\' || ch == '/' || ch == '\b' || ch == '\f' || ch == '\n' || ch == '\r' ||
|
||||||
|
ch == '\t') {
|
||||||
|
str += ch;
|
||||||
|
} else if (ch == 'u') {
|
||||||
|
//unicode TODO
|
||||||
|
} else {
|
||||||
|
throw JsonInvalidEscapedSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
}
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
} else {
|
||||||
|
str += ch;
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.get_char();
|
||||||
|
node->set_value(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonParser::parseNumber(simpleJson::JsonReader &reader, simpleJson::JsonNodePtr &node) {}
|
||||||
|
|
||||||
|
/****************************************************************************************************************/
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,15 @@ namespace simpleJson {
|
|||||||
JSON_TYPE_LIST,
|
JSON_TYPE_LIST,
|
||||||
JSON_TYPE_OBJECT
|
JSON_TYPE_OBJECT
|
||||||
};
|
};
|
||||||
|
const static std::string_view JSON_TYPE_STR[] = {
|
||||||
|
"JSON_TYPE_NULL",
|
||||||
|
"JSON_TYPE_INT",
|
||||||
|
"JSON_TYPE_DOUBLE",
|
||||||
|
"JSON_TYPE_BOOL",
|
||||||
|
"JSON_TYPE_STRING",
|
||||||
|
"JSON_TYPE_LIST",
|
||||||
|
"JSON_TYPE_OBJECT"
|
||||||
|
};
|
||||||
union JsonValue {
|
union JsonValue {
|
||||||
int int_value;
|
int int_value;
|
||||||
double double_value;
|
double double_value;
|
||||||
|
|||||||
Reference in New Issue
Block a user