{"id":27024086,"url":"https://github.com/habedi/bptree","last_synced_at":"2025-04-09T18:13:07.532Z","repository":{"id":286133880,"uuid":"960131876","full_name":"habedi/bptree","owner":"habedi","description":"A B+ tree implementation in C ","archived":false,"fork":false,"pushed_at":"2025-04-09T16:53:08.000Z","size":72,"stargazers_count":25,"open_issues_count":6,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T18:13:03.807Z","etag":null,"topics":["bplus-tree","btree","c","c-library","indexing","search-algorithm"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/habedi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-04-03T23:03:44.000Z","updated_at":"2025-04-08T20:55:41.000Z","dependencies_parsed_at":"2025-04-04T15:22:48.769Z","dependency_job_id":"26fe9a2a-fd73-4c1a-b3b5-383c77f27179","html_url":"https://github.com/habedi/bptree","commit_stats":null,"previous_names":["habedi/bptree"],"tags_count":0,"template":false,"template_full_name":"habedi/template-c-project","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/habedi%2Fbptree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/habedi%2Fbptree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/habedi%2Fbptree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/habedi%2Fbptree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/habedi","download_url":"https://codeload.github.com/habedi/bptree/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248085327,"owners_count":21045139,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bplus-tree","btree","c","c-library","indexing","search-algorithm"],"created_at":"2025-04-04T21:17:28.600Z","updated_at":"2025-04-09T18:13:07.527Z","avatar_url":"https://github.com/habedi.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cpicture\u003e\n    \u003cimg alt=\"B+ tree\" src=\"assets/bptree_v4.svg\" height=\"90%\" width=\"90%\"\u003e\n\u003c/picture\u003e\n\u003cbr\u003e\n\n\u003ch2\u003eBptree\u003c/h2\u003e\n\n[![Tests](https://img.shields.io/github/actions/workflow/status/habedi/bptree/tests.yml?label=tests\u0026style=flat\u0026labelColor=282c34\u0026logo=github)](https://github.com/habedi/bptree/actions/workflows/tests.yml)\n[![Lints](https://img.shields.io/github/actions/workflow/status/habedi/bptree/lints.yml?label=lints\u0026style=flat\u0026labelColor=282c34\u0026logo=github)](https://github.com/habedi/bptree/actions/workflows/lints.yml)\n[![Benchmarks](https://img.shields.io/github/actions/workflow/status/habedi/bptree/benches.yml?label=benches\u0026style=flat\u0026labelColor=282c34\u0026logo=github)](https://github.com/habedi/bptree/actions/workflows/benches.yml)\n[![Code Coverage](https://img.shields.io/codecov/c/github/habedi/bptree?label=coverage\u0026style=flat\u0026labelColor=282c34\u0026logo=codecov)](https://codecov.io/gh/habedi/bptree)\n[![CodeFactor](https://img.shields.io/codefactor/grade/github/habedi/bptree?label=code%20quality\u0026style=flat\u0026labelColor=282c34\u0026logo=codefactor)](https://www.codefactor.io/repository/github/habedi/bptree)\n[![License](https://img.shields.io/badge/license-MIT-007ec6?label=license\u0026style=flat\u0026labelColor=282c34\u0026logo=open-source-initiative)](https://github.com/habedi/bptree/blob/main/LICENSE)\n[![Release](https://img.shields.io/github/release/habedi/bptree.svg?label=release\u0026style=flat\u0026labelColor=282c34\u0026logo=github)](https://github.com/habedi/bptree/releases/latest)\n\nA B+ tree implementation in C\n\n\u003c/div\u003e\n\n---\n\nBptree is a single-header, generic [B+ tree](https://en.wikipedia.org/wiki/B%2B_tree) implementation written in pure C.\n\n### Features\n\n- Single-header C library (see [include/bptree.h](include/bptree.h))\n- Generic pointer storage with custom key comparator\n- Supports insertion, deletion, point, and range queries\n- Supports bulk loading from sorted items\n- In-order iteration using an iterator API\n- Custom memory allocator support via user-provided `malloc`, `free`, and `realloc` functions\n- Compatible with C99 and newer\n\n\u003e [!NOTE]\n\u003e Bptree is in early stage of development, so breaking (API) changes may happen.\n\u003e Additionally, it is not thoroughly tested and benchmarked yet, so it may have lots of bugs and performance issues.\n\u003e Currently, it is more for educational purposes to learn about B+ trees than for real-world usage.\n\n---\n\n### Getting Started\n\nTo use Bptree, download the [include/bptree.h](include/bptree.h) file and include it in your project like this:\n\n```c\n// Add these lines to one C source file before including bptree.h\n#define BPTREE_IMPLEMENTATION\n#include \"bptree.h\"\n```\n\n### Example\n\nTo run the example shown below, run the `make example` command.\n\n```c\n#define BPTREE_IMPLEMENTATION\n#include \u003cstdio.h\u003e\n\n#include \"bptree.h\"\n\n// Define a record structure for our sample data (a user record)\nstruct record {\n    int id;         // Unique identifier\n    char name[32];  // Name of the user\n};\n\n// Comparison function for records based on id\nint record_compare(const void *a, const void *b, const void *udata) {\n    (void)udata;  // Not used for this example\n    const struct record *rec1 = a;\n    const struct record *rec2 = b;\n    return (rec1-\u003eid \u003e rec2-\u003eid) - (rec1-\u003eid \u003c rec2-\u003eid);\n}\n\nint main() {\n    // Create a new B+ tree instance. We set max_keys to 4 for this example.\n    // Passing NULL for user_data, alloc_ctx, and custom allocators uses the defaults.\n    bptree *tree = bptree_new(4, record_compare, NULL, NULL, NULL, NULL, NULL, true);\n    if (!tree) {\n        printf(\"Failed to create the tree\\n\");\n        return 1;\n    }\n\n    // Insert some records into the tree\n    struct record rec1 = {1, \"A\"};\n    struct record rec2 = {2, \"B\"};\n    struct record rec3 = {3, \"C\"};\n    struct record rec4 = {4, \"D\"};\n    struct record rec5 = {5, \"E\"};\n    struct record rec6 = {6, \"F\"};\n    struct record rec7 = {7, \"G\"};\n    struct record rec8 = {8, \"H\"};\n    struct record rec9 = {9, \"I\"};\n\n    // Insert records into the tree (not sorted)\n    bptree_put(tree, \u0026rec1);\n    bptree_put(tree, \u0026rec2);\n    bptree_put(tree, \u0026rec3);\n\n    bptree_put(tree, \u0026rec6);\n    bptree_put(tree, \u0026rec7);\n    bptree_put(tree, \u0026rec8);\n    bptree_put(tree, \u0026rec9);\n\n    bptree_put(tree, \u0026rec4);\n    bptree_put(tree, \u0026rec5);\n    \n    // Try inserting a duplicate record\n    bptree_status dup_status = bptree_put(tree, \u0026rec3);\n    if (dup_status == BPTREE_DUPLICATE) {\n        printf(\"Duplicate insert for id=%d correctly rejected.\\n\", rec3.id);\n    }\n\n    // Retrieve a record by key (id)\n    const struct record key = {3, \"\"};\n    struct record *result = bptree_get(tree, \u0026key);\n    if (result) {\n        printf(\"Found record: id=%d, name=%s\\n\", result-\u003eid, result-\u003ename);\n    } else {\n        printf(\"Record with id=%d not found\\n\", key.id);\n    }\n\n    // Perform a range search: get records with id between 2 and 4 (including boundaries)\n    // Note that only the `id` field is relevant here since the comparator uses it.\n    int count = 0;\n    void **range_results =\n        bptree_get_range(tree, \u0026(struct record){2, \"\"}, \u0026(struct record){4, \"\"}, \u0026count);\n    if (range_results) {\n        printf(\"Range search results:\\n\");\n        for (int i = 0; i \u003c count; i++) {\n            struct record *r = range_results[i];\n            printf(\"  id=%d, name=%s\\n\", r-\u003eid, r-\u003ename);\n        }\n        // Free the results array returned by bptree_get_range.\n        // Pass 0 for the size as the default free ignores it.\n        tree-\u003efree_fn(range_results, 0, tree-\u003ealloc_ctx);\n    }\n\n    // Iterate through the whole tree using the iterator\n    printf(\"Iterating all records:\\n\");\n    bptree_iterator *iter = bptree_iterator_new(tree);\n    void *item;\n    while ((item = bptree_iterator_next(iter))) {\n        struct record *r = item;\n        printf(\"  id=%d, name=%s\\n\", r-\u003eid, r-\u003ename);\n    }\n    bptree_iterator_free(iter, tree-\u003efree_fn, tree-\u003ealloc_ctx);\n\n    // Remove a record\n    const bptree_status status = bptree_remove(tree, \u0026rec2);\n    if (status == BPTREE_OK) {\n        printf(\"Record with id=%d removed successfully.\\n\", rec2.id);\n    } else {\n        printf(\"Failed to remove record with id=%d.\\n\", rec2.id);\n    }\n\n    // Try to retrieve the removed record\n    result = bptree_get(tree, \u0026rec2);\n    if (result) {\n        printf(\"Found record: id=%d, name=%s\\n\", result-\u003eid, result-\u003ename);\n    } else {\n        printf(\"Record with id=%d not found (as expected)\\n\", rec2.id);\n    }\n\n    // Check the tree stats\n    const bptree_stats stats = bptree_get_stats(tree);\n    printf(\"Count: %d, Height: %d, Nodes: %d\\n\", stats.count, stats.height, stats.node_count);\n\n    // Free the tree\n    bptree_free(tree);\n\n    return 0;\n}\n```\n\n### Documentation\n\nBptree documentation can be generated using [Doxygen](https://www.doxygen.nl).\nTo generate the documentation,\nuse `make doc` command and then open the `doc/html/index.html` file in a web browser.\n\n#### API\n\n| Function / Type                                        | Description                                                                                                                                                                                                         |\n|--------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `bptree_new`                                           | Creates a new B+ tree. It takes max keys, a key comparator (must return negative/zero/positive similar to `strcmp`), optional user data, custom allocators, and a debug flag. Returns a pointer or NULL on failure. |\n| `bptree_free`                                          | Frees all nodes and internal structures. Does **not** free user-provided items.                                                                                                                                     |\n| `bptree_put`                                           | Inserts an item. Returns `BPTREE_DUPLICATE` if the key already exists.                                                                                                                                              |\n| `bptree_get`                                           | Retrieves an item by key. Returns the item pointer or NULL if not found.                                                                                                                                            |\n| `bptree_remove`                                        | Removes an item by key and rebalances the tree if needed. Returns a status code (`BPTREE_OK`, `BPTREE_NOT_FOUND`, etc.).                                                                                            |\n| `bptree_get_range`                                     | Returns an array of items between `start_key` and `end_key` (inclusive). Stores the number of results in a count variable. Must free the result array using `free_fn` (size can be 0).                              |\n| `bptree_bulk_load`                                     | Builds a tree from a sorted, deduplicated array of items. Much faster than inserting one by one.                                                                                                                    |\n| `bptree_iterator_new`                                  | Returns an iterator (`bptree_iterator *`) starting at the smallest key. Returns NULL if the tree is empty.                                                                                                          |\n| `bptree_iterator_next`                                 | Returns the next item in key order by walking linked leaf nodes. Returns NULL when iteration is complete.                                                                                                           |\n| `bptree_iterator_free`                                 | Frees the iterator. You must pass the `free_fn` and `alloc_ctx` used to allocate it.                                                                                                                                |\n| `bptree_get_stats`                                     | Returns a `bptree_stats` struct with total item count, tree height, and total node count.                                                                                                                           |\n| `bptree_iterator`                                      | Struct for maintaining state during in-order traversal. Contains current leaf and position.                                                                                                                         |\n| `bptree_stats`                                         | Struct returned by `bptree_get_stats`, includes `count`, `height`, and `node_count` fields.                                                                                                                         |\n| `bptree_malloc_t`, `bptree_free_t`, `bptree_realloc_t` | Function pointer types for custom allocators. See `bptree.h` for exact signatures. Used in `bptree_new` and `bptree_bulk_load`.                                                                                     |\n| `debug_enabled`                                        | Boolean flag in `bptree_new` that enables internal debug logging to stdout via `bptree_logger`.                                                                                                                     |\n\n#### Status Codes\n\nThe status codes are defined in the `bptree.h` header file as an enum:\n\n```c\ntypedef enum {\n    BPTREE_OK,               /* Operation performed successfully */\n    BPTREE_DUPLICATE,        /* Duplicate key found during insertion */\n    BPTREE_ALLOCATION_ERROR, /* Memory allocation error */\n    BPTREE_NOT_FOUND,        /* Key not found */\n    BPTREE_ERROR             /* General error */\n} bptree_status;\n```\n\n### Tests and Benchmarks\n\nCheck out [test/test_bptree.c](test/test_bptree.c) for more detailed usage examples and test cases,\nand [test/bench_bptree.c](test/bench_bptree.c) for performance benchmarks.\n\nTo run the tests and benchmarks, use the `make test` and `make bench` commands respectively.\n\nRun `make all` to run the tests, benchmarks, examples, and generate the documentation.\n\n---\n\n### Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to make a contribution.\n\n### License\n\nBptree is licensed under the MIT License ([LICENSE](LICENSE)).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhabedi%2Fbptree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhabedi%2Fbptree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhabedi%2Fbptree/lists"}