├── v2 └── src │ ├── example │ ├── meta │ ├── example │ ├── serialize_example │ ├── out.json │ ├── example.json │ ├── meta.cc │ ├── serialize_example.cc │ └── example.cc │ ├── json_assert.hpp │ ├── json_serialization.hpp │ ├── json_writer.hpp │ ├── test │ └── pson_test.cc │ ├── json_parser.hpp │ └── json_value.hpp ├── pson.hpp ├── .gitignore ├── LICENSE └── README.md /v2/src/example/meta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PinkDoc/pson/HEAD/v2/src/example/meta -------------------------------------------------------------------------------- /v2/src/example/example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PinkDoc/pson/HEAD/v2/src/example/example -------------------------------------------------------------------------------- /v2/src/example/serialize_example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PinkDoc/pson/HEAD/v2/src/example/serialize_example -------------------------------------------------------------------------------- /pson.hpp: -------------------------------------------------------------------------------- 1 | #include "v2/src/json_parser.hpp" 2 | #include "v2/src/json_writer.hpp" 3 | #include "v2/src/json_serialization.hpp" 4 | -------------------------------------------------------------------------------- /v2/src/example/out.json: -------------------------------------------------------------------------------- 1 | { 2 | "array" : [], 3 | "m" : { 4 | "age" : 40.000000, 5 | "items" : {}, 6 | "name" : "Taylor", 7 | "object" : {} 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /v2/src/json_assert.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace pson { 9 | 10 | #define PSON_ASSERT(expr) \ 11 | do { \ 12 | if (!expr) {\ 13 | fprintf(stderr, "[PSON-ASSERT][FILE: %s][LINE: %d]\n", __FILE__, __LINE__); \ 14 | assert(true);\ 15 | }\ 16 | }while(0) 17 | 18 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /v2/src/example/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "glossary": { 3 | "title": "example glossary", 4 | "GlossDiv": { 5 | "title": "S", 6 | "GlossList": { 7 | "GlossEntry": { 8 | "ID": "SGML", 9 | "SortAs": "SGML", 10 | "GlossTerm": "Standard Generalized Markup Language", 11 | "Acronym": "SGML", 12 | "Abbrev": "ISO 8879:1986", 13 | "GlossDef": { 14 | "para": "A meta-markup language, used to create markup languages such as DocBook.", 15 | "GlossSeeAlso": ["GML", "XML"] 16 | }, 17 | "GlossSee": "markup" 18 | } 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /v2/src/example/meta.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | template 5 | struct TypesCmp 6 | { 7 | enum { 8 | value = false 9 | }; 10 | }; 11 | 12 | template 13 | struct TypesCmp 14 | { 15 | enum { 16 | value = false | TypesCmp::value 17 | }; 18 | }; 19 | 20 | template 21 | struct TypesCmp 22 | { 23 | enum { 24 | value = true | TypesCmp::value 25 | }; 26 | }; 27 | 28 | int main() 29 | { 30 | if (TypesCmp::value) { 31 | std::cout << "Issame" << std::endl; 32 | } else { 33 | std::cout << "Is not same" << std::endl; 34 | } 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Pink 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /v2/src/example/serialize_example.cc: -------------------------------------------------------------------------------- 1 | #include "../json_serialization.hpp" 2 | #include "../json_writer.hpp" 3 | #include 4 | 5 | struct Mom 6 | { 7 | int age; 8 | std::string name; 9 | pson::Value items; 10 | pson::Object object; 11 | 12 | Mom(): age(40), name("Taylor"), items(pson::JSON_OBJECT) 13 | {} 14 | 15 | Serialize_Start 16 | Serialize_Insert(age) 17 | Serialize_Insert(name) 18 | Serialize_Insert(items) 19 | Serialize_Insert(object) 20 | Serialize_End 21 | 22 | 23 | DeSerialize_Start 24 | DeSerialize_Fetch(age) 25 | DeSerialize_Fetch(name) 26 | DeSerialize_Fetch(items) 27 | DeSerialize_Fetch(object) 28 | DeSerialize_End 29 | }; 30 | 31 | struct Tank 32 | { 33 | Mom m; 34 | pson::Array array; 35 | 36 | Serialize_Start 37 | Serialize_Insert(m) 38 | Serialize_Insert(array) 39 | Serialize_End 40 | 41 | DeSerialize_Start 42 | DeSerialize_Fetch(m) 43 | DeSerialize_Fetch(array) 44 | DeSerialize_End 45 | }; 46 | 47 | int main() 48 | { 49 | Tank t; 50 | t.m.age = 1989; 51 | t.m.name = "Oly"; 52 | auto json_data = t.Serialize(); 53 | Tank t2; 54 | t2.DeSerializeFromValue(json_data); 55 | assert(t2.m.name == "Oly"); 56 | assert(t2.m.age == 1989); 57 | } -------------------------------------------------------------------------------- /v2/src/example/example.cc: -------------------------------------------------------------------------------- 1 | #include "../json_parser.hpp" 2 | #include "../json_writer.hpp" 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace pson; 8 | 9 | #define LOG_OUTPUT_STREAM stdout 10 | #define LOG_LOG_TIME_FORMAT "%Y-%m-%d %H:%M:%S" 11 | 12 | #define LOG(...) do { \ 13 | OutPutHeader(__FILE__, __FUNCTION__);\ 14 | fprintf(LOG_OUTPUT_STREAM, __VA_ARGS__);\ 15 | fprintf(LOG_OUTPUT_STREAM, "\n");\ 16 | fflush(LOG_OUTPUT_STREAM); } while(0) 17 | 18 | 19 | 20 | 21 | void OutPutHeader(const char* filename, const char* function) 22 | { 23 | auto t = time(nullptr); 24 | tm *curTime = localtime(&t); // NOLINT 25 | char time_str[32]; 26 | ::strftime(time_str, 32, LOG_LOG_TIME_FORMAT, curTime); 27 | fprintf(LOG_OUTPUT_STREAM, "[%s]""[FileName : %s]""[Function : %s] ", time_str, filename, function); 28 | } 29 | 30 | 31 | std::vector GetJsonData(const std::string& filename) 32 | { 33 | LOG("json file name %s", filename.c_str()); 34 | FILE* file_stream = fopen(filename.c_str(), "r+"); 35 | std::vector data; 36 | 37 | if (file_stream == nullptr) { 38 | LOG("fopen FAIL"); 39 | return data; 40 | } 41 | auto cur_offset = ftell(file_stream); 42 | fseek(file_stream, 0, SEEK_END); 43 | auto size = ftell(file_stream); 44 | fseek(file_stream, cur_offset, SEEK_SET); 45 | LOG("json data size : %ld",size); 46 | data.resize(size); 47 | auto ok = fread(data.data(), size, 1, file_stream); 48 | fclose(file_stream); 49 | return data; 50 | } 51 | 52 | int main() { 53 | Value v; 54 | // example for 55 | std::string filename = "example.json"; 56 | std::vector data = GetJsonData("example.json"); 57 | Parser p(data.data(), data.size()); 58 | bool ok = p.Parse(v); 59 | if (!ok) { 60 | LOG("parse FAIL!"); 61 | return 0; 62 | } 63 | 64 | std::cout << "====================================" << std::endl; 65 | std::cout << v.print() << std::endl; 66 | 67 | 68 | } -------------------------------------------------------------------------------- /v2/src/json_serialization.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include "json_value.hpp" 5 | 6 | namespace pson { 7 | 8 | 9 | #define IS_INTEGER(type) \ 10 | (pson::TypesCmp::value) 11 | 12 | // This is for json data 13 | template 14 | struct FetchJsonDataT 15 | { 16 | inline void Fetch(pson::Object& o, const std::string& name, T& t) {} 17 | }; 18 | 19 | template 20 | struct FetchJsonDataT 21 | { 22 | inline void Fetch(pson::Object& o, const std::string& name, T& t) { 23 | pson::Number n = o.at(name).as(); 24 | t = static_cast(n); 25 | } 26 | }; 27 | 28 | template 29 | struct FetchJsonDataT 30 | { 31 | inline void Fetch(pson::Object& o, const std::string& name, T& t) { 32 | t = o.at(name).as(); 33 | } 34 | }; 35 | 36 | 37 | template 38 | struct enable_if 39 | { 40 | inline void ObjectInsert(pson::Object& o, std::string name, T t) {} 41 | inline void ObjectFetch(pson::Object& o, const std::string& name, T &t) {} 42 | }; 43 | 44 | template 45 | struct enable_if 46 | { 47 | inline void ObjectInsert(pson::Object& o, std::string name, T t) 48 | { 49 | o.insert(std::move(name), t); 50 | } 51 | 52 | inline void ObjectFetch(pson::Object& o, const std::string& name, T& t) 53 | { 54 | FetchJsonDataT().Fetch(o, name, t); 55 | } 56 | }; 57 | 58 | template 59 | struct enable_if 60 | { 61 | inline void ObjectInsert(pson::Object& o, std::string name, T t) 62 | { 63 | auto&& json = t.Serialize(); 64 | o.insert(std::move(name), json); 65 | } 66 | 67 | inline void ObjectFetch(pson::Object& o, const std::string& name, T& t) 68 | { 69 | auto&& v = o.at(name); 70 | t.DeSerializeFromValue(v); 71 | } 72 | }; 73 | 74 | } 75 | 76 | #define VALUE_NAME(a) (#a) 77 | 78 | #define Serialize_Start inline pson::Value Serialize() {\ 79 | pson::Value v{pson::JSON_OBJECT};\ 80 | pson::Object& obj = v.as(); 81 | 82 | #define Serialize_Insert(a) pson::enable_if().ObjectInsert(obj, std::move(std::string(VALUE_NAME(a))), a); 83 | 84 | #define Serialize_End \ 85 | return v; } 86 | 87 | 88 | #define DeSerialize_Start inline void DeSerializeFromValue(pson::Value& v) { \ 89 | auto&& obj = v.as(); 90 | 91 | #define DeSerialize_Fetch(a) pson::enable_if().ObjectFetch(obj, std::string(VALUE_NAME(a)), a); 92 | 93 | #define DeSerialize_End } 94 | 95 | 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### pson 2 | 3 | pson is a lightweight parser and it support six type, null , bool, number, string, array, object, and it can parse the encoding of UTF-8. 4 | 5 | It's fast, small and it's simple to use. 6 | 7 | You just need to `#include "pson.hpp"` to your projects~ 8 | 9 | ### Feature 10 | * Serialize struct 11 | * Parser struct 12 | ### Usage 13 | #### parse 14 | 15 | ``` 16 | using namespace pson; 17 | std::string json = "{\n" 18 | " \"pink\" : {\n" 19 | " \"ktouch\" : \"phone\",\n" 20 | " \"xiaomi\" : \"phone\"\n" 21 | " },\n" 22 | " \"computer\" : [\"惠普\", 100.0, false, true],\n" 23 | " \"age\" : 20,\n" 24 | " \"best code\" : \"non\",\n" 25 | " \"man\" : true\n" 26 | "}"; 27 | 28 | Value v; 29 | v.parse(json); 30 | 31 | Value v_hello{"hello"}; 32 | Value v_false{false}; 33 | Value v_number(1.2); 34 | 35 | assert(v.is() == true); 36 | assert(v["computer"][0].as() == "惠普"); 37 | assert(v["pink"]["ktouch"].as_string() == "phone"); 38 | assert(v["computer"][1].as_number() == 100.0); 39 | assert(v["man"].as() == true); 40 | 41 | Value cp_v(v); // Copy 42 | Value mv_c(std::move(v)); // Move 43 | 44 | // Use array, or object to move and copy 45 | Value a(JSON_ARRAY), o(JSON_OBJECT); 46 | a.push_back(std::move(v)); // Move 47 | o.insert("This is copy", v); // Copy 48 | 49 | // To string 50 | std::string tostr = a.print(); 51 | 52 | 53 | 54 | ``` 55 | 56 | #### serialize 57 | ``` 58 | 59 | struct Mom 60 | { 61 | int age; 62 | std::string name; 63 | pson::Value items; 64 | pson::Object object; 65 | 66 | Mom(): age(40), name("Taylor"), items(pson::JSON_OBJECT) 67 | {} 68 | 69 | Serialize_Start 70 | Serialize_Insert(age) 71 | Serialize_Insert(name) 72 | Serialize_Insert(items) 73 | Serialize_Insert(object) 74 | Serialize_End 75 | 76 | 77 | DeSerialize_Start 78 | DeSerialize_Fetch(age) 79 | DeSerialize_Fetch(name) 80 | DeSerialize_Fetch(items) 81 | DeSerialize_Fetch(object) 82 | DeSerialize_End 83 | }; 84 | 85 | struct Tank 86 | { 87 | Mom m; 88 | pson::Array array; 89 | 90 | Serialize_Start 91 | Serialize_Insert(m) 92 | Serialize_Insert(array) 93 | Serialize_End 94 | 95 | DeSerialize_Start 96 | DeSerialize_Fetch(m) 97 | DeSerialize_Fetch(array) 98 | DeSerialize_End 99 | }; 100 | 101 | int main() 102 | { 103 | Tank t; 104 | t.m.age = 1989; 105 | t.m.name = "Oly"; 106 | auto json_data = t.Serialize(); 107 | Tank t2; 108 | t2.DeSerializeFromValue(json_data); 109 | assert(t2.m.name == "Oly"); 110 | assert(t2.m.age == 1989); 111 | } 112 | ``` 113 | 114 | hf! 115 | 116 | 117 | #### TODO 118 | 119 | fix v1 120 | -------------------------------------------------------------------------------- /v2/src/json_writer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "json_value.hpp" 4 | 5 | namespace pson { 6 | namespace imple { 7 | void pson_print_value(pson::Value& v, std::string& to_print); 8 | void pson_print_object(pson::Value& v, std::string& to_print); 9 | void pson_print_array(pson::Value& v, std::string& to_print); 10 | 11 | inline void pson_print_array(pson::Value& v, std::string& to_print) 12 | { 13 | using namespace pson; 14 | Array& a = v.as(); 15 | 16 | if (v.size() == 0) 17 | { 18 | to_print.append("[]"); 19 | return; 20 | } 21 | 22 | to_print.append("["); 23 | 24 | for (auto i = 0; i < a.size(); ++i) { 25 | pson_print_value(a.at(i), to_print); 26 | if (i != a.size() - 1) 27 | to_print.append(" , "); 28 | } 29 | 30 | to_print.append("]"); 31 | } 32 | 33 | inline void pson_print_object(pson::Value& v, std::string& to_print) 34 | { 35 | using namespace pson; 36 | Object& o = v.as(); 37 | 38 | if (o.size() == 0) 39 | { 40 | to_print.append("{}"); 41 | return; 42 | } 43 | 44 | auto& c = o.value_map(); 45 | 46 | to_print.append("{\n"); 47 | 48 | std::size_t s = 0; 49 | 50 | for (auto& i : c) 51 | { 52 | to_print.push_back('"'); 53 | to_print.append(i.first); 54 | to_print.append("\" : "); 55 | 56 | pson_print_value(i.second, to_print); 57 | 58 | if (s++ != c.size() - 1) { 59 | to_print.append(", \n"); 60 | } 61 | } 62 | 63 | to_print.append("\n}"); 64 | } 65 | 66 | 67 | inline void pson_print_value(pson::Value& v, std::string& to_print) 68 | { 69 | using namespace pson; 70 | 71 | switch (v.type()) 72 | { 73 | case JSON_NULL: 74 | to_print.append("null"); 75 | break; 76 | case JSON_BOOL: { 77 | const char* b = v.as() ? "true" : "false"; 78 | to_print.append(b); 79 | } 80 | break; 81 | case JSON_NUMBER: 82 | to_print.append(std::to_string(v.as())); 83 | break; 84 | case JSON_STRING: 85 | to_print.push_back('"'); 86 | to_print.append(v.as()); 87 | to_print.push_back('"'); 88 | break; 89 | case JSON_ARRAY: 90 | pson_print_array(v, to_print); 91 | break; 92 | case JSON_OBJECT: 93 | pson_print_object(v, to_print); 94 | break; 95 | default: 96 | return; 97 | } 98 | } 99 | } 100 | } 101 | 102 | namespace pson { 103 | 104 | inline std::string Value::print() 105 | { 106 | std::string ret; 107 | imple::pson_print_object(*this, ret); 108 | return std::move(ret); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /v2/src/test/pson_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "src/json_writer.hpp" 4 | #include "src/json_parser.hpp" 5 | #include "src/json_value.hpp" 6 | 7 | 8 | TEST(ValueTest, move) 9 | { 10 | using namespace pson; 11 | Value varray(JSON_ARRAY); 12 | Value vbool(JSON_BOOL); 13 | varray = std::move(vbool); 14 | 15 | EXPECT_EQ(varray.is_bool(), true); 16 | EXPECT_EQ(vbool.is_null(), true); 17 | } 18 | 19 | TEST(ValueTest, copy) 20 | { 21 | using namespace pson; 22 | Value varray(JSON_ARRAY); 23 | Value vbool(JSON_BOOL); 24 | varray = vbool; 25 | 26 | Value cp_bool(vbool); 27 | 28 | EXPECT_EQ(varray.is_bool(), true); 29 | EXPECT_EQ(vbool.is_bool(), true); 30 | EXPECT_EQ(cp_bool.is_bool(), true); 31 | } 32 | 33 | TEST(ValueTest, reset_as_and_is) 34 | { 35 | using namespace pson; 36 | 37 | Value v; 38 | EXPECT_EQ(v.is(), true); 39 | v.reset_as(); 40 | EXPECT_EQ(v.is(), true); 41 | v.reset_as(); 42 | EXPECT_EQ(v.is(), true); 43 | v.reset_as(); 44 | EXPECT_EQ(v.is(), true); 45 | v.reset_as(); 46 | EXPECT_EQ(v.is(), true); 47 | } 48 | 49 | TEST(ValueTest, swap_test) 50 | { 51 | using namespace pson; 52 | 53 | Value v1, v2; 54 | v1.reset_as(); 55 | v2.reset_as(); 56 | v1.swap(v2); 57 | EXPECT_EQ(v1.is(), true); 58 | EXPECT_EQ(v2.is(), true); 59 | } 60 | 61 | TEST(ObjectTest, oper_test) 62 | { 63 | using namespace pson; 64 | Value o(JSON_OBJECT); 65 | Value o2(JSON_OBJECT); 66 | 67 | // insert, size, operator[], erase, at, as 68 | // insert 69 | o.insert("hello world", Value(JSON_ARRAY)); 70 | o.insert("my null", Value(JSON_NULL)); 71 | o.insert("my string", Value(JSON_STRING)); 72 | o["my string"].as() = "I am String"; 73 | 74 | EXPECT_EQ(o.size(), 3); 75 | EXPECT_EQ(o["hello world"].size(), 0); 76 | EXPECT_EQ(o["my null"].is(), true); 77 | 78 | o.erase("my null"); 79 | 80 | EXPECT_EQ(o.size(), 2); 81 | EXPECT_EQ(o.at("my string").as(), "I am String"); 82 | 83 | // basic copy and move 84 | o2 = o; 85 | 86 | EXPECT_EQ(o.at("my string").as(), "I am String"); 87 | 88 | Value o3(std::move(o2)); 89 | 90 | EXPECT_EQ(o3.size() > 0, true); 91 | EXPECT_EQ(o3["my string"].as(), "I am String"); 92 | EXPECT_EQ(o2.is(), true); 93 | } 94 | 95 | TEST(ParserTest, parse) 96 | { 97 | using namespace pson; 98 | 99 | std::string json = "{\n" 100 | " \"pink\" : {\n" 101 | " \"ktouch\" : \"phone\",\n" 102 | " \"xiaomi\" : \"phone\"\n" 103 | " },\n" 104 | " \"computer\" : [\"惠普\", 100.0, false, true],\n" 105 | " \"age\" : 20,\n" 106 | " \"best code\" : \"non\",\n" 107 | " \"man\" : true\n" 108 | "}"; 109 | 110 | Value v; 111 | v.parse(json); 112 | 113 | EXPECT_EQ(v.is(), true); 114 | EXPECT_EQ(v["computer"][0].as(), "惠普"); 115 | EXPECT_EQ(v["pink"]["ktouch"].as_string(), "phone"); 116 | EXPECT_EQ(v["computer"][1].as_number(), 100.0); 117 | EXPECT_EQ(v["man"].as(), true); 118 | 119 | 120 | } 121 | 122 | int main() 123 | { 124 | testing::InitGoogleTest(); 125 | RUN_ALL_TESTS(); 126 | } -------------------------------------------------------------------------------- /v2/src/json_parser.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "json_value.hpp" 6 | 7 | namespace pson { 8 | 9 | class Parser { 10 | private: 11 | 12 | struct state { 13 | char* data_; 14 | size_t size_; 15 | size_t offset_; 16 | 17 | inline state(char* data, size_t size): 18 | data_(data), 19 | size_(size), 20 | offset_(0) {} 21 | 22 | inline state(): 23 | data_(nullptr), 24 | size_(0), 25 | offset_(0) {} 26 | 27 | inline void reset() { data_ = nullptr; size_ = 0; offset_ = 0; } 28 | inline void set(char* data, size_t len) { reset(); data_ = data; size_ = len; } 29 | }; 30 | 31 | state state_; 32 | 33 | // Insignificant whitespace is allowed before or after any of the six 34 | // structural characters. 35 | // 36 | // ws = *( 37 | // %x20 / ; Space 38 | // %x09 / ; Horizontal tab 39 | // %x0A / ; Line feed or New line 40 | // %x0D ; Carriage return 41 | // ) 42 | void skip_write_blank(); 43 | 44 | // [name] : true 45 | bool parse_true(Value& v); 46 | 47 | // [name] : false 48 | bool parse_false(Value& v); 49 | 50 | // [name] : null 51 | bool parse_null(Value& v); 52 | 53 | // :) 54 | bool parse_number(Value& v); 55 | 56 | // 0xffff 57 | bool parse_hex4(unsigned& u); 58 | 59 | bool parse_utf8(String & v, unsigned u); 60 | 61 | // Only parse string 62 | bool parse_string_row(String& s); 63 | 64 | // parse value string 65 | bool parse_string(Value& v); 66 | 67 | // [name]: [val1, val2, val3......] 68 | bool parse_array(Value& v); 69 | 70 | bool parse_object(Value& v); 71 | 72 | bool parse_value(Value& v); 73 | public: 74 | 75 | inline Parser(const std::string& data): 76 | state_(const_cast(data.data()) , data.size()) {} 77 | 78 | inline Parser(char* data, size_t size): 79 | state_(const_cast(data ), size) {} 80 | 81 | bool Parse(Value& v); 82 | 83 | inline void Reset() { state_.reset(); } 84 | inline void SetData(char* data, size_t len) { Reset(); state_.set(data, len); } 85 | inline void SetData(std::string& data) { Reset(); state_.set(const_cast(data.data()), data.size()); } 86 | 87 | }; 88 | 89 | inline void Parser::skip_write_blank() 90 | { 91 | auto& offset = state_.offset_; 92 | auto d = state_.data_; 93 | while(offset < state_.size_) 94 | { 95 | auto ch = d[offset]; 96 | if (ch == 0x20 || ch == 0x09 || ch == 0x0A || ch == 0x0D ) offset++; 97 | else break; 98 | } 99 | } 100 | 101 | inline bool Parser::parse_true(Value &v) 102 | { 103 | auto& offset = state_.offset_; 104 | auto d = state_.data_; 105 | PSON_ASSERT(d[offset] == 't'); 106 | 107 | if (offset + 3 >= state_.size_ || 108 | d[offset + 1] != 'r' || 109 | d[offset + 2] != 'u' || 110 | d[offset + 3] != 'e') return false; 111 | 112 | offset += 4; 113 | v.reset_as(); 114 | v.as() = true; 115 | 116 | return true; 117 | } 118 | 119 | inline bool Parser::parse_false(Value &v) 120 | { 121 | auto& offset = state_.offset_; 122 | auto d = state_.data_; 123 | PSON_ASSERT(d[offset] == 'f'); 124 | 125 | if (offset + 4 >= state_.size_ || 126 | d[offset + 1] != 'a' || 127 | d[offset + 2] != 'l' || 128 | d[offset + 3] != 's' || 129 | d[offset + 4] != 'e') return false; 130 | 131 | offset += 5; 132 | v.reset_as(); 133 | v.as() = false; 134 | 135 | return true; 136 | } 137 | 138 | inline bool Parser::parse_null(Value &v) 139 | { 140 | auto& offset = state_.offset_; 141 | auto d = state_.data_; 142 | PSON_ASSERT(d[offset] == 'n'); 143 | 144 | if (offset + 3 >= state_.size_ || 145 | d[offset + 1] != 'u' || 146 | d[offset + 2] != 'l' || 147 | d[offset + 3] != 'l') return false; 148 | 149 | offset += 4; 150 | v.reset_as(); 151 | 152 | return true; 153 | } 154 | 155 | inline bool Parser::parse_number(Value &v) 156 | { 157 | #define ISDIGIT(ch) (ch >= '0' && ch <= '9') 158 | #define ISONETONINE(ch) (ch >= '1' && ch <= '9') 159 | 160 | const char* begin = state_.data_ + state_.offset_; 161 | char* end = const_cast(begin); 162 | 163 | if (*end == '-') end++; 164 | if (*end == '0') end++; 165 | else { 166 | if (!ISONETONINE(*end)) return false; // 00.1 167 | for(;ISDIGIT(*end); end++); 168 | } 169 | if (*end == '.') 170 | { 171 | end++; 172 | if (!ISDIGIT(*end)) return false; // 0.e1 173 | for(;ISDIGIT(*end); end++); 174 | } 175 | if (*end == 'e' || *end == 'E') 176 | { 177 | end++; 178 | if (*end == '+' || *end == '-') end++; 179 | if (!ISDIGIT(*end)) return false; 180 | for(;ISDIGIT(*end); end++); 181 | } 182 | errno = 0; 183 | Number res = strtod(begin , nullptr); 184 | if (errno == ERANGE || res == HUGE_VAL || res == -HUGE_VAL) return false; // Number too big ! 185 | v.reset_as(); 186 | v.as() = res; 187 | state_.offset_ += end - begin; 188 | return true; 189 | 190 | #undef ISONETONINE 191 | #undef ISDIGIT 192 | 193 | } 194 | 195 | inline bool Parser::parse_hex4(unsigned& u) 196 | { 197 | int i; 198 | u = 0; 199 | char* d = state_.data_; 200 | auto& offset = state_.offset_; 201 | for(i = 0; i < 4; i++) 202 | { 203 | char ch = d[offset++]; 204 | u <<= 4; 205 | if (ch >= '0' && ch <= '9') u |= ch - '0'; 206 | else if (ch >= 'A' && ch <= 'F') u |= ch - ('A' - 10); 207 | else if (ch >= 'a' && ch <= 'f') u |= ch - ('a' - 10); 208 | else return false; 209 | } 210 | return true; 211 | } 212 | 213 | inline bool Parser::parse_utf8(String &s, unsigned u) 214 | { 215 | if (u <= 0x7F) 216 | { 217 | s.push_back(u & 0xFF); 218 | } 219 | else if (u <= 0x7FF) 220 | { 221 | s.push_back(0xC0 | (u >> 6) & 0xFF); 222 | s.push_back(0x80 | (u & 0x3F)); 223 | } 224 | else if (u <= 0xFFFF) 225 | { 226 | s.push_back(0xE0 | ((u >> 12) & 0xFF)); 227 | s.push_back(0x80 | ((u >> 6) & 0x3F)); 228 | s.push_back(0x80 | (u & 0x3F)); 229 | } 230 | else 231 | { 232 | PSON_ASSERT(u <= 0x10FFFF); 233 | s.push_back(0xF0 | ((u >> 18) & 0xFF)); 234 | s.push_back(0x80 | ((u >> 12) & 0x3F)); 235 | s.push_back(0x80 | ((u >> 6) & 0x3F)); 236 | s.push_back(0x80 | (u & 0x3F)); 237 | } 238 | return true; 239 | } 240 | 241 | inline bool Parser::parse_string_row(String& s) 242 | { 243 | auto& offset = state_.offset_; 244 | auto d = state_.data_; 245 | unsigned u{0}, u2{0}; 246 | PSON_ASSERT(d[offset] == '\"'); 247 | ++offset; 248 | while (true) 249 | { 250 | if (offset >= state_.size_) return false; 251 | char ch = d[offset]; 252 | switch (ch) { 253 | case '\"': {offset++; return true; } 254 | case '\0': return false; 255 | case '\\': 256 | switch (d[offset++]) { 257 | case '\"': s.push_back('\"'); break; 258 | case '\\': s.push_back('\\'); break; 259 | case '/': s.push_back('/'); break; 260 | case 'b': s.push_back('\b'); break; 261 | case 'f': s.push_back('\f'); break; 262 | case 'n': s.push_back('\n'); break; 263 | case 'r': s.push_back('\r'); break; 264 | case 't': s.push_back('\t'); break; 265 | case 'u': 266 | if (!parse_hex4(u)) return false; 267 | if (u >= 0xD800 & u <= 0xDBFF) 268 | { 269 | if (d[offset++] != '\\') return false; 270 | if (d[offset++] != 'u') return false; 271 | if (!parse_hex4(u2)) return false; 272 | if (u2 < 0xDC00 || u2 > 0xDFFF) return false; 273 | u = (((u - 0xD800) << 10) | (u2 - 0xDC00)) + 0x10000; 274 | } 275 | parse_utf8(s, u); 276 | break; 277 | } 278 | default: { 279 | s.push_back(ch); 280 | ++offset; 281 | } 282 | } 283 | } 284 | 285 | } 286 | 287 | inline bool Parser::parse_string(Value &v) 288 | { 289 | String s; 290 | if (!parse_string_row(s)) return false; 291 | v.reset_as(); 292 | v.as() = std::move(s); 293 | return true; 294 | } 295 | 296 | inline bool Parser::parse_array(Value &v) 297 | { 298 | auto& offset = state_.offset_; 299 | char* d = state_.data_; 300 | PSON_ASSERT(d[offset] == '['); 301 | ++offset; 302 | skip_write_blank(); 303 | if (offset >= state_.size_) return false; 304 | 305 | Array array; 306 | v.reset_as(); 307 | v.as() = std::move(array); 308 | 309 | if (d[offset] == ']') 310 | { 311 | offset++; 312 | return true; 313 | } 314 | 315 | while(true) 316 | { 317 | Value val; 318 | if (!Parse(val)) return false; 319 | v.as().push_back(std::move(val)); 320 | skip_write_blank(); 321 | 322 | if (d[offset] == ',') 323 | offset++; 324 | else if (d[offset] == ']') 325 | { 326 | offset++; 327 | return true; 328 | } 329 | else 330 | return false; 331 | 332 | } 333 | } 334 | 335 | inline bool Parser::parse_object(Value &v) 336 | { 337 | auto& offset = state_.offset_; 338 | char* d = state_.data_; 339 | PSON_ASSERT(d[offset] == '{'); 340 | ++offset; 341 | skip_write_blank(); 342 | 343 | if (offset >= state_.size_) { 344 | return false; 345 | } 346 | 347 | Object obj; 348 | v.reset_as(); 349 | v.as() = std::move(obj); 350 | 351 | if (d[offset] == '}') 352 | { 353 | offset++; 354 | return true; 355 | } 356 | 357 | while(true) 358 | { 359 | String name; 360 | if (!parse_string_row(name)) return false; 361 | skip_write_blank(); 362 | 363 | Value val; 364 | char ch = d[offset]; 365 | if (d[offset] != ':') return false; 366 | ++offset; 367 | 368 | auto ret = Parse(val); 369 | if (!ret) return false; 370 | v.as().insert(std::move(name), std::move(val)); 371 | 372 | skip_write_blank(); 373 | if (d[offset] == ',') { 374 | ++offset; 375 | skip_write_blank(); 376 | } 377 | else if (d[offset] == '}') 378 | { 379 | ++offset; 380 | return true; 381 | } 382 | else if (offset >= state_.size_) 383 | { 384 | return false; 385 | } 386 | } 387 | } 388 | 389 | inline bool Parser::parse_value(Value& v) 390 | { 391 | if (state_.size_ == 0) { 392 | v.reset_as(); 393 | return true; 394 | } 395 | 396 | char ch = state_.data_[state_.offset_]; 397 | switch (ch) { 398 | case 't': 399 | return parse_true(v); 400 | case 'f': 401 | return parse_false(v); 402 | case 'n': 403 | return parse_null(v); 404 | case '\"': 405 | return parse_string(v); 406 | case '[': 407 | return parse_array(v); 408 | case '{': 409 | return parse_object(v); 410 | default: 411 | return parse_number(v); 412 | } 413 | // Make happy 414 | return false; 415 | } 416 | 417 | inline bool Parser::Parse(Value& v) 418 | { 419 | skip_write_blank(); 420 | return parse_value(v); 421 | } 422 | 423 | // Implement for value 424 | inline bool Value::parse(const std::string &json_data) 425 | { 426 | Parser p(json_data); 427 | return p.Parse(*this); 428 | } 429 | 430 | inline bool Value::parse(char *json_data, std::size_t len) 431 | { 432 | Parser p(json_data, len); 433 | return p.Parse(*this); 434 | } 435 | 436 | } -------------------------------------------------------------------------------- /v2/src/json_value.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "json_assert.hpp" 9 | 10 | namespace pson { 11 | 12 | // Json type 13 | enum JSON_TYPE 14 | { 15 | JSON_NULL, 16 | JSON_BOOL, 17 | JSON_NUMBER, 18 | JSON_STRING, 19 | JSON_ARRAY, 20 | JSON_OBJECT 21 | }; 22 | 23 | struct null_type 24 | {}; 25 | 26 | class Value; 27 | class Array; 28 | class Object; 29 | 30 | using Null = null_type; 31 | using Bool = bool; 32 | using Number = double; 33 | using String = std::string; 34 | using ArrayContainer = std::vector; 35 | using ObjectContainer = std::map; 36 | 37 | // some util... 38 | template 39 | struct is_same 40 | { 41 | enum { 42 | value = false 43 | }; 44 | }; 45 | 46 | template 47 | struct is_same 48 | { 49 | enum { 50 | value = true 51 | }; 52 | }; 53 | 54 | template 55 | struct TypesCmp 56 | { 57 | enum { 58 | value = false 59 | }; 60 | }; 61 | 62 | template 63 | struct TypesCmp 64 | { 65 | enum { 66 | value = false || TypesCmp::value 67 | }; 68 | }; 69 | 70 | template 71 | struct TypesCmp 72 | { 73 | enum { 74 | value = true || TypesCmp::value 75 | }; 76 | }; 77 | 78 | 79 | 80 | #define IS_JSON_TYPE(type) ( std::is_trivial::value || \ 81 | pson::TypesCmp::value) 82 | 83 | class Object { 84 | private: 85 | ObjectContainer value_map_; 86 | public: 87 | 88 | Object() = default; 89 | ~Object() = default; 90 | 91 | Object(const Object& o); 92 | 93 | Object(Object&& o); 94 | 95 | Object& operator= (const Object& o); 96 | Object& operator= (Object&& o); 97 | 98 | template 99 | void insert(std::string name, T t); 100 | 101 | // You could use move to zero over head, 102 | // eg. obj.insert(std::move(name), std::move(val)); 103 | // Copy eg. obj.insert(name, val); 104 | void insert(std::string name, Value v); 105 | void erase(const std::string& name); 106 | Value& operator[] (const std::string& name); 107 | Value& at(const std::string& name); 108 | 109 | bool empty() const; 110 | bool has(const std::string& name) const ; 111 | std::size_t size() const; 112 | 113 | ObjectContainer& value_map(); 114 | }; 115 | 116 | 117 | class Array { 118 | private: 119 | ArrayContainer values_; 120 | public: 121 | 122 | Array() = default; 123 | ~Array() = default; 124 | 125 | Array(const Array &a); 126 | Array(Array &&a); 127 | 128 | Array &operator=(const Array &a); 129 | Array &operator=(Array &&a); 130 | 131 | Value& operator[] (int p); 132 | void push_back(Value v); 133 | void pop_back(); 134 | Value& back(); 135 | Value& at(int i); 136 | 137 | bool has(int i) const; 138 | std::size_t size() const; 139 | bool empty() const; 140 | 141 | ArrayContainer& values(); 142 | }; 143 | 144 | class Value { 145 | private: 146 | JSON_TYPE type_; 147 | union holder { 148 | Null null_; 149 | Number number_; 150 | Bool bool_; 151 | String* string_; 152 | Array* array_; 153 | Object* object_; 154 | } val_; 155 | 156 | inline bool judge_type(const JSON_TYPE& t) const { return type_ == t; } 157 | 158 | void init_base(const JSON_TYPE& t); 159 | 160 | inline void swap_value(Value& v) { 161 | std::swap(this->val_, v.val_); 162 | std::swap(this->type_, v.type_); 163 | } 164 | 165 | void copy_value(const Value& v); 166 | 167 | public: 168 | 169 | Value(); 170 | Value(bool b); 171 | Value(const char* s); 172 | Value(String s); 173 | Value(Number n); 174 | Value(int32_t n); 175 | Value(uint32_t n); 176 | Value(int64_t n); 177 | Value(uint64_t n); 178 | 179 | Value(const Array& array); 180 | Value(const Object& obj); 181 | 182 | 183 | Value(const JSON_TYPE&); 184 | 185 | // Copy 186 | Value(const Value&); 187 | 188 | // Move 189 | Value(Value&&); 190 | 191 | ~Value(); 192 | 193 | // Copy 194 | Value& operator= (const Value&); 195 | 196 | // Move 197 | Value& operator= (Value&&); 198 | 199 | void reset(); 200 | 201 | inline void reset_as(JSON_TYPE t) { reset(); init_base(t); } 202 | 203 | template 204 | void reset_as(); 205 | 206 | inline void swap(Value& v) { swap_value(v); } 207 | 208 | inline JSON_TYPE type() const { return type_; } 209 | 210 | inline bool is_null() const { return judge_type(JSON_NULL); } 211 | inline bool is_bool() const { return judge_type(JSON_BOOL); } 212 | inline bool is_number() const { return judge_type(JSON_NUMBER); } 213 | inline bool is_string() const { return judge_type(JSON_STRING); } 214 | inline bool is_array() const { return judge_type(JSON_ARRAY); } 215 | inline bool is_object() const { return judge_type(JSON_OBJECT); } 216 | 217 | template 218 | bool is(); 219 | 220 | inline Null as_null() { 221 | PSON_ASSERT(judge_type(JSON_NULL)); 222 | return val_.null_; 223 | } 224 | 225 | inline Number& as_number() { 226 | PSON_ASSERT(judge_type(JSON_NUMBER)); 227 | return val_.number_; 228 | } 229 | 230 | inline Bool& as_bool() { 231 | PSON_ASSERT(judge_type(JSON_BOOL)); 232 | return val_.bool_; 233 | } 234 | 235 | inline String& as_string() { 236 | PSON_ASSERT(judge_type(JSON_STRING)); 237 | return *val_.string_; 238 | } 239 | 240 | inline Array& as_array() { 241 | PSON_ASSERT(judge_type(JSON_ARRAY)); 242 | return *val_.array_; 243 | } 244 | 245 | inline Object& as_object() { 246 | PSON_ASSERT(judge_type(JSON_OBJECT)); 247 | return *val_.object_; 248 | } 249 | 250 | template 251 | T& as(); 252 | 253 | 254 | bool empty() const; 255 | std::size_t size() const; // For array, object 256 | 257 | // operator for Array 258 | void push_back(Value v); 259 | void pop_back(); 260 | Value& back(); 261 | bool has(int i) const; 262 | Value& operator[] (int i); 263 | Value& at(int i); 264 | 265 | // operator for Object 266 | void insert(std::string name, Value v); 267 | bool has(const std::string& name) const; 268 | Value& operator[] (const std::string& name); 269 | Value& at(const std::string& name); 270 | void erase(const std::string& name); 271 | 272 | bool parse(const std::string& json_data); 273 | bool parse(char* json_data, std::size_t len); 274 | 275 | std::string print(); 276 | }; 277 | 278 | 279 | 280 | // Implement 281 | // Object 282 | inline Object::Object(const Object& o): 283 | value_map_(o.value_map_) 284 | {} 285 | 286 | inline Object::Object(Object&& o): 287 | value_map_(std::move(o.value_map_)) 288 | {} 289 | 290 | inline Object& Object::operator= (const Object& o) 291 | { 292 | value_map_ = o.value_map_; 293 | return *this; 294 | } 295 | 296 | inline Object& Object::operator= (Object&& o) 297 | { 298 | value_map_ = std::move(o.value_map_); 299 | return *this; 300 | } 301 | 302 | inline Value &Object::operator[](const std::string &name) 303 | { 304 | return value_map_.at(name); 305 | } 306 | 307 | inline bool Object::empty() const 308 | { 309 | return value_map_.empty(); 310 | } 311 | 312 | inline Value& Object::at(const std::string& name) 313 | { 314 | return value_map_.at(name); 315 | } 316 | 317 | inline std::size_t Object::size() const 318 | { 319 | return value_map_.size(); 320 | } 321 | 322 | inline ObjectContainer& Object::value_map() 323 | { 324 | return value_map_; 325 | } 326 | 327 | inline bool Object::has(const std::string &name) const 328 | { 329 | return value_map_.find(name) != value_map_.end(); 330 | } 331 | 332 | template 333 | inline void Object::insert(std::string name, T t) 334 | { 335 | static_assert(IS_JSON_TYPE(T), "Object::insert(std::string, T) tparam not a json type"); 336 | pson::Value v(t); 337 | insert(std::move(name), std::move(v)); 338 | } 339 | 340 | inline void Object::insert(std::string name, Value v) 341 | { 342 | value_map_.emplace(std::move(name), std::move(v)); 343 | } 344 | 345 | inline void Object::erase(const std::string& name) 346 | { 347 | value_map_.erase(name); 348 | } 349 | 350 | // Array 351 | 352 | inline Array::Array(const Array& a): 353 | values_(a.values_) 354 | {} 355 | 356 | inline Array::Array(Array&& a): 357 | values_(std::move(a.values_)) 358 | {} 359 | 360 | inline Array& Array::operator= (const Array& a) 361 | { 362 | values_ = a.values_; 363 | return *this; 364 | } 365 | 366 | inline Array& Array::operator= (Array&& a) 367 | { 368 | values_ = std::move(a.values_); 369 | return *this; 370 | } 371 | 372 | inline bool Array::empty() const 373 | { 374 | return values_.empty(); 375 | } 376 | 377 | inline ArrayContainer& Array::values() 378 | { 379 | return values_; 380 | } 381 | 382 | inline Value &Array::back() 383 | { 384 | return values_.back(); 385 | } 386 | 387 | inline Value &Array::at(int i) 388 | { 389 | return values_[i]; 390 | } 391 | 392 | inline bool Array::has(int i) const 393 | { 394 | return i >= 0 && values_.size() > i; 395 | } 396 | 397 | inline std::size_t Array::size() const 398 | { 399 | return values_.size(); 400 | } 401 | 402 | inline void Array::push_back(Value v) 403 | { 404 | values_.emplace_back(std::move(v)); 405 | } 406 | 407 | inline void Array::pop_back() 408 | { 409 | values_.pop_back(); 410 | } 411 | 412 | inline Value &Array::operator[](int p) 413 | { 414 | return values_[p]; 415 | } 416 | 417 | inline Value& Value::back() 418 | { 419 | PSON_ASSERT(judge_type(JSON_ARRAY)); 420 | return val_.array_->back(); 421 | } 422 | 423 | inline void Value::pop_back() 424 | { 425 | PSON_ASSERT(judge_type(JSON_ARRAY)); 426 | val_.array_->pop_back(); 427 | } 428 | 429 | // Value 430 | inline Value::Value(): 431 | type_(JSON_NULL) 432 | { 433 | val_.null_ = Null{}; 434 | } 435 | 436 | inline Value::Value(bool b): 437 | type_(JSON_BOOL) 438 | { 439 | val_.bool_ = b; 440 | } 441 | 442 | inline Value::Value(Number n) : 443 | type_(JSON_NUMBER) 444 | { 445 | val_.number_ = n; 446 | } 447 | 448 | inline Value::Value(int32_t n): 449 | type_(JSON_NUMBER) 450 | { 451 | val_.number_ = static_cast(n); 452 | } 453 | 454 | inline Value::Value(uint32_t n) : 455 | type_(JSON_NUMBER) 456 | { 457 | val_.number_ = static_cast(n); 458 | } 459 | 460 | inline Value::Value(int64_t n): 461 | type_(JSON_NUMBER) 462 | { 463 | val_.number_ = static_cast(n); 464 | } 465 | 466 | inline Value::Value(uint64_t n): 467 | type_(JSON_NUMBER) 468 | { 469 | val_.number_ = static_cast(n); 470 | } 471 | 472 | inline Value::Value(const Array& a): 473 | type_(JSON_ARRAY) 474 | { 475 | val_.array_ = new Array(a); 476 | } 477 | 478 | inline Value::Value(const Object& o): 479 | type_(JSON_OBJECT) 480 | { 481 | val_.object_ = new Object(o); 482 | } 483 | 484 | inline Value::Value(const char* s) : 485 | type_(JSON_STRING) 486 | { 487 | val_.string_ = new String(s); 488 | } 489 | 490 | inline Value::Value(String s) : 491 | type_(JSON_STRING) 492 | { 493 | val_.string_ = new String(std::move(s)); 494 | } 495 | 496 | inline Value::Value(const JSON_TYPE &t) 497 | { 498 | init_base(t); 499 | } 500 | 501 | inline Value::Value(const Value& v): 502 | type_(JSON_NULL) 503 | { 504 | copy_value(v); 505 | } 506 | 507 | inline Value::Value(Value&& other) 508 | { 509 | init_base(JSON_NULL); 510 | swap_value(other); 511 | } 512 | 513 | inline Value& Value::operator= (const Value& v) 514 | { 515 | copy_value(v); 516 | return *this; 517 | } 518 | 519 | inline Value& Value::operator= (Value&& v) 520 | { 521 | reset(); 522 | swap_value(v); 523 | return *this; 524 | } 525 | 526 | inline Value::~Value() 527 | { 528 | switch (type_) 529 | { 530 | case JSON_STRING: 531 | delete val_.string_; 532 | break; 533 | case JSON_ARRAY: 534 | delete val_.array_; 535 | break; 536 | case JSON_OBJECT: 537 | delete val_.object_; 538 | break; 539 | } 540 | } 541 | 542 | inline void Value::reset() 543 | { 544 | switch (type_) 545 | { 546 | case JSON_STRING: 547 | delete val_.string_; 548 | break; 549 | case JSON_ARRAY: 550 | delete val_.array_; 551 | break; 552 | case JSON_OBJECT: 553 | delete val_.object_; 554 | break; 555 | } 556 | type_ = JSON_NULL; 557 | val_.null_ = Null{}; 558 | } 559 | 560 | inline void Value::init_base(const JSON_TYPE& t) 561 | { 562 | type_ = t; 563 | switch (type_) 564 | { 565 | case JSON_NULL: 566 | val_.null_ = Null{}; 567 | break; 568 | case JSON_BOOL: 569 | val_.bool_ = false; 570 | break; 571 | case JSON_NUMBER: 572 | val_.number_ = 0.0; 573 | break; 574 | case JSON_STRING: 575 | val_.string_ = new String(); 576 | break; 577 | case JSON_ARRAY: 578 | val_.array_ = new Array(); 579 | break; 580 | case JSON_OBJECT: 581 | val_.object_ = new Object(); 582 | break; 583 | } 584 | } 585 | 586 | inline void Value::copy_value(const Value& v) 587 | { 588 | if (type_ == v.type_) { 589 | switch (v.type_) 590 | { 591 | case JSON_NULL: 592 | val_.null_ = Null{}; 593 | break; 594 | case JSON_BOOL: 595 | val_.bool_ = v.val_.bool_; 596 | break; 597 | case JSON_NUMBER: 598 | val_.number_ = v.val_.number_; 599 | break; 600 | case JSON_STRING: 601 | *val_.string_ = *v.val_.string_; 602 | break; 603 | case JSON_ARRAY: 604 | *val_.array_ = *v.val_.array_; 605 | break; 606 | case JSON_OBJECT: 607 | *val_.object_ = *v.val_.object_; 608 | break; 609 | } 610 | } else { 611 | switch (v.type_) 612 | { 613 | case JSON_NULL: 614 | val_.null_ = Null{}; 615 | break; 616 | case JSON_BOOL: 617 | val_.bool_ = v.val_.bool_; 618 | break; 619 | case JSON_NUMBER: 620 | val_.number_ = v.val_.number_; 621 | break; 622 | case JSON_STRING: 623 | val_.string_ = new String(*v.val_.string_); 624 | break; 625 | case JSON_ARRAY: 626 | val_.array_ = new Array(*v.val_.array_); 627 | break; 628 | case JSON_OBJECT: 629 | val_.object_ = new Object(*v.val_.object_); 630 | break; 631 | } 632 | type_ = v.type_; 633 | } 634 | } 635 | 636 | 637 | // void Value::reset_as() 638 | template <> 639 | inline void Value::reset_as() 640 | { 641 | reset_as(JSON_NULL); 642 | } 643 | 644 | template <> 645 | inline void Value::reset_as() 646 | { 647 | reset_as(JSON_BOOL); 648 | } 649 | 650 | template <> 651 | inline void Value::reset_as() 652 | { 653 | reset_as(JSON_NUMBER); 654 | } 655 | 656 | template <> 657 | inline void Value::reset_as() 658 | { 659 | reset_as(JSON_STRING); 660 | } 661 | 662 | template <> 663 | inline void Value::reset_as() 664 | { 665 | reset_as(JSON_ARRAY); 666 | } 667 | 668 | template <> 669 | inline void Value::reset_as() 670 | { 671 | reset_as(JSON_OBJECT); 672 | } 673 | 674 | // bool Value::is() 675 | template <> 676 | inline bool Value::is() 677 | { 678 | return judge_type(JSON_NULL); 679 | } 680 | 681 | template <> 682 | inline bool Value::is() 683 | { 684 | return judge_type(JSON_BOOL); 685 | } 686 | 687 | template <> 688 | inline bool Value::is() 689 | { 690 | return judge_type(JSON_NUMBER); 691 | } 692 | 693 | template <> 694 | inline bool Value::is() 695 | { 696 | return judge_type(JSON_STRING); 697 | } 698 | 699 | template <> 700 | inline bool Value::is() 701 | { 702 | return judge_type(JSON_ARRAY); 703 | } 704 | 705 | template <> 706 | inline bool Value::is() 707 | { 708 | return judge_type(JSON_OBJECT); 709 | } 710 | 711 | // T& Value::as() 712 | template <> 713 | inline Value& Value::as() 714 | { 715 | return *this; 716 | } 717 | 718 | template <> 719 | inline Null& Value::as() 720 | { 721 | PSON_ASSERT(judge_type(JSON_NULL)); 722 | return val_.null_; 723 | } 724 | 725 | template <> 726 | inline Bool& Value::as() 727 | { 728 | PSON_ASSERT(judge_type(JSON_BOOL)); 729 | return val_.bool_; 730 | } 731 | 732 | template <> 733 | inline Number& Value::as() 734 | { 735 | PSON_ASSERT(judge_type(JSON_NUMBER)); 736 | return val_.number_; 737 | } 738 | 739 | template <> 740 | inline String& Value::as() 741 | { 742 | PSON_ASSERT(judge_type(JSON_STRING)); 743 | return *val_.string_; 744 | } 745 | 746 | template <> 747 | inline Array& Value::as() 748 | { 749 | PSON_ASSERT(judge_type(JSON_ARRAY)); 750 | return *val_.array_; 751 | } 752 | 753 | template <> 754 | inline Object& Value::as() 755 | { 756 | PSON_ASSERT(judge_type(JSON_OBJECT)); 757 | return *val_.object_; 758 | } 759 | 760 | inline bool Value::empty() const 761 | { 762 | switch (type_) 763 | { 764 | case JSON_NULL: 765 | return true; 766 | case JSON_ARRAY: 767 | return val_.array_->empty(); 768 | case JSON_OBJECT: 769 | return val_.object_->empty(); 770 | default: 771 | PSON_ASSERT(false); 772 | } 773 | return false; // Make happy 774 | } 775 | 776 | inline std::size_t Value::size() const 777 | { 778 | switch(type_) 779 | { 780 | case JSON_STRING: 781 | return val_.string_->size(); 782 | case JSON_ARRAY: 783 | return val_.array_->size(); 784 | case JSON_OBJECT: 785 | return val_.object_->size(); 786 | default: 787 | PSON_ASSERT(true); 788 | } 789 | return 0; 790 | } 791 | 792 | inline void Value::push_back(Value v) 793 | { 794 | PSON_ASSERT(judge_type(JSON_ARRAY)); 795 | val_.array_->push_back(std::move(v)); 796 | } 797 | 798 | inline bool Value::has(int i) const 799 | { 800 | PSON_ASSERT(judge_type(JSON_BOOL)); 801 | return val_.array_->has(i); 802 | } 803 | 804 | inline Value& Value::operator[] (int i) 805 | { 806 | PSON_ASSERT(judge_type(JSON_ARRAY)); 807 | return val_.array_->at(i); 808 | } 809 | 810 | inline Value& Value::at(int i) 811 | { 812 | PSON_ASSERT(judge_type(JSON_ARRAY)); 813 | return val_.array_->at(i); 814 | } 815 | 816 | inline void Value::insert(std::string name, Value v) 817 | { 818 | PSON_ASSERT(judge_type(JSON_OBJECT)); 819 | return val_.object_->insert(std::move(name), std::move(v)); 820 | } 821 | 822 | inline bool Value::has(const std::string& name) const 823 | { 824 | PSON_ASSERT(judge_type(JSON_OBJECT)); 825 | return val_.object_->has(name); 826 | } 827 | 828 | inline Value& Value::operator[] (const std::string& name) 829 | { 830 | PSON_ASSERT(judge_type(JSON_OBJECT)); 831 | return val_.object_->at(name); 832 | } 833 | 834 | inline Value& Value::at(const std::string& name) 835 | { 836 | PSON_ASSERT(judge_type(JSON_OBJECT)); 837 | return val_.object_->at(name); 838 | } 839 | 840 | inline void Value::erase(const std::string &name) 841 | { 842 | PSON_ASSERT(judge_type(JSON_OBJECT)); 843 | val_.object_->erase(name); 844 | } 845 | 846 | } 847 | --------------------------------------------------------------------------------