Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

6 Commits
ย 
ย 
ย 
ย 

Repository files navigation

claujson-document

first check!

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.

claujson ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ธฐ์ˆ  ๋ฌธ์„œ - using claude

C++17 ๊ธฐ๋ฐ˜ ๊ณ ์„ฑ๋Šฅ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ JSON ํŒŒ์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ


๋ชฉ์ฐจ

  1. ๊ฐœ์š”
  2. ์•„ํ‚คํ…์ฒ˜ ๋ฐ ํ•ต์‹ฌ ํด๋ž˜์Šค
  3. ํด๋ž˜์Šค ์ƒ์„ธ ์„ค๋ช…
  4. ํŒŒ์‹ฑ ํ๋ฆ„
  5. ์ง๋ ฌํ™” ํ๋ฆ„
  6. ์ฃผ์š” API
  7. ๋‚ด๋ถ€ ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ
  8. ์ฃผ์˜์‚ฌํ•ญ ๋ฐ ์ œ์•ฝ

1. ๊ฐœ์š”

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

2. ์•„ํ‚คํ…์ฒ˜ ๋ฐ ํ•ต์‹ฌ ํด๋ž˜์Šค

ํด๋ž˜์Šค ๊ตฌ์กฐ ๊ฐœ์š”

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 (๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํŒŒ์‹ฑ ์ค‘๊ฐ„ ๊ฒฐ๊ณผ)

3. ํด๋ž˜์Šค ์ƒ์„ธ ์„ค๋ช…

3.1 _Value

๋ชจ๋“  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์— ์ ‘๊ทผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๋ถ„๊ธฐ๋Š” ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

_ValueType ์—ด๊ฑฐํ˜•

๊ฐ’ ์˜๋ฏธ
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;

3.2 Value

_Value๋ฅผ ์†Œ์œ ํ•˜๋Š” RAII ๋ž˜ํผ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์†Œ๋ฉธ ์‹œ claujson::clean()์„ ์ž๋™ ํ˜ธ์ถœํ•˜์—ฌ ํ•˜์œ„ ๊ตฌ์กฐ์ฒด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค. ๋ณต์‚ฌ๋Š” ๋ถˆ๊ฐ€ํ•˜๋ฉฐ ์ด๋™๋งŒ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค.

Value v(Array::Make());        // _Value๋ฅผ Value๋กœ ๋ž˜ํ•‘
_Value& inner = v.Get();       // ๋‚ด๋ถ€ _Value ์ ‘๊ทผ

3.3 Document

ํŒŒ์‹ฑ ๊ฒฐ๊ณผ๋ฅผ ๋‹ด๋Š” ์ตœ์ƒ์œ„ ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค. 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();

3.4 Array

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()์„ ํ˜ธ์ถœํ•˜์—ฌ ํ•˜์œ„ ๊ตฌ์กฐ์ฒด๊นŒ์ง€ ์žฌ๊ท€ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.


3.5 Object

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)). ๋Œ€๊ทœ๋ชจ ๊ฐ์ฒด์—์„œ ๋นˆ๋ฒˆํ•œ ํ‚ค ํƒ์ƒ‰์€ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


3.6 StructuredPtr

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์„ ๋™์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.


3.7 String (Short String Optimization)

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()์„ ํ†ตํ•ด ๊ฐ„์ ‘ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.


3.8 Pointer (๋น„ํŠธ ํŒจํ‚น ๋ถ€๋ชจ ํฌ์ธํ„ฐ)

Array์™€ Object์˜ parent ํ•„๋“œ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. 64๋น„ํŠธ ํฌ์ธํ„ฐ ํ•˜๋‚˜์— ์„ธ ๊ฐ€์ง€ ์ •๋ณด๋ฅผ ์ธ์ฝ”๋”ฉํ•ฉ๋‹ˆ๋‹ค.

bit 63      : is_virtual ํ”Œ๋ž˜๊ทธ (1์ด๋ฉด ๊ฐ€์ƒ ๋…ธ๋“œ)
bits 62~2   : ์‹ค์ œ ๋ถ€๋ชจ ํฌ์ธํ„ฐ ์ฃผ์†Œ
bits 1~0    : ๋ถ€๋ชจ ํƒ€์ž… (1: Array, 2: Object, 3: PartialJson)

ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” use() ๋ฉ”์„œ๋“œ๋กœ ๋น„ํŠธ ๋งˆ์Šคํฌ๋ฅผ ์ œ๊ฑฐํ•œ ์ˆœ์ˆ˜ ์ฃผ์†Œ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.


3.9 PartialJson (๋‚ด๋ถ€์šฉ)

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํŒŒ์‹ฑ ์ค‘ ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์ƒ์‚ฐํ•˜๋Š” ๋ถ€๋ถ„ ํŒŒ์‹ฑ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์™ธ๋ถ€ ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

๋ฐฐ์—ด ํŒŒํŽธ๊ณผ ๊ฐ์ฒด ํŒŒํŽธ์„ ๊ฐ๊ฐ arr_vec, obj_data์— ์ €์žฅํ•˜๊ณ , ์Šค๋ ˆ๋“œ ๊ฒฝ๊ณ„์— ๊ฑธ์ณ ์žˆ๋Š” ๊ฐ€์ƒ ๋…ธ๋“œ๋Š” virtualJson์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.


3.10 parser / writer

// ํŒŒ์‹ฑ
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);

4. ํŒŒ์‹ฑ ํ๋ฆ„

์ž…๋ ฅ (ํŒŒ์ผ / ๋ฌธ์ž์—ด)
        โ”‚
        โ–ผ
[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 ์ €์žฅ

__LoadData ๋‚ด๋ถ€ ๋™์ž‘

simdjson์ด ์ƒ์„ฑํ•œ structural_indexes๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ์•„๋ž˜ ์ƒํƒœ ๋จธ์‹ ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

ํ† ํฐ ๋™์ž‘
{ ์ƒˆ Object ์ƒ์„ฑ, nowUT ๊ฐฑ์‹ 
[ ์ƒˆ Array ์ƒ์„ฑ, nowUT ๊ฐฑ์‹ 
} / ] (brace > 0) nowUT๋ฅผ ๋ถ€๋ชจ๋กœ ์ด๋™
} / ] (brace == 0) ์Šค๋ ˆ๋“œ ๊ฒฝ๊ณ„ ์ฒ˜๋ฆฌ: ๊ฐ€์ƒ(virtual) ๋…ธ๋“œ ์ƒ์„ฑ
key : value add_item_type() ํ˜ธ์ถœ
value (๋ฐฐ์—ด ์›์†Œ) add_item_type() ํ˜ธ์ถœ
, ์Šคํ‚ต

Merge ์•Œ๊ณ ๋ฆฌ์ฆ˜

๊ฐ ์Šค๋ ˆ๋“œ์˜ PartialJson์€ Merge() / Merge2()๋ฅผ ํ†ตํ•ด ์ˆœ์„œ๋Œ€๋กœ ๋ณ‘ํ•ฉ๋ฉ๋‹ˆ๋‹ค.

next (์•ž ์ฒญํฌ ๋ ๋…ธ๋“œ)  +  ut (๋‹ค์Œ ์ฒญํฌ ๊ฐ€์ƒ ๋…ธ๋“œ)
    โ†’ MergeWith()๋กœ ut์˜ ์›์†Œ๋“ค์„ next์— ์ด๋™
    โ†’ ๋ถ€๋ชจ ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋ผ ๋ฃจํŠธ๊นŒ์ง€ ๋ฐ˜๋ณต

5. ์ง๋ ฌํ™” ํ๋ฆ„

claujson์€ ๋‘ ๊ฐ€์ง€ ์ง๋ ฌํ™” ๋ฐฉ์‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ฐฉ์‹ 1: ์žฌ๊ท€ ์ˆœํšŒ (_write)

LoadData2::_write()๊ฐ€ _Value ํŠธ๋ฆฌ๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ์ˆœํšŒํ•˜๋ฉฐ StrStream์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ผ ์Šค๋ ˆ๋“œ ๋ฐฉ์‹๊ณผ ๋ณ‘๋ ฌ ๋ฐฉ์‹(write_parallel) ๋ชจ๋‘ ์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ณ‘๋ ฌ ์ง๋ ฌํ™” ์‹œ:

  1. Divide2()๋กœ ํŠธ๋ฆฌ๋ฅผ n๊ฐœ ์ฒญํฌ๋กœ ๋ถ„ํ• 
  2. ๊ฐ ์ฒญํฌ๋ฅผ ๋ณ„๋„ ์Šค๋ ˆ๋“œ์—์„œ write_()๋กœ ์ง๋ ฌํ™”
  3. ๊ฒฐ๊ณผ StrStream๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ ํŒŒ์ผ์— ๊ธฐ๋ก
  4. ๋ถ„ํ• ๋œ ํŠธ๋ฆฌ๋Š” Merge2()๋กœ ์›์ƒ๋ณต๊ตฌ

๋ฐฉ์‹ 2: JsonView ๊ธฐ๋ฐ˜ (write_to_str2, write_parallel2)

  1. Size2()๋กœ ์ „์ฒด ๋…ธ๋“œ ์ˆ˜ ๊ณ„์‚ฐ
  2. run()์œผ๋กœ ํŠธ๋ฆฌ๋ฅผ JsonView[] ๋ฐฐ์—ด(์„ ํ˜•ํ™”)๋กœ ๋ณ€ํ™˜
  3. ๋ฐฐ์—ด์„ n ๊ตฌ๊ฐ„์œผ๋กœ ๋‚˜๋ˆ  print() / print_pretty()๋ฅผ ๋ณ‘๋ ฌ ์‹คํ–‰

JsonView ํƒ€์ž… ์ฝ”๋“œ:

type ์˜๋ฏธ
0 ARRAY ์‹œ์ž‘
1 OBJECT ์‹œ์ž‘
2 KEY
3 VALUE (์›์‹œ๊ฐ’)
4 ARRAY ๋
5 OBJECT ๋
-1 ์ข…๋ฃŒ ๋งˆ์ปค

6. ์ฃผ์š” API

ํŒŒ์‹ฑ

#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();
}

JSON Pointer

// /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);

diff / patch

_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();

7. ๋‚ด๋ถ€ ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ

_Value ์ด๋™ ์‹œ๋งจํ‹ฑ

_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)๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ด์ „ ๊ฐ’์„ ๋ช…์‹œ์ ์œผ๋กœ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ž์—ด ํŒŒ์‹ฑ (set_str)

์™ธ๋ถ€์—์„œ ์ž…๋ ฅ๋˜๋Š” ๋ฌธ์ž์—ด์€ simdjson::parse_string()์„ ํ†ตํ•ด JSON ์ด์Šค์ผ€์ดํ”„ ์‹œํ€€์Šค(\n, \uXXXX ๋“ฑ)๋ฅผ ๋””์ฝ”๋”ฉํ•˜๊ณ , validate_utf8()๋กœ UTF-8 ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค. 1024๋ฐ”์ดํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์Šคํƒ ๋ฒ„ํผ์™€ ํž™ ๋ฒ„ํผ๋ฅผ ๋ถ„๊ธฐํ•˜์—ฌ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

ํŒŒ์‹ฑ ์ค‘์—๋Š” ์ด ๊ณผ์ •์„ ์ƒ๋žตํ•˜๊ณ  set_str_in_parse()(simdjson์ด ์ด๋ฏธ ์ฒ˜๋ฆฌํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ง์ ‘ ์ €์žฅ)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

count_vec์™€ reserve_data_list

is_valid2()๋Š” ๊ตฌ์กฐ ๊ฒ€์ฆ๊ณผ ๋™์‹œ์— ๊ฐ Array/Object๊ฐ€ ๊ฐ€์ง„ ์ง์ ‘ ์ž์‹ ์›์†Œ ์ˆ˜๋ฅผ count_vec์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. __LoadData()๋Š” { / [ ์ง„์ž… ์‹œ ์ด ๊ฐ’์œผ๋กœ reserve_data_list()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ฒกํ„ฐ ์žฌํ• ๋‹น์„ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.

clean() ํ•จ์ˆ˜

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ํ•˜๋ฉด ์ „์ฒด ํŠธ๋ฆฌ๊ฐ€ ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค.


8. ์ฃผ์˜์‚ฌํ•ญ ๋ฐ ์ œ์•ฝ

ํ•ญ๋ชฉ ๋‚ด์šฉ
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 ํŠธ๋ฆฌ์— ๋Œ€ํ•œ ๋™์‹œ ์ฝ๊ธฐ/์“ฐ๊ธฐ๋Š” ์™ธ๋ถ€์—์„œ ๋ณ„๋„๋กœ ๋™๊ธฐํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors