add parser unicode
This commit is contained in:
@@ -38,6 +38,20 @@ TEST(TestCase, testParseStr) {
|
|||||||
EXPECT_EQ(parser.get_root().obj_get("key").as_string(), "1");
|
EXPECT_EQ(parser.get_root().obj_get("key").as_string(), "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TestCase, testParseNumber) {
|
||||||
|
std::string json_str = "{\"key\":1}";
|
||||||
|
simpleJson::JsonParser parser(json_str);
|
||||||
|
EXPECT_EQ(parser.get_root().obj_get("key").as_int(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestCase, testParseList) {
|
||||||
|
std::string json_str = "{\"key\":[1,2,\"2\"]}";
|
||||||
|
simpleJson::JsonParser parser(json_str);
|
||||||
|
EXPECT_EQ(parser.get_root().obj_get("key").list_get(0).as_int(), 1);
|
||||||
|
EXPECT_EQ(parser.get_root().obj_get("key").list_get(1).as_int(), 2);
|
||||||
|
EXPECT_EQ(parser.get_root().obj_get("key").list_get(2).as_string(), "2");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
namespace simpleJson {
|
namespace simpleJson {
|
||||||
const std::string_view SYNTAX_ERROR = "Syntax Error";
|
const std::string_view SYNTAX_ERROR = "Syntax Error";
|
||||||
const std::string_view INVALID_TYPE = "Invalid Type";
|
const std::string_view INVALID_TYPE = "Invalid Type";
|
||||||
|
const std::string_view FILE_NOT_FOUND = "File Not Found";
|
||||||
|
|
||||||
class JsonException : public std::exception {
|
class JsonException : public std::exception {
|
||||||
protected:
|
protected:
|
||||||
@@ -23,6 +24,18 @@ namespace simpleJson {
|
|||||||
virtual ~JsonException() = default;
|
virtual ~JsonException() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FilePathNotValid : public JsonException {
|
||||||
|
public:
|
||||||
|
FilePathNotValid(std::string_view str) : JsonException{str} {}
|
||||||
|
|
||||||
|
const char *what() {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "[JsonFileNotFound]File path\"" << message << "\" is not valid";
|
||||||
|
return ss.str().c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class JsonTypeError : public JsonException {
|
class JsonTypeError : public JsonException {
|
||||||
protected:
|
protected:
|
||||||
std::string function_name;
|
std::string function_name;
|
||||||
@@ -83,6 +96,18 @@ namespace simpleJson {
|
|||||||
return ss.str().c_str();
|
return ss.str().c_str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class JsonInvalidUnicodeSym : public JsonInvalidSym {
|
||||||
|
public:
|
||||||
|
JsonInvalidUnicodeSym(int line, int column, char detail) : JsonInvalidSym{line, column, detail} {}
|
||||||
|
|
||||||
|
const char *what() {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "[JsonParseError]" << message << " :invalid unicode symbol " << detail << " at line " << line
|
||||||
|
<< " column " << column << " detail " << detail;
|
||||||
|
return ss.str().c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //SIMPLEJSON_EXCEPTION_H
|
#endif //SIMPLEJSON_EXCEPTION_H
|
||||||
|
|||||||
+134
-2
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
namespace simpleJson {
|
namespace simpleJson {
|
||||||
|
|
||||||
@@ -793,7 +794,20 @@ namespace simpleJson {
|
|||||||
ch == '\t') {
|
ch == '\t') {
|
||||||
str += ch;
|
str += ch;
|
||||||
} else if (ch == 'u') {
|
} else if (ch == 'u') {
|
||||||
//unicode TODO
|
std::string unicode_str;
|
||||||
|
for (int i = 0; i < 4; i ++) {
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F') {
|
||||||
|
unicode_str += ch;
|
||||||
|
} else {
|
||||||
|
throw JsonInvalidUnicodeSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long unicode = std::stol(unicode_str.data(), nullptr, 16);
|
||||||
|
std::string utf8_str;
|
||||||
|
encode_utf8(unicode, utf8_str);
|
||||||
|
str += utf8_str;
|
||||||
} else {
|
} else {
|
||||||
throw JsonInvalidEscapedSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
throw JsonInvalidEscapedSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
}
|
}
|
||||||
@@ -809,7 +823,125 @@ namespace simpleJson {
|
|||||||
node->set_value(str);
|
node->set_value(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonParser::parseNumber(simpleJson::JsonReader &reader, simpleJson::JsonNodePtr &node) {}
|
void JsonParser::parseNumber(simpleJson::JsonReader &reader, simpleJson::JsonNodePtr &node) {
|
||||||
|
node->setValueType(JSON_TYPE_DOUBLE);
|
||||||
|
bool sign = 1;
|
||||||
|
double value = 0;
|
||||||
|
bool exp_sign = 1;
|
||||||
|
int exp_val = 0;
|
||||||
|
int scale = 0, sub_scale = 0;
|
||||||
|
|
||||||
|
char ch = reader.curr_char();
|
||||||
|
if (ch != '-' && !isdigit(ch)) {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
}
|
||||||
|
if (ch == '-') {
|
||||||
|
sign = 0;
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
if (isdigit(ch) && ch != '0') {
|
||||||
|
while(isdigit(ch)) {
|
||||||
|
value = value * 10 + (ch - '0');
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
} else if (ch == '0') {
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
if (ch == '.') {
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
if (!isdigit(ch)) {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
}
|
||||||
|
while(isdigit(ch)) {
|
||||||
|
sub_scale += 1;
|
||||||
|
value = value + double(ch-'0')*std::pow(0.1, double(sub_scale));
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch == 'e' || ch == 'E') {
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
|
||||||
|
if (ch == '-') {
|
||||||
|
exp_sign = 0;
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
} else if (ch == '+') {
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isdigit(ch)) {
|
||||||
|
throw JsonInvalidSym(reader.get_curr_line(), reader.get_curr_col(), ch);
|
||||||
|
}
|
||||||
|
while(isdigit(ch)) {
|
||||||
|
exp_val = exp_val * 10 + (ch - '0');
|
||||||
|
reader.get_char();
|
||||||
|
ch = reader.curr_char();
|
||||||
|
}
|
||||||
|
|
||||||
|
exp_val *= exp_sign ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = (value * (sign ? 1 : -1)) * std::pow(10, exp_val);
|
||||||
|
node->set_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JsonParser::to_json_string(std::string &_dst_str, bool _one_line) const {
|
||||||
|
_dst_str.clear();
|
||||||
|
root->to_json_string(_dst_str, false, 0, _one_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonParser::save_to_file(const std::string &_file_path, bool _one_line) const {
|
||||||
|
std::ofstream output_file_stream(_file_path);
|
||||||
|
if (!output_file_stream) {
|
||||||
|
throw FilePathNotValid(_file_path);
|
||||||
|
}
|
||||||
|
std::string json_str;
|
||||||
|
to_json_string(json_str, _one_line);
|
||||||
|
output_file_stream << json_str;
|
||||||
|
output_file_stream.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************************************************/
|
/****************************************************************************************************************/
|
||||||
|
|
||||||
|
void encode_utf8(long _unicode, std::string& _out)
|
||||||
|
{
|
||||||
|
if (_unicode < 0 || _unicode > 0x10FFFF)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_out.clear();
|
||||||
|
if (_unicode <= 0x7F)
|
||||||
|
{
|
||||||
|
_out += static_cast<char>(_unicode);
|
||||||
|
}
|
||||||
|
else if (_unicode >= 0x80 && _unicode <= 0x7FF)
|
||||||
|
{
|
||||||
|
_out += static_cast<char>((_unicode >> 6) | 0xC0);
|
||||||
|
_out += static_cast<char>((_unicode & 0x3F) | 0x80);
|
||||||
|
}
|
||||||
|
else if (_unicode >= 0x800 && _unicode <= 0xFFFF)
|
||||||
|
{
|
||||||
|
_out += static_cast<char>((_unicode >> 12) | 0xE0);
|
||||||
|
_out += static_cast<char>(((_unicode >> 6) & 0x3F) | 0x80);
|
||||||
|
_out += static_cast<char>((_unicode & 0x3F) | 0x80);
|
||||||
|
}
|
||||||
|
else if (_unicode >= 0x10000 && _unicode <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
_out += static_cast<char>((_unicode >> 18) | 0xF0);
|
||||||
|
_out += static_cast<char>(((_unicode >> 12) & 0x3F) | 0x80);
|
||||||
|
_out += static_cast<char>(((_unicode >> 6) & 0x3F) | 0x80);
|
||||||
|
_out += static_cast<char>((_unicode & 0x3F) | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -194,6 +194,9 @@ namespace simpleJson {
|
|||||||
|
|
||||||
bool save_to_file(const std::string &_file_path, bool _one_line = 0) const;
|
bool save_to_file(const std::string &_file_path, bool _one_line = 0) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void encode_utf8(long _unicode, std::string &_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //SIMPLEJSON_JSON_H
|
#endif //SIMPLEJSON_JSON_H
|
||||||
|
|||||||
Reference in New Issue
Block a user