-
Notifications
You must be signed in to change notification settings - Fork 0
/
serjson.h
173 lines (141 loc) · 4.77 KB
/
serjson.h
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//
// Created by Matteo Cardinaletti on 11/05/23.
//
#ifndef SERJSON_H
#define SERJSON_H
#include <vector>
#include <string>
#include <variant>
#include <fstream>
#include <ostream>
namespace json {
// json node type
typedef enum ObjType {
empty,
string,
number,
object,
null,
array,
boolean,
} ObjType;
// a json element
typedef struct Node {
ObjType type = ObjType::empty;
std::string key;
std::variant<std::string, float, std::vector<Node>, bool> value;
template<typename T>
T &get_value() {
return std::get<T>(value);
}
Node &operator[](const std::string &k) {
static Node empty{.type = ObjType::empty, .key = "", .value = ""};
if (type != ObjType::object) return empty;
for (auto &n: get_value<std::vector<Node>>()) {
if (n.key == k) return n;
}
return empty;
}
Node &operator[](const int index) {
static Node empty{.type = ObjType::empty, .key = "", .value = ""};
if (type != ObjType::array) return empty;
if (get_value<std::vector<Node>>().empty()) return empty;
if (index < 0 || index >= get_value<std::vector<Node>>().size()) return empty;
return get_value<std::vector<Node>>()[index];
}
friend std::ostream &operator<<(std::ostream &os, Node &node) {
if (!node.key.empty()) os << "{ key: \"" << node.key << "\", value: ";
switch (node.type) {
case string:
os << node.get_value<std::string>();
break;
case number:
os << node.get_value<float>();
break;
case object: {
std::vector<Node> v = node.get_value<std::vector<Node>>();
os << "{ ";
for (int i = 0; i < v.size(); ++i) {
if (i > 0) os << ", ";
os << v[i];
}
os << " } ";
}
break;
case null:
os << node.get_value<std::string>();
break;
case array: {
std::vector<Node> v = node.get_value<std::vector<Node>>();
os << "[ ";
for (int i = 0; i < v.size(); ++i) {
if (i > 0) os << ", ";
os << v[i];
}
os << " ] ";
}
break;
case boolean:
os << std::boolalpha;
os << node.get_value<bool>();
os << std::noboolalpha;
break;
default:
break;
}
if (!node.key.empty()) os << "}";
return os;
}
} Node;
// a json object
typedef struct Object {
std::string file_path;
std::vector<Node> nodes;
[[nodiscard]] bool empty() const {
return nodes.empty();
}
[[nodiscard]] bool is_array() const {
return !empty() && nodes[0].key.empty();
}
void clear() {
this->nodes.clear();
}
Node &operator[](const std::string &key) {
static Node empty{.type = ObjType::empty, .key = "", .value = ""};
for (auto &n: nodes) {
if (n.key == key) return n;
}
return empty;
}
Node &operator[](const int index) {
static Node empty{.type = ObjType::empty, .key = "", .value = ""};
if (nodes.empty()) return empty;
if (index < 0 || index >= nodes.size()) return empty;
return nodes[index];
}
friend std::ostream &operator<<(std::ostream &os, Object &object) {
os << "{ file path: \"" << object.file_path << "\", number of nodes: " << object.nodes.size() << " }";
return os;
}
} Object;
class Serializable {
public:
virtual json::Node serialize() = 0;
};
class Extension_error : public std::exception {
public:
explicit Extension_error(std::string &msg) : m_msg(std::move(msg)) {}
[[nodiscard]] const char *what() const noexcept override {
return m_msg.c_str();
}
private:
std::string m_msg;
};
// read from file
Object read(const std::string &path);
Node generate_parent(std::string key, std::vector<Node> children);
void add_node(Serializable &obj, Object &json);
void add_node(Node &obj, Object &json);
void write(Object &json);
}
#endif //SERJSON_H