docs(readme): rewrite project overview and usage
This commit is contained in:
140
README.md
140
README.md
@@ -1,28 +1,124 @@
|
||||
# iKv
|
||||
|
||||
Standalone iKv C library.
|
||||
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.
|
||||
|
||||
Build:
|
||||
- CMake: `cmake -S . -B build && cmake --build build`
|
||||
- Scripted local build on Linux runners: `./demo/build.sh`
|
||||
## What it does
|
||||
|
||||
Layout:
|
||||
- `include/ikv.h`: public API only.
|
||||
- `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 node layout and loader interface.
|
||||
- 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`
|
||||
|
||||
Behavior:
|
||||
- The generic parse APIs auto-detect iKv1 vs iKv2 and choose the correct loader.
|
||||
- The generic write APIs emit the current format version, which is `iKv2`.
|
||||
- Public callers do not depend on loader-specific headers or internal structs.
|
||||
- `iKv2` binary files now use an indexed root layout with a key table and payload offsets.
|
||||
- Parsing an `iKv2` binary file reads the root index first and loads individual top-level values on demand.
|
||||
- `iKv1` binary files still use the legacy full-tree format for compatibility.
|
||||
## Syntax preview
|
||||
|
||||
Adding a new version:
|
||||
1. Add `src/loaders/ikv3.h` and `src/loaders/ikv3.c` exporting an `ikv_loader_t`.
|
||||
2. Implement that loader using the shared internal helpers or custom logic.
|
||||
3. Register the loader in `src/ikv.c`.
|
||||
4. Add the new version constant to `include/ikv.h` if it is part of the public API.
|
||||
```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 used in CI:
|
||||
|
||||
```sh
|
||||
./demo/build.sh
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
Reference in New Issue
Block a user