{"id":35113999,"url":"https://github.com/orefkov/simstr","last_synced_at":"2026-02-27T22:15:31.480Z","repository":{"id":286297247,"uuid":"960992391","full_name":"orefkov/simstr","owner":"orefkov","description":"Yet another C++ strings library implementation","archived":false,"fork":false,"pushed_at":"2026-01-25T10:49:38.000Z","size":927,"stargazers_count":14,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-01-26T01:42:26.881Z","etag":null,"topics":["expression-templates","modern-cpp","string-manipulation","string-matching","string-method","strings"],"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/orefkov.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-04-05T14:21:10.000Z","updated_at":"2026-01-25T10:39:30.000Z","dependencies_parsed_at":"2025-04-25T09:28:58.871Z","dependency_job_id":"071f15da-227d-4821-86fa-71ad74103937","html_url":"https://github.com/orefkov/simstr","commit_stats":null,"previous_names":["orefkov/simstr"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/orefkov/simstr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orefkov%2Fsimstr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orefkov%2Fsimstr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orefkov%2Fsimstr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orefkov%2Fsimstr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/orefkov","download_url":"https://codeload.github.com/orefkov/simstr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orefkov%2Fsimstr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28947571,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T14:26:55.697Z","status":"ssl_error","status_checked_at":"2026-01-31T14:26:52.545Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["expression-templates","modern-cpp","string-manipulation","string-matching","string-method","strings"],"created_at":"2025-12-27T20:22:57.589Z","updated_at":"2026-02-27T22:15:31.472Z","avatar_url":"https://github.com/orefkov.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# simstr - String Object and Function Library\n\u003cspan class=\"obfuscator\"\u003e\u003ca href=\"readme_ru.md\"\u003eRussian | По-русски\u003c/a\u003e\u003c/span\u003e\n\n[![CMake on multiple platforms](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml/badge.svg)](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)\n\nVersion 1.7.2.\n\n\u003ch2\u003eSpeed up your work with strings by 2-10 times!\u003c/h2\u003e\n\n\nThis library contains a modern implementation of several types of string objects and various algorithms for working with strings.\n## Generated Documentation\n[Located here](https://orefkov.github.io/simstr/docs_en/)\n\n## Brief Description\nThe goal of the library is to make working with strings in C++ as simple and easy as in many other languages, especially\nscripting languages, while maintaining optimality and performance at the level of C and C++, and even improving them.\n\nIt's no secret that working with strings in C++ often causes pain. The `std::string` class is often inconvenient or inefficient.\nMany functions that are usually necessary when working with strings are simply not there, and everyone has to write them themselves.\nEven concatenating `std::string` and `std::string_view` became possible only with C++26.\nThat's why I started creating this library for myself around 2012, and now I'm ready to share it with all C++ developers.\n\nThis library was not made as a universal combine that \"can do everything\", I implemented what I had to\nuse in my work, trying to do it in the most efficient way, and I modestly hope that I have succeeded in something\nand will be useful to other people, either directly or as a source of ideas.\n\nThe library contains two parts:\n- Implementation of [*\"String Expressions\"*](https://orefkov.github.io/simstr/articles/fast_concat.html) and algorithms for working\n  with constant strings.\\\n  To use this part, just take the file `\"include/simstr/strexpr.h\"` and write in your code\n  ```cpp\n  #include \"path/to file/strexpr.h\"\n  ```\n  This will allow you to use powerful and fast *\"string expressions\"* for concatenation and string construction for standard string types\n  (`std::basic_string`, `std::basic_string_view`), as well as simplified versions of the `simple_str` and\n  `simple_str_nt` classes, which implement all those string algorithms of the library that do not require storing or modifying strings.\n  Since this is a header-only part, it does not include working with UTF encodings and simplified Unicode.\n- The full version, requiring the connection of the entire library (`\"include/simstr/sstring.h\"`), adds its string types with\n  the ability to store and modify strings, works with UTF encodings and simplified Unicode.\n\nThe library does not pretend to be a \"changed header and everything worked better\" - it gets along well with standard strings\nand does not change the behavior of existing code working with them. I tried to make many methods in it compatible\nwith `std::string` and `std::string_view`, but I didn't bother with this much. Rewriting your code to work with `simstr`\nwill require some effort, but I assure you that it will pay off. And thanks to compatibility with standard strings, this work can be done\nin stages, in small pieces. Creating new code for working with strings with its use is easy and enjoyable :)\n\n\nThe main difference between `simstr` and `std::string` is that not a single universal class is used for working with strings, but several\ntypes of objects, each of which is good for its own purposes, and at the same time interact well with each other.\nIf you actively used `std::string_view` and understood its advantages and disadvantages compared to `std::string`,\nthen the `simstr` approach will also be clear to you.\n\n## Key Features of the Library\nWhen using only `#include \"simstr/strexpr.h\"`:\n- Support for working with strings `char`, `char8_t`, `char16_t`, `char32_t`, `wchar_t`.\n- Powerful and extensible *\"String Expressions\"* system.\n  Allows you to efficiently implement the conversion and addition (concatenation) of strings, string literals, numbers (and possibly other objects),\n  achieving significant acceleration of string operations.\n  Compatible with both `simstr` string objects and standard strings (`std::basic_string`,\n  `std::basic_string_view`), which allows you to apply fast concatenation even where it is not yet possible to abandon standard strings.\n  Also allows you to mix strings of compatible character types in operations.\n- Constant string functions (do not change the original string):\n  - Getting substrings.\n  - Comparing strings, comparing strings ignoring the case of ASCII characters.\n  - Searching for substrings and characters - from the beginning or from the end of the string.\n  - Various trimming of strings - right, left, everywhere, by whitespace characters, by specified characters.\n  - Replacing substrings (creating a copy of the string with the replacement).\n  - Replacing a set of characters with a set of corresponding substrings (creating a copy of the string with the replacement).\n  - Merging (join) containers of strings into a single string, with specifying separators and options - \"skip empty\", \"separator after last\".\n  - Splitting strings into parts by a specified delimiter. Splitting is possible immediately into a container with strings, or by calling a functor for\n    each substring, or by iterating using the `Splitter` iterator.\n- Functions for modifying standard strings with string expressions:\n  - str::append, str::prepend, str::insert, str::change - change str::string with string expressions,\n    for example `str::append(text, \"count = \"_ss + count)`.\n  - str::replace - replaces occurrences of the search substring with a replacement string or string expression.\n    If the substring is not found, the string expression is not even evaluated.\n  - str::make_ascii_upper, str::make_ascii_lower - change the case of ASCII characters.\n- Parsing integers with the possibility of \"fine\" tuning at compile time - you can set options for checking overflow,\n  skipping whitespace characters, a specific radix or auto-selection by prefixes `0x`, `0`, `0b`, `0o`,\n  the admissibility of the `+` sign. Parsing is implemented for all types of strings and characters.\n- Parsing double for `char` and `wchar_t`, as well as character types compatible with them in size.\n\nWhen using the full version of the library:\n- Everything that is listed above, plus\n- Additional efficient string objects - `sstring` (shared string), `lstring` (local string).\n- `lstring` - supports many mutable operations with strings - various replacements, insertions, deletions, etc.\n  Allows you to set the size for the internal character buffer, which can turn *Small String Optimization* into *Big String Optimization* :).\n- Transparent conversion of strings from one character type to another, with automatic conversion between UTF-8, UTF-16, UTF-32,\n  using [simdutf](https://github.com/simdutf/simdutf). Strings of \"compatible\" types are converted by simple copying:\n  `char \u003c-\u003e char8_t`, `wchar_t \u003c-\u003e char32_t` in Linux, `wchar_t \u003c-\u003e char16_t` in Windows.\n- Integration with `format` and `sprintf` formatting functions (with automatic buffer increase).\n  Formatting is possible for `char`, `wchar_t` strings and strings compatible with them in size.\n  That is, under Windows it is `char8_t`, `char16_t`, under Linux - `char8_t`, `char32_t` (writing my own formatting library for all types of\n  characters was not part of my plans).\n- Contains minimal Unicode support when converting `upper`, `lower` and case-insensitive string comparison.\n  Works only for characters of the first Unicode plane (up to 0xFFFF), and when changing the case, cases are not taken into account when one code point\n  can be converted into several, that is, the case conversion of characters corresponds to `std::towupper`, `std::towlower` for the unicode locale, only faster and can work with any type of characters.\n- Implemented `hash map` for string type keys, based on `std::unordered_map`, with the possibility of more efficient storage and\n  comparison of keys compared to `std::string` keys. Supports the possibility of case-insensitive comparison of keys (Ascii or\n  minimal Unicode (see previous paragraph)).\n\n## Benchmarks\nBenchmarks are performed using the [Google benchmark](https://github.com/google/benchmark) framework.\nI tried to make measurements for the most typical operations that occur in normal work. I took measurements on my equipment, under\nWindows and Linux (in WSL), using MSVC, Clang, GCC compilers. Third-party results are welcome.\nI also took measurements in WASM, built in Emscripten. I draw attention to the fact that a 32-bit build is built under WASM in Emscripten, which means that\nthe sizes of SSO buffers in objects are smaller.\n\nOn the [release page](https://github.com/orefkov/simstr/releases) you can download binary builds of benchmarks and run them on your equipment.\n\nYou can also run the [Emscripten build of benchmarks](https://orefkov.github.io/simstr/bench/benchStr.html) directly in the browser.\n\n- [Benchmark source code](bench/bench_str.cpp)\n- [Benchmark results](https://orefkov.github.io/simstr/results.html)\n\n## String Expressions\nThese are special objects that efficiently implement string concatenation using `operator+`.\nThe main principle, due to which efficient work is achieved - no matter how many operands are included in the entire expression,\nno temporary (intermediate) strings are created, the total length of the entire result is calculated only once,\nmemory is allocated for the result character buffer only once, after which the characters are copied directly to the result buffer\nto its place. No memory reallocations, no moving characters in various intermediate buffers - everything is\nas efficient as possible. Thanks to the capabilities of C++ templates and operator overloading, the expression is written as close as possible\nto the usual syntax for adding strings.\nIn addition, there are special overloads for adding string objects and string literals, strings and numbers,\nfor copying with replacement, for merging containers of strings and much more.\nThanks to the extensibility of this system, it is possible to create new options for building strings, and development is constantly ongoing.\n\nAll string objects from `simstr` are themselves string expressions, that is, they can be used in concatenation operations\nstring expressions directly. Standard strings (`std::basic_string`, `std::basic_string_view`) can also serve as operands\nin addition operations with string expressions. Or they can be easily converted into a string expression by placing them in front of them\nunary `+`.\n\n## Usage Examples\n### Adding strings with numbers\n```cpp\nstd::string s1 = \"start \";\nint i;\n....\n// Was\n    std::string str = s1 + std::to_string(i) + \" end\";\n// Became\n    std::string str = +s1 + i + \" end\";\n```\n`+s1` - converts `std::string` into an object - a string expression for which there is an efficient concatenation with numbers and string literals.\n\nAccording to benchmarks, [acceleration 1.6 - 2 times](https://orefkov.github.io/simstr/results.html#bs70109915512075798510).\n\n### Adding strings with numbers in hex format\n```cpp\n....\n// Was\n    std::string str = s1 + std::format(\"0x{:x}\", i) + \" end\";\n// Became\n    std::string str = +s1 + e_hex\u003cHexFlags::Short\u003e(i) + \" end\";\n```\nAcceleration by [**9 - 14 times!!!**](https://orefkov.github.io/simstr/results.html#bs146911715078927772520)\n\n### Adding multiple literals and searching in `std::string_view`\n```cpp\n// It was like this\nsize_t find_pos(std::string_view src, std::string_view name) {\n    // before C++26 we can not concatenate string and string_view...\n    return src.find(\"\\n- \"s + std::string{name} + \" -\\n\");\n}\n// When using only \"strexpr.h\" it became like this\nsize_t find_pos(ssa src, ssa name) {\n    return src.find(std::string{\"\\n- \" + name + \" -\\n\"});\n}\n\n// And when using the full library, you can do this\nsize_t find_pos(ssa src, ssa name) {\n    // In this version, if the result of the concatenation fits into 207 characters, it is produced in a buffer on the stack,\n    // without allocation and deallocation of memory, acceleration several times. And only if the result is longer than 207 characters -\n    // there will be only one allocation, and the concatenation will be immediately into the allocated buffer, without copying characters.\n    return src.find(lstringa\u003c200\u003e{\"\\n- \" + name + \" -\\n\"});\n}\n```\n`ssa` - alias for `simple_str\u003cchar\u003e` - analogue of `std::string_view`, allows you to accept as a function parameter with minimal costs\nany string object that does not need to be modified or passed to the C-API: `std::string`, `std::string_view`, `\"string literal\"`,\n`simple_str_nt`, `sstring`, `lstring`. Also, since it is also a \"string expression\", it allows you to easily\nbuild concatenations with its participation.\n\nAccording to measurements, [acceleration 1.5 - 9 times](https://orefkov.github.io/simstr/results.html#bs68116594352702954700).\n\n### Addition with conditions\n```cpp\n// Was\nstd::string buildTypeName(std::string_view type_name, size_t prec, size_t scale) {\n    std::string res{type_name};\n    if (prec) {\n        res += \"(\" + std::to_string(prec);\n        if (scale) {\n            res += \",\" + std::to_string(scale);\n        }\n        res += \")\";\n    }\n    return res;\n}\n// Became when using only strexpr.h and wanting to use only standard strings\nstd::string buildTypeName(std::string_view type_name, size_t prec, size_t scale) {\n    if (prec) {\n        //     + turns type_name from string_view into a string expression\n        return +type_name + \"(\" + prec + e_if(scale, \",\"_ss + scale) + \")\";\n    }\n    return type_name;\n}\n// Became when using only strexpr.h and simple_str string\nstd::string buildTypeName(ssa type_name, size_t prec, size_t scale) {\n    if (prec) {\n        //     ssa is already a string expression, + in front of it is not needed\n        return type_name + \"(\" + prec + e_if(scale, \",\"_ss + scale) + \")\";\n    }\n    return type_name;\n}\n// Became when using the full library\nstringa buildTypeName(ssa type_name, size_t prec, size_t scale) {\n    if (prec) {\n        return type_name + \"(\" + prec + e_if(scale, \",\"_ss + scale) + \")\";\n    }\n    return type_name;\n}\n```\nWhen `prec != 0`, [acceleration 1.5 - 2.2 times](https://orefkov.github.io/simstr/results.html#bs145290966789248325200).\n\n### Addition with replacements\n```cpp\n// Was\n// There is no standard analogue of the replace function from other programming languages, let's write our own \"head-on\".\nstd::string str_replace(std::string_view from, std::string_view pattern, std::string_view repl) {\n    std::string result;\n    for (size_t offset = 0;;) {\n        size_t pos = from.find(pattern, offset);\n        if (pos == std::string::npos) {\n            result += from.substr(offset);\n            break;\n        }\n        result += from.substr(offset, pos - offset);\n        result += repl;\n        offset = pos + pattern.length();\n    }\n    return result;\n}\n\nstd::string make_str_str(std::string_view from, std::string_view pattern, std::string_view repl) {\n    return \"\u003c\" + str_replace(from, pattern, repl) + \"\u003e\";\n}\n// Became - copying with replacements\nstd::string make_str_exp(std::string_view from, std::string_view pattern, std::string_view repl) {\n    return \"\u003c\" + e_repl(from, pattern, repl) + \"\u003e\";\n}\n```\n[Acceleration from 1.5 times and higher](https://orefkov.github.io/simstr/results.html#bs54035654251116789780) - depending on the content of the strings.\n\n### Splitting strings into parts, parsing numbers\n```cpp\n// Was - split the string by delimiter and calculate the sum of numbers\nint split_and_calc_total_str(std::string_view numbers, std::string_view delimiter) {\n    int total = 0;\n    for (size_t start = 0; start \u003c numbers.length(); ) {\n        int delim = numbers.find(delimiter, start);\n        if (delim == std::string::npos) {\n            delim = numbers.size();\n        }\n        std::string part{numbers.substr(start, delim - start)};\n        total += std::strtol(part.c_str(), nullptr, 0);\n        start = delim + delimiter.length();\n    }\n    return total;\n}\n// Became\nint split_and_calc_total_sim(ssa numbers, ssa delimiter) {\n    int total = 0;\n    for (auto splitter = numbers.splitter(delimiter); !splitter.is_done();) {\n        total += splitter.next().as_int\u003cint\u003e();\n    }\n    return total;\n}\n```\n[Acceleration by 2-3 times](https://orefkov.github.io/simstr/results.html#bs7106975351756760120).\n\nIn addition to the individual examples given here, you can look at the sources:\n- [tests of the entire library](https://github.com/orefkov/simstr/blob/main/tests/test_str.cpp)\n- [tests of only the strexpr part](https://github.com/orefkov/simstr/blob/main/tests/test_expr_only.cpp)\n- [examples of using your types in string expressions](https://github.com/orefkov/simstr/blob/main/tests/test_tostrexpr.cpp)\n- [benchmarks](https://github.com/orefkov/simstr/blob/main/bench/bench_str.cpp)\n- [utility for preparing html](https://github.com/orefkov/simstr/blob/main/bench/process_result.cpp) from benchmark results.\n\n## Main Objects of the Library\nAvailable with any use:\n- `simple_str\u003cK\u003e` - the simplest string (or piece of string), immutable, not owning, analogue of `std::string_view`.\n- `simple_str_nt\u003cK\u003e` - the same, only declares that it ends with 0. For working with third-party C-API.\n\nAvailable when using the entire library:\n- `sstring\u003cK\u003e` - shared string, immutable, owning, with a shared character buffer, SSO support.\n- `lstring\u003cK, N\u003e` - local string, mutable, owning, with a specified size of the SSO buffer.\n\nWhen connecting only `strexpr.h` - the types `simple_str\u003cK\u003e` and `simple_str_nt\u003cK\u003e` do not contain methods for working with UTF and Unicode.\n\n## Articles\n- [Overview and introduction](docs/overview.md)\n- [So how do you quickly concatenate strings?](https://orefkov.github.io/simstr/articles/fast_concat.html)\n- [Overview article on Habr](https://habr.com/ru/articles/935590) (on Russian)\n- [Description of the applied technique \"Expression Templates\"](https://habr.com/ru/articles/936468/)(on Russian)\n\n## Usage\nThe library can be used partially, simply by taking the file `\"include/simstr/strexpr.h\"` and including it in your sources\n```cpp\n#include \"include/simstr/strexpr.h\"\n```\nThis will only connect string expressions and simplified implementations of `simple_str` and `simple_str_nt`, without UTF and Unicode functions.\n\nThe full version of the `simstr` library consists of three header files and two source files.\nYou can connect as a CMake project via `add_subdirectory` (the `simstr` library),\nyou can simply include the files in your project. Building also requires [simdutf](https://github.com/simdutf/simdutf) (when using CMake\nit is downloaded automatically).\n\n### Connection via FetchContent\n```\nfunction(add_simstr)\n    set(SIMSTR_BUILD_TESTS OFF)\n    set(SIMSTR_BENCHMARKS OFF)\n    FetchContent_Declare(\n        simstr\n        GIT_REPOSITORY https://github.com/orefkov/simstr.git\n        GIT_SHALLOW TRUE\n        GIT_TAG tags/rel1.7.2 # Specify the desired release\n        FIND_PACKAGE_ARGS NAMES simstr 1.7.2\n    )\n    FetchContent_MakeAvailable(simstr)\nendfunction()\n\nadd_simstr()\n\ntarget_link_libraries(\u003cyour target\u003e PUBLIC simstr::simstr)\n```\n\nThe library is also included in [vcpkg](https://vcpkg.io), connected as `orefkov-simstr`.\n\nFor `simstr` to work, a compiler of the standard no lower than C++20 is required - concepts and std::format are used.\nThe work was checked under Windows on MSVC-19 and Clang-19, under Linux - on GCC-13 and Clang-21.\nThe work in WASM was also checked, built in Emscripten 4.0.6, Clang-21.\n\n## Convenient Debugging\nAlong with the library, two files are supplied that make viewing simstr string objects in debuggers\nmore convenient.\\\nMore details are described [here](for_debug/readme.md).\n\n## Where it is already used\nSimstr is also used in my projects:\n- [simjson](https://github.com/orefkov/simjson) - a library for simple work with JSON using simstr strings.\n- [simrex](https://github.com/orefkov/simrex) - a wrapper for working with regular expressions [Oniguruma](https://github.com/kkos/oniguruma) using simstr strings.\n- [v8sqlite](https://github.com/orefkov/v8sqlite) - an external component for 1C-Enterprise V8 for working with sqlite.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forefkov%2Fsimstr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Forefkov%2Fsimstr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forefkov%2Fsimstr/lists"}