{"id":18720474,"url":"https://github.com/stiffstream/cpp-util","last_synced_at":"2025-11-10T21:30:15.705Z","repository":{"id":109496710,"uuid":"278312525","full_name":"Stiffstream/cpp-util","owner":"Stiffstream","description":"A collection of various helpers for C++. Some of them could be obsolete due to the evolution of C++.","archived":false,"fork":false,"pushed_at":"2020-07-09T09:16:28.000Z","size":141,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-12-28T11:28:18.657Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Stiffstream.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":"2020-07-09T08:50:44.000Z","updated_at":"2020-07-09T09:18:26.000Z","dependencies_parsed_at":"2023-04-25T04:37:18.624Z","dependency_job_id":null,"html_url":"https://github.com/Stiffstream/cpp-util","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stiffstream%2Fcpp-util","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stiffstream%2Fcpp-util/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stiffstream%2Fcpp-util/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stiffstream%2Fcpp-util/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Stiffstream","download_url":"https://codeload.github.com/Stiffstream/cpp-util/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239583642,"owners_count":19663236,"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":[],"created_at":"2024-11-07T13:31:15.354Z","updated_at":"2025-11-10T21:30:15.670Z","avatar_url":"https://github.com/Stiffstream.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# What Is It?\r\n\r\ncpp\\_util is a header-only C++11 library. It is a collection of some small\r\ntools which were created to simplify application developement. Some of them are\r\nrather old and even ancient, created even before C++98 was standartized. Some\r\nare relative new and require C++ compilers with good support of C++11 standard.\r\n\r\n# How To Use\r\n\r\nJust clone Hg repository somewhere and add path to `dev` folder to your\r\nINCLUDE path. For example:\r\n\r\n```sh\r\ncd ~/projects\r\ngit clone https://github.com/Stiffstream/cpp-util\r\nexport CPLUS_INCLUDE_PATH=$(CPLUS_INCLUDE_PATH):~/projects/cpp_util-3.0/dev\r\n```\r\n\r\nor\r\n\r\n```\r\ncd c:\\projects\r\ngit clone https://github.com/Stiffstream/cpp-util\r\nset INCLUDE=%INCLUDE%;c:\\projects\\cpp_util-3.0\\dev\r\n```\r\n\r\n## Recipe For MxxRu::externals\r\n\r\nInclusion of cpp\\_util via MxxRu::externals can be done with recipes like\r\nthese:\r\n\r\n```ruby\r\nMxxRu::arch_externals :cpp_util_3 do |e|\r\n  e.url 'https://github.com/Stiffstream/cpp-util/archive/v3.0.0-rc9.tar.gz'\r\n\r\n  e.map_dir 'dev/cpp_util_3' =\u003e 'dev'\r\nend\r\n```\r\n\r\nOr\r\n\r\n```ruby\r\nMxxRu::hg_externals :cpp_util_3 do |e|\r\n  e.url 'https://github.com/Stiffstream/cpp-util'\r\n  e.tag 'v.3.0.0-rc9'\r\n\r\n  e.map_dir 'dev/cpp_util_3' =\u003e 'dev'\r\nend\r\n```\r\n\r\n## Building Samples And Test\r\n\r\n[Mxx_ru](https://sourceforge.net/projects/mxxru/) build tool is necessary\r\nfor building samples and tests. To install Mxx\\_ru you need Ruby and RubyGems\r\ninstalled in your system (in most cases RubyGems is installed with\r\nRuby automatically). Then:\r\n\r\n```rb\r\ngem install Mxx_ru\r\n```\r\n\r\nTo build all tests and samples it is necessary to run `ruby build.rb` from\r\n`dev` folder:\r\n\r\n```rb\r\ncd ~/projects\r\nhg clone https://github.com/Stiffstream/cpp-util\r\ncd cpp-util/dev\r\nruby build.rb\r\n```\r\n\r\nTo build some specific sample or test it is necessary to run corresponding\r\nproject file from `dev` folder:\r\n\r\n```rb\r\ncd ~/projects\r\nhg clone https://github.com/Stiffstream/cpp-util\r\ncd cpp-util/dev\r\nruby sample/lexcast/util/prj.rb\r\n```\r\n\r\n*Note.* Mxx\\_ru tries to detect type of your compiler automatically. In most\r\ncases it just works. But sometimes it is necessary to specify your compiler\r\nmanually via `MXX_RU_CPP_TOOLSET` environment variable. For example if you have\r\nGCC and clang in your Linux and want to use clang, then `MXX_RU_CPP_TOOLSET`\r\nmust be set as:\r\n\r\n```sh\r\nexport MXX_RU_CPP_TOOLSET=clang_linux\r\n```\r\n\r\n# License\r\n\r\ncpp\\_util is distributed under 3-clauses BSD license.\r\n\r\n# What's Inside?\r\n\r\n## cpp_util_3/at_scope_exit.hpp\r\n\r\nHelper function `at_scope_exit`. Something like `scope_exit` from D language\r\nor `defer` from Go:\r\n\r\n```cpp\r\n#include \u003ccpp_util_3/at_scope_exit.hpp\u003e\r\n...\r\nvoid dump_content_to_file( const char * file_name, const content \u0026 cnt )\r\n{\r\n\tstd::FILE * file = std::fopen( file_name, \"w\" );\r\n\tif( file )\r\n\t{\r\n\t\tauto file_closer = cpp_util_3::at_scope_exit( [file]{ std::fclose( file ); } );\r\n\t\t...\r\n\t}\r\n}\r\n```\r\n\r\n## cpp_util_3/detect_compiler.hpp\r\n\r\nDefinition for macros like `CPP_UTIL_3_EXPORT`, `CPP_UTIL_3_IMPORT`,\r\n`CPP_UTIL_3_UNIX`, `CPP_UTIL_3_WINDOWS`, `CPP_UTIL_3_WIN64` and so on.\r\n\r\nMacros `CPP_UTIL_3_EXPORT` and `CPP_UTIL_3_IMPORT` hide compiler-specific\r\nkeywords for exporting/importing functions from dynamic-link libraries:\r\n\r\n```cpp\r\n// Somewhere in DLL-related header file...\r\n#pragma once\r\n...\r\n#include \u003ccpp_util_3/detect_compiler.hpp\u003e\r\n\r\n#if defined(MY_DLL)\r\n\t// Header included during compilation of the DLL.\r\n\t// Symbols must be exported.\r\n\t#define MY_DLL_DECLSPEC CPP_UTIL_3_EXPORT\r\n#else\r\n\t// Header included during compilation of a DLL client.\r\n\t// Symbols must be imported.\r\n\t#define MY_DLL_DECLSPEC CPP_UTIL_3_IMPORT\r\n#endif\r\n...\r\nclass MY_DLL_DECLSPEC some_exported_class { ... };\r\n\r\nMY_DLL_DECLSPEC void some_exported_function();\r\n```\r\n\r\n## cpp_util_3/ensure.hpp\r\n\r\nHelper function `ensure` for simplification of checking for some condition\r\nand throwing an exception if that condition is not fulfilled:\r\n\r\n```cpp\r\n#include \u003ccpp_util_3/ensure.hpp\u003e\r\n...\r\n// Do some 3rd-party library call.\r\nauto r = mosquitto_subscribe( m_mosq.get(),\r\n\t\t\u0026mid, topic_name.c_str(), qos_to_use );\r\n// Expect only a subset of error codes.\r\n// If another error code is returned then exception must be thrown.\r\ncpp_util_3::ensure\u003c std::runtime_error \u003e(\r\n\t\tMOSQ_ERR_SUCCESS == r || MOSQ_ERR_NO_CONN == r || MOSQ_ERR_CONN_LOST == r,\r\n\t\t[\u0026]{\r\n\t\t\treturn tfm::format( \"mosquitto_subscribe(%s, %d) failed, rc=%d\",\r\n\t\t\t\ttopic_name, qos_to_use, r );\r\n\t\t} );\r\n\r\n```\r\n\r\n## cpp_util_3/terminate_if_throws.hpp\r\n\r\nHelper function `terminate_if_throws` is intended to be used in cases where\r\nsome block of code must be run without any exceptions. If an exception is thrown\r\nfrom that block then the whole application must be terminated.\r\n\r\n```cpp\r\n#include \u003ccpp_util_3/terminate_if_throws.hpp\u003e\r\n...\r\n// We want to provide strong exception guarantee for that method.\r\nvoid some_complex_class::do_some_modification(const params \u0026 p) {\r\n  // Checks all necessary conditions first.\r\n  // Some exceptions can be thrown here.\r\n  check_condition_one(p);\r\n  check_condition_two(p);\r\n  ...\r\n  // Preallocate some resources.\r\n  // Exceptions are expected here. But this is not a problem\r\n  // because there is no any actual state changes yet.\r\n  auto r1 = preallocate_resource_one(p);\r\n  auto r2 = preallocate_resource_two(p);\r\n  ...\r\n  // All preparations are done. We don't expect exceptions\r\n  // in the following block of code. But if some exception is thrown\r\n  // then we don't know how to repair from it.\r\n  cpp_util_3::terminate_if_throws( [\u0026] {\r\n    do_state_change_action_one(...);\r\n\tdo_state_change_action_two(...);\r\n\t...\r\n  } );\r\n}\r\n```\r\n\r\n## cpp_util_3/outliving.hpp\r\n\r\nHelper class and related stuff for lifetime indication via type:\r\n\r\n```cpp\r\nclass config { ... };\r\n\r\nclass data_processor {\r\n\t// Indicator that reference to config must outlive data_processor object.\r\n\tcpp_util_3::outliving_reference_t\u003cconst config\u003e cfg_;\r\npublic :\r\n\tdata_processor(\r\n\t\t// Indicator that reference to config must outlive data_processor object.\r\n\t\tcpp_util_3::outliving_reference_t\u003cconst config\u003e cfg)\r\n\t: cfg_(cfg)\r\n\t{...}\r\n\t...\r\n};\r\n\r\nvoid f() {\r\n\tconfig cfg = load_config();\r\n\tdata_processor processor( cpp_util_3::outliving_const(cfg) );\r\n\t...\r\n}\r\n```\r\n\r\n## cpp_util_3/lexcast.hpp\r\n\r\nFamily of functions `lexcast` and `slexcast`. They are very old and now it\r\nis better to use more modern and efficient alternatives (*Boost.LexicalCast*,\r\n*cppformat* or *tinyformat*). Functions `lexcast`/`slexcast` are still in\r\ncpp\\_util library mostly by reasons of compatibility.\r\n\r\nBut there are some lexcast helpers which can be useful even now.\r\n\r\n### cpp_util_3/lexcasts/utils.hpp\r\n\r\nSeveral tools like `hex`, `hex_0x` and `all`. For example, it is possible to\r\nshow content of a vector by help from cppformat and cpp\\_util:\r\n\r\n```cpp\r\n#include \u003ccppformat/format.h\u003e\r\n\r\n#include \u003ccpp_util_3/lexcasts/util.hpp\u003e\r\n\r\n#include \u003ciostream\u003e\r\n#include \u003calgorithm\u003e\r\n#include \u003cvector\u003e\r\n\r\nusing namespace std;\r\nusing namespace cpp_util_3;\r\n\r\nint main()\r\n\t{\r\n\t\tvector\u003c int \u003e v{ 1, 2, 3, 4, 5, 6 };\r\n\r\n\t\tfmt::print( \"vector is: {}\\n\", lexcasts::all( v, \", \" ) );\r\n\t\tfmt::print( \"vector is: {}\\n\", lexcasts::all( v, \", \", lexcasts::hex_0x() ) );\r\n\t\tfmt::print( \"items greater than 3: {}\\n\",\r\n\t\t\t\tlexcasts::all(\r\n\t\t\t\t\tupper_bound( begin(v), end(v), 3),\r\n\t\t\t\t\tend(v),\r\n\t\t\t\t\t\", \", lexcasts::hex() ) );\r\n\t}\r\n```\r\n\r\nThis example will print:\r\n\r\n```\r\nvector is: 1, 2, 3, 4, 5, 6\r\nvector is: 0x1, 0x2, 0x3, 0x4, 0x5, 0x6\r\nitems greater than 3: 4, 5, 6\r\n```\r\n\r\n## cpp_util_3/loops.hpp\r\n\r\nHelper function(s) for writing loops in declarative style. For example:\r\n\r\n```cpp\r\n#include \u003ccpp_util_3/loops.hpp\u003e\r\n\r\nusing namespace cpp_util_3;\r\n...\r\nn_times( 3, []{ std::cout \u003c\u003c \"===\" \u003c\u003c std::endl; } );\r\n```\r\n\r\n## cpp_util_3/hex_dumps/string_dumper.hpp\r\n\r\nHelper functions for creation of hex dumps of strings or byte buffers\r\n(could be useful for logging):\r\n\r\n```cpp\r\n#include \u003ccpp_util_3/hex_dumps/string_dumper.hpp\u003e\r\n#include \u003ciostream\u003e\r\n\r\nusing namespace std;\r\nnamespace dumps = cpp_util_3::hex_dumps;\r\n\r\nint main()\r\n\t{\r\n\t\t// Will print '68 65 6c 6c 6f 2c 20 77 6f 72 6c 64':\r\n\t\tcout \u003c\u003c \"'\" \u003c\u003c dumps::string_dumper(\"hello, world\") \u003c\u003c \"'\\n\";\r\n\t\t// Will print '68656c6c6f2c20776f726c64'\r\n\t\tcout \u003c\u003c \"'\" \u003c\u003c dumps::string_dumper_without_spaces(\"hello, world\") \u003c\u003c \"'\\n\";\r\n\t}\r\n```\r\n\r\n## cpp_util_3/rollback_on_exception.hpp\r\n\r\nHelper function `do_with_rollback_on_exception` which simplifies\r\nwritting of exception safe code:\r\n\r\n```cpp\r\n#include \u003ccpp_util_3/rollback_on_exception.hpp\u003e\r\n...\r\nvoid some_complex_container::insert_item( const some_data \u0026 item )\r\n{\r\n\t// Three internal containers must be updated.\r\n\t// Any update can lead to exception.\r\n\t// Container update must be rolled back on exception.\r\n\tfirst_container_.push_back( item );\r\n\tcpp_util_3::do_with_rollback_on_exception(\r\n\t\t[\u0026]{\r\n\t\t\tsecond_container_.push_back( item );\r\n\t\t\tcpp_util_3::do_with_rollback_on_exception(\r\n\t\t\t\t[\u0026]{ thrid_container_.push_back( itsm ); },\r\n\t\t\t\t// Rollback action.\r\n\t\t\t\t[\u0026]{ second_container_.pop_back(); } );\r\n\t\t},\r\n\t\t// Rollback action.\r\n\t\t[\u0026]{ first_container_.pop_back(); } );\r\n}\r\n```\r\n\r\n## cpp_util_3/string_piece.hpp\r\n\r\nHelper class `string_piece_t` is old and simple analog of `string_span` from\r\nC++ Core Guidelines or `string_view` from proposals for C++17.\r\n\r\nIt can be used for functions and methods which except string-like params:\r\n\r\n```cpp\r\n#include \u003ccpp_util_3/string_piece.hpp\u003e\r\n...\r\nbool is_valid_name( cpp_util_3::string_piece_t name ) {\r\n  ... // Some manipulation of name's contents.\r\n}\r\n...\r\nchar name1[ 16 ] = {...};\r\nif( is_valid_name( name1 ) ) { ... }\r\n\r\nif( is_valid_name( \"some name\" ) ) { ... }\r\n\r\nstd::string name2 = ...;\r\nif( is_valid_name( name2 ) ) { ... }\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstiffstream%2Fcpp-util","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstiffstream%2Fcpp-util","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstiffstream%2Fcpp-util/lists"}