GraceFt v2.3
开源图形引擎 EGE(Easy Graphics Engine) 的高层封装库
 
载入中...
搜索中...
未找到
json.hpp
1
10#pragma once
11
12#include <iostream>
13#include <variant>
14#include <string>
15#include <vector>
16#include <unordered_map>
17#include <cmath>
18
19namespace GFt {
22 namespace json {
23 enum class Type {
24 Null,
25 Boolean,
26 Number,
27 String,
28 Array,
29 Object,
30 Invalid
31 };
32 template<typename CharT>
33 class Value;
34 template<typename CharT>
35 using StdString = std::basic_string<CharT>;
36 template<typename CharT>
37 using StdIStream = std::basic_istream<CharT>;
38 template<typename CharT>
39 using StdOStream = std::basic_ostream<CharT>;
40 template<typename CharT>
41 using Array = std::vector<Value<CharT>>;
42 template<typename CharT>
43 using Object = std::unordered_map<StdString<CharT>, Value<CharT>>;
44
55 struct Format {
56 template<typename CharT>
57 friend class Value;
58 private:
59 static inline bool format_json_ = false;
60 static inline int tabsize_ = 4;
61 public:
62 using jFormat = std::ios_base& (*)(std::ios_base&);
65 Format(int tabsize = -1) {
66 tabsize_ = tabsize;
67 format_json_ = tabsize >= 0;
68 }
69 operator jFormat() {
70 return [](std::ios_base& os)->std::ios_base& {
71 return os;
72 };
73 }
74
75 static inline bool isFormat() {
76 return format_json_;
77 }
78
79 static inline int tabSize() {
80 return tabsize_;
81 }
82 };
83
85 template<typename CharT>
86 class Value {
87 static inline const CharT null_[]{ 'n', 'u', 'l', 'l', 0 };
88 static inline const CharT true_[]{ 't', 'r', 'u', 'e', 0 };
89 static inline const CharT fals_[]{ 'f', 'a', 'l', 's', 0 };
90 static inline const CharT false_[]{ 'f', 'a', 'l', 's', 'e', 0 };
91 static inline const CharT invaild_[]{
92 '/', '*', 'I', 'n', 'v', 'a', 'i', 'l', 'd', ' ', 'v', 'a', 'l', 'u', 'e', '*', '/', 0 };
93
94 Type type_;
95 using Variant = std::variant<bool, double, StdString<CharT>, Array<CharT>, Object<CharT>>;
96 Variant value_;
97 void removeRedundantComma(StdIStream<CharT>& is) const {
98 do {
99 is >> std::ws;
100 if (is.peek() == '/') {
101 is.get();
102 if (is.peek() == '/') {
103 is.ignore(std::string().max_size(), '\n');
104 }
105 else if (is.peek() == '*') {
106 is.get();
107 while (is.peek() == '/')
108 is.get();
109 while (is.peek() != '/')
110 is.ignore(std::string().max_size(), '*');
111 }
112 }
113 else {
114 break;
115 }
116 } while (true);
117 }
118 public:
119 Value() : type_(Type::Invalid) {}
120 Value(bool b) : type_(Type::Boolean), value_(b) {}
121 Value(double d) : type_(Type::Number), value_(d) {}
122 template<size_t N>
123 Value(const CharT(&s)[N]) : type_(Type::String), value_(StdString<CharT>(s)) {}
124 Value(const CharT* s) : type_(Type::String), value_(StdString<CharT>(s)) {}
125 Value(const StdString<CharT>& s) : type_(Type::String), value_(s) {}
126 Value(const Array<CharT>& a) : type_(Type::Array), value_(a) {}
127 Value(const Object<CharT>& o) : type_(Type::Object), value_(o) {}
128
129 Value& operator=(bool b) { type_ = Type::Boolean; value_ = b; return *this; }
130 Value& operator=(double d) { type_ = Type::Number; value_ = d; return *this; }
131 template<size_t N>
132 Value& operator=(const CharT(&s)[N]) { type_ = Type::String; value_ = StdString<CharT>(s); return *this; }
133 Value& operator=(const CharT* s) { type_ = Type::String; value_ = StdString<CharT>(s); return *this; }
134 Value& operator=(const StdString<CharT>& s) { type_ = Type::String; value_ = s; return *this; }
135 Value& operator=(const Array<CharT>& a) { type_ = Type::Array; value_ = a; return *this; }
136 Value& operator=(const Object<CharT>& o) { type_ = Type::Object; value_ = o; return *this; }
137
139 Type type() const { return type_; }
140
141 bool isNull() const { return type_ == Type::Null; }
142 bool isBool() const { return type_ == Type::Boolean; }
143 bool isString() const { return type_ == Type::String; }
144 bool isArray() const { return type_ == Type::Array; }
145 bool isObject() const { return type_ == Type::Object; }
146 bool isNumber() const { return type_ == Type::Number; }
147 bool isInteger() const {
148 if (!isNumber()) return false;
149 double d = std::get<double>(value_);
150 return d == std::floor(d);
151 }
152 bool isFloat() const { return isNumber() && !isInteger(); }
153
154 bool& asBoolean() { return std::get<bool>(value_); }
155 double& asNumber() { return std::get<double>(value_); }
156 StdString<CharT>& asString() { return std::get<StdString<CharT>>(value_); }
157 Array<CharT>& asArray() { return std::get<Array<CharT>>(value_); }
158 Object<CharT>& asObject() { return std::get<Object<CharT>>(value_); }
159
160 const bool& asBoolean() const { return std::get<bool>(value_); }
161 const int& asInteger() const { return std::get<int>(value_); }
162 const double& asNumber() const { return std::get<double>(value_); }
163 const StdString<CharT>& asString() const { return std::get<StdString<CharT>>(value_); }
164 const Array<CharT>& asArray() const { return std::get<Array<CharT>>(value_); }
165 const Object<CharT>& asObject() const { return std::get<Object<CharT>>(value_); }
166
167 bool toBool() const { return std::get<bool>(value_); }
168 int toInt() const { return static_cast<int>(std::get<double>(value_)); }
169 double toFloat() const { return std::get<double>(value_); }
170 const StdString<CharT>& toString() const { return std::get<StdString<CharT>>(value_); }
171 Value& operator[](size_t i) { return asArray()[i]; }
172 const Value& operator[](size_t i) const { return asArray()[i]; }
173 Value& operator[](const StdString<CharT>& key) { return asObject()[key]; }
174 const Value& operator[](const StdString<CharT>& key) const { return asObject()[key]; }
175 Value& at(const StdString<CharT>& key) { return asObject().at(key); }
176 const Value& at(const StdString<CharT>& key) const { return asObject().at(key); }
177 private:
178 static inline int indent_ = 0;
179 public:
182 switch (v.type_) {
183 case Type::Null: os << null_; break;
184 case Type::Boolean: os << (v.asBoolean() ? true_ : false_); break;
185 case Type::Number:
186 {
187 if (v.isFloat())
188 os << v.toFloat();
189 else
190 os << v.toInt();
191 } break;
192 case Type::String: os << '"' << v.asString() << '"'; break;
193 case Type::Array:
194 {
195 os << '[' << (Format::isFormat() ? StdString<CharT>(1, '\n') : StdString<CharT>());
197 for (std::size_t i = 0; i < v.asArray().size(); ++i)
198 os << (Format::isFormat()
201 << v[i] << (i == v.asArray().size() - 1 ? StdString<CharT>() : StdString<CharT>(1, ','))
204 os << (Format::isFormat()
206 : StdString<CharT>()) << ']';
207 } break;
208 case Type::Object:
209 {
210 os << '{' << (Format::isFormat() ? StdString<CharT>(1, '\n') : StdString<CharT>());
212 std::size_t i = 0;
213 for (const auto& [key, value] : v.asObject()) {
214 os << (Format::isFormat()
217 << '"' << key << '"' << ':' << (Format::isFormat()
218 ? StdString<CharT>(1, ' ')
220 << value << (i == v.asObject().size() - 1
223 ++i;
224 }
226 os << (Format::isFormat()
228 : StdString<CharT>()) << '}';
229 } break;
230 case Type::Invalid: os << invaild_; break;
231 }
232 return os;
233 }
239 v.removeRedundantComma(is);
240 char c = is.peek();
241 switch (c) {
242 case 'n':
243 {
244 CharT null[4] = { 0 };
245 is.read(null, 4);
246 if (StdString<CharT>(null) != null_) {
247 is.setstate(std::ios_base::failbit);
248 return is;
249 }
250 v = nullptr;
251 }break;
252 case 't':
253 case 'f':
254 {
255 CharT boolean[5] = { 0 };
256 is.read(boolean, 4);
257 if (StdString<CharT>(boolean) == true_) {
258 v = true;
259 }
260 else if (StdString<CharT>(boolean) == fals_ && is.get() == 'e') {
261 v = false;
262 }
263 else {
264 is.setstate(std::ios_base::failbit);
265 return is;
266 }
267 }break;
268 case '-':
269 case '0':
270 case '1':
271 case '2':
272 case '3':
273 case '4':
274 case '5':
275 case '6':
276 case '7':
277 case '8':
278 case '9':
279 {
280 std::string number;
281 bool is_end = false;
282 while (!is_end) switch (is.peek()) {
283 case '0': case '1': case '2': case '3': case '4':
284 case '5': case '6': case '7': case '8': case '9':
285 case '.': case '+': case '-': case 'e': case 'E':
286 number += is.get();
287 break;
288 default:
289 is_end = true;
290 break;
291 }
292 try { v = std::stod(number); }
293 catch (const std::exception&) {
294 is.setstate(std::ios_base::failbit);
295 return is;
296 }
297 }break;
298 case '"':
299 {
300 v = StdString<CharT>();
301 is.get();
302 std::getline(is, v.asString(), (CharT)'"');
303 }break;
304 case '[':
305 {
306 v = Array<CharT>();
307 is.get();
308 while (is.peek() != ']') {
309 v.removeRedundantComma(is);
310 Value value;
311 is >> value;
312 v.asArray().push_back(std::move(value));
313 v.removeRedundantComma(is);
314 if (is.peek() == ']') {
315 break;
316 }
317 if (is.peek() != ',') {
318 is.setstate(std::ios_base::failbit);
319 return is;
320 }
321 is.get();
322 v.removeRedundantComma(is);
323 }
324 if (is.get() != ']') {
325 is.setstate(std::ios_base::failbit);
326 return is;
327 }
328 }break;
329 case '{':
330 {
331 v = Object<CharT>();
332 is.get();
333 while (is.peek() != '}') {
334 v.removeRedundantComma(is);
335 Value key;
336 is >> key;
337 if (key.type() != Type::String) {
338 is.setstate(std::ios_base::failbit);
339 return is;
340 }
341 v.removeRedundantComma(is);
342 if (is.get() != ':') {
343 is.setstate(std::ios_base::failbit);
344 return is;
345 }
346 Value value;
347 is >> value;
348 v[key.toString()] = std::move(value);
349 v.removeRedundantComma(is);
350 if (is.peek() == '}') {
351 break;
352 }
353 if (is.peek() != ',') {
354 is.setstate(std::ios_base::failbit);
355 return is;
356 }
357 is.get();
358 v.removeRedundantComma(is);
359 }
360 if (is.get() != '}') {
361 is.setstate(std::ios_base::failbit);
362 return is;
363 }
364 }break;
365 default:
366 is.setstate(std::ios_base::failbit);
367 }
368 return is;
369 }
370 };
371 }
372}
373
374/*
375(仅)此文件以 MIT 许可证独立于此项目发布
376
377MIT License
378
379Copyright (c) 2024 Weiyi Anglebase
380
381Permission is hereby granted, free of charge, to any person obtaining a copy
382of this software and associated documentation files (the "Software"), to deal
383in the Software without restriction, including without limitation the rights
384to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
385copies of the Software, and to permit persons to whom the Software is
386furnished to do so, subject to the following conditions:
387
388The above copyright notice and this permission notice shall be included in all
389copies or substantial portions of the Software.
390
391THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
392IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
393FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
394AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
395LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
396OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
397SOFTWARE.
398*/
JSON 值对象
定义 json.hpp:86
const int & asInteger() const
定义 json.hpp:161
bool isArray() const
定义 json.hpp:144
Value(bool b)
定义 json.hpp:120
bool isNumber() const
定义 json.hpp:146
Value(const StdString< CharT > &s)
定义 json.hpp:125
Value & operator=(const Object< CharT > &o)
定义 json.hpp:136
const StdString< CharT > & asString() const
定义 json.hpp:163
double & asNumber()
定义 json.hpp:155
Value(const Object< CharT > &o)
定义 json.hpp:127
Value & operator=(double d)
定义 json.hpp:130
bool isInteger() const
定义 json.hpp:147
int toInt() const
定义 json.hpp:168
Value & operator=(const CharT *s)
定义 json.hpp:133
const bool & asBoolean() const
定义 json.hpp:160
bool isFloat() const
定义 json.hpp:152
Value(const Array< CharT > &a)
定义 json.hpp:126
const Object< CharT > & asObject() const
定义 json.hpp:165
Value()
定义 json.hpp:119
bool isObject() const
定义 json.hpp:145
bool isBool() const
定义 json.hpp:142
Value(double d)
定义 json.hpp:121
Value(const CharT(&s)[N])
定义 json.hpp:123
Value & operator[](const StdString< CharT > &key)
定义 json.hpp:173
bool & asBoolean()
定义 json.hpp:154
bool isString() const
定义 json.hpp:143
const Value & operator[](size_t i) const
定义 json.hpp:172
Value(const CharT *s)
定义 json.hpp:124
const Value & at(const StdString< CharT > &key) const
定义 json.hpp:176
bool isNull() const
定义 json.hpp:141
Array< CharT > & asArray()
定义 json.hpp:157
const Array< CharT > & asArray() const
定义 json.hpp:164
Value & operator[](size_t i)
定义 json.hpp:171
const Value & operator[](const StdString< CharT > &key) const
定义 json.hpp:174
Value & operator=(const CharT(&s)[N])
定义 json.hpp:132
Type type() const
获取当前 JSON 值对象持有的 JSON 值类型
定义 json.hpp:139
friend StdOStream< CharT > & operator<<(StdOStream< CharT > &os, const Value< CharT > &v)
向流中写入 JSON 值对象
定义 json.hpp:181
friend StdIStream< CharT > & operator>>(StdIStream< CharT > &is, Value< CharT > &v)
从流中读取 JSON 值对象
定义 json.hpp:238
Value & at(const StdString< CharT > &key)
定义 json.hpp:175
bool toBool() const
定义 json.hpp:167
double toFloat() const
定义 json.hpp:169
StdString< CharT > & asString()
定义 json.hpp:156
const double & asNumber() const
定义 json.hpp:162
Object< CharT > & asObject()
定义 json.hpp:158
Value & operator=(const StdString< CharT > &s)
定义 json.hpp:134
const StdString< CharT > & toString() const
定义 json.hpp:170
Value & operator=(bool b)
定义 json.hpp:129
Value & operator=(const Array< CharT > &a)
定义 json.hpp:135
@ N
N 键
std::basic_istream< CharT > StdIStream
定义 json.hpp:37
std::vector< Value< CharT > > Array
定义 json.hpp:41
std::basic_string< CharT > StdString
定义 json.hpp:35
std::basic_ostream< CharT > StdOStream
定义 json.hpp:39
Type
定义 json.hpp:23
@ String
字符串
@ Boolean
布尔值
@ Invalid
无效值
std::unordered_map< StdString< CharT >, Value< CharT > > Object
定义 json.hpp:43
GraceFt库的命名空间
定义 _private.inl:64
std::size_t size
定义 Matrix.hpp:19
格式化选项
定义 json.hpp:55
static int tabSize()
定义 json.hpp:79
std::ios_base &(*)(std::ios_base &) jFormat
定义 json.hpp:62
Format(int tabsize=-1)
设置格式化选项
定义 json.hpp:65
static bool isFormat()
定义 json.hpp:75