yyjson.c


Overview

`yyjson.c` is the primary implementation file of the **yyjson** library, a high-performance, memory-efficient JSON parser and writer implemented in C. This file contains the core functionalities for reading (parsing), writing (serializing), and manipulating JSON data with support for:

The implementation emphasizes speed and correctness, using techniques like finite state machines (FSM) with `goto` statements, branch prediction hints, manual memory alignment, and precomputed lookup tables for numeric computations.


Detailed Explanations

Memory Allocators

Default Allocator (YYJSON_DEFAULT_ALC)

A wrapper over the standard `malloc`, `realloc`, and `free` functions, used by default when no custom allocator is provided.

Null Allocator (YYJSON_NULL_ALC)

A placeholder allocator where all allocation functions return `NULL` or do nothing, ensuring no actual memory operations occur.

Pool Allocator

Manages a fixed-size buffer split into chunks (`pool_chunk`) linked in a free list.

Dynamic Allocator

Allocates variable-sized chunks on demand, maintains freelist for reuse.


JSON Document and Value Management


JSON Reader (Parser)

Entry Points

Parsing Strategy

Number Parsing

String Parsing


JSON Writer (Serializer)


JSON Pointer API (RFC 6901)


JSON Patch API (RFC 6902)


JSON Merge Patch API (RFC 7386)


Utilities and Constants


Important Implementation Details and Algorithms


Interaction with Other Parts of the System or Application


Usage Examples

Parsing JSON from a buffer

yyjson_read_err err = {0};
yyjson_doc *doc = yyjson_read_opts(json_data, json_len, NULL, &err);
if (!doc) {
    printf("Failed to parse JSON at position %zu: %s\n", err.pos, err.msg);
} else {
    yyjson_val *root = yyjson_doc_get_root(doc);
    // Use the root value...
    yyjson_doc_free(doc);
}

Writing a JSON number

u8 buffer[32];
yyjson_val val;
val.tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
val.uni.f64 = 3.14159;
u8 *end = write_number(buffer, &val, YYJSON_WRITE_PRETTY);
printf("%.*s\n", (int)(end - buffer), buffer);

Using JSON Pointer to get a value

yyjson_val *val = unsafe_yyjson_ptr_getx(root, "/foo/bar", strlen("/foo/bar"), NULL);
if (val) {
    // Use val
}

Applying a JSON Patch

yyjson_patch_err err = {0};
yyjson_mut_val *patched = yyjson_patch(doc, orig, patch, &err);
if (!patched) {
    printf("Patch failed: %s\n", err.msg);
}

Visual Diagram: Core Function and Module Flow in yyjson.c

flowchart TD

    subgraph Allocators
        DefaultAlloc["default_malloc/realloc/free"]
        PoolAlloc["pool_malloc/realloc/free"]
        DynAlloc["dyn_malloc/realloc/free"]
    end

    subgraph JSON_Parsing
        ReadOpts["yyjson_read_opts()"]
        ReadRootMinify["read_root_minify()"]
        ReadRootPretty["read_root_pretty()"]
        ReadRootSingle["read_root_single()"]
        ReadNumber["read_number()"]
        ReadString["read_string()"]
        SkipSpaces["skip_spaces_and_comments()"]
    end

    subgraph JSON_Writing
        WriteNumber["write_number()"]
        WriteF64Raw["write_f64_raw()"]
        WriteString["write_string()"]
    end

    subgraph JSON_Utilities
        JsonPtrGet["unsafe_yyjson_ptr_getx()"]
        JsonPtrMutGet["unsafe_yyjson_mut_ptr_getx()"]
        JsonPatch["yyjson_patch()"]
        JsonMergePatch["yyjson_merge_patch()"]
        ValCopy["yyjson_val_mut_copy()"]
        MutValCopy["yyjson_mut_val_mut_copy()"]
        Equals["unsafe_yyjson_equals() / unsafe_yyjson_mut_equals()"]
    end

    DefaultAlloc --> ReadOpts
    PoolAlloc --> ReadOpts
    DynAlloc --> ReadOpts

    ReadOpts --> SkipSpaces
    SkipSpaces -->|Determines format| ReadRootMinify
    SkipSpaces --> ReadRootPretty
    SkipSpaces --> ReadRootSingle

    ReadRootMinify --> ReadNumber
    ReadRootPretty --> ReadNumber
    ReadRootSingle --> ReadNumber

    ReadRootMinify --> ReadString
    ReadRootPretty --> ReadString
    ReadRootSingle --> ReadString

    ReadNumber --- ValCopy
    ReadString --- ValCopy

    JSON_Parsing --> JSON_Utilities

    JSON_Utilities --> JsonPtrGet
    JSON_Utilities --> JsonPtrMutGet
    JSON_Utilities --> JsonPatch
    JSON_Utilities --> JsonMergePatch
    JSON_Utilities --> Equals

    JSON_Writing --> WriteNumber
    WriteNumber --> WriteF64Raw
    JSON_Writing --> WriteString

Summary

The `yyjson.c` file embodies the core implementation of the **yyjson** library, providing a highly optimized C-based JSON parsing and writing engine. It manages memory with flexible allocators, parses JSON efficiently using FSM and advanced numeric algorithms, and supports extended JSON utilities such as JSON Pointer and Patch. This file is critical for applications requiring blazing-fast, standards-compliant JSON processing with custom memory management and advanced features.