このページの内容

データ構造

yyjsonには、不変と可変の2種類のデータ構造があります。

不変可変
ドキュメントyyjson_docyyjson_mut_doc
値yyjson_valyyjson_mut_val
  • 不変のデータ構造は、JSONドキュメントを読み込むと返されます。変更はできません。
  • 可変のデータ構造は、JSONドキュメントを構築するときに作られます。変更できます。
  • yyjsonは、これらの2種類のデータ構造を相互に変換する関数も提供しています。

この文書で説明するデータ構造は非公開扱いであることに注意してください。アクセスには公開APIを使うことを推奨します。


不変の値

各JSON値は、不変のyyjson_val構造体に格納されます。

struct yyjson_val {
    uint64_t tag;
    union {
        uint64_t    u64;
        int64_t     i64;
        double      f64;
        const char *str;
        void       *ptr;
        size_t      ofs;
    } uni;
}
yyjson_val
Original image / 図の原寸表示

値の型は、tagの下位8ビットに格納します。
文字列長、オブジェクトサイズ、配列サイズなど、値のサイズは、tagの上位56ビットに格納します。

現代の64ビットプロセッサーでは、RAMアドレスに使えるビット数が通常64ビット未満に制限されています(Wikipedia)。たとえば、Intel64、AMD64、ARMv8の物理アドレスは52ビット(4PB)が上限です。そのため、64ビットのtag内に型とサイズの情報を格納しても安全です。

不変のドキュメント

JSONドキュメントは、すべての文字列を連続したメモリ領域に格納します。
各文字列は、その場所でエスケープが解除され、NUL終端文字で終わります。
例:

yyjson_doc
Original image / 図の原寸表示

JSONドキュメントは、すべての値を、別の連続したメモリ領域に格納します。
objectとarrayのコンテナーは、自身のメモリ使用量を格納するため、子の値を容易に走査できます。
例:

yyjson_doc
Original image / 図の原寸表示

可変の値

各可変JSON値は、yyjson_mut_val構造体に格納されます。

struct yyjson_mut_val {
    uint64_t tag;
    union {
        uint64_t    u64;
        int64_t     i64;
        double      f64;
        const char *str;
        void       *ptr;
        size_t      ofs;
    } uni;
    yyjson_mut_val *next;
}
yyjson_mut_val
Original image / 図の原寸表示

tagとuniフィールドは、不変の値と同じです。nextフィールドは、連結リストの構築に使います。

可変のドキュメント

可変JSONドキュメントは、複数のyyjson_mut_valで構成されます。

objectまたはarrayの子の値は、循環するように連結されています。
親は循環連結リストの末尾を保持するため、yyjsonはappend、prepend、remove_firstを定数時間で実行できます。

例:

yyjson_mut_doc
Original image / 図の原寸表示

メモリ管理

JSONドキュメント(yyjson_doc、yyjson_mut_doc)は、すべてのJSON値と文字列のメモリを管理します。ドキュメントが不要になったら、利用者はyyjson_doc_free()またはyyjson_mut_doc_free()を呼び出して、関連するメモリを解放することが重要です。

JSON値(yyjson_val、yyjson_mut_val)の寿命は、そのドキュメントと同じです。メモリはドキュメントが管理し、個別に解放することはできません。

詳細はAPI文書を参照してください。