{"id":25117832,"url":"https://github.com/wye-sh/aport","last_synced_at":"2025-10-26T20:50:48.606Z","repository":{"id":275891319,"uuid":"927504187","full_name":"wye-sh/aport","owner":"wye-sh","description":"A Proximate Optimistic Radix Tree","archived":false,"fork":false,"pushed_at":"2025-02-26T18:03:08.000Z","size":41,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-26T19:19:35.650Z","etag":null,"topics":["cpp","cpp20","radix-tree"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wye-sh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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-02-05T04:10:25.000Z","updated_at":"2025-02-26T18:03:11.000Z","dependencies_parsed_at":"2025-02-05T06:19:05.540Z","dependency_job_id":"68131028-98ee-4a64-b141-19a404521bd0","html_url":"https://github.com/wye-sh/aport","commit_stats":null,"previous_names":["wye-sh/aport"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wye-sh%2Faport","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wye-sh%2Faport/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wye-sh%2Faport/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wye-sh%2Faport/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wye-sh","download_url":"https://codeload.github.com/wye-sh/aport/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246811316,"owners_count":20837753,"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":["cpp","cpp20","radix-tree"],"created_at":"2025-02-08T03:25:54.449Z","updated_at":"2025-10-26T20:50:48.587Z","avatar_url":"https://github.com/wye-sh.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# APORT\r\n\r\nAPORT (A Proximate Optimistic Radix Tree) is a high-performance variant of the\r\nradix tree written in C++ that employs an optimistic retrieval strategy: while\r\nstandard operations (insertion, deletion, and inclusion checks) work exactly\r\nlike a radix tree, retrieval only verifies characters at disambiguation points,\r\nsignificantly improving lookup speed at the expense of accuracy. This makes it\r\nideal for performance-critical applications where keys share long common\r\nprefixes and some loss in accuracy is acceptable.\r\n\r\n## Table of Contents\r\n- [How It Works](#how-it-works)\r\n- [Installation](#installation)\r\n  - [Options](#options)\r\n- [Quick Start](#quick-start)\r\n- [Documentation](#documentation)\r\n\r\n## How It Works\r\n\r\nFor example, if we have an entry in our tree `\"arnold\" → 3`, the only\r\ndisambiguation point is at `'a'`. Assuming no other entries exist in the tree,\r\nlooking up \"astrid\" will retrieve a reference to our value `3`, because the\r\nonly disambiguation point matched and the keys share the same length. If we\r\nthen insert another entry `\"andrew\" → 4`, we now have two disambiguation\r\npoints: one at `'a'` and another furcating `'r'` and `'n'`. Now looking up\r\n`\"astrid\"` would fail (since `'s'` matches neither `'r'` or `'n'`), but lookups\r\nlike `\"arbold\"` or `\"answer\"` would retrieve a reference to `'3'` and `'4'`\r\nrespectively.\r\n\r\nThis behaviour emphasizes the importance of using correct keys, as the addition\r\nof new entries can introduce new disambiguation points, potentially changing\r\nwhich keys match against existing entries.\r\n\r\n## Installation\r\n\r\nIf you're using CMake, add the following to your `CMakeLists.txt`:\r\n```cmake\r\ninclude(FetchContent)\r\nFetchContent_Declare(\r\n  aport\r\n  GIT_REPOSITORY https://github.com/wye-sh/aport\r\n  GIT_TAG v1.2.0 # (latest version)\r\n)\r\nFetchContent_MakeAvailable(aport)\r\n\r\n# Link against aport in your project\r\ntarget_link_libraries(\u003cyour_target\u003e PRIVATE aport)\r\n```\r\n\r\nOtherwise, you can clone the repository and include the headers manually in\r\nyour project.\r\n\r\n### Options\r\n\r\nYou have the opportunity for further customization before your call to\r\n`FetchContent_MakeAvailable()`.\r\n```cmake\r\n# If on, APORT will behave exactly like a normal radix tree\r\nset(APORT_RADIX_MODE \u003cOFF|ON\u003e) # Default: OFF\r\n```\r\n\r\n## Quick Start\r\n\r\nTo get started:\r\n\r\n```cpp\r\n// The value can be any type, not just `int`\r\naport::tree\u003cint\u003e Tree;\r\n\r\n// Insert multiple entries with similar disambiguation points\r\nTree.insert(\"arnold\", 12);\r\nTree.insert(\"arbold\", 13);\r\nTree.insert(\"arcold\", 14);\r\nTree.insert(\"arwold\", 15);\r\n\r\ntry {\r\n  // get() is the only method that uses the optimized lookup\r\n  int \u0026Arbold = Tree.get(\"arbold\");\r\n} catch (aport::no_such_key \u0026Exception) {\r\n  printf(\"No such key.\\n\");\r\n}\r\n\r\n// Remove entries\r\nTree.erase(\"arbold\");\r\nTree.erase(\"arwold\");\r\n\r\n// Range-based for loop; `Key` and `Value` are references\r\nfor (auto [ Key, Value ] : Tree)\r\nprintf(\"[%s]: %d\\n\", Key.c_str(), Value);\r\n// Will print:\r\n// $ [arnold]: 12\r\n// $ [arcold]: 14\r\n\r\n// Delete the rest of the entries\r\nfor (auto I = Tree.begin(); I != Tree.end(); ++ I)\r\n  I = Tree.erase(I);\r\n```\r\n\r\n## Documentation\r\n- namespace aport\r\n  - [struct aport::no_such_key](#struct-aportno_such_key)\r\n  - [struct aport::tree](#struct-aporttree)\r\n    - [struct tree::iterator](#struct-treeiterator)\r\n    - [tree::insert()](#treeinsert)\r\n    - [tree::erase()](#treeerase)\r\n    - [tree::erase()](#treeerase-1)\r\n    - [tree::contains()](#treecontains)\r\n    - [tree::get()](#treeget)\r\n    - [tree::get()](#treeget-1)\r\n    - [tree::operator\\[\\]()](#treeoperator)\r\n    - [tree::query()](#treequery)\r\n    - [tree::clear()](#treeclear)\r\n    - [tree::length()](#treelength)\r\n    - [tree::print()](#treeprint)\r\n    - [tree::begin()](#treebegin)\r\n    - [tree::end()](#treeend)\r\n\r\n##\r\n\r\n### struct aport::no_such_key\r\n```cpp\r\nstruct no_such_key;\r\n```\r\nWhen thrown, it denotes that the key that was attempted to be retrieved does not exist in the structure.\r\n\r\n##\r\n\r\n### struct aport::tree\r\n`movable`\r\n```cpp\r\ntemplate\u003ctypename T\u003e\r\nstruct tree;\r\n```\r\nThe APORT tree container, into which data can be inserted or erased, looked up or checked for inclusion.\r\n\r\n#### Template Parameters\r\n- `T`: Specifies the type stored in the tree.\r\n\r\n##\r\n\r\n### struct tree::iterator\r\n```cpp\r\nstruct iterator;\r\n```\r\nForward iterator.\r\n\r\n##\r\n\r\n### tree::insert()\r\n```cpp\r\nvoid insert (string Key, T Value);\r\n```\r\nInserts an object of type `T` into the tree at `Key`.\r\n\r\n#### Parameters\r\n- `Key`: Location the inserted `Value` should be retrievable per.\r\n- `Value`: Value to be inserted per `Key`.\r\n\r\n##\r\n\r\n### tree::erase()\r\n```cpp\r\nvoid erase (string Key);\r\n```\r\nErases the entry at location `Key`.\r\n\r\n#### Parameters\r\n- `Key`: Location at which an entry should be deleted from the tree.\r\n\r\n##\r\n\r\n### tree::erase()\r\n```cpp\r\niterator erase (iterator Iterator);\r\n```\r\nErases an element using an iterator `Iterator`. It is undefined behaviour to call this using an iterator that does not point to an element.\r\n\r\n#### Parameters\r\n- `Iterator`: Is an iterator to the element you want to delete.\r\n\r\n#### Returns\r\nAn iterator to the element after the one that was erased.\r\n\r\n##\r\n\r\n### tree::contains()\r\n```cpp\r\nbool contains (string Key);\r\n```\r\nChecks if tree contains an entry whose key is `Key`.\r\n\r\n#### Parameters\r\n- `Key`: Key to check for to see if it is contained by the tree.\r\n\r\n#### Returns\r\n`true` if entry per `Key` exists in the tree, and `false` otherwise.\r\n\r\n##\r\n\r\n### tree::get()\r\n`throws`\r\n```cpp\r\nT \u0026get (const string \u0026Key, bool PermitUnterminated = false);\r\n```\r\nRetrieve data of type `T` from tree node at `Key` if it exists.\r\n\r\n#### Parameters\r\n- `Key`: Location to retrieve data from.\r\n- `PermitUnterminated`: If `true`, will return a node even if the `Key` was not fully consumed.\r\n\r\n#### Returns\r\nData of type `T` at location `Key` (if it exists), otherwise if no data or key exists, throws `no_such_key` exception.\r\n\r\n##\r\n\r\n### tree::get()\r\n`throws`\r\n```cpp\r\nT \u0026get (char *Key, size_t KeyLength, bool PermitUnterminated = false);\r\n```\r\nRetrieve data of type `T` from tree node at `Key` if it exists.\r\n\r\n#### Parameters\r\n- `Key`: Location to retrieve data from.\r\n- `KeyLength`: Length of the key.\r\n- `PermitUnterminated`: If `true`, will return a node even if the `Key` was not fully consumed.\r\n\r\n#### Returns\r\nData of type `T` at location `Key` (if it exists), otherwise if no data or key exists, throws `no_such_key` exception.\r\n\r\n##\r\n\r\n### tree::operator\\[\\]()\r\n```cpp\r\nT \u0026operator[] (string Key);\r\n```\r\nRetrieve the data of type `T` from tree node at `Key` if it exists, otherwise creates it, returning the data of type `T` from the newly inserted node.\r\n\r\n#### Parameters\r\n- `Key`: Location to retrieve data from (or insert data into).\r\n\r\n#### Returns\r\nData of type `T` at location `Key` (if it exists), otherwise creates it and returns the newly created data.\r\n\r\n##\r\n\r\n### tree::query()\r\n```cpp\r\nvector\u003cT *\u003e query (string String);\r\n```\r\nRetrieves all entries that match against query string `String`, supporting wildcard expressions using \"\\*\". For instance, if two entries are stored in the tree \"astrid\" and \"arnold\", the query string \"a\\*d\" would retrieve both entries.\r\n\r\n#### Parameters\r\n- `String`: Query string that is used to determine what is returned.\r\n\r\n#### Returns\r\nA vector containing all entries that matched against query string `String`.\r\n\r\n##\r\n\r\n### tree::clear()\r\n```cpp\r\nvoid clear ();\r\n```\r\nClears all the content inside the tree.\r\n\r\n##\r\n\r\n### tree::length()\r\n```cpp\r\nsize_t length ();\r\n```\r\nReturns the number of entries stored inside the tree.\r\n\r\n#### Returns\r\nNumber of entries stored inside the tree.\r\n\r\n##\r\n\r\n### tree::print()\r\n```cpp\r\nvoid print ();\r\n```\r\nOutputs a visual representation of the tree. Could be useful for someone outside testing, so rather than making it local to the root test file, it has been provided here directly.\r\n\r\n##\r\n\r\n### tree::begin()\r\n```cpp\r\niterator begin ();\r\n```\r\nBegin iterator.\r\n\r\n##\r\n\r\n### tree::end()\r\n```cpp\r\niterator end ();\r\n```\r\nEnd iterator.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwye-sh%2Faport","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwye-sh%2Faport","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwye-sh%2Faport/lists"}