{"id":18840214,"url":"https://github.com/maxim2266/smap","last_synced_at":"2025-07-06T03:06:56.120Z","repository":{"id":151956891,"uuid":"359793090","full_name":"maxim2266/smap","owner":"maxim2266","description":"smap: a hash table for C language.","archived":false,"fork":false,"pushed_at":"2024-10-17T17:34:39.000Z","size":97,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T20:02:10.414Z","etag":null,"topics":["c","hashmap","hashtable"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maxim2266.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":"2021-04-20T11:37:24.000Z","updated_at":"2024-10-27T12:22:35.000Z","dependencies_parsed_at":"2024-10-21T15:19:45.261Z","dependency_job_id":null,"html_url":"https://github.com/maxim2266/smap","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/maxim2266/smap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxim2266%2Fsmap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxim2266%2Fsmap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxim2266%2Fsmap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxim2266%2Fsmap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxim2266","download_url":"https://codeload.github.com/maxim2266/smap/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxim2266%2Fsmap/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263841615,"owners_count":23518488,"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":["c","hashmap","hashtable"],"created_at":"2024-11-08T02:46:46.952Z","updated_at":"2025-07-06T03:06:56.098Z","avatar_url":"https://github.com/maxim2266.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# smap: a hash table for C language.\n\n[![License: BSD 3 Clause](https://img.shields.io/badge/License-BSD_3--Clause-yellow.svg)](https://opensource.org/licenses/BSD-3-Clause)\n\n### About\nThe hash table maps keys (byte arrays) to `void*` pointers.\n\n_Main features:_\n* Simple and minimalist API;\n* Good [performance](bench64.md) with typical compiler settings and without tuning for a particular CPU model;\n* Support for both 32- and 64-bit platforms;\n\n### Installation\n```bash\ngit clone --recurse-submodules 'https://github.com/maxim2266/smap'\ncd smap\nmake   # or 'make test' to run tests as well\n```\n\nAfter that just `#include` the file `smap.h` into your source code, and link with `libsmap.a`.\nExtra compiler options can be given to `make`, for example:\n\n```bash\nmake 'CFLAGS=-flto'\n```\n\nIt is usually convenient to include this project as a `git` submodule.\n\n### Code Example\n```c\n// declare a map object and initialise it\nsmap map = smap_empty;\n\n// insert a new key (or replace the existing one); all values in the map have\n// type void*, and the function below returns a pointer to the location\n// of the value (i.e., void**), so adding a key and a value can be done like\nint key = ...\n*smap_add(\u0026map, \u0026key, sizeof(key)) = pointer_to_object_of_type_T;\n\n// check if the key exists\nassert(smap_get(\u0026map, \u0026key, sizeof(key));\n\n// retrieve address of the value added above\nT** pp = (T**)smap_get(\u0026map, \u0026key, sizeof(key));\n\nassert(pp \u0026\u0026 *pp == pointer_to_object_of_type_T);\n// and the value can also be replaced: *pp = some_other_pointer;\n\n// or all in one line, because the key exists\nassert(*smap_get(\u0026map, \u0026key, sizeof(key)) == pointer_to_object_of_type_T);\n\n// delete the key\nT* value = smap_del(\u0026map, \u0026key, sizeof(key));\n\nassert(value == pointer_to_object_of_type_T);\nfree(value);\n\n// or all in one line, because the key exists\nfree(smap_del(\u0026map, smap_lit(\"some key\")));\n\n// clear the map, with all values passed to free() function\nsmap_release(\u0026map, free);\n```\nIn this example all checks for memory allocation failures are omitted for brevity.\n\n### Implementation\nThis is essentially an implementation of the open addressing scheme with linear probing,\nlike described, for example, [here](https://en.wikipedia.org/wiki/Open_addressing), and\n[wyhash](https://github.com/wangyi-fudan/wyhash) is used as the hash function.\n\n### API\n\n`typedef struct { ... } smap;`\u003cbr\u003e\nOpaque type of the hash map. Should not be accessed or modified other than via the provided API.\nEach new instance of the map _must_ be initialised with `smap_empty` value.\n\n`smap* smap_clear(smap* const map, void (*free_value)(void*))`\u003cbr\u003e\nReleases resources allocated for the map. The map object itself is reset to empty state and can be\nreused. The `free_value` callback function (if not NULL) is called once per each value in the map\nand is expected to deallocate resources associated with the value. The return value is a copy\nof the first parameter, only to simplify deallocation when the map itself is on the heap, like\n`free(smap_clear(\u0026map, free))`. The function _must_ always be called at the end of `smap` object\nlifetime.\n\n`int smap_resize(smap* const map, size_t n)`\u003cbr\u003e\nResizes the map to accommodate for the given number of keys, or the number of keys currently in\nthe map, whichever is greater. Returns 0 on success, or a non-zero value on memory allocation failure.\n\n`void** smap_get(const smap* const map, const void* key, size_t len)`\u003cbr\u003e\nRetrieves the address of the value associated with the given key. Returns NULL if the\nkey is not found. The returned address is valid for as long as the given key is in the map,\nand the value at that address can be modified.\n\n`void** smap_add(smap* const map, const void* key, size_t len)`\u003cbr\u003e\nRetrieves the address of the value associated with the given key, inserting the key if not already\npresent. The map will grow as necessary. Initial value of a newly inserted key is NULL. The returned\naddress is valid for as long as the given key is in the map. Returns NULL on memory allocation failure.\n\n`void* smap_del(smap* const map, const void* key, size_t len)`\u003cbr\u003e\nRemoves the given key from the map. Returns the value associated with the key, or NULL if the\nkey is not found. _Note_: NULL return value does not necessarily mean the key was not in the map,\nbecause the value itself may be NULL.\n\n`uint32_t smap_cap(const smap* const map)`\u003cbr\u003e\nReturns the current capacity of the map.\n\n`uint32_t smap_size(const smap* const map)`\u003cbr\u003e\nReturns the number of keys currently in the map.\n\n`int smap_scan(smap* const map, const smap_scan_func fn, void* const param)`\u003cbr\u003e\nIterate the map calling the given callback function on each entry. Opaque `param` is passed\nover to the callback function, unmodified. The callback function has the type:\u003cbr\u003e\n`typedef int (*smap_scan_func)(void* param, const void* key, size_t len, void** pval)`\u003cbr\u003e\nand the parameters are:\n* `param`: the opaque value given to `smap_scan()` function;\n* `key`: pointer to the key;\n* `len`: length of the key;\n* `pval`: address of the value associated with the `key`.\n\nThe value returned from the function is treated as follows:\n* `0`: proceed to the next entry;\n* `\u003c 0`: delete the current entry and continue. Before returning a negative value the function\nshould deallocate all resources associated with the value at `pval`;\n* `\u003e 0`: stop the scan and return the value.\n\n#### Constants\n\n`SMAP_MAX_KEY_LEN` - maximum key length; an arbitrary large number, currently set to 256MB.\nIt can be redefined externally.\n\n### Status\nTested and benchmarked on Linux Mint 21.3 with gcc v11.4.0 and clang v14.0.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxim2266%2Fsmap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxim2266%2Fsmap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxim2266%2Fsmap/lists"}