{"id":13731141,"url":"https://github.com/eteran/cpp-utilities","last_synced_at":"2025-05-04T22:50:25.435Z","repository":{"id":29833461,"uuid":"33378117","full_name":"eteran/cpp-utilities","owner":"eteran","description":"Miscellaneous C++11 utility classes and functions","archived":false,"fork":false,"pushed_at":"2025-04-01T14:10:05.000Z","size":193,"stargazers_count":429,"open_issues_count":0,"forks_count":63,"subscribers_count":34,"default_branch":"master","last_synced_at":"2025-04-01T15:28:14.200Z","etag":null,"topics":["c-plus-plus","cpp"],"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/eteran.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":"2015-04-03T19:03:26.000Z","updated_at":"2025-04-01T14:10:09.000Z","dependencies_parsed_at":"2024-11-14T21:33:08.334Z","dependency_job_id":"8edd0156-aadf-48f6-9c18-192b8723bd2c","html_url":"https://github.com/eteran/cpp-utilities","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eteran%2Fcpp-utilities","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eteran%2Fcpp-utilities/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eteran%2Fcpp-utilities/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eteran%2Fcpp-utilities/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eteran","download_url":"https://codeload.github.com/eteran/cpp-utilities/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252411805,"owners_count":21743604,"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-plus-plus","cpp"],"created_at":"2024-08-03T02:01:24.422Z","updated_at":"2025-05-04T22:50:25.429Z","avatar_url":"https://github.com/eteran.png","language":"C++","funding_links":[],"categories":["Libraries"],"sub_categories":[],"readme":"# cpp-utilities\nMiscellaneous C++11/C++14/C++17 utility classes and functions\n\n### Hash Library\nFound in [md5.h](hash/include/cpp-utilities/md5.h) and [sha1.h](hash/include/cpp-utilities/sha1.h)\n\nAs you might expect, this is an implementation of the MD5 and SHA1 hashing algorithms. The usage of both are identical and designed for ease of use.\n\n    // create an MD5 object and give it some data\n    hash::md5 hasher(\"Hello World\");\n    hasher.update('!'); // you can stream new values in as you please\n    auto digest = hasher.finalize();  // create a digest for \"Hello World!\"\n    std::cout \u003c\u003c digest.to_string() \u003c\u003c std::endl;\n\n**NOTE:** One thing to note that I feel is a nice design feature. `finalize()` does not modify the internal state of the hasher, it returns a copy of the digest in finalized form. This means that you can call `finalize()`, then continue to append new data into the hasher, call `finalize()` again, and get correct hashes.\n\n### Arena Allocator\n\nFound in [arena.h](arena/include/cpp-utilities/arena.h). This is an implementation of a very efficient fixed block size arena allocator. It allows allocating and freeing back to the arena (if you want to, it isn't necessary), and will use one of two strategies depending on the size of blocks you need. If the blocks are smaller than the size of a pointer, and the arena is relatively small, then it will use a bitmap along with compiler intrinsics to find free blocks. If the the blocks are at least as large as a pointer, it will use a freelist implementation. Template deduction will choose the best backend for you.\n\nUsage is **very** simple:\n\n    // create an arena of 1024 64-bit blocks \n    auto arena = memory::make_arena\u003cuint64_t, 1024\u003e();\n    auto p1 = arena.allocate(); // get a single uint64_t sized block\n    arena.release(p1);          // free that block back into the system \n                                // (not necessary, the arena will clean itself up)\n    \nOn my system , the allocate function when using the freelist strategy, allocate was **as few a 5 instructions**. Some of which were simple `nullptr` checks. Since this is a low level allocator, constructors are not called, you get a block of memory suitably aligned and sized for the type specified.\n\n### Bitset Utility Functions\n\nFound in [bitset.h](bitset/include/cpp-utilities/bitset.h). This header provides a nice utility function to find the first set bit in a bitset. When possible using GCC intrinsics to do it in O(1) time, but falling back on an iterative implementation when this is not possible.\n\n    std::bitset\u003c32\u003e bs;\n    bs[4]  = true;\n    bs[10] = true;\n    int bit_l = bitset::find_first(bs); // returns 4\n    int bit_h = bitset::find_last(bs); // returns 10\n    \nThe function is defined to return `bitset.size()` when no bits are set, this is similar to containers returning `.end()` for find operations.\n\n### Bitwise Operations\n\n[bitwise.h](bitwise/include/cpp-utilities/bitwise.h) provides efficient and type safe rotation operations that will work with any integral type. A future version may be implemented using intrinsics, but for now it's a fairly straight forward shift and mask solution. Impressively, gcc will often reduce this to a single `rol` instruction when optimizations are enabled!\n\n    int x = 5;\n    int y = bitwise::rotate_right(x, 15);\n    int x = bitwise::rotate_left(x, 20);\n\n### String Utility Functions\n\n[string.h](string/include/cpp-utilities/string.h) provides several common string functions such as trimming, upper/lower casing, testing what it starts and ends with, etc.\n\n### Algorithms\n\n[algorithm.h](algorithm/include/cpp-utilities/algorithm.h) is a set of algorithms for general purpose use. Currently there are implementations of variadic min and max functions which are compile time. For example:\n\n\tint n = algorithm::static_max(1, 2, 3, 10, 5, 6);\n\tprintf(\"%d\\n\", n); // prints 10\n\t\nBecause it is a compile time constant, you can also safely use it in templates as well. For example:\n\n\ttemplate \u003cint N\u003e\n\tstruct Foo {\n\t\tstatic const int value = N * 2;\n\t};\n\n\tint main() {\n\t\tint n = Foo\u003calgorithm::static_max(1, 2, 3, 10, 5, 6)\u003e::value;\n\t\tprintf(\"%d\\n\", n); // prints 20\n\t}\n\nOf course your compiler will have to have good support for `constexpr` :-).\n\n### Pretty Printers\n\n[pprint.h](pprint/include/cpp-utilities/pprint.h) is a set of utility functions to print common data structures in a \"pretty\" way. Similar to PHP's `print_r()`. Usage looks like this:\n\n\tstd::vector\u003cint\u003e v = { 1, 2, 3, 4, 5, 6, 7 };\n\tstd::cout \u003c\u003c pprint::to_string(v) \u003c\u003c std::endl;\n\t\nWhich will print:\n\n\tstd::vector\u003c\u003e\n\t(\n\t   [0] =\u003e 1\n\t   [1] =\u003e 2\n\t   [2] =\u003e 3\n\t   [3] =\u003e 4\n\t   [4] =\u003e 5\n\t   [5] =\u003e 6\n\t   [6] =\u003e 7\n\t)\n\n`std::vector`, `std::list`, `std::deque`, `std::set`, `std::map` are all supported. Additionally, complex nesting of containers should work just fine. For example, a list of vectors:\n\n\tstd::list\u003cstd::vector\u003cint\u003e\u003e v = { {1, 2, 3}, {4, 5, 6, 7} };\n\tstd::cout \u003c\u003c pprint::to_string(v) \u003c\u003c std::endl;\n\t\nWill print:\n\n\tstd::list\u003c\u003e\n\t(\n\t   [0] =\u003e std::vector\u003c\u003e\n\t   (\n    \t   [0] =\u003e 1\n    \t   [1] =\u003e 2\n    \t   [2] =\u003e 3\n\t   )\n\t   [1] =\u003e std::vector\u003c\u003e\n\t   (\n    \t   [0] =\u003e 4\n    \t   [1] =\u003e 5\n    \t   [2] =\u003e 6\n    \t   [3] =\u003e 7\n\t   )\n\t)\n\n\n### Fixed Point Math\n[fixed.h](fixed/include/cpp-utilities/fixed.h)\n\nThis is a Fixed Point math class. It supports all combinations which add up to a native data types (8.8/16.16/24.8/etc). The template parameters are the number of bits to use as the base type for both the integer and fractional portions, invalid combinations will yield a compiler error; the current implementation makes use of `static assert` to make this more readable. It should be a nice drop in replacement for native `float` types. Here's an example usage:\n\n\ttypedef numeric::fixed\u003c16, 16\u003e fixed;\n\tfixed f;\n\t\nThis will declare a 16.16 fixed point number. Operators are provided though the use of boost::operators. multiplication and division are implemented in free functions named `numeric::multiply` and `numeric::divide` which use `std::enable_if` to choose the best option. If a larger type is available, it will use the accurate and fast scaled math version. If there is not a larger type available, then it will fall back on the slower multiply and emulated divide (which unfortunately has less precision). This system allows the user to specialize the multiplication and division as needed.\t\n\n\n### Flat associative containers\n[flat_map.h](container/include/cpp-utilities/flat_map.h)\n\nThis is an implementation of a `std::map` but using a contiguous data structure (`std::vector`) as the underlying storage. The elements are stored sorted by key, so lookup should be as efficient as a `binary_search`, and iteration is as efficient as accessing a `std::vector`.\n\n[flat_set.h](container/include/cpp-utilities/flat_set.h)\n\nThis is an implementation of a `std::set` but using a contiguous data structure (`std::vector`) as the underlying storage. The elements are stored sorted by key, so lookup should be as efficient as a `binary_search`, and iteration is as efficient as accessing a `std::vector`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feteran%2Fcpp-utilities","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feteran%2Fcpp-utilities","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feteran%2Fcpp-utilities/lists"}