01. 64bit only
02. need fast memory allocator like mimalloc, for speed.
03. C++14~
04. experimental!
05. Array has std::vector<_Value>
06. Object has std::vector<Pair<_Value, _Value>> (not a std::map!)
07. in Object, key can be dupplicated, are not sorted, just in order of input.
08. scanning - modified? simdjson, parsing - parallel
09. it is not read-only!
10. _Value <- json_Value, (in destructor, no remove data(Array or Object!), no copy, only move or clone!
11. Value <- wrap _Value, (in destructor, remove data(Array or Object!)
12. Array, Object <- in destructor, remove data.
C++17 ๊ธฐ๋ฐ ๊ณ ์ฑ๋ฅ ๋ฉํฐ์ค๋ ๋ JSON ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- ๊ฐ์
- ์ํคํ ์ฒ ๋ฐ ํต์ฌ ํด๋์ค
- ํด๋์ค ์์ธ ์ค๋ช
- ํ์ฑ ํ๋ฆ
- ์ง๋ ฌํ ํ๋ฆ
- ์ฃผ์ API
- ๋ด๋ถ ๊ตฌํ ์ธ๋ถ์ฌํญ
- ์ฃผ์์ฌํญ ๋ฐ ์ ์ฝ
claujson์ C++17๋ก ์์ฑ๋ ๊ณ ์ฑ๋ฅ JSON ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ๋ด๋ถ์ ์ผ๋ก simdjson์ SIMD ๊ธฐ๋ฐ ์คํ ์ด์ง 1 ํ ํฌ๋์ด์ ๋ฅผ ์ฌํ์ฉํ๋ฉฐ, ๋ฉํฐ์ค๋ ๋ ๋ณ๋ ฌ ํ์ฑ๊ณผ ์ง๋ ฌํ๋ฅผ ์ง์ํฉ๋๋ค.
- simdjson ๊ธฐ๋ฐ SIMD ๊ฐ์ ํ ํฌ๋์ด์ง (Stage 1)
- ๋ฉํฐ์ค๋ ๋ ๋ณ๋ ฌ ํ์ฑ ๋ฐ ์ง๋ ฌํ (
ThreadPool์ฌ์ฉ) - JSON ํ์ผ ๋ฐ ๋ฌธ์์ด ํ์ฑ ์ง์
- JSON Pointer(
json_pointerB) ์ง์ diff/patch๊ธฐ๋ฅ ๋ด์ฅ- Short String Optimization: 11๋ฐ์ดํธ ์ดํ ๋ฌธ์์ด์ ํ ํ ๋น ์์
- UTF-8 ์ ํจ์ฑ ๊ฒ์ฌ ํตํฉ
- C++20
char8_t(u8string_view) ์ง์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| C++ ํ์ค | C++17 ์ด์ (char8_t ์ฌ์ฉ ์ C++20) |
| ์ํคํ ์ฒ | 64๋นํธ ์ ์ฉ (32๋นํธ ๋น๋ ๋ถ๊ฐ) |
| ์์กด์ฑ | simdjson (์์ ๋ณธ), C++ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ |
| ์ค๋ ๋ฉ | std::thread ๊ธฐ๋ฐ ThreadPool |
Document
โโโ _Value (๋ฃจํธ JSON ๊ฐ)
โโโ Array* โ Array (arr_vec: vector<_Value>)
โ โโโ _Value (์ฌ๊ท)
โโโ Object* โ Object (obj_data: vector<Pair<_Value, _Value>>)
โ โโโ Pair<key:_Value, value:_Value> (์ฌ๊ท)
โโโ ์์๊ฐ (int64 / uint64 / double / bool / null / String)
| ํ์ผ | ์ญํ |
|---|---|
claujson.h / .cpp |
์ง์
์ , parser, writer, StructuredPtr, ์ ์ญ ์ ํธ |
claujson_internal.h |
๊ณต์ฉ ํ์
(_ValueType, Pair, Vector, Log) |
claujson_string.h |
String (SSO ๋ฌธ์์ด ํด๋์ค) |
claujson_value.cpp |
_Value ๋ฉ์๋ ๊ตฌํ |
claujson_array.h / .cpp |
Array ํด๋์ค |
claujson_object.h / .cpp |
Object ํด๋์ค |
claujson_partialjson.h / .cpp |
PartialJson (๋ฉํฐ์ค๋ ๋ ํ์ฑ ์ค๊ฐ ๊ฒฐ๊ณผ) |
๋ชจ๋ JSON ๊ฐ์ ํํํ๋ ํต์ฌ ํ์
์
๋๋ค. ๋ณต์ฌ ์์ฑ/๋์
์ด ์ญ์ ๋์ด ์์ผ๋ฉฐ, ์ด๋๋ง ํ์ฉ๋ฉ๋๋ค. ๋ช
์์ ๋ณต์ฌ๊ฐ ํ์ํ ๋๋ clone()์ ์ฌ์ฉํฉ๋๋ค.
union {
struct {
union {
int64_t _int_val;
uint64_t _uint_val;
double _float_val;
Array* _array_ptr;
Object* _obj_ptr;
PartialJson* _pj_ptr;
bool _bool_val;
};
uint32_t temp;
_ValueType _type; // ํ์
๊ตฌ๋ถ์
};
String _str_val; // STRING / SHORT_STRING์ผ ๋ ์ฌ์ฉ
};
_type์ดSTRING๋๋SHORT_STRING์ผ ๋๋ง_str_val์ ์ ๊ทผํด์ผ ํฉ๋๋ค. ๋ ๋ถ๊ธฐ๋ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํฉ๋๋ค.
| ๊ฐ | ์๋ฏธ |
|---|---|
NONE |
์ด๊ธฐํ๋์ง ์์ ์ํ |
ARRAY |
JSON ๋ฐฐ์ด (_array_ptr ์ ํจ) |
OBJECT |
JSON ๊ฐ์ฒด (_obj_ptr ์ ํจ) |
PARTIAL_JSON |
ํ์ฑ ์ค๊ฐ ๊ฒฐ๊ณผ (๋ด๋ถ์ฉ) |
INT |
64๋นํธ ๋ถํธ ์๋ ์ ์ |
UINT |
64๋นํธ ๋ถํธ ์๋ ์ ์ |
FLOAT |
64๋นํธ ๋ถ๋์์์ (double) |
BOOL |
๋ถ๋ฆฌ์ธ |
NULL_ |
JSON null |
STRING |
๋์ ํ ๋น ๋ฌธ์์ด (๊ธธ์ด โฅ 11) |
SHORT_STRING |
์คํ ๋ด ์ธ๋ผ์ธ ๋ฌธ์์ด (๊ธธ์ด < 11, SSO) |
NOT_VALID |
์ ํจํ์ง ์์ ๊ฐ (์ค๋ฅ ๋ฐํ ์) |
ERROR |
๋ด๋ถ ์ค๋ฅ ์ํ |
// ํ์
ํ์ธ
bool is_valid() const;
bool is_null() const;
bool is_primitive() const; // int/uint/float/bool/string/null
bool is_structured() const; // array ๋๋ object
bool is_array() const;
bool is_object() const;
bool is_int() const;
bool is_uint() const;
bool is_float() const;
bool is_number() const; // int || uint || float
bool is_bool() const;
bool is_str() const;
// ๊ฐ ์ ๊ทผ (getter)
int64_t int_val() const;
uint64_t uint_val() const;
double float_val() const;
bool bool_val() const;
String& str_val();
// ๊ตฌ์กฐ์ฒด ์ ๊ทผ
Array* as_array();
Object* as_object();
StructuredPtr as_structured_ptr();
// ๊ฐ ์ค์ (setter)
void set_int(long long x);
void set_uint(unsigned long long x);
void set_float(double x);
bool set_str(const char* str, uint64_t len);
void set_bool(bool x);
void set_null();
// ์ธ๋ฑ์ค/ํค ์ ๊ทผ
_Value& operator[](uint64_t idx);
_Value& operator[](const _Value& key);
// JSON Pointer ํ์
_Value& json_pointerB(const std_vector<_Value>& routeVec);
// ๋ช
์์ ๋ณต์ฌ
_Value clone() const;_Value๋ฅผ ์์ ํ๋ RAII ๋ํผ ํด๋์ค์
๋๋ค. ์๋ฉธ ์ claujson::clean()์ ์๋ ํธ์ถํ์ฌ ํ์ ๊ตฌ์กฐ์ฒด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํฉ๋๋ค. ๋ณต์ฌ๋ ๋ถ๊ฐํ๋ฉฐ ์ด๋๋ง ํ์ฉ๋ฉ๋๋ค.
Value v(Array::Make()); // _Value๋ฅผ Value๋ก ๋ํ
_Value& inner = v.Get(); // ๋ด๋ถ _Value ์ ๊ทผํ์ฑ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ ์ต์์ ์ปจํ
์ด๋์
๋๋ค. parser::parse() ๋๋ parser::parse_str()์ ์ถ๋ ฅ ๋์์
๋๋ค.
claujson::parser p;
claujson::Document doc;
auto [ok, len] = p.parse("data.json", doc, 0 /*auto thread*/);
_Value& root = doc.Get();JSON ๋ฐฐ์ด์ ๋ํ๋ด๋ฉฐ, std::vector<_Value> (arr_vec)๋ก ์์๋ฅผ ์ ์ฅํฉ๋๋ค.
std_vector<_Value> arr_vec; // ์์ ์ ์ฅ
Pointer parent; // ๋ถ๋ชจ ํฌ์ธํฐ (๋นํธ ํจํน)static _Value Make(); // ๋น ๋ฐฐ์ด _Value ์์ฑ
static _Value MakeVirtual(); // ๊ฐ์(virtual) ๋ฐฐ์ด ์์ฑ (๋ฉํฐ์ค๋ ๋ ๋ด๋ถ์ฉ)
bool add_element(Value val); // ์์ ์ถ๊ฐ (๋ง๋ฏธ)
bool assign_element(uint64_t idx, Value val); // ์์ ๊ต์ฒด
bool insert(uint64_t idx, Value val); // ์ค๊ฐ ์ฝ์
void erase(uint64_t idx, bool real = false); // ์์ ์ญ์
uint64_t get_data_size() const;
_Value& get_value_list(uint64_t idx);
uint64_t find(const _Value& value, uint64_t start = 0) const;
StructuredPtr get_parent() const;
bool is_virtual() const;
erase(idx, real=true)์ด๋ฉด ์์์clean()์ ํธ์ถํ์ฌ ํ์ ๊ตฌ์กฐ์ฒด๊น์ง ์ฌ๊ท ํด์ ํฉ๋๋ค.
JSON ๊ฐ์ฒด๋ฅผ ๋ํ๋ด๋ฉฐ, std::vector<Pair<_Value, _Value>> (obj_data)๋ก ํค-๊ฐ ์์ ์์๋๋ก ์ ์ฅํฉ๋๋ค. (๋น์ ๋ ฌ ๋งต์ด ์๋ ์์ ๋ณด์กด ๋ฒกํฐ ๊ตฌ์กฐ)
static _Value Make();
static _Value MakeVirtual();
bool add_element(Value key, Value val);
bool assign_value_element(uint64_t idx, Value val);
void erase(const _Value& key, bool real = false);
void erase(uint64_t idx, bool real = false);
bool change_key(const _Value& key, Value new_key);
bool change_key(uint64_t idx, Value new_key);
uint64_t find(const _Value& key) const; // ์ ํ ํ์ O(n)
bool chk_key_dup(uint64_t* idx) const; // ์ค๋ณต ํค ๊ฒ์ฌ
_Value& get_key_list(uint64_t idx);
_Value& get_value_list(uint64_t idx);
find()๋ ๋ด๋ถ์ ์ผ๋ก ์ ํ ํ์์ ์ํํฉ๋๋ค (O(n)). ๋๊ท๋ชจ ๊ฐ์ฒด์์ ๋น๋ฒํ ํค ํ์์ ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค.
Array*, Object*, PartialJson* ์ค ํ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํ์
์ด๋ ์ด์ (type-erased) ํฌ์ธํฐ์
๋๋ค. type ํ๋๋ก ์ค์ ํ์
์ ๊ตฌ๋ถํฉ๋๋ค.
union { Array* arr; Object* obj; PartialJson* pj; };
uint32_t type; // 0: null, 1: Array, 2: Object, 3: PartialJsonํ์ฑ ์์ง(LoadData2)์์ Array/Object/PartialJson์ ๋์ผํ ์ธํฐํ์ด์ค๋ก ๋ค๋ฃจ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค.
11๋ฐ์ดํธ(CLAUJSON_STRING_BUF_SIZE) ์ดํ ๋ฌธ์์ด์ ํ ํ ๋น ์์ด ์ธ๋ผ์ธ ๋ฒํผ์ ์ ์ฅํฉ๋๋ค.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SHORT_STRING (len < 11) โ
โ buf[11] + buf_sz(uint8) + type_(_ValueType)โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ STRING (len >= 11) โ
โ char* str + uint32_t sz + _ValueType type โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๋ณต์ฌ ์์ฑ์๋ protected๋ก ์ ํ๋์ด ์์ผ๋ฉฐ, _Value๋ง ์ง์ ์์ฑํ ์ ์์ต๋๋ค. ์ธ๋ถ์์๋ _Value::clone()์ ํตํด ๊ฐ์ ๋ณต์ฌํฉ๋๋ค.
Array์ Object์ parent ํ๋์ ์ฌ์ฉ๋ฉ๋๋ค. 64๋นํธ ํฌ์ธํฐ ํ๋์ ์ธ ๊ฐ์ง ์ ๋ณด๋ฅผ ์ธ์ฝ๋ฉํฉ๋๋ค.
bit 63 : is_virtual ํ๋๊ทธ (1์ด๋ฉด ๊ฐ์ ๋
ธ๋)
bits 62~2 : ์ค์ ๋ถ๋ชจ ํฌ์ธํฐ ์ฃผ์
bits 1~0 : ๋ถ๋ชจ ํ์
(1: Array, 2: Object, 3: PartialJson)
ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ ๋๋ use() ๋ฉ์๋๋ก ๋นํธ ๋ง์คํฌ๋ฅผ ์ ๊ฑฐํ ์์ ์ฃผ์๋ฅผ ์ป์ต๋๋ค.
๋ฉํฐ์ค๋ ๋ ํ์ฑ ์ค ๊ฐ ์ค๋ ๋๊ฐ ์์ฐํ๋ ๋ถ๋ถ ํ์ฑ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๋ ํด๋์ค์ ๋๋ค. ์ธ๋ถ ์ฌ์ฉ์๊ฐ ์ง์ ์์ฑํ๊ฑฐ๋ ์ฌ์ฉํ ํ์๋ ์์ต๋๋ค.
๋ฐฐ์ด ํํธ๊ณผ ๊ฐ์ฒด ํํธ์ ๊ฐ๊ฐ arr_vec, obj_data์ ์ ์ฅํ๊ณ , ์ค๋ ๋ ๊ฒฝ๊ณ์ ๊ฑธ์ณ ์๋ ๊ฐ์ ๋
ธ๋๋ virtualJson์ ์ ์ฅํฉ๋๋ค.
// ํ์ฑ
claujson::parser p(thr_num); // thr_num=0์ด๋ฉด ์๋ ๊ฒฐ์
auto [ok, len] = p.parse("file.json", doc, thr_num);
auto [ok, len] = p.parse_str("{ \"key\": 1 }", doc, thr_num);
// ์ง๋ ฌํ
claujson::writer w(thr_num);
std::string s = w.write_to_str(doc.Get(), /*pretty=*/false);
std::string s2 = w.write_to_str2(doc.Get(), false); // JsonView ๊ธฐ๋ฐ ๋ฐฉ์
w.write("output.json", doc.Get(), false);
w.write_parallel("output.json", doc.Get(), thr_num, false);
w.write_parallel2("output.json", doc.Get(), thr_num, false);์
๋ ฅ (ํ์ผ / ๋ฌธ์์ด)
โ
โผ
[Stage 1: simdjson] ํ ํฌ๋์ด์ง โ structural_indexes ๋ฐฐ์ด ์์ฑ
โ
โผ
[is_valid2] ๋ณ๋ ฌ ๊ตฌ์กฐ ๊ฒ์ฆ + count_vec(๊ฐ ๋
ธ๋ ์์ ์) ๊ณ์ฐ
โ
โผ
[FindDivisionPlace] comma ๊ธฐ์ค์ผ๋ก ์ค๋ ๋ ๋ถํ ๊ฒฝ๊ณ(pivot) ํ์
โ
โโ Thread 0 โโบ __LoadData(pivot[0] ~ pivot[1]) โ PartialJson 0
โโ Thread 1 โโบ __LoadData(pivot[1] ~ pivot[2]) โ PartialJson 1
โโ Thread N โโบ __LoadData(pivot[N-1] ~ pivot[N]) โ PartialJson N
โ
โผ
[Merge] PartialJson๋ค์ ์์๋๋ก ๋ณํฉ
โ
โผ
Document::Get() ์ ์ต์ข
_Value ์ ์ฅ
simdjson์ด ์์ฑํ structural_indexes๋ฅผ ์ํํ๋ฉด์ ์๋ ์ํ ๋จธ์ ์ ์คํํฉ๋๋ค.
| ํ ํฐ | ๋์ |
|---|---|
{ |
์ Object ์์ฑ, nowUT ๊ฐฑ์ |
[ |
์ Array ์์ฑ, nowUT ๊ฐฑ์ |
} / ] (brace > 0) |
nowUT๋ฅผ ๋ถ๋ชจ๋ก ์ด๋ |
} / ] (brace == 0) |
์ค๋ ๋ ๊ฒฝ๊ณ ์ฒ๋ฆฌ: ๊ฐ์(virtual) ๋ ธ๋ ์์ฑ |
key : value |
add_item_type() ํธ์ถ |
value (๋ฐฐ์ด ์์) |
add_item_type() ํธ์ถ |
, |
์คํต |
๊ฐ ์ค๋ ๋์ PartialJson์ Merge() / Merge2()๋ฅผ ํตํด ์์๋๋ก ๋ณํฉ๋ฉ๋๋ค.
next (์ ์ฒญํฌ ๋ ๋
ธ๋) + ut (๋ค์ ์ฒญํฌ ๊ฐ์ ๋
ธ๋)
โ MergeWith()๋ก ut์ ์์๋ค์ next์ ์ด๋
โ ๋ถ๋ชจ ํฌ์ธํฐ๋ฅผ ๋ฐ๋ผ ๋ฃจํธ๊น์ง ๋ฐ๋ณต
claujson์ ๋ ๊ฐ์ง ์ง๋ ฌํ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค.
LoadData2::_write()๊ฐ _Value ํธ๋ฆฌ๋ฅผ ์ฌ๊ท์ ์ผ๋ก ์ํํ๋ฉฐ StrStream์ ์ถ๋ ฅํฉ๋๋ค. ๋จ์ผ ์ค๋ ๋ ๋ฐฉ์๊ณผ ๋ณ๋ ฌ ๋ฐฉ์(write_parallel) ๋ชจ๋ ์ด ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค.
๋ณ๋ ฌ ์ง๋ ฌํ ์:
Divide2()๋ก ํธ๋ฆฌ๋ฅผ n๊ฐ ์ฒญํฌ๋ก ๋ถํ- ๊ฐ ์ฒญํฌ๋ฅผ ๋ณ๋ ์ค๋ ๋์์
write_()๋ก ์ง๋ ฌํ - ๊ฒฐ๊ณผ
StrStream๋ค์ ์์๋๋ก ํ์ผ์ ๊ธฐ๋ก - ๋ถํ ๋ ํธ๋ฆฌ๋
Merge2()๋ก ์์๋ณต๊ตฌ
Size2()๋ก ์ ์ฒด ๋ ธ๋ ์ ๊ณ์ฐrun()์ผ๋ก ํธ๋ฆฌ๋ฅผJsonView[]๋ฐฐ์ด(์ ํํ)๋ก ๋ณํ- ๋ฐฐ์ด์ n ๊ตฌ๊ฐ์ผ๋ก ๋๋
print()/print_pretty()๋ฅผ ๋ณ๋ ฌ ์คํ
JsonView ํ์
์ฝ๋:
| type | ์๋ฏธ |
|---|---|
| 0 | ARRAY ์์ |
| 1 | OBJECT ์์ |
| 2 | KEY |
| 3 | VALUE (์์๊ฐ) |
| 4 | ARRAY ๋ |
| 5 | OBJECT ๋ |
| -1 | ์ข ๋ฃ ๋ง์ปค |
#include "claujson.h"
claujson::parser parser(/*thr_num=*/0); // 0: ์๋
// ํ์ผ ํ์ฑ
claujson::Document doc;
auto [ok, len] = parser.parse("data.json", doc, 0);
// ๋ฌธ์์ด ํ์ฑ
auto [ok2, len2] = parser.parse_str(R"({"name":"claujson","version":1})", doc, 0);
// C++20 char8_t
auto [ok3, len3] = parser.parse_str(u8R"({"hello":"world"})", doc, 0);_Value& root = doc.Get();
// ๋ฐฐ์ด ์ ๊ทผ
if (root.is_array()) {
uint64_t sz = root.as_array()->size();
for (uint64_t i = 0; i < sz; ++i) {
_Value& elem = root[i];
if (elem.is_int()) std::cout << elem.get_integer();
if (elem.is_str()) std::cout << elem.str_val().data();
}
}
// ๊ฐ์ฒด ์ ๊ทผ
if (root.is_object()) {
_Value key = _Value("name"sv);
_Value& val = root[key];
if (val.is_str()) std::cout << val.str_val().data();
}// /users/0/name ๊ฒฝ๋ก ํ์
std_vector<_Value> route;
route.push_back(_Value("users"sv));
route.push_back(_Value((uint64_t)0));
route.push_back(_Value("name"sv));
_Value& target = root.json_pointerB(route);// ๋ฐฐ์ด์ ์์ ์ถ๊ฐ
StructuredPtr sp(root.as_array());
sp.add_array_element(_Value((int64_t)42));
// ๊ฐ์ฒด์ ํค-๊ฐ ์ถ๊ฐ
StructuredPtr so(root.as_object());
so.add_object_element(_Value("score"sv), _Value(99.5));
// ์์ ์ญ์
sp.erase((uint64_t)0, /*real=*/true);
so.erase(_Value("score"sv), true);claujson::writer writer(0);
// ๋ฌธ์์ด๋ก ์ง๋ ฌํ
std::string json_str = writer.write_to_str(doc.Get(), /*pretty=*/false);
// ํ์ผ๋ก ์ ์ฅ
writer.write("output.json", doc.Get(), false);
// ๋ณ๋ ฌ ์ง๋ ฌํ (๋์ฉ๋)
writer.write_parallel("output.json", doc.Get(), /*thr_num=*/0, false);
writer.write_parallel2("output.json", doc.Get(), 0, false);_Value a = /* ... */;
_Value b = /* ... */;
_Value d = claujson::diff(a, b); // ์ฐจ์ด ๊ณ์ฐ (JSON Patch ์ ์ฌ ํ์)
claujson::patch(a, d); // a์ ํจ์น ์ ์ฉ โ b์ ๋์ผํด์ง// ๋ฉ๋ชจ๋ฆฌ ํด์ (Array/Object ์ฌ๊ท ์ญ์ )
claujson::clean(value);
/*
// ๋ฌธ์์ด ์ ํจ์ฑ ๊ฒ์ฌ
bool ok = claujson::is_valid_string_in_json("hello\\nworld");
// JSON ์ด์ค์ผ์ดํ ๋ณํ
auto [ok, converted] = claujson::convert_to_string_in_json("hello\\nworld");
// ์ซ์ ํ์ฑ
_Value num;
claujson::convert_number("3.14", num);
*/
// ๋ก๊ทธ ์ค์
claujson::log.console();
claujson::log.info();
claujson::log.warn();_Value::_Value(_Value&& other) noexcept {
if (other.is_str()) {
_str_val = std::move(other._str_val); // String ์ด๋
} else {
std::swap(_int_val, other._int_val);
std::swap(_type, other._type); // ํ์
๊ณผ ๊ฐ๋ง ์ค์
}
}operator=(_Value&&)๋ std::swap ํ clean(other)๋ฅผ ํธ์ถํ์ฌ ์ด์ ๊ฐ์ ๋ช
์์ ์ผ๋ก ์ ๋ฆฌํฉ๋๋ค.
์ธ๋ถ์์ ์
๋ ฅ๋๋ ๋ฌธ์์ด์ simdjson::parse_string()์ ํตํด JSON ์ด์ค์ผ์ดํ ์ํ์ค(\n, \uXXXX ๋ฑ)๋ฅผ ๋์ฝ๋ฉํ๊ณ , validate_utf8()๋ก UTF-8 ์ ํจ์ฑ์ ๊ฒ์ฌํฉ๋๋ค. 1024๋ฐ์ดํธ๋ฅผ ๊ธฐ์ค์ผ๋ก ์คํ ๋ฒํผ์ ํ ๋ฒํผ๋ฅผ ๋ถ๊ธฐํ์ฌ ์ฒ๋ฆฌํฉ๋๋ค.
ํ์ฑ ์ค์๋ ์ด ๊ณผ์ ์ ์๋ตํ๊ณ set_str_in_parse()(simdjson์ด ์ด๋ฏธ ์ฒ๋ฆฌํ ๊ฒฐ๊ณผ๋ฅผ ์ง์ ์ ์ฅ)๋ฅผ ์ฌ์ฉํฉ๋๋ค.
is_valid2()๋ ๊ตฌ์กฐ ๊ฒ์ฆ๊ณผ ๋์์ ๊ฐ Array/Object๊ฐ ๊ฐ์ง ์ง์ ์์ ์์ ์๋ฅผ count_vec์ ๊ธฐ๋กํฉ๋๋ค. __LoadData()๋ { / [ ์ง์
์ ์ด ๊ฐ์ผ๋ก reserve_data_list()๋ฅผ ํธ์ถํ์ฌ ๋ฒกํฐ ์ฌํ ๋น์ ์ต์ํํฉ๋๋ค.
void clean(_Value& x) {
if (x.is_array()) delete x.as_array();
else if (x.is_object()) delete x.as_object();
else if (x.is_partial_json()) delete x.as_partial_json();
x.set_none();
}Array์ Object์ ์๋ฉธ์๊ฐ ํ์ ๊ตฌ์กฐ์ฒด ํฌ์ธํฐ๋ฅผ ์ฌ๊ท ์ญ์ ํ๋ฏ๋ก, clean()์ ์ต์์ ๋
ธ๋ ํ๋๋ง deleteํ๋ฉด ์ ์ฒด ํธ๋ฆฌ๊ฐ ์ ๋ฆฌ๋ฉ๋๋ค.
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| 64๋นํธ ์ ์ฉ | Pointer ํด๋์ค๊ฐ 64๋นํธ ํฌ์ธํฐ ๋นํธ ์กฐ์์ ์์กดํฉ๋๋ค. 32๋นํธ ๋น๋๋ ๋ถ๊ฐํฉ๋๋ค. |
_Value ๋ณต์ฌ ๋ถ๊ฐ |
๋ณต์ฌ ์์ฑ์์ ๋ณต์ฌ ๋์
์ฐ์ฐ์๊ฐ delete๋์ด ์์ต๋๋ค. ๋ณต์ฌ๊ฐ ํ์ํ๋ฉด clone()์ ์ฌ์ฉํ์ธ์. |
Object::find() ์ฑ๋ฅ |
์ ํ ํ์(O(n))์ ๋๋ค. ๋งค์ฐ ํฐ ๊ฐ์ฒด์์ ๋ฐ๋ณต ํค ๊ฒ์์ ํผํ์ธ์. |
PartialJson ์ง์ ์ฌ์ฉ ๊ธ์ง |
ํ์ฑ ์์ง ๋ด๋ถ์ฉ ํด๋์ค์ด๋ฉฐ, ์ธ๋ถ์์ ์ง์ ์์ฑํ๊ฑฐ๋ ์กฐ์ํด์๋ ์ ๋ฉ๋๋ค. |
String ๋ณต์ฌ ์์ฑ์ |
protected๋ก ์ ํ๋์ด ์์ด _Value ์ธ๋ถ์์๋ ๋ณต์ฌ ์์ฑ์ด ๋ถ๊ฐํฉ๋๋ค. |
is_valid() ํ์ธ |
NOT_VALID ๋๋ ERROR ์ํ์ _Value์ ๊ฐ ์ ๊ทผ ์ ๋ฏธ์ ์ ๋์์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ํญ์ is_valid()๋ฅผ ๋จผ์ ํ์ธํ์ธ์. |
clean() ์ค๋ณต ํธ์ถ |
clean() ํ ํด๋น _Value๋ก delete๋ฅผ ๋ค์ ํธ์ถํ๋ฉด ์ด์ค ํด์ (double-free)๊ฐ ๋ฐ์ํฉ๋๋ค. Document์ Value ์๋ฉธ์๊ฐ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ฏ๋ก ์๋ ํธ์ถ์ ์ฃผ์ํ์ธ์. |
| ๋ฉํฐ์ค๋ ๋ ์์ ์ฑ | ํ์ฑ/์ง๋ ฌํ ์์ฒด๋ ๋ด๋ถ์ ์ผ๋ก ์ค๋ ๋๋ฅผ ๊ด๋ฆฌํ์ง๋ง, _Value ํธ๋ฆฌ์ ๋ํ ๋์ ์ฝ๊ธฐ/์ฐ๊ธฐ๋ ์ธ๋ถ์์ ๋ณ๋๋ก ๋๊ธฐํํด์ผ ํฉ๋๋ค. |