From 973b94a348af3e15b599f4d7d88494e463d5f16a Mon Sep 17 00:00:00 2001 From: GigabiteStudios Date: Wed, 17 Jun 2026 19:12:46 -0500 Subject: [PATCH] docs(readme): simplify project overview --- README.md | 273 ++---------------------------------------------------- 1 file changed, 10 insertions(+), 263 deletions(-) diff --git a/README.md b/README.md index 4d5fbf4..e8a800d 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,10 @@ # iKvxx -iKvxx is a modern C++17 binding for [iKv](https://dock-it.dev/iDENTITY-Technology/iKv). -It provides automatic resource management, exceptions, type-safe accessors, and a -compact `Value` API modeled after JsonCpp while preserving iKv text and binary format -compatibility. +Modern C++17 bindings for [iKv](https://dock-it.dev/iDENTITY-Technology/iKv), with RAII ownership and a JsonCpp-style `Value` API. -## What it does +For installation, the complete API reference, format details, binary layout, testing, and more examples, see the **[iKvxx Wiki](https://dock-it.dev/iDENTITY-Technology/iKvxx/wiki)**. -- Parse iKv text from strings or files -- Parse iKv binary data from memory or files -- Build object and array trees with a JsonCpp-style API -- Read and write both `iKv1` and `iKv2` -- Write the current `iKv2` format by default -- Manage the underlying C tree automatically with RAII -- Report parse, type, bounds, allocation, and I/O failures with exceptions -- Provide a reusable `ikvxx::ikvxx` CMake target and installable package - -## Syntax preview +## Simple syntax ```ikv ikv2 "player_save" @@ -24,7 +12,7 @@ ikv2 "player_save" "title" "iKvxx demo" "version" 2 "player" { - "name" "jondoe" + "name" "Ada" "alive" true "speed" 12.5 } @@ -48,7 +36,7 @@ int main() root["version"] = 2; auto player = root.makeObject("player"); - player["name"] = "jondoe"; + player["name"] = "Ada"; player["alive"] = true; player["speed"] = 12.5; @@ -58,255 +46,14 @@ int main() inventory.append("map"); root.write("player_save.ikv"); + + auto loaded = ikv::Value::load("player_save.ikv"); + return loaded["player"]["alive"].asBool() ? 0 : 1; } ``` -The root and all child handles release their underlying iKv tree automatically. No -manual `ikv_free` call is required. - -## Reading values - -Use `load` for text files and the familiar `operator[]` syntax for object and array -access: - -```cpp -#include -#include - -int main() -{ - auto root = ikv::Value::load("player_save.ikv"); - - std::cout << root["title"].asString() << '\n'; - std::cout << root["version"].asInt() << '\n'; - std::cout << root["player"]["speed"].asDouble() << '\n'; - - auto inventory = root["inventory"]; - for (ikv::Value::ArrayIndex i = 0; i < inventory.size(); ++i) - std::cout << inventory[i].asString() << '\n'; -} -``` - -Missing object members produce a null `Value`. Invalid conversions and out-of-range -array indexes throw a standard exception: - -```cpp -if (!root.isMember("difficulty")) - root["difficulty"] = "normal"; - -if (root["optional"].isNull()) - root["optional"] = false; - -try -{ - int value = root["title"].asInt(); -} -catch (const ikv::Error& error) -{ - // "title" is a string, not an integer. -} -``` - -## Parsing text - -`Value::parse` auto-detects `iKv1` and `iKv2` input: - -```cpp -const std::string text = R"( -ikv2 "settings" -{ - "fullscreen" true - "width" 1920 - "height" 1080 -} -)"; - -auto settings = ikv::Value::parse(text); -bool fullscreen = settings["fullscreen"].asBool(); -``` - -## Arrays - -Arrays may be untyped or restricted to one iKv value type. Typed arrays reject values -of the wrong type: - -```cpp -ikv::Value root; - -auto scores = root.makeArray("scores", ikv::intValue); -scores.append(10); -scores.append(25); -scores.append(100); - -auto mixed = root.makeArray("mixed"); -mixed.append("ready"); -mixed.append(42); -mixed.append(true); - -auto players = root.makeArray("players", ikv::objectValue); -auto first = players.appendObject(); -first["name"] = "Ada"; -first["score"] = 100; -``` - -## Binary data - -Binary iKv can be written to a file or encoded directly into a byte vector: - -```cpp -ikv::Value root; -root["answer"] = 42; - -root.writeBinary("data.ikvb"); -auto from_file = ikv::Value::loadBinary("data.ikvb"); - -std::vector bytes = root.toBinary(); -auto from_memory = ikv::Value::fromBinary(bytes.data(), bytes.size()); -``` - -Pass an explicit version when compatibility with older data is required: - -```cpp -root.write("legacy.ikv", ikv::Version::v1); -root.writeBinary("legacy.ikvb", ikv::Version::v1); -auto legacy_bytes = root.toBinary(ikv::Version::v1); -``` - -## Refreshing a tree - -An existing root can be updated in place from a text or binary file. Other `Value` -handles that share that root observe the refreshed data: - -```cpp -auto settings = ikv::Value::load("settings.ikv"); -auto shared = settings; - -settings.refresh("updated-settings.ikv"); -// shared now refers to the refreshed tree as well. -``` - -`refresh` is only valid on a mutable root value. If refresh fails, the existing tree -is preserved. - -## Build - -Clone with the iKv submodule and build with CMake: - -```sh -git clone --recurse-submodules https://dock-it.dev/iDENTITY-Technology/iKvxx.git -cd iKvxx -cmake -S . -B build -cmake --build build -``` - -If the repository was cloned without submodules: - -```sh -git submodule update --init --recursive -``` - -This produces the reusable static library targets: - -- `ikvxx` -- `ikvxx::ikvxx` for CMake consumers - -### CMake consumer usage - -When iKvxx is included directly in another source tree: - -```cmake -add_subdirectory(path/to/iKvxx) -target_link_libraries(your_target PRIVATE ikvxx::ikvxx) -``` - -The library can also be installed and consumed with `find_package`: - -```sh -cmake --install build --prefix /path/to/ikvxx-install -``` - -```cmake -find_package(ikvxx 0.1 REQUIRED CONFIG) -target_link_libraries(your_target PRIVATE ikvxx::ikvxx) -``` - -Point `CMAKE_PREFIX_PATH` at the selected installation prefix when it is not in a -standard system location. - -## Tests - -Build and run the binding tests with CTest: - -```sh -cmake -S . -B build -DIKVXX_BUILD_TESTS=ON -cmake --build build -ctest --test-dir build --output-on-failure -``` - -CTest runs every iKvxx test group separately and also includes the complete upstream -iKv suite. The binding tests cover construction, every value type, object and array -access, assignment and append overloads, conversion failures, bounds checks, text and -binary I/O, format versions, refresh behavior, and shared ownership. The Gitea Actions -workflow follows iKv's Ubuntu build-and-test structure, with one CMake build job and -one job that runs the complete test suite. - -On Windows, the complete configure, build, and test sequence can be run with: - -```bat -tests\run.bat -tests\run.bat Debug -``` - -## Project layout - -- `include/ikvxx/ikvxx.hpp`: public C++ API -- `src/value.cpp`: C++ binding implementation -- `tests/value_tests.cpp`: unit and integration tests -- `third_party/iKv`: pinned iKv Git submodule -- `cmake/ikvxxConfig.cmake.in`: installed CMake package configuration -- `.gitea/workflows/bindings.yml`: Ubuntu compiler and build matrix - -## Format behavior - -- Generic parse APIs auto-detect `iKv1` and `iKv2` -- Generic write APIs default to `iKv2` -- Text and binary files remain compatible with the underlying iKv C library -- Explicit `ikv::Version::v1` and `ikv::Version::v2` output is supported -- `iKv2` binary input retains iKv's indexed, lazy root lookup behavior - -## Public API - -The public interface is declared in -[`include/ikvxx/ikvxx.hpp`](./include/ikvxx/ikvxx.hpp). Key areas include: - -- `ikv::Value` construction and automatic lifetime management -- JsonCpp-style object lookup with `operator[]` -- Array indexing and append operations -- Runtime type inspection with `isString`, `isInt`, `isObject`, and related methods -- Typed scalar access with `asString`, `asInt`, `asInt64`, `asDouble`, and `asBool` -- Text parsing, loading, writing, and in-place refresh -- Binary memory and file I/O -- Explicit format-version selection - -## API constraints - -iKvxx intentionally exposes errors where the underlying iKv model cannot safely -provide JsonCpp behavior: - -- Roots must be objects or arrays; scalar roots are not supported by iKv -- Arrays of arrays are not supported by the current iKv C API -- Existing array elements cannot be replaced in place -- Copied `Value` handles share ownership of the same tree -- Structural assignment between two `Value` objects is disabled because the public C - API cannot clone arbitrary subtrees -- A child handle must not be retained across replacement of that child or a root - refresh; acquire the child again after modifying the structure - ## License -This repository ships with the license text in [`LICENSE`](./LICENSE): +This project is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International license](./LICENSE). -- Creative Commons Attribution-ShareAlike 4.0 International (`CC BY-SA 4.0`) - -The iKv submodule includes its own license file at -[`third_party/iKv/LICENSE`](./third_party/iKv/LICENSE). +The iKv submodule includes its own [license file](./third_party/iKv/LICENSE).