![iKv banner](.gitea/images/iKv_banner.png) [![Build](https://dock-it.dev/iDENTITY-Technology/iKv/actions/workflows/build.yml/badge.svg?branch=main)](https://dock-it.dev/iDENTITY-Technology/iKv/actions?workflow=build.yml) [![Latest release](https://img.shields.io/gitea/v/release/iDENTITY-Technology/iKv?gitea_url=https%3A%2F%2Fdock-it.dev&label=release)](https://dock-it.dev/iDENTITY-Technology/iKv/releases/latest) [![Language](https://img.shields.io/badge/C-C99-00599C?logo=c)](https://en.cppreference.com/w/c/language) [![License](https://img.shields.io/badge/license-CC_BY--SA_4.0-lightgrey.svg)](https://dock-it.dev/iDENTITY-Technology/iKv/src/branch/main/LICENSE) iKv is a small standalone C library for reading, writing, and building iKv data trees. It supports both text and binary formats, keeps the public API in a single header, and handles multiple on-disk versions behind one interface. ## Quick start Build with CMake: ```sh cmake -S . -B build cmake --build build ``` Link it from another CMake project: ```cmake add_subdirectory(path/to/iKv) target_link_libraries(your_target PRIVATE ikv::ikv) ``` ## What it does - Parse iKv text from strings or files - Parse iKv binary blobs from memory or files - Build object and array trees in memory - Write text or binary output - Auto-detect `iKv1` vs `iKv2` for generic parse calls - Write the current format version by default, which is `iKv2` ## Syntax preview ```ikv ikv2 "player_save" { "title" "iKv demo" "version" 2 "player" { "name" "jondoe" "alive" true "speed" 12.5 } "inventory" [ "wrench" "battery" "map" ] } ``` ## Library example ```c #include "ikv.h" ikv_node_t *root = ikv_create_object("demo"); ikv_node_t *player = ikv_object_add_object(root, "player"); ikv_object_set_string(root, "title", "iKv demo"); ikv_object_set_int(root, "version", 2); ikv_object_set_string(player, "name", "jondoe"); ikv_object_set_bool(player, "alive", true); ikv_write_file("demo_output.ikv", root); ikv_free(root); ``` ## Build ### CMake ```sh cmake -S . -B build cmake --build build ``` This produces the reusable static library target: - `ikv` - `ikv::ikv` for CMake consumers Example consumer usage: ```cmake add_subdirectory(path/to/iKv) target_link_libraries(your_target PRIVATE ikv::ikv) ``` ### Script build For the repo-local non-CMake build path: ```sh ./demo/build.sh ``` On Windows: ```bat demo\build.bat ``` ## Project layout - `include/ikv.h`: public API - `src/ikv.c`: shared implementation and loader dispatch - `src/loaders/ikv1.c`: iKv1 loader - `src/loaders/ikv2.c`: iKv2 loader - `src/internal/ikv_internal.h`: private internals and loader interface - `demo/main.c`: small usage example - `demo/unit_test.c`: unit tests ## Format behavior - Generic parse APIs auto-detect `iKv1` and `iKv2` - Generic write APIs default to `iKv2` - Public callers do not need loader-specific headers - `iKv2` binary files use an indexed root layout with key tables and payload offsets - `iKv1` binary files remain supported for compatibility ## Public API The public interface is declared in [`include/ikv.h`](./include/ikv.h). Key areas include: - node creation and cleanup - object and array mutation - scalar accessors - text parse/write APIs - binary parse/write APIs - explicit versioned APIs when auto-detection is not desired ## License This repository currently ships with the license text in [`LICENSE`](./LICENSE): - Creative Commons Attribution-ShareAlike 4.0 International (`CC BY-SA 4.0`) ## Extending the format To add a new format version: 1. Add `src/loaders/ikv3.h` and `src/loaders/ikv3.c` exporting an `ikv_loader_t` 2. Implement the loader 3. Register it in `src/ikv.c` 4. Add a public version constant to `include/ikv.h` if needed