diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f526f1..af6639f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ include(FetchContent) project( simstr - VERSION 1.3.1 + VERSION 1.4.0 DESCRIPTION "Yet another modern C++ string library" HOMEPAGE_URL "https://github.com/orefkov/simstr" LANGUAGES CXX @@ -115,13 +115,17 @@ if(SIMSTR_BUILD_TESTS) FetchContent_Declare( googletest # Specify the commit you depend on and update it regularly. - URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.zip - FIND_PACKAGE_ARGS NAMES GTest + URL https://github.com/google/googletest/archive/refs/tags/v1.17.0.zip + FIND_PACKAGE_ARGS NAMES GTest 1.17.0 ) # For Windows: Prevent overriding the parent project's compiler/linker settings set(gtest_force_shared_crt FALSE CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) add_subdirectory(tests) + if(TARGET gtest) + target_compile_features(gtest PUBLIC cxx_std_23) + target_compile_features(gtest_main PUBLIC cxx_std_23) + endif() endif() function(GBencmark) @@ -130,7 +134,7 @@ function(GBencmark) googlebench # Specify the commit you depend on and update it regularly. URL https://github.com/google/benchmark/archive/refs/tags/v1.9.4.zip - FIND_PACKAGE_ARGS NAMES benchmark + FIND_PACKAGE_ARGS NAMES benchmark 1.9.4 ) set(BENCHMARK_ENABLE_TESTING OFF) set(BENCHMARK_ENABLE_LTO OFF) @@ -140,7 +144,9 @@ function(GBencmark) set(BENCHMARK_ENABLE_GTEST_TESTS OFF) add_compile_definitions(BENCHMARK_STATIC_DEFINE) FetchContent_MakeAvailable(googlebench) - target_compile_features(benchmark PUBLIC cxx_std_20) + if(TARGET benchmark) + target_compile_features(benchmark PUBLIC cxx_std_23) + endif() if(EMSCRIPTEN) # Свежий Clang в Emscripten ругается на __COUNTER__ diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt index fb0bd70..c84253e 100644 --- a/bench/CMakeLists.txt +++ b/bench/CMakeLists.txt @@ -5,6 +5,7 @@ cmake_minimum_required (VERSION 3.15) add_executable(benchStr bench_str.cpp bench.h) target_link_libraries(benchStr simstr::simstr benchmark::benchmark) +target_compile_features(benchStr PUBLIC cxx_std_23) add_executable(process_result process_result.cpp) target_link_libraries(process_result simstr_simstr) diff --git a/bench/bench_str.cpp b/bench/bench_str.cpp index f4f0157..f0ecc42 100644 --- a/bench/bench_str.cpp +++ b/bench/bench_str.cpp @@ -19,6 +19,318 @@ using namespace std::literals; void __(benchmark::State& state) { for (auto _: state) {} } +void ConcatStdToStd(benchmark::State& state) { + std::string s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = s1 + std::to_string(i) + " end"; + benchmark::DoNotOptimize(str); + } + } +} + +void ConcatSimToStd(benchmark::State& state) { + std::string s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = +s1 + i + " end"; + benchmark::DoNotOptimize(str); + } + } +} + +void ConcatSimToSim(benchmark::State& state) { + stra s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + stringa str = s1 + i + " end"; + benchmark::DoNotOptimize(str); + } + } +} + +BENCHMARK(__)->Name("----- Concatenate string + Number + \"Literal\" ---------")->Repetitions(1); +BENCHMARK(ConcatStdToStd) ->Name("Concat std::string and number by std to std::string"); +BENCHMARK(ConcatSimToStd) ->Name("Concat std::string and number by StrExpr to std::string"); +BENCHMARK(ConcatSimToSim) ->Name("Concat stringa and number by StrExpr to simstr::stringa"); + +void ConcatStdToStdHex(benchmark::State& state) { + // We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer. + std::string s1 = "art "; + for (auto _: state) { + for (unsigned i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + // What is standard method to get hex number? + std::string str = s1 + std::format("0x{:x}", i) + " end"; + benchmark::DoNotOptimize(str); + } + } +} +void ConcatSimToStdHex(benchmark::State& state) { + // We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer. + std::string s1 = "art "; + for (auto _: state) { + for (unsigned i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = +s1 + e_hex(i) + " end"; + benchmark::DoNotOptimize(str); + } + } +} + +void ConcatSimToSimHex(benchmark::State& state) { + // stringa SSO buffer is 23, but we use a short string to compare under the same conditions + stra s1 = "art "; + for (auto _: state) { + for (unsigned i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + stringa str = s1 + e_hex(i) + " end"; + benchmark::DoNotOptimize(str); + } + } +} + +BENCHMARK(__)->Name("----- Concatenate string + Hex Number + \"Literal\" ---------")->Repetitions(1); +BENCHMARK(ConcatStdToStdHex) ->Name("Concat std::string and hex number by std to std::string"); +BENCHMARK(ConcatSimToStdHex) ->Name("Concat std::string and hex number by StrExpr to std::string"); +BENCHMARK(ConcatSimToSimHex) ->Name("Concat stringa and hex number by StrExpr to simstr::stringa"); + +void ConcatStdToStdS(benchmark::State& state) { + std::string s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = s1 + " end"; + benchmark::DoNotOptimize(str); + } + } +} + +void ConcatSimToStdS(benchmark::State& state) { + std::string s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = +s1 + " end"; + benchmark::DoNotOptimize(str); + } + } +} + +void ConcatSimToSimS(benchmark::State& state) { + stra s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + stringa str = s1 + " end"; + benchmark::DoNotOptimize(str); + } + } +} + +BENCHMARK(__)->Name("----- Concatenate string + \"Literal\" ---------")->Repetitions(1); +BENCHMARK(ConcatStdToStdS) ->Name("Concat std::string by std to std::string"); +BENCHMARK(ConcatSimToStdS) ->Name("Concat std::string by StrExpr to std::string"); +BENCHMARK(ConcatSimToSimS) ->Name("Concat stringa by StrExpr to stringa"); + +size_t find_pos_str(std::string_view src, std::string_view name) { + // before C++26 we can not concatenate string and string_view... + return src.find("\n- "s + std::string{name} + " -\n"); +} + +size_t find_pos_exp(ssa src, ssa name) { + return src.find(std::string{"\n- " + name + " -\n"}); +} + +size_t find_pos_sim(ssa src, ssa name) { + return src.find(lstringa<200>{"\n- " + name + " -\n"}); +} + +//> size_t find_pos_str(std::string_view src, std::string_view name) { +void FindConcatThreeStr(benchmark::State& state) { + std::string_view src = "sdfsdf\n- testtesttesttesttesttesttestte -\nsfrgdgfsg"; + std::string_view fnd = "testtesttesttesttesttesttestte"; + for (auto _: state) { + benchmark::DoNotOptimize(src); + benchmark::DoNotOptimize(fnd); + size_t pos = find_pos_str(src, fnd); + benchmark::DoNotOptimize(pos); + #ifdef CHECK_RESULT + if (pos != 6) { + state.SkipWithError("fail"); + } + #endif + } +} + +//> size_t find_pos_exp(ssa src, ssa name) { +void FindConcatThreeExp(benchmark::State& state) { + std::string_view src = "sdfsdf\n- testtesttesttesttesttesttestte -\nsfrgdgfsg"; + std::string_view fnd = "testtesttesttesttesttesttestte"; + for (auto _: state) { + benchmark::DoNotOptimize(src); + benchmark::DoNotOptimize(fnd); + size_t pos = find_pos_exp(src, fnd); + benchmark::DoNotOptimize(pos); + #ifdef CHECK_RESULT + if (pos != 6) { + state.SkipWithError("fail"); + } + #endif + } +} + +//> size_t find_pos_sim(ssa src, ssa name) { +void FindConcatThreeSim(benchmark::State& state) { + ssa src = "sdfsdf\n- testtesttesttesttesttesttestte -\nsfrgdgfsg"; + ssa fnd = "testtesttesttesttesttesttestte"; + for (auto _: state) { + benchmark::DoNotOptimize(src); + benchmark::DoNotOptimize(fnd); + size_t pos = find_pos_sim(src, fnd); + benchmark::DoNotOptimize(pos); + #ifdef CHECK_RESULT + if (pos != 6) { + state.SkipWithError("fail"); + } + #endif + } +} + +BENCHMARK(__)->Name("----- Find three concatenated string in string_view -----")->Repetitions(1); +BENCHMARK(FindConcatThreeStr)->Name("Find concat three std::string"); +BENCHMARK(FindConcatThreeExp)->Name("Find concat three strexpr"); +BENCHMARK(FindConcatThreeSim)->Name("Find concat three simstr"); + + +std::string buildTypeNameStr(std::string_view type_name, size_t prec, size_t scale) { + std::string res{type_name}; + if (prec) { + res += "(" + std::to_string(prec); + if (scale) { + res += "," + std::to_string(scale); + } + res += ")"; + } + return res; +} + +std::string buildTypeNameExp(ssa type_name, size_t prec, size_t scale) { + if (prec) { + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +} + +stringa buildTypeNameSim(ssa type_name, size_t prec, size_t scale) { + if (prec) { + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +} + +//> std::string buildTypeNameStr(std::string_view type_name, size_t prec, size_t scale) { +void BuildTypeNameStr(benchmark::State& state) { + std::string_view type_name = "numeric"; + size_t prec = state.range(0), scale = prec / 2; + for (auto _: state) { + benchmark::DoNotOptimize(type_name); + benchmark::DoNotOptimize(prec); + benchmark::DoNotOptimize(scale); + std::string res = buildTypeNameStr(type_name, prec, scale); + benchmark::DoNotOptimize(res); + } +} + +//> std::string buildTypeNameExp(ssa type_name, size_t prec, size_t scale) { +void BuildTypeNameExp(benchmark::State& state) { + std::string_view type_name = "numeric"; + size_t prec = state.range(0), scale = prec / 2; + for (auto _: state) { + benchmark::DoNotOptimize(type_name); + benchmark::DoNotOptimize(prec); + benchmark::DoNotOptimize(scale); + std::string res = buildTypeNameExp(type_name, prec, scale); + benchmark::DoNotOptimize(res); + } +} + +//> stringa buildTypeNameSim(ssa type_name, size_t prec, size_t scale) { +void BuildTypeNameSim(benchmark::State& state) { + ssa type_name = "numeric"; + size_t prec = state.range(0), scale = prec / 2; + for (auto _: state) { + benchmark::DoNotOptimize(type_name); + benchmark::DoNotOptimize(prec); + benchmark::DoNotOptimize(scale); + stringa res = buildTypeNameSim(type_name, prec, scale); + benchmark::DoNotOptimize(res); + } +} + +BENCHMARK(__)->Name("----- Build Type Name ---------")->Repetitions(1); +BENCHMARK(BuildTypeNameStr) ->Name("BuildTypeNameStr 0")->Arg(0); +BENCHMARK(BuildTypeNameExp) ->Name("BuildTypeNameExp 0")->Arg(0); +BENCHMARK(BuildTypeNameSim) ->Name("BuildTypeNameSim 0")->Arg(0); +BENCHMARK(BuildTypeNameStr) ->Name("BuildTypeNameStr 10")->Arg(10); +BENCHMARK(BuildTypeNameExp) ->Name("BuildTypeNameExp 10")->Arg(10); +BENCHMARK(BuildTypeNameSim) ->Name("BuildTypeNameSim 10")->Arg(10); + +std::string make_str_str(std::string_view from, std::string_view pattern, std::string_view repl) { + auto str_replace = [](std::string_view from, std::string_view pattern, std::string_view repl) { + std::string result; + for (size_t offset = 0; ;) { + size_t pos = from.find(pattern, offset); + if (pos == std::string::npos) { + result += from.substr(offset); + break; + } + result += from.substr(offset, pos - offset); + result += repl; + offset = pos + pattern.length(); + } + return result; + }; + return "<" + str_replace(from, pattern, repl) + ">"; +} + +std::string make_str_exp(std::string_view from, std::string_view pattern, std::string_view repl) { + return "<" + e_repl(from, pattern, repl) + ">"; +} + +//> std::string make_str_str(std::string_view from, std::string_view pattern, std::string_view repl) { +void ReplaceStr(benchmark::State& state) { + std::string_view from = "testitestitestitesti", what = "te", repl = "--+--"; + + for (auto _: state) { + benchmark::DoNotOptimize(from); + benchmark::DoNotOptimize(what); + benchmark::DoNotOptimize(repl); + std::string res = make_str_str(from, what, repl); + benchmark::DoNotOptimize(res); + } +} + +//> std::string make_str_exp(std::string_view from, std::string_view pattern, std::string_view repl) { +void ReplaceExp(benchmark::State& state) { + std::string_view from = "testitestitestitesti", what = "te", repl = "--+--"; + + for (auto _: state) { + benchmark::DoNotOptimize(from); + benchmark::DoNotOptimize(what); + benchmark::DoNotOptimize(repl); + std::string res = make_str_exp(from, what, repl); + benchmark::DoNotOptimize(res); + } +} + +BENCHMARK(__)->Name("----- Replace string by copy -----")->Repetitions(1); +BENCHMARK(ReplaceStr)->Name("Concat with replace str"); +BENCHMARK(ReplaceExp)->Name("Concat with replace exp"); + template void CreateEmpty(benchmark::State& state) { for (auto _: state) { @@ -1861,7 +2173,7 @@ void BuildFuncNameSimStr(benchmark::State& state) { stringa res = f.f.build_full_name(); benchmark::DoNotOptimize(res); #ifdef CHECK_RESULT - if (res != stra{f.check}) { + if (res != ssa{f.check}) { std::cout << res << "\n"; state.SkipWithError("not equal"); break; @@ -1878,7 +2190,7 @@ void BuildFuncNameSimStr1(benchmark::State& state) { stringa res = f.f.build_full_name1(); benchmark::DoNotOptimize(res); #ifdef CHECK_RESULT - if (res != stra{f.check}) { + if (res != ssa{f.check}) { std::cout << res << "\n"; state.SkipWithError("not equal"); break; diff --git a/bench/comments.txt b/bench/comments.txt index 129b912..b58da33 100644 --- a/bench/comments.txt +++ b/bench/comments.txt @@ -1,5 +1,27 @@ +- Concat stringa and number by StrExpr to simstr::stringa +stringa в отличии от std::string, +вмещает в SSO 23 символа вместо 15, поэтому +в конце теста std::string приходится аллоцировать память, +а в stringa весь тест входит в SSO. +Unlike std::string, stringa +holds 23 characters in SSO instead of 15, so +at the end of the std::string test, memory has to be allocated, +while in stringa , the entire test is included in SSO. + +- Find concat three simstr +Если результат конкатенации меньше 207 символов, +он собирается в буфере на стеке, без аллокации и деалокации. +If the concatenation result is less than 207 characters, +it is collected in a stack-based buffer, without allocation or deallocation. + +- Concat with replace exp +В simstr строковое выражение для замены подстрок +есть "из коробки". +simstr has a string expression for replacing substrings out of the box. + - std::string e; Пустые строки, ничего необычного. +Empty lines, nothing unusual. - std::string_view e; - ssa e; @@ -10,80 +32,111 @@ - std::string e = "Test text"; Короткий литерал помещается во внутренний буфер std::string, время тратится только на копирование 10 байтов. +The short literal is placed in the internal std::string buffer; +time is spent only copying 10 bytes. - std::string_view e = "Test text"; И string_view, и ssa - по сути одно и то же: указатель на текст и его длина. +Both string_view and ssa are essentially the same thing: +a pointer to text and its length. - ssa e = "Test text"; - stringa e = "Test text"; stringa при инициализации константным литералом так же сохраняет только указатель на текст и его длину. +When initialized with a constant literal, stringa also stores +only a pointer to the text and its length. - lstringa<20> e = "Test text"; Внутреннего буфера хватает для размещения символов, время уходит только на копирование байтов. +The internal buffer is sufficient to accommodate characters; +time is spent only on copying bytes. - lstringa<40> e = "Test text"; - std::string e = "123456789012345678901234567890"; Вот тут уже литерал не помещается во внутренний буфер, возникает аллокация и копирование 30-и байтов. Но как же отстает аллокация под Windows от Linux'а, 20 vs 70 ns... - +Here, the literal doesn't fit into the internal buffer, +and 30 bytes are allocated and copied. +But how much slower is allocation under Windows than under Linux, 20 ns vs. 70 ns... - std::string_view e = "123456789012345678901234567890"; string_view и ssa по прежнему ничего не делают, кроме запоминания указателя на текст и его размера. +string_view and ssa still do nothing except +remember the pointer to the text and its size. - ssa e = "123456789012345678901234567890"; - stringa e = "123456789012345678901234567890"; stringa на константных литералах не отстает! +stringa doesn't lag behind on constant literals! - lstringa<20> e = "123456789012345678901234567890"; lstringa<20> может вместить в себя до 23 символов, Очевидно, что для 30-и символов уже нужна аллокация. +Obviously, 30 characters already require allocation. - lstringa<40> e = "123456789012345678901234567890"; А в lstringa<40> влезает до 47 символов, так что просто копируется 30 байтов. +And lstringa<40> can hold up to 47 characters, so 30 +bytes are simply copied. - std::string e = "Test text"; auto c{e}; Строка в пределах SSO, так что просто копирует байты. +The string is within the SSO, so it just copies the bytes. - std::string_view e = "Test text"; auto c{e}; - ssa e = "Test text"; auto c{e}; ssa и string_view не владеют строкой, копируется только информация о строке. +ssa and string_view don't own the string; only the +string information is copied. - stringa e = "Test text"; auto c{e}; Копирование stringa происходит быстро, особенно если она инициализирована литералом. +Copying a stringa is fast, +especially if it is initialized with a literal. - lstringa<20> e = "Test text"; auto c{e}; В обоих случаях хватает внутреннего буфера. +In both cases, the internal buffer is sufficient. - lstringa<40> e = "Test text"; auto c{e}; Только копируются байты. +Only bytes are copied. - std::string e = "123456789012345678901234567890"; auto c{e}; Копирования длинной строки вызывает аллокацию, SSO уже не хватает. И снова как же отстаёт аллокация под Windows... +Copying a long string causes allocations, +SSO is no longer sufficient. And again, how allocation lags under Windows... - std::string_view e = "123456789012345678901234567890"; auto c{e}; - ssa e = "123456789012345678901234567890"; auto c{e}; - stringa e = "123456789012345678901234567890"; auto c{e}; А вот у stringa копирование литерала не зависит от его длины, сравни с предыдущим бенчмарком. +But with stringa, literal copying doesn't depend on its length, +compare with the previous benchmark. - lstringa<20> e = "123456789012345678901234567890"; auto c{e}; Не влезает, аллокация. +Doesn't fit, allocation. - lstringa<40> e = "123456789012345678901234567890"; auto c{e}; Уложили во внутренний буфер. +Placed in the internal buffer. - std::string::find; Здесь "победила дружба", у всех типов по колонке примерно одинаково. Однако, Windows и Linux явно в разных весовых категориях. +Here, "friendship wins," with all types scoring roughly equally. +However, Windows and Linux are clearly in different weight classes. - std::string_view::find; - ssa::find; @@ -95,9 +148,13 @@ SSO уже не хватает. И снова как же отстаёт алл Явно виден скачок, где заканчивается SSO и начинается аллокация. Обратите внимание, что WASM - 32-битный, и там размер SSO у std::string меньше, насколько я помню, 11 символов + 0. +The jump where SSO ends and allocation begins is clearly visible. +Note that WASM is 32-bit, and the size of the SSO for std::string is +smaller, as far as I remember: 11 characters + 0. - std::string copy{str_with_len_N};/23 Дальше просто добавляется время на копирование байтов. +Then the time for copying bytes is simply added. - std::string copy{str_with_len_N};/24 - std::string copy{str_with_len_N};/32 @@ -109,23 +166,33 @@ SSO у std::string меньше, насколько я помню, 11 симво - std::string copy{str_with_len_N};/2048 - std::string copy{str_with_len_N};/4096 Чем длиннее строка, тем дольше создаётся копия. +The longer the string, the longer it takes to create a copy. - stringa copy{str_with_len_N};/15 Здесь stringa инициализируется не литералом, а значит, должна сама хранить символы. +Here, stringa is not initialized with a literal, +meaning it must store characters itself. - stringa copy{str_with_len_N};/16 Под WASM SSO у stringa составляет 15 символов. Кроме того, -собиралось без поддержки потоков, поэтому возможно атомарный +собиралось без поддержки потоков, поэтому атомарный инкремент заменён на обычный, судя по времени. +Under WASM, stringa has a 15-character SSO. Furthermore, +it was built without thread support, so the atomic +increment was replaced with a regular one, judging by the time. - stringa copy{str_with_len_N};/23 SSO в stringa до 23 символов, и даже 23 копируются быстрее, чем 15 в std::string. +SSO in stringa is up to 23 characters, and even 23 +copies faster than 15 in std::string. - stringa copy{str_with_len_N};/24 Всё, не влезаем в SSO, а значит, используем shared буфер. Добавляется время на атомарный инкремент счётчика. +That's it, we're not using SSO, so we're using a shared buffer. +Time is added for the atomic counter increment. - stringa copy{str_with_len_N};/32 - stringa copy{str_with_len_N};/64 @@ -137,15 +204,20 @@ SSO в stringa до 23 символов, и даже 23 - stringa copy{str_with_len_N};/4096 И как видно, кроме инкремента нет накладных расходов, время копирования не зависит от длины строки. +And as you can see, there are no overhead costs other than the +increment; copying time does not depend on the string length. - lstringa<16> copy{str_with_len_N};/15 lstringa<16> использует SSO до 23 символов. А в WASM 32-битная архитектура, SSO до 19 символов. +lstringa<16> uses SSO up to 23 characters. +WASM has a 32-bit architecture, so SSO is up to 19 characters. - lstringa<16> copy{str_with_len_N};/16 - lstringa<16> copy{str_with_len_N};/23 - lstringa<16> copy{str_with_len_N};/24 И после начинает вести себя при копировании, как std::string. +And then it starts to behave like std::string when copied. - lstringa<16> copy{str_with_len_N};/32 - lstringa<16> copy{str_with_len_N};/64 @@ -158,6 +230,8 @@ lstringa<16> использует SSO до 23 символов. - lstringa<512> copy{str_with_len_N};/8 А вот lstringa<512> имеет гораздо больший внутренний буфер и копирует символы без аллокации. +But lstringa<512> has a much larger internal +buffer and copies characters without allocation. - lstringa<512> copy{str_with_len_N};/16 - lstringa<512> copy{str_with_len_N};/32 @@ -167,9 +241,12 @@ lstringa<16> использует SSO до 23 символов. - lstringa<512> copy{str_with_len_N};/512 Даже 512 символов копируются быстрее, чем одна аллокация или атомарный инкремент. +Even 512 characters are copied faster than a single +allocation or atomic increment. - lstringa<512> copy{str_with_len_N};/1024 -А дальше уже как у всех +А дальше уже как у всех. +And then it's like everyone else. - lstringa<512> copy{str_with_len_N};/2048 - lstringa<512> copy{str_with_len_N};/4096 @@ -180,19 +257,28 @@ lstringa<16> использует SSO до 23 символов. поведения "std::from_chars", но он к сожалению очень ограничен по возможностям. Здесь я попытался произвести тесты, близкие по логике к работе std::from_chars +In simstr, a string fragment is sufficient for conversion to a number; +there's no need for null termination. The closest analog to this behavior +is "std::from_chars," but unfortunately, it is very limited in its capabilities. +Here, I attempted to run tests that are similar in logic to std::from_chars. - std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10); from_chars требует точного указания основания счисления, не допускает знаков плюс, пробелов, префиксов 0x и т.п. +from_chars requires an exact radix specification and does not allow plus +signs, spaces, 0x prefixes, etc. - stringa s = "123456789"; int res = s.to_int Здесь для to_int заданы такие же ограничения - проверять переполнение, десятичная система, без лидирующих пробелов и знака плюс +Here, to_int has the same restrictions: check for overflow, +decimal system, no leading spaces, and no plus sign. - ssa s = "123456789"; int res = s.to_int - lstringa<20> s = "123456789"; int res = s.to_int - std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16); Всё то же, только для 16ричной системы +Everything is the same, only for the hexadecimal system - std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16); - stringa s = "abcDef"; int res = s.to_int @@ -200,6 +286,7 @@ from_chars требует точного указания основания с - lstringa<20> s = "abcDef"; int res = s.to_int - std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0); А здесь уже парсинг произвольного числа. +And here we have parsing of an arbitrary number. - stringa s = " 123456789"; int res = s.to_int; // Check overflow - ssa s = " 123456789"; int res = s.to_int; // No check overflow @@ -209,6 +296,8 @@ from_chars требует точного указания основания с - lstringa<128> str; ... str += "abbaabbaabbaabba"; Чем больше внутренний буфер, тем меньше раз требуется аллокация, тем быстрее результат. +The larger the internal buffer, the fewer allocations are +required, and the faster the result. - lstringa<512> str; ... str += "abbaabbaabbaabba"; - lstringa<1024> str; ... str += "abbaabbaabbaabba"; @@ -236,20 +325,28 @@ from_chars требует точного указания основания с - std::string str = std::format("test = {} times", k); - lstringa<8> str; str.format("test = {} times", k); В simstr format с первого раза не помещается в такую строку без аллокации. +In simstr format, the first time it doesn't fit into such a +string without allocation. - lstringa<32> str; str.format("test = {} times", k); А в такую помещается. Используйте сразу буфера подходящего размера. +And it fits in this one. Use buffers of the appropriate size right away. - lstringa<8> str = "test = " + k + " times"; Результат не помещается в SSO, возникает аллокация. +The result does not fit into SSO, an allocation occurs. - lstringa<32> str = "test = " + k + " times"; А здесь и ниже - результат укладывается в SSO. Ещё раз - используйте сразу буфера подходящего размера. +And here and below, the result fits within SSO. +Once again, use appropriately sized buffers from the start. - stringa str = "test = " + k + " times"; Под WASM размер SSO 15 символов, что явно не хватает для размещения результата, отсюда и такое время. +Under WASM, the SSO size is 15 characters, which is clearly not +enough to accommodate the result, hence the long time. - std::string::find + substr + std::strtol - ssa::splitter + ssa::as_int @@ -258,9 +355,14 @@ from_chars требует точного указания основания с Это наивная реализация, которая неверно отработает на таких заменах, как 'a'->'b' и 'b'->'a'. Но если замены не конфликтуют, то работает быстро. +This is a naive implementation that will fail to handle substitutions +such as 'a'->'b' and 'b'->'a'. But if the substitutions don't conflict, +it works quickly. - replace symbols with std::string find_first_of + replace Дальше уже правильные реализации, не зависящие от конфликтующих замен. +Further, there are correct implementations that do not depend on +conflicting replacements. - replace symbols with std::string_view find_first_of + copy - replace runtime symbols with string expressions and without remembering all search results @@ -278,6 +380,8 @@ from_chars требует точного указания основания с - replace bb to ---- in 64 std::string Тут проверяется тяжелый случай - замена подстроки на более длинную. Обычная реализация несколько раз передвигает хвост. +This checks for a difficult case: replacing a substring with a longer +one. The standard implementation moves the tail several times. - replace bb to ---- in 64 lstringa<8> - replace bb to ---- in 64 str by init stringa @@ -292,11 +396,13 @@ from_chars требует точного указания основания с - replace bb to ---- in 1024 str by init stringa - replace bb to ---- in 2048 std::string Чем длиннее строка, тем больше замедляется std::string +The longer the string, the slower std::string becomes. - replace bb to ---- in 2048 lstringa<8> - replace bb to ---- in 2048 str by init stringa - replace bb to -- in 64 std::string Идеальный случай замены - на подстроку такой же длины +The ideal case of replacement is with a substring of the same length. - replace bb to -- in 64 lstringa<8> - replace bb to -- in 64 by init stringa @@ -315,37 +421,55 @@ from_chars требует точного указания основания с - hashStrMapA emplace & find stringa; Вставляем в hashStrMapA 10000 stringa длиной от 30 до 50 символов, а потом ищем их в ней +We insert 10,000 strings of length from 30 to 50 characters into +hashStrMapA, and then search for them in it. - std::unordered_map emplace & find std::string; То же самое c std::string и std::unordered_map +Same thing with std::string and std::unordered_map - hashStrMapA emplace & find ssa; Теперь вставляем stringa, а ищем ssa +Now we insert stringa and search for ssa - std::unordered_map emplace & find std::string_view; Вставляем std::string, а ищем std::string_view +We insert std::string and look for std::string_view - Build func full name std::string; Обыденная задача, подобные часто могут встретится в работе: По неким данным сгенерировать текст. В этом случае по данным о неких функциях сформировать их полное имя с типами параметров и возвращаемого значения. Алгоритм на std::string. +A common task, similar to this one, can often be encountered in work: +Generate text from given data. In this case, using data +on certain functions, generate their full names with parameter types and +return values. The algorithm uses std::string. - Build func full name std::string 1; Почти тот же алгоритм, но несколько последовательных += к строке заменены на одно += + + +. +Almost the same algorithm, but several consecutive ++= to a string are replaced with a single += + + +. - Build func full name std::stream; Строим имя функции через std::ostringstream и << +We construct the function name through std::ostringstream and << - Build func full name stringa; Реализация на simstr строках и строковых выражениях. Инфа о параметрах добавляется в текущую строку +Implementation using simstr strings and string expressions. +Parameter information is appended to the current line. - Build func full name stringa 1; Реализация на simstr строках и строковых выражениях. Инфа о параметрах добавляется во временную строку, а потом разом добавляется в текущую строку. Позволяет операции в цикле записать в одну строку, но чуть проигрывает по времени выполнения. +Implementation using simstr strings and string expressions. +Parameter information is added to a temporary string, and then +all at once to the current string. This allows loop operations +to be written in a single string, but is slightly slower in execution time. - Пусто diff --git a/bench/process_result.cpp b/bench/process_result.cpp index 829ae06..0c82d7d 100644 --- a/bench/process_result.cpp +++ b/bench/process_result.cpp @@ -27,7 +27,7 @@ bool extract_cpu_info(ssa text, ssa& res) { struct result_info { stringa text_; stringa platform_; - ssa current_text_{text_}; + ssa current_text_ = text_.to_str(); ssa cpu_info_; result_info(stringa text, stringa platform) : text_(std::move(text)), platform_(std::move(platform)) { @@ -94,9 +94,9 @@ results_vector get_results_infos() { ssa fileName = f; // В начале имени файла может идти число и дефис, для сортировки, уберём их // At the beginning of the file name there can be a number and a hyphen, for sorting, remove them - if (auto delimeter = fileName.find('-'); delimeter + 1 > 1) { - if (fileName(0, delimeter).to_int().ec == IntConvertResult::Success) { - fileName.remove_prefix(delimeter + 1); + if (auto delimiter = fileName.find('-'); delimiter + 1 > 1) { + if (fileName(0, delimiter).to_int().ec == IntConvertResult::Success) { + fileName.remove_prefix(delimiter + 1); } } results.emplace_back(get_file_content(lstringa<128>{dirForResults + f}), fileName(0, -suffix.length())); @@ -129,9 +129,19 @@ auto repl_html_symbols(ssa text) { return e_repl_const_symbols(text, '\"', """, '<', "<", '\'', "'", '&', "&"); } -void write_benchset_header(out_t& out, const results_vector& results, ssa benchsetName, unsigned id) { +void write_benchset_header(out_t& out, const results_vector& results, ssa benchsetName, unsigned benchSetId) { + size_t hash = fnv_hash(benchsetName.symbols(), benchsetName.length()); + static std::unordered_map ids; + auto [id, _] = ids.try_emplace(hash, 0); + if (id->second) { + std::cout << "Duplicate hash for " << benchsetName << "\n"; + } + int ii = id->second++; + size_t width = 40 / results.size(); - out += "\n\n

" + repl_html_symbols(benchsetName) + "

\n"; + out += "\n\n

# " + repl_html_symbols(benchsetName) + + "

\n
Benchmark nameComment
"; for (const auto& r : results) { out += ""; } @@ -184,6 +194,9 @@ void write_one_result(out_t& out, ssa result, ssa line, auto& script_text, bool } ssa extract_source_for_benchmark(ssa benchName, ssa sourceText) { + if (benchName == "ReplaceStr") { + int t = 0; + } static hashStrMapA textes; size_t delim = benchName.find_last('/'); diff --git a/bench/results.html b/bench/results.html index 64b5d4e..3509e8b 100644 --- a/bench/results.html +++ b/bench/results.html @@ -274,13 +274,15 @@ L1 Instruction 32 KiB (x16) L2 Unified 256 KiB (x16) L3 Unified 40960 KiB (x1) -Load Average: 0.10, 0.62, 0.73 Include in charts: +Load Average: 0.00, 0.23, 0.51 +***WARNING*** ASLR is enabled, the results may have unreproducible noise in them. Include in charts:
  • Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-1332 X 2494.22 MHz CPU sCPU Caches: L1 Data 32 KiB (x16) L1 Instruction 32 KiB (x16) L2 Unified 256 KiB (x16) L3 Unified 40960 KiB (x1) -Load Average: 0.02, 0.05, 0.12 Include in charts:
  • +Load Average: 0.00, 0.00, 0.00 +***WARNING*** ASLR is enabled, the results may have unreproducible noise in them. Include in charts:
  • Xeon E5-2682 v4, Windows 10, Clang-1932 X 2494 MHz CPU sCPU Caches: L1 Data 32 KiB (x16) L1 Instruction 32 KiB (x16) @@ -291,66 +293,299 @@ Load Average: 0.02, 0.05, 0.12 Include in charts:  Include in charts:
  • -
  • Xeon E5-2682 v4, WASM Chrome, Clang-2132 X 2513.96 MHz CPU sChromium: 142.0.7444.60 webasm Include in charts:
  • +
  • Xeon E5-2682 v4, WASM Firefox, Clang-2132 X 2513.96 MHz CPU sFirefox: 146.0.1.60 webasm Include in charts:
  • - + -

    Create Empty Str

    -
    Benchmark nameComment" + r.platform_ + "
    +

    # Concatenate string + Number + "Literal"

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    + + + +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    Concat std::string and number by std to std::stringvoid ConcatStdToStd(benchmark::State& state) { + std::string s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = s1 + std::to_string(i) + " end"; + benchmark::DoNotOptimize(str); + } + } +}226207266331925
    Concat std::string and number by StrExpr to std::stringvoid ConcatSimToStd(benchmark::State& state) { + std::string s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = +s1 + i + " end"; + benchmark::DoNotOptimize(str); + } + } +}104102157211415
    Concat stringa and number by StrExpr to simstr::stringavoid ConcatSimToSim(benchmark::State& state) { + stra s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + stringa str = s1 + i + " end"; + benchmark::DoNotOptimize(str); + } + } +} >> stringa в отличии от std::string, +вмещает в SSO 23 символа вместо 15, поэтому +в конце теста std::string приходится аллоцировать память, +а в stringa весь тест входит в SSO. +Unlike std::string, stringa +holds 23 characters in SSO instead of 15, so +at the end of the std::string test, memory has to be allocated, +while in stringa , the entire test is included in SSO.63.770.466.4108211
    + +

    # Concatenate string + Hex Number + "Literal"

    + + + + +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    Concat std::string and hex number by std to std::stringvoid ConcatStdToStdHex(benchmark::State& state) { + // We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer. + std::string s1 = "art "; + for (auto _: state) { + for (unsigned i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + // What is standard method to get hex number? + std::string str = s1 + std::format("0x{:x}", i) + " end"; + benchmark::DoNotOptimize(str); + } + } +}68166877710741446
    Concat std::string and hex number by StrExpr to std::stringvoid ConcatSimToStdHex(benchmark::State& state) { + // We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer. + std::string s1 = "art "; + for (auto _: state) { + for (unsigned i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = +s1 + e_hex<HexFlags::Short>(i) + " end"; + benchmark::DoNotOptimize(str); + } + } +}71.765.976.6136365
    Concat stringa and hex number by StrExpr to simstr::stringavoid ConcatSimToSimHex(benchmark::State& state) { + // stringa SSO buffer is 23, but we use a short string to compare under the same conditions + stra s1 = "art "; + for (auto _: state) { + for (unsigned i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + stringa str = s1 + e_hex<HexFlags::Short>(i) + " end"; + benchmark::DoNotOptimize(str); + } + } +}67.968.267.9101196
    + +

    # Concatenate string + "Literal"

    + + + + +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    Concat std::string by std to std::stringvoid ConcatStdToStdS(benchmark::State& state) { + std::string s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = s1 + " end"; + benchmark::DoNotOptimize(str); + } + } +}49.744.739.855.4111
    Concat std::string by StrExpr to std::stringvoid ConcatSimToStdS(benchmark::State& state) { + std::string s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + std::string str = +s1 + " end"; + benchmark::DoNotOptimize(str); + } + } +}40.535.939.177.9113
    Concat stringa by StrExpr to stringavoid ConcatSimToSimS(benchmark::State& state) { + stra s1 = "start "; + for (auto _: state) { + for (int i = 1; i <= 100'000; i *= 10) { + benchmark::DoNotOptimize(s1); + stringa str = s1 + " end"; + benchmark::DoNotOptimize(str); + } + } +}27.025.929.252.595.9
    + +

    # Find three concatenated string in string_view

    + + + + +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    Find concat three std::stringsize_t find_pos_str(std::string_view src, std::string_view name) { + // before C++26 we can not concatenate string and string_view... + return src.find("\n- "s + std::string{name} + " -\n"); +}116130208225178
    Find concat three strexprsize_t find_pos_exp(ssa src, ssa name) { + return src.find(std::string{"\n- " + name + " -\n"}); +}51.139.8116122106
    Find concat three simstrsize_t find_pos_sim(ssa src, ssa name) { + return src.find(lstringa<200>{"\n- " + name + " -\n"}); +} >> Если результат конкатенации меньше 207 символов, +он собирается в буфере на стеке, без аллокации и деалокации. +If the concatenation result is less than 207 characters, +it is collected in a stack-based buffer, without allocation or deallocation.19.620.222.228.473.7
    + +

    # Build Type Name

    + + + + + + + +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    BuildTypeNameStr 0/0std::string buildTypeNameStr(std::string_view type_name, size_t prec, size_t scale) { + std::string res{type_name}; + if (prec) { + res += "(" + std::to_string(prec); + if (scale) { + res += "," + std::to_string(scale); + } + res += ")"; + } + return res; +}7.6410.78.2517.918.2
    BuildTypeNameExp 0/0std::string buildTypeNameExp(ssa type_name, size_t prec, size_t scale) { + if (prec) { + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +}6.526.637.5014.217.0
    BuildTypeNameSim 0/0stringa buildTypeNameSim(ssa type_name, size_t prec, size_t scale) { + if (prec) { + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +}4.995.238.3517.217.0
    BuildTypeNameStr 10/10std::string buildTypeNameStr(std::string_view type_name, size_t prec, size_t scale) { + std::string res{type_name}; + if (prec) { + res += "(" + std::to_string(prec); + if (scale) { + res += "," + std::to_string(scale); + } + res += ")"; + } + return res; +}56.891.959.579.4275
    BuildTypeNameExp 10/10std::string buildTypeNameExp(ssa type_name, size_t prec, size_t scale) { + if (prec) { + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +}30.525.334.240.099.6
    BuildTypeNameSim 10/10stringa buildTypeNameSim(ssa type_name, size_t prec, size_t scale) { + if (prec) { + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +}22.722.726.437.971.2
    + +

    # Replace string by copy

    + + + +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    Concat with replace strstd::string make_str_str(std::string_view from, std::string_view pattern, std::string_view repl) { + auto str_replace = [](std::string_view from, std::string_view pattern, std::string_view repl) { + std::string result; + for (size_t offset = 0; ;) { + size_t pos = from.find(pattern, offset); + if (pos == std::string::npos) { + result += from.substr(offset); + break; + } + result += from.substr(offset, pos - offset); + result += repl; + offset = pos + pattern.length(); + } + return result; + }; + return "<" + str_replace(from, pattern, repl) + ">"; +}207242318362451
    Concat with replace expstd::string make_str_exp(std::string_view from, std::string_view pattern, std::string_view repl) { + return "<" + e_repl(from, pattern, repl) + ">"; +} >> В simstr строковое выражение для замены подстрок +есть "из коробки". +simstr has a string expression for replacing substrings out of the box.149135224223248
    + +

    # Create Empty Str

    + +} +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } -} >> Пустые строки, ничего необычного.1.111.151.112.955.87
     >> Пустые строки, ничего необычного. +Empty lines, nothing unusual.1.121.121.112.632.18
    std::string_view e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } -}0.3690.7430.3681.855.26
    0.3730.7370.3721.840.993
    ssa e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } -}0.3690.1850.3611.524.67
    0.3670.1820.3641.830.952
    stringa e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } -}0.7420.7590.7362.254.82
    0.7530.7510.7572.222.19
    lstringa<20> e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } -}1.131.131.122.584.64
    1.131.121.122.592.26
    lstringa<40> e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } -}1.131.131.132.594.76
    -

    Create Str from short literal (9 symbols)

    - +

    # Create Str from short literal (9 symbols)

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +время тратится только на копирование 10 байтов. +The short literal is placed in the internal std::string buffer; +time is spent only copying 10 bytes. +указатель на текст и его длина. +Both string_view and ssa are essentially the same thing: +a pointer to text and its length. +} +сохраняет только указатель на текст и его длину. +When initialized with a constant literal, stringa also stores +only a pointer to the text and its length. +время уходит только на копирование байтов. +The internal buffer is sufficient to accommodate characters; +time is spent only on copying bytes. -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { @@ -358,7 +593,9 @@ void CreateShortLiteral(benchmark::State& state) { benchmark::DoNotOptimize(empty_string); } } >> Короткий литерал помещается во внутренний буфер std::string, -время тратится только на копирование 10 байтов.1.911.851.872.585.17
    1.841.871.852.642.37
    std::string_view e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { @@ -366,14 +603,16 @@ void CreateShortLiteral(benchmark::State& state) { benchmark::DoNotOptimize(empty_string); } } >> И string_view, и ssa - по сути одно и то же: -указатель на текст и его длина.0.7480.7510.7271.905.57
    0.7500.7300.7281.851.29
    ssa e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; benchmark::DoNotOptimize(empty_string); } -}0.3740.7810.3641.853.41
    0.3810.7360.3701.831.01
    stringa e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { @@ -381,7 +620,9 @@ void CreateShortLiteral(benchmark::State& state) { benchmark::DoNotOptimize(empty_string); } } >> stringa при инициализации константным литералом так же -сохраняет только указатель на текст и его длину.1.111.131.102.925.07
    1.851.121.852.202.63
    lstringa<20> e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { @@ -389,25 +630,27 @@ void CreateShortLiteral(benchmark::State& state) { benchmark::DoNotOptimize(empty_string); } } >> Внутреннего буфера хватает для размещения символов, -время уходит только на копирование байтов.1.881.861.852.595.37
    1.871.871.892.592.77
    lstringa<40> e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; benchmark::DoNotOptimize(empty_string); } -}1.861.881.842.615.37
    -

    Create Str from long literal (30 symbols)

    - +

    # Create Str from long literal (30 symbols)

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +Но как же отстает аллокация под Windows от Linux'а, 20 vs 70 ns... +Here, the literal doesn't fit into the internal buffer, +and 30 bytes are allocated and copied. +But how much slower is allocation under Windows than under Linux, 20 ns vs. 70 ns... +запоминания указателя на текст и его размера. +string_view and ssa still do nothing except +remember the pointer to the text and its size. +} +} +Очевидно, что для 30-и символов уже нужна аллокация. +Obviously, 30 characters already require allocation. -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { @@ -416,7 +659,10 @@ void CreateLongLiteral(benchmark::State& state) { } } >> Вот тут уже литерал не помещается во внутренний буфер, возникает аллокация и копирование 30-и байтов. -Но как же отстает аллокация под Windows от Linux'а, 20 vs 70 ns...18.819.978.576.063.4
    18.819.374.977.516.5
    std::string_view e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { @@ -424,21 +670,24 @@ void CreateLongLiteral(benchmark::State& state) { benchmark::DoNotOptimize(empty_string); } } >> string_view и ssa по прежнему ничего не делают, кроме -запоминания указателя на текст и его размера.0.7470.8080.7311.825.58
    0.7470.7440.7361.831.26
    ssa e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; benchmark::DoNotOptimize(empty_string); } -}0.3730.7540.3711.823.33
    0.3700.7350.3651.831.01
    stringa e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; benchmark::DoNotOptimize(empty_string); } -} >> stringa на константных литералах не отстает!1.131.121.122.584.95
     >> stringa на константных литералах не отстает! +stringa doesn't lag behind on constant literals!1.881.121.852.242.67
    lstringa<20> e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { @@ -446,7 +695,8 @@ void CreateLongLiteral(benchmark::State& state) { benchmark::DoNotOptimize(empty_string); } } >> lstringa<20> может вместить в себя до 23 символов, -Очевидно, что для 30-и символов уже нужна аллокация.21.219.680.176.863.1
    21.020.076.877.716.9
    lstringa<40> e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { @@ -454,18 +704,20 @@ void CreateLongLiteral(benchmark::State& state) { benchmark::DoNotOptimize(empty_string); } } >> А в lstringa<40> влезает до 47 символов, так что просто -копируется 30 байтов.2.571.862.533.335.86
    -

    Create copy of Str with 9 symbols

    - +

    # Create copy of Str with 9 symbols

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +только информация о строке. +ssa and string_view don't own the string; only the +string information is copied. +особенно если она инициализирована литералом. +Copying a stringa is fast, +especially if it is initialized with a literal. +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; @@ -474,7 +726,8 @@ void CopyShortString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -} >> Строка в пределах SSO, так что просто копирует байты.4.984.951.856.0011.0
     >> Строка в пределах SSO, так что просто копирует байты. +The string is within the SSO, so it just copies the bytes.4.834.801.875.432.27
    std::string_view e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; @@ -483,7 +736,7 @@ void CopyShortString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}0.3730.3810.3703.465.91
    0.3770.3730.3682.941.26
    ssa e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; @@ -493,7 +746,9 @@ void CopyShortString(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> ssa и string_view не владеют строкой, копируется -только информация о строке.0.3760.3770.3703.516.84
    0.3680.3760.3752.921.27
    stringa e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; @@ -503,7 +758,9 @@ void CopyShortString(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> Копирование stringa происходит быстро, -особенно если она инициализирована литералом.1.131.351.304.035.18
    1.111.371.324.132.64
    lstringa<20> e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; @@ -512,7 +769,8 @@ void CopyShortString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -} >> В обоих случаях хватает внутреннего буфера.4.844.495.258.5117.5
     >> В обоих случаях хватает внутреннего буфера. +In both cases, the internal buffer is sufficient.4.184.435.307.7414.1
    lstringa<40> e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; @@ -521,18 +779,19 @@ void CopyShortString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -} >> Только копируются байты.4.534.935.368.4317.4
    -

    Create copy of Str with 30 symbols

    - +

    # Create copy of Str with 30 symbols

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +SSO уже не хватает. И снова как же отстаёт аллокация под Windows... +Copying a long string causes allocations, +SSO is no longer sufficient. And again, how allocation lags under Windows... +} +} +сравни с предыдущим бенчмарком. +But with stringa, literal copying doesn't depend on its length, +compare with the previous benchmark. +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; @@ -541,7 +800,9 @@ void CopyLongString(benchmark::State& state) { benchmark::DoNotOptimize(copy); } } >> Копирования длинной строки вызывает аллокацию, -SSO уже не хватает. И снова как же отстаёт аллокация под Windows...19.624.281.783.093.3
    19.824.381.377.534.3
    std::string_view e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; @@ -549,7 +810,7 @@ void CopyLongString(benchmark::State& state) { T copy{x}; benchmark::DoNotOptimize(copy); } -}0.7480.7470.7411.905.57
    0.7520.7240.7411.881.25
    ssa e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; @@ -557,7 +818,7 @@ void CopyLongString(benchmark::State& state) { T copy{x}; benchmark::DoNotOptimize(copy); } -}0.3730.7460.3682.023.32
    0.3750.7520.3621.831.01
    stringa e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; @@ -566,7 +827,9 @@ void CopyLongString(benchmark::State& state) { benchmark::DoNotOptimize(copy); } } >> А вот у stringa копирование литерала не зависит от его длины, -сравни с предыдущим бенчмарком.1.131.131.863.414.89
    1.891.111.833.022.66
    lstringa<20> e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; @@ -574,7 +837,8 @@ void CopyLongString(benchmark::State& state) { T copy{x}; benchmark::DoNotOptimize(copy); } -} >> Не влезает, аллокация.20.024.479.390.466.3
     >> Не влезает, аллокация. +Doesn't fit, allocation.21.020.176.179.317.2
    lstringa<40> e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; @@ -582,18 +846,19 @@ void CopyLongString(benchmark::State& state) { T copy{x}; benchmark::DoNotOptimize(copy); } -} >> Уложили во внутренний буфер.5.404.614.947.1117.0
    -

    Find 9 symbols text in end of 99 symbols text

    - +

    # Find 9 symbols text in end of 99 symbols text

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +Однако, Windows и Linux явно в разных весовых категориях. +Here, "friendship wins," with all types scoring roughly equally. +However, Windows and Linux are clearly in different weight classes. +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; @@ -609,7 +874,9 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> Здесь "победила дружба", у всех типов по колонке примерно одинаково. -Однако, Windows и Linux явно в разных весовых категориях.6.876.8739.545.0101
    7.867.3338.340.754.3
    std::string_view::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; @@ -624,7 +891,7 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } -}7.757.3940.044.2103
    7.366.7838.140.853.4
    ssa::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; @@ -639,7 +906,7 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } -}6.966.9318.121.8102
    7.036.3218.322.652.7
    stringa::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; @@ -654,7 +921,7 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } -}7.388.0019.431.0105
    7.176.7719.828.453.8
    lstringa<20>::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; @@ -669,7 +936,7 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } -}6.906.9218.126.399.9
    6.436.3317.623.252.5
    lstringa<40>::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; @@ -684,18 +951,18 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } -}6.836.8718.124.9100
    -

    Copy not literal Str with N symbols

    - +

    # Copy not literal Str with N symbols

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +SSO у std::string меньше, насколько я помню, 11 символов + 0. +The jump where SSO ends and allocation begins is clearly visible. +Note that WASM is 32-bit, and the size of the SSO for std::string is +smaller, as far as I remember: 11 characters + 0. +} +} +} +} +} +} +} +} +} +} +а значит, должна сама хранить символы. +Here, stringa is not initialized with a literal, +meaning it must store characters itself. +собиралось без поддержки потоков, поэтому атомарный +инкремент заменён на обычный, судя по времени. +Under WASM, stringa has a 15-character SSO. Furthermore, +it was built without thread support, so the atomic +increment was replaced with a regular one, judging by the time. +копируются быстрее, чем 15 в std::string. +SSO in stringa is up to 23 characters, and even 23 +copies faster than 15 in std::string. +Добавляется время на атомарный инкремент счётчика. +That's it, we're not using SSO, so we're using a shared buffer. +Time is added for the atomic counter increment. +} +} +} +} +} +} +} +время копирования не зависит от длины строки. +And as you can see, there are no overhead costs other than the +increment; copying time does not depend on the string length. +А в WASM 32-битная архитектура, SSO до 19 символов. +lstringa<16> uses SSO up to 23 characters. +WASM has a 32-bit architecture, so SSO is up to 19 characters. +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +одна аллокация или атомарный инкремент. +Even 512 characters are copied faster than a single +allocation or atomic increment. +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -704,7 +971,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}4.905.071.864.4597.2
    5.695.201.865.2735.9
    std::string copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -715,7 +982,10 @@ void CopyDynString(benchmark::State& state) { } } >> Явно виден скачок, где заканчивается SSO и начинается аллокация. Обратите внимание, что WASM - 32-битный, и там размер -SSO у std::string меньше, насколько я помню, 11 символов + 0.23.123.781.694.094.6
    23.623.680.483.435.4
    std::string copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -724,7 +994,8 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -} >> Дальше просто добавляется время на копирование байтов.23.223.979.894.891.6
     >> Дальше просто добавляется время на копирование байтов. +Then the time for copying bytes is simply added.24.023.078.082.936.3
    std::string copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -733,7 +1004,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}22.324.980.597.794.5
    23.323.180.283.835.6
    std::string copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -742,7 +1013,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}22.222.686.295.897.0
    23.223.482.788.039.4
    std::string copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -751,7 +1022,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}22.622.979.394.198.1
    23.324.082.084.339.6
    std::string copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -760,7 +1031,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}26.224.285.0103103
    25.224.589.887.841.3
    std::string copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -769,7 +1040,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}27.325.584.4105161
    25.425.191.488.558.6
    std::string copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -778,7 +1049,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}28.329.286.697.1151
    29.929.089.291.653.9
    std::string copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -787,7 +1058,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}39.637.295.399.1131
    44.144.396.899.953.1
    std::string copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -796,7 +1067,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}81.381.5127140148
    13013013012977.9
    std::string copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -805,7 +1076,8 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -} >> Чем длиннее строка, тем дольше создаётся копия.117118176187185
     >> Чем длиннее строка, тем дольше создаётся копия. +The longer the string, the longer it takes to create a copy.153157178177130
    stringa copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -815,7 +1087,9 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> Здесь stringa инициализируется не литералом, -а значит, должна сама хранить символы.1.131.131.344.035.19
    1.101.141.284.052.64
    stringa copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -825,8 +1099,11 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> Под WASM SSO у stringa составляет 15 символов. Кроме того, -собиралось без поддержки потоков, поэтому возможно атомарный -инкремент заменён на обычный, судя по времени.1.121.141.354.0910.0
    1.101.101.284.034.98
    stringa copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -836,7 +1113,9 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> SSO в stringa до 23 символов, и даже 23 -копируются быстрее, чем 15 в std::string.1.111.201.354.069.97
    1.101.111.284.105.00
    stringa copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -846,7 +1125,9 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> Всё, не влезаем в SSO, а значит, используем shared буфер. -Добавляется время на атомарный инкремент счётчика.16.616.315.818.710.1
    16.716.215.818.55.02
    stringa copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -855,7 +1136,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}16.216.215.818.610.0
    16.016.315.718.54.98
    stringa copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -864,7 +1145,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}16.016.216.018.99.95
    16.016.515.818.64.94
    stringa copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -873,7 +1154,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}16.216.315.818.49.93
    16.016.415.818.54.99
    stringa copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -882,7 +1163,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}16.016.215.818.69.95
    16.016.215.718.54.90
    stringa copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -891,7 +1172,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}16.016.116.019.510.0
    16.016.315.718.45.01
    stringa copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -900,7 +1181,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}16.416.515.918.39.92
    16.016.315.718.95.07
    stringa copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -909,7 +1190,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}16.116.316.018.510.0
    16.116.415.918.45.01
    stringa copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -919,7 +1200,9 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> И как видно, кроме инкремента нет накладных расходов, -время копирования не зависит от длины строки.16.116.215.918.910.1
    16.016.515.918.34.92
    lstringa<16> copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -929,7 +1212,9 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> lstringa<16> использует SSO до 23 символов. -А в WASM 32-битная архитектура, SSO до 19 символов.5.084.884.967.8517.2
    4.124.514.887.8414.1
    lstringa<16> copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -938,7 +1223,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}4.974.894.878.0717.0
    4.094.504.787.8914.6
    lstringa<16> copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -947,7 +1232,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}4.905.014.987.9477.8
    4.044.564.807.7331.6
    lstringa<16> copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -956,7 +1241,8 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -} >> И после начинает вести себя при копировании, как std::string.24.225.084.082.876.5
     >> И после начинает вести себя при копировании, как std::string. +And then it starts to behave like std::string when copied.22.924.276.982.130.9
    lstringa<16> copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -965,7 +1251,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}24.124.588.085.579.5
    22.923.780.584.135.1
    lstringa<16> copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -974,7 +1260,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}25.625.984.885.182.9
    24.125.481.784.834.9
    lstringa<16> copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -983,7 +1269,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}27.326.585.189.883.0
    24.826.881.684.735.5
    lstringa<16> copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -992,7 +1278,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}27.629.688.2655133
    26.027.883.064954.3
    lstringa<16> copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1001,7 +1287,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}30.430.989.492.5130
    28.531.987.091.648.8
    lstringa<16> copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1010,7 +1296,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}70.071.7101101111
    93.296.996.896.248.6
    lstringa<16> copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1019,7 +1305,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}74.574.3131132122
    11311713312871.5
    lstringa<16> copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1028,7 +1314,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}90.993.3194196167
    127130195185118
    lstringa<512> copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1037,7 +1323,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}5.144.934.948.6217.9
    4.485.235.128.5415.2
    lstringa<512> copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1046,7 +1332,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}4.864.975.368.9418.5
    4.4911.55.098.6315.3
    lstringa<512> copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1055,7 +1341,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}4.914.945.058.6718.6
    4.4311.75.258.5814.6
    lstringa<512> copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1064,7 +1350,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}4.994.904.838.4418.8
    4.5511.65.158.5515.2
    lstringa<512> copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1073,7 +1359,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}4.585.037.9412.025.0
    4.1220.07.9211.517.8
    lstringa<512> copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1082,7 +1368,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}6.066.127.9212.121.2
    6.3020.87.9911.918.3
    lstringa<512> copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1091,7 +1377,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}6.447.878.2612.322.3
    6.0723.48.4312.118.8
    lstringa<512> copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1100,7 +1386,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}8.008.709.3113.224.0
    7.8718.19.4013.020.1
    lstringa<512> copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1110,7 +1396,9 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } } >> Даже 512 символов копируются быстрее, чем -одна аллокация или атомарный инкремент.10.710.610.914.626.8
    10.220.612.314.326.9
    lstringa<512> copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1119,7 +1407,8 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -} >> А дальше уже как у всех69.871.499.098.2113
     >> А дальше уже как у всех. +And then it's like everyone else.95.596.994.197.248.0
    lstringa<512> copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1128,7 +1417,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}73.477.5131131129
    11611812812771.3
    lstringa<512> copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); @@ -1137,60 +1426,60 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } -}90.893.4191195169
    -

    Convert to int '1234567'

    - +

    # Convert to int '1234567'

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +логике к работе std::from_chars +In simstr, a string fragment is sufficient for conversion to a number; +there's no need for null termination. The closest analog to this behavior +is "std::from_chars," but unfortunately, it is very limited in its capabilities. +Here, I attempted to run tests that are similar in logic to std::from_chars. +не допускает знаков плюс, пробелов, префиксов 0x и т.п. +from_chars requires an exact radix specification and does not allow plus +signs, spaces, 0x prefixes, etc. +десятичная система, без лидирующих пробелов и знака плюс +Here, to_int has the same restrictions: check for overflow, +decimal system, no leading spaces, and no plus sign. +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);void ToIntStr10(benchmark::State& state, const std::string& s, int c) { for (auto _: state) { int res = std::strtol(s.c_str(), nullptr, 10); @@ -1206,7 +1495,11 @@ void CopyDynString(benchmark::State& state) { нет нужды в null терминированности. Ближайший аналог такого поведения "std::from_chars", но он к сожалению очень ограничен по возможностям. Здесь я попытался произвести тесты, близкие по -логике к работе std::from_chars27.527.031.732.4204
    27.527.430.832.269.5
    std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);void ToIntFromChars10(benchmark::State& state, const std::string_view& s, int c) { for (auto _: state) { int res = 0; @@ -1220,7 +1513,9 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(res); } } >> from_chars требует точного указания основания счисления, -не допускает знаков плюс, пробелов, префиксов 0x и т.п.15.812.313.915.065.9
    15.112.513.513.828.4
    stringa s = "123456789"; int res = s.to_int<int, true, 10, false>template<typename T> void ToIntSimStr10(benchmark::State& state, T t, int c) { for (auto _: state) { @@ -1235,7 +1530,9 @@ void ToIntSimStr10(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(t); } } >> Здесь для to_int заданы такие же ограничения - проверять переполнение, -десятичная система, без лидирующих пробелов и знака плюс12.88.3814.315.358.9
    12.48.2414.115.719.0
    ssa s = "123456789"; int res = s.to_int<int, true, 10, false>template<typename T> void ToIntSimStr10(benchmark::State& state, T t, int c) { for (auto _: state) { @@ -1249,7 +1546,7 @@ void ToIntSimStr10(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } -}12.58.4813.016.254.2
    12.27.9413.515.117.3
    lstringa<20> s = "123456789"; int res = s.to_int<int, true, 10, false>template<typename T> void ToIntSimStr10(benchmark::State& state, T t, int c) { for (auto _: state) { @@ -1263,17 +1560,17 @@ void ToIntSimStr10(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } -}12.58.3613.415.954.1
    -

    Convert to unsigned 'abcDef'

    - +

    # Convert to unsigned 'abcDef'

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);void ToIntStr16(benchmark::State& state, const std::string& s, int c) { for (auto _: state) { int res = std::strtol(s.c_str(), nullptr, 16); @@ -1285,7 +1582,8 @@ void ToIntSimStr10(benchmark::State& state, T t, int c) { #endif benchmark::DoNotOptimize(res); } -} >> Всё то же, только для 16ричной системы23.924.334.535.7158
     >> Всё то же, только для 16ричной системы +Everything is the same, only for the hexadecimal system24.123.733.535.154.6
    std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);void ToIntFromChars16(benchmark::State& state, const std::string_view& s, int c) { for (auto _: state) { int res = 0; @@ -1298,7 +1596,7 @@ void ToIntSimStr10(benchmark::State& state, T t, int c) { #endif benchmark::DoNotOptimize(res); } -}10.015.08.499.9085.4
    9.609.818.149.5630.6
    stringa s = "abcDef"; int res = s.to_int<int, true, 16, false>template<typename T> void ToIntSimStr16(benchmark::State& state, T t, int c) { for (auto _: state) { @@ -1312,7 +1610,7 @@ void ToIntSimStr16(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } -}12.98.5712.314.650.4
    12.78.3013.913.517.9
    ssa s = "abcDef"; int res = s.to_int<int, true, 16, false>template<typename T> void ToIntSimStr16(benchmark::State& state, T t, int c) { for (auto _: state) { @@ -1326,7 +1624,7 @@ void ToIntSimStr16(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } -}12.57.9012.014.047.5
    13.17.8612.613.016.8
    lstringa<20> s = "abcDef"; int res = s.to_int<int, true, 16, false>template<typename T> void ToIntSimStr16(benchmark::State& state, T t, int c) { for (auto _: state) { @@ -1340,17 +1638,17 @@ void ToIntSimStr16(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } -}12.77.9411.813.947.2
    -

    Convert to int ' 1234567'

    - +

    # Convert to int ' 1234567'

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);void ToIntStr0(benchmark::State& state, const std::string& s, int c) { for (auto _: state) { int res = std::strtol(s.c_str(), nullptr, 0); @@ -1362,7 +1660,8 @@ void ToIntSimStr16(benchmark::State& state, T t, int c) { #endif benchmark::DoNotOptimize(res); } -} >> А здесь уже парсинг произвольного числа.28.928.744.147.2226
     >> А здесь уже парсинг произвольного числа. +And here we have parsing of an arbitrary number.28.929.343.645.374.6
    stringa s = " 123456789"; int res = s.to_int<int>; // Check overflowtemplate<typename T> void ToIntSimStr0(benchmark::State& state, T t, int c) { for (auto _: state) { @@ -1376,7 +1675,7 @@ void ToIntSimStr0(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } -}18.815.717.220.080.3
    18.415.118.219.725.4
    ssa s = " 123456789"; int res = s.to_int<int, false>; // No check overflowvoid ToIntNoOverflow(benchmark::State& state, ssa t, int c) { for (auto _: state) { int res = t.to_int<int, false>().value; @@ -1389,15 +1688,15 @@ void ToIntSimStr0(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } -}16.110.916.618.553.0
    -

    Convert to double '1234.567e10'

    - +

    # Convert to double '1234.567e10'

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);void ToDoubleStr(benchmark::State& state, const std::string& s, double c) { for (auto _: state) { char* ptr = nullptr; @@ -1413,7 +1712,7 @@ void ToIntSimStr0(benchmark::State& state, T t, int c) { #endif benchmark::DoNotOptimize(res); } -}65.065.0103106460
    65.765.198.3102200
    std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);void ToDoubleFromChars(benchmark::State& state, const std::string_view& s, double c) { for (auto _: state) { double res = 0; @@ -1428,7 +1727,7 @@ void ToIntSimStr0(benchmark::State& state, T t, int c) { #endif benchmark::DoNotOptimize(res); } -}24.223.962.885.6294
    24.624.459.276.5111
    ssa s = "1234.567e10"; double res = *s.to_double()template<typename T> void ToDoubleSimStr(benchmark::State& state, T t, double c) { for (auto _: state) { @@ -1446,15 +1745,15 @@ void ToDoubleSimStr(benchmark::State& state, T t, double c) { benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } -}26.124.335.737.7105
    -

    Append const literal of 16 bytes 64 times, 1024 total length

    - +

    # Append const literal of 16 bytes 64 times, 1024 total length

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +} +аллокация, тем быстрее результат. +The larger the internal buffer, the fewer allocations are +required, and the faster the result. +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::stringstream str; ... str << "abbaabbaabbaabba";void AppendStreamConstLiteral(benchmark::State& state) { for (auto _: state) { std::string result; @@ -1472,7 +1771,7 @@ void ToDoubleSimStr(benchmark::State& state, T t, double c) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(str); } -}140315134774583011819
    13541395466157054383
    std::string str; ... str += "abbaabbaabbaabba";void AppendStdStringConstLiteral(benchmark::State& state) { for (auto _: state) { std::string result; @@ -1487,7 +1786,7 @@ void ToDoubleSimStr(benchmark::State& state, T t, double c) { #endif benchmark::DoNotOptimize(result); } -}359346108413131174
    37237710701288587
    lstringa<8> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { @@ -1503,7 +1802,7 @@ void AppendLstringConstLiteral(benchmark::State& state) { #endif benchmark::DoNotOptimize(result); } -}3373717679731294
    361407736923704
    lstringa<128> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { @@ -1520,7 +1819,9 @@ void AppendLstringConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); } } >> Чем больше внутренний буфер, тем меньше раз требуется -аллокация, тем быстрее результат.242264391541900
    272267396531569
    lstringa<512> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { @@ -1536,7 +1837,7 @@ void AppendLstringConstLiteral(benchmark::State& state) { #endif benchmark::DoNotOptimize(result); } -}227239246365637
    228240234349516
    lstringa<1024> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { @@ -1552,18 +1853,18 @@ void AppendLstringConstLiteral(benchmark::State& state) { #endif benchmark::DoNotOptimize(result); } -}138141154254501
    -

    Append string of 16 bytes and const literal of 16 bytes 32 times, 1024 total length

    - +

    # Append string of 16 bytes and const literal of 16 bytes 32 times, 1024 total length

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::stringstream str; ... str << str_var << "abbaabbaabbaabba";void AppendStreamStrConstLiteral(benchmark::State& state) { std::string s1 = TEXT_16; for (auto _: state) { @@ -1582,7 +1883,7 @@ void AppendLstringConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); } -}140314564816557111807
    13631404479356374402
    std::string str; ... str += str_var + "abbaabbaabbaabba";void AppendStdStrStrConstLiteral(benchmark::State& state) { std::string p1 = TEXT_16; for (auto _: state) { @@ -1599,7 +1900,7 @@ void AppendLstringConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}12961276396841824085
    12821265386138811940
    lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; @@ -1617,7 +1918,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}4314207968271439
    445442726839834
    lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; @@ -1635,7 +1936,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}3263554925421179
    386376440533698
    lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; @@ -1653,7 +1954,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}312310315381934
    323316287387592
    lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; @@ -1671,18 +1972,18 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}253253216271734
    -

    Append string of 16 bytes and const literal of 16 bytes 2048 times, 65536 total length

    - +

    # Append string of 16 bytes and const literal of 16 bytes 2048 times, 65536 total length

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 timesvoid AppendStreamStrConstLiteralBig(benchmark::State& state) { std::string s1 = TEXT_16; for (auto _: state) { @@ -1701,7 +2002,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); } -}125727132670219773284627609176
    7654475371221750274181227747
    std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 timesvoid AppendStdStrStrConstLiteralBig(benchmark::State& state) { std::string p1 = TEXT_16; for (auto _: state) { @@ -1718,7 +2019,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}7716074369193770193928207760
    7245873091194313196295107590
    lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; @@ -1736,7 +2037,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}5247955191194462352553812
    1968920644179652392639528
    lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; @@ -1754,7 +2055,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}2838928835194102244451889
    1595617277170212211338289
    lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; @@ -1772,7 +2073,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}1813719500187722284850113
    1583717504168932378439586
    lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; @@ -1790,18 +2091,18 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } -}1550318108185572168052780
    -

    Append 2 string of 16 bytes 32 times, 1024 total length

    - +

    # Append 2 string of 16 bytes 32 times, 1024 total length

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::stringstream str; ... str << str_var1 << str_var2;void AppendStream2String(benchmark::State& state) { std::string s1 = TEXT_16; std::string s2 = TEXT_16; @@ -1822,7 +2123,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } -}136914254503545311836
    13971414439953734714
    std::string str; ... str += str_var1 + str_var2;void AppendStdStr2String(benchmark::State& state) { std::string s1 = TEXT_16; std::string s2 = TEXT_16; @@ -1842,7 +2143,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } -}13961392406244154507
    13541409392039642421
    lstringa<16> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; @@ -1862,7 +2163,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } -}5236308429591657
    5245448179321187
    lstringa<128> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; @@ -1882,7 +2183,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } -}4195345466561413
    4494335455971062
    lstringa<512> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; @@ -1902,7 +2203,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } -}3954704164841088
    385417381449907
    lstringa<1024> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; @@ -1922,18 +2223,18 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } -}311434311388977
    -

    Append text, number, text

    - +

    # Append text, number, text

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +} +} +} +} +} +Ещё раз - используйте сразу буфера подходящего размера. +And here and below, the result fits within SSO. +Once again, use appropriately sized buffers from the start. -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::stringstream str; str << "test = " << k << " times";void AppendStreamStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { @@ -1950,7 +2251,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(k); } } -}31493106109761217419450
    3102299811067112526369
    std::string str = "test = " + std::to_string(k) + " times";void AppendStdStringStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { @@ -1965,7 +2266,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(k); } } -}482448113112443261
    471456107812221655
    char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;void AppendSprintfStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { @@ -1982,7 +2283,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(k); } } -}14161526294128867677
    13951527277628072916
    std::string str = std::format("test = {} times", k);void AppendFormatStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { @@ -1997,7 +2298,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(k); } } -}11341271208224804200
    12051266200124212078
    lstringa<8> str; str.format("test = {} times", k);template<typename T> void AppendSimStrStrNumStrF(benchmark::State& state) { for (auto _: state) { @@ -2014,7 +2315,9 @@ void AppendSimStrStrNumStrF(benchmark::State& state) { benchmark::DoNotOptimize(k); } } -} >> В simstr format с первого раза не помещается в такую строку без аллокации.13901674213726416598
     >> В simstr format с первого раза не помещается в такую строку без аллокации. +In simstr format, the first time it doesn't fit into such a +string without allocation.13771633207626713396
    lstringa<32> str; str.format("test = {} times", k);template<typename T> void AppendSimStrStrNumStrF(benchmark::State& state) { for (auto _: state) { @@ -2031,7 +2334,8 @@ void AppendSimStrStrNumStrF(benchmark::State& state) { benchmark::DoNotOptimize(k); } } -} >> А в такую помещается. Используйте сразу буфера подходящего размера.9631138100415514632
     >> А в такую помещается. Используйте сразу буфера подходящего размера. +And it fits in this one. Use buffers of the appropriate size right away.9791117100415312581
    lstringa<8> str = "test = " + k + " times";template<typename T> void AppendSimStrStrNumStr(benchmark::State& state) { for (auto _: state) { @@ -2047,7 +2351,8 @@ void AppendSimStrStrNumStr(benchmark::State& state) { benchmark::DoNotOptimize(k); } } -} >> Результат не помещается в SSO, возникает аллокация.2903178309111342
     >> Результат не помещается в SSO, возникает аллокация. +The result does not fit into SSO, an allocation occurs.295313778880610
    lstringa<32> str = "test = " + k + " times";template<typename T> void AppendSimStrStrNumStr(benchmark::State& state) { for (auto _: state) { @@ -2064,7 +2369,9 @@ void AppendSimStrStrNumStr(benchmark::State& state) { } } } >> А здесь и ниже - результат укладывается в SSO. -Ещё раз - используйте сразу буфера подходящего размера.157154158195614
    152153154187342
    stringa str = "test = " + k + " times";template<typename T> void AppendSimStrStrNumStr(benchmark::State& state) { for (auto _: state) { @@ -2081,21 +2388,23 @@ void AppendSimStrStrNumStr(benchmark::State& state) { } } } >> Под WASM размер SSO 15 символов, что явно не хватает для размещения -результата, отсюда и такое время.1491701582471303
    -

    Split text and convert to int

    - +

    # Split text and convert to int

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    std::string::find + substr + std::strtolvoid SplitConvertIntStdString(benchmark::State& state) { std::string numbers = NUMBER_LIST; for (auto _: state) { @@ -2118,7 +2427,7 @@ void AppendSimStrStrNumStr(benchmark::State& state) { benchmark::DoNotOptimize(total); benchmark::DoNotOptimize(numbers); } -}2762735585711414
    270273546550651
    ssa::splitter + ssa::as_intvoid SplitConvertIntSimStr(benchmark::State& state) { stra numbers = NUMBER_LIST; for (auto _: state) { @@ -2135,7 +2444,7 @@ void AppendSimStrStrNumStr(benchmark::State& state) { benchmark::DoNotOptimize(total); benchmark::DoNotOptimize(numbers); } -}154137171311670
    154135170303279
    ssa::splitf + functorvoid SplitConvertIntSplitf(benchmark::State& state) { stra numbers = NUMBER_LIST; for (auto _: state) { @@ -2150,15 +2459,15 @@ void AppendSimStrStrNumStr(benchmark::State& state) { benchmark::DoNotOptimize(total); benchmark::DoNotOptimize(numbers); } -}214130190220939
    -

    Replace symbols in text ~400 symbols

    - +

    # Replace symbols in text ~400 symbols

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +то работает быстро. +This is a naive implementation that will fail to handle substitutions +such as 'a'->'b' and 'b'->'a'. But if the substitutions don't conflict, +it works quickly. +} +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    Naive (and wrong) replace symbols with std::string find + replacevoid ReplaceSymbolsStdStringNaiveWrong(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2213,7 +2522,10 @@ void AppendSimStrStrNumStr(benchmark::State& state) { } } >> Это наивная реализация, которая неверно отработает на таких заменах, как 'a'->'b' и 'b'->'a'. Но если замены не конфликтуют, -то работает быстро.852851117112586175
    865852115312983588
    replace symbols with std::string find_first_of + replacevoid ReplaceSymbolsStdStringNaiveRight(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2266,7 +2578,9 @@ void AppendSimStrStrNumStr(benchmark::State& state) { benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } -} >> Дальше уже правильные реализации, не зависящие от конфликтующих замен.251024962063234410124
     >> Дальше уже правильные реализации, не зависящие от конфликтующих замен. +Further, there are correct implementations that do not depend on +conflicting replacements.24002378204722314762
    replace symbols with std::string_view find_first_of + copyvoid ReplaceSymbolsStdString(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2318,7 +2632,7 @@ void AppendSimStrStrNumStr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}1110973241026065505
    11001037230025203410
    replace runtime symbols with string expressions and without remembering all search resultstemplate<bool UseVector> void ReplaceSymbolsDynPatternSimStr(benchmark::State& state) { stra source = @@ -2364,7 +2678,7 @@ void ReplaceSymbolsDynPatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } -}12351508144115245599
    12901465143415803466
    replace runtime symbols with simstr and memorization of all search resultstemplate<bool UseVector> void ReplaceSymbolsDynPatternSimStr(benchmark::State& state) { stra source = @@ -2410,7 +2724,7 @@ void ReplaceSymbolsDynPatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } -}10691172139614055123
    10391035134913893059
    replace const symbols with string expressions and without remembering all search resultstemplate<bool UseVector> void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { stra source = @@ -2453,7 +2767,7 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}10841253120912884773
    10341231114612832820
    replace const symbols with string expressions and memorization of all search resultstemplate<bool UseVector> void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { stra source = @@ -2496,19 +2810,19 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}862874120611984477
    -

    Replace symbols in text ~40 symbols

    - +

    # Replace symbols in text ~40 symbols

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    Short Naive (and wrong) replace symbols with std::string find + replacevoid ShortReplaceSymbolsStdStringNaiveWrong(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2547,7 +2861,7 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } -}170161331346827
    156159314339475
    Short replace symbols with std::string find_first_of + replacevoid ShortReplaceSymbolsStdStringNaiveRight(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2586,7 +2900,7 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } -}3103213754351187
    343319369431518
    Short replace symbols with std::string_view find_first_of + copyvoid ShortReplaceSymbolsStdString(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2624,7 +2938,7 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}165155329381694
    167166322357391
    Short replace runtime symbols with string expressions and without remembering all search resultstemplate<bool UseVector> void ShortReplaceSymbolsDynPatternSimStr(benchmark::State& state) { stra source = @@ -2656,7 +2970,7 @@ void ShortReplaceSymbolsDynPatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } -}167192256277583
    191196258315397
    Short replace runtime symbols with simstr and memorization of all search resultstemplate<bool UseVector> void ShortReplaceSymbolsDynPatternSimStr(benchmark::State& state) { stra source = @@ -2688,7 +3002,7 @@ void ShortReplaceSymbolsDynPatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } -}176190369374669
    185211344393405
    Short replace const symbols with string expressions and without remembering all search resultstemplate<bool UseVector> void ShortReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { stra source = @@ -2717,7 +3031,7 @@ void ShortReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}142159223252440
    132153213253250
    Short replace const symbols with string expressions and memorization of all search resultstemplate<bool UseVector> void ShortReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { stra source = @@ -2746,19 +3060,19 @@ void ShortReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}157149310342512
    -

    Replace All Str To Longer Size

    - +

    # Replace All Str To Longer Size

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +} +} +} +} +} +} +} +} +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    replace bb to ---- in std::string|64template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -2791,7 +3105,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}164174236248759
    161172227251382
    replace bb to ---- in std::string|256template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -2824,7 +3138,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}5315117808072371
    5435107658251410
    replace bb to ---- in std::string|512template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -2857,7 +3171,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}12171180144915514397
    1041989146515012725
    replace bb to ---- in std::string|1024template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -2890,7 +3204,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}23742244323936228983
    23292308319333195829
    replace bb to ---- in std::string|2048template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -2923,7 +3237,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}573560098127825120059
    581558247883839312920
    replace bb to ---- in lstringa<8>|64template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -2945,7 +3259,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}145154336331734
    143161320330339
    replace bb to ---- in lstringa<8>|256template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -2967,7 +3281,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}4354596596852096
    4394626296921065
    replace bb to ---- in lstringa<8>|512template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -2989,7 +3303,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}825850109111983770
    833882106511541968
    replace bb to ---- in lstringa<8>|1024template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3011,7 +3325,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}17131775193721077288
    16691827190721023761
    replace bb to ---- in lstringa<8>|2048template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3033,7 +3347,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}305533223647406513342
    31233363357939397335
    replace bb to ---- by init stringa|64template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3054,7 +3368,7 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}117124212230498
    98.9104172209220
    replace bb to ---- by init stringa|256template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3075,7 +3389,7 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}3984835595821896
    300299377485738
    replace bb to ---- by init stringa|512template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3096,7 +3410,7 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}803888103510073611
    70673381310861733
    replace bb to ---- by init stringa|1024template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3117,7 +3431,7 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}16241787185019136933
    15111625163722323695
    replace bb to ---- by init stringa|2048template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3138,27 +3452,27 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}315637413423360513812
    -

    Replace All Str To Same Size

    - +

    # Replace All Str To Same Size

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +} +} +} +} +} +} +} +} +} +} +} +} +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    replace bb to -- in std::string|64template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3190,7 +3504,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}119118192206545
    121115190209270
    replace bb to -- in std::string|256template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3222,7 +3536,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}4153704955331885
    4113674685531011
    replace bb to -- in std::string|512template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3254,7 +3568,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}7837398549683368
    7597338429751878
    replace bb to -- in std::string|1024template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3286,7 +3600,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}14991423167018406925
    14601409161418263626
    replace bb to -- in std::string|2048template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3318,7 +3632,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}296028983178364113051
    30522902315735477194
    replace bb to -- in lstringa<8>|64template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3339,7 +3653,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}10199.1192200483
    99.0103185189222
    replace bb to -- in lstringa<8>|256template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3360,7 +3674,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}3263014464751542
    300299435470775
    replace bb to -- in lstringa<8>|512template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3381,7 +3695,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}5695667898162827
    5525487638071461
    replace bb to -- in lstringa<8>|1024template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3402,7 +3716,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}11281104152615085568
    11471133140415152776
    replace bb to -- in lstringa<8>|2048template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3423,7 +3737,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } -}215520882820296910863
    21832150274129675522
    replace bb to -- by init stringa|64template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3448,7 +3762,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}86.999.6162192363
    82.493.9162179180
    replace bb to -- by init stringa|256template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3473,7 +3787,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}2322743543921249
    244275357392646
    replace bb to -- by init stringa|512template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3498,7 +3812,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}4415276006602243
    4444985806421220
    replace bb to -- by init stringa|1024template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3523,7 +3837,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}8831029107911964204
    8861033109111512371
    replace bb to -- by init stringa|2048template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; @@ -3548,27 +3862,27 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } -}16702041206724328206
    -

    Hash Map insert and find

    - +

    # Hash Map insert and find

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +символов, а потом ищем их в ней +We insert 10,000 strings of length from 30 to 50 characters into +hashStrMapA, and then search for them in it. +} +} -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    hashStrMapA<size_t> emplace & find stringa;void HashMapSimStr(benchmark::State& state) { for (auto _: state) { hashStrMapA<size_t> store; @@ -3592,7 +3906,9 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { } } } >> Вставляем в hashStrMapA 10000 stringa длиной от 30 до 50 -символов, а потом ищем их в ней35650513720924385288642702255371717
    36252423750693369388342039833162304
    std::unordered_map<std::string, size_t> emplace & find std::string;void HashMapStdStr(benchmark::State& state) { for (auto _: state) { std::unordered_map<std::string, size_t> store; @@ -3615,7 +3931,8 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(res); } } -} >> То же самое c std::string и std::unordered_map35045813624563532983753850505883527
     >> То же самое c std::string и std::unordered_map +Same thing with std::string and std::unordered_map35177843625926525888153441213370915
    hashStrMapA<size_t> emplace & find ssa;void HashMapSimSsa(benchmark::State& state) { for (auto _: state) { hashStrMapA<size_t> store; @@ -3639,7 +3956,8 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(res); } } -} >> Теперь вставляем stringa, а ищем ssa36487333730268351104639537905376097
     >> Теперь вставляем stringa, а ищем ssa +Now we insert stringa and search for ssa36187163687972341816640112483151333
    std::unordered_map<std::string, size_t> emplace & find std::string_view;void HashMapStdStrView(benchmark::State& state) { for (auto _: state) { std::unordered_map<std::string, size_t> store; @@ -3663,16 +3981,17 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(res); } } -} >> Вставляем std::string, а ищем std::string_view42524384036697633634768745096884220
    -

    Build Full Func Name

    - +

    # Build Full Func Name

    +
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Chrome, Clang-21
    +возвращаемого значения. Алгоритм на std::string. +A common task, similar to this one, can often be encountered in work: +Generate text from given data. In this case, using data +on certain functions, generate their full names with parameter types and +return values. The algorithm uses std::string. ++= к строке заменены на одно += + + +. +Almost the same algorithm, but several consecutive ++= to a string are replaced with a single += + + +. +} +Инфа о параметрах добавляется в текущую строку +Implementation using simstr strings and string expressions. +Parameter information is appended to the current line. -
    Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
    Build func full name std::string;std::string build_full_name_std() const { std::string str{has_ret_type_resolver ? "any"sv : type_names_sv[(unsigned)ret_type]}; str += " "; @@ -3706,7 +4025,11 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { } >> Обыденная задача, подобные часто могут встретится в работе: По неким данным сгенерировать текст. В этом случае по данным о неких функциях сформировать их полное имя с типами параметров и -возвращаемого значения. Алгоритм на std::string.7331031158116514861
    708966153316452652
    Build func full name std::string 1;std::string build_full_name_std1() const { std::string str{has_ret_type_resolver ? "any"sv : type_names_sv[(unsigned)ret_type]}; str += " " + std_name + "("; @@ -3736,7 +4059,9 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { //std::cout << "Len=" << str.length() << ", Cap=" << str.capacity() << "\n"; return str; } >> Почти тот же алгоритм, но несколько последовательных -+= к строке заменены на одно += + + +.829999165417065220
    8461010160217112955
    Build func full name std::stream;std::string build_full_name_stream() const { std::ostringstream str; if (has_ret_type_resolver) { @@ -3769,7 +4094,8 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { } str << ")"; return str.str(); -} >> Строим имя функции через std::ostringstream и <<255426268195995016474
     >> Строим имя функции через std::ostringstream и << +We construct the function name through std::ostringstream and <<257126138228101106584
    Build func full name stringa;stringa build_full_name() const { lstringa<512> str = e_choice(has_ret_type_resolver, "any", type_names[(unsigned)ret_type]) + " " + name + "("; @@ -3785,7 +4111,9 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { } return str + e_if(unlim_params, e_if(add_comma, ", ") + "...") + ")"; } >> Реализация на simstr строках и строковых выражениях. -Инфа о параметрах добавляется в текущую строку5256028599482853
    5084658189241274
    Build func full name stringa 1;stringa build_full_name1() const { lstringa<512> str = e_choice(has_ret_type_resolver, "any", type_names[(unsigned)ret_type]) + " " + name + "("; @@ -3799,11 +4127,15 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { } >> Реализация на simstr строках и строковых выражениях. Инфа о параметрах добавляется во временную строку, а потом разом добавляется в текущую строку. Позволяет операции в цикле -записать в одну строку, но чуть проигрывает по времени выполнения.672674101511083292
    \ No newline at end of file diff --git a/bench/results/000-Xeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21.txt b/bench/results/000-Xeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21.txt index 761ffff..46f002f 100644 --- a/bench/results/000-Xeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21.txt +++ b/bench/results/000-Xeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21.txt @@ -1,4 +1,4 @@ -2025-11-26T18:35:01+03:00 +2026-01-21T07:43:36+03:00 Running ./benchStr Run on (32 X 2494.22 MHz CPU s) CPU Caches: @@ -6,786 +6,873 @@ CPU Caches: L1 Instruction 32 KiB (x16) L2 Unified 256 KiB (x16) L3 Unified 40960 KiB (x1) -Load Average: 0.10, 0.62, 0.73 +Load Average: 0.00, 0.23, 0.51 +***WARNING*** ASLR is enabled, the results may have unreproducible noise in them. -------------------------------------------------------------------------------------------------------------------------------------------------------- Benchmark Time CPU Iterations -------------------------------------------------------------------------------------------------------------------------------------------------------- +----- Concatenate string + Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and number by std to std::string_mean 226 ns 226 ns 10 +Concat std::string and number by std to std::string_median 222 ns 222 ns 10 +Concat std::string and number by std to std::string_stddev 15.0 ns 15.0 ns 10 +Concat std::string and number by std to std::string_cv 6.64 % 6.64 % 10 +Concat std::string and number by StrExpr to std::string_mean 104 ns 104 ns 10 +Concat std::string and number by StrExpr to std::string_median 103 ns 103 ns 10 +Concat std::string and number by StrExpr to std::string_stddev 4.29 ns 4.29 ns 10 +Concat std::string and number by StrExpr to std::string_cv 4.10 % 4.10 % 10 +Concat stringa and number by StrExpr to simstr::stringa_mean 63.7 ns 63.7 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_median 62.8 ns 62.8 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_stddev 2.92 ns 2.92 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_cv 4.59 % 4.59 % 10 +----- Concatenate string + Hex Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and hex number by std to std::string_mean 681 ns 681 ns 10 +Concat std::string and hex number by std to std::string_median 673 ns 673 ns 10 +Concat std::string and hex number by std to std::string_stddev 19.0 ns 19.0 ns 10 +Concat std::string and hex number by std to std::string_cv 2.80 % 2.80 % 10 +Concat std::string and hex number by StrExpr to std::string_mean 71.7 ns 71.7 ns 10 +Concat std::string and hex number by StrExpr to std::string_median 71.6 ns 71.6 ns 10 +Concat std::string and hex number by StrExpr to std::string_stddev 1.90 ns 1.90 ns 10 +Concat std::string and hex number by StrExpr to std::string_cv 2.65 % 2.65 % 10 +Concat stringa and hex number by StrExpr to simstr::stringa_mean 67.9 ns 67.9 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_median 67.5 ns 67.5 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_stddev 1.41 ns 1.41 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_cv 2.08 % 2.08 % 10 +----- Concatenate string + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string by std to std::string_mean 49.7 ns 49.7 ns 10 +Concat std::string by std to std::string_median 49.9 ns 49.9 ns 10 +Concat std::string by std to std::string_stddev 0.890 ns 0.890 ns 10 +Concat std::string by std to std::string_cv 1.79 % 1.79 % 10 +Concat std::string by StrExpr to std::string_mean 40.5 ns 40.5 ns 10 +Concat std::string by StrExpr to std::string_median 40.5 ns 40.5 ns 10 +Concat std::string by StrExpr to std::string_stddev 0.767 ns 0.767 ns 10 +Concat std::string by StrExpr to std::string_cv 1.89 % 1.89 % 10 +Concat stringa by StrExpr to stringa_mean 27.0 ns 27.0 ns 10 +Concat stringa by StrExpr to stringa_median 26.6 ns 26.6 ns 10 +Concat stringa by StrExpr to stringa_stddev 1.50 ns 1.50 ns 10 +Concat stringa by StrExpr to stringa_cv 5.54 % 5.54 % 10 +----- Find three concatenated string in string_view -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Find concat three std::string_mean 116 ns 116 ns 10 +Find concat three std::string_median 116 ns 116 ns 10 +Find concat three std::string_stddev 4.32 ns 4.32 ns 10 +Find concat three std::string_cv 3.72 % 3.72 % 10 +Find concat three strexpr_mean 51.1 ns 51.1 ns 10 +Find concat three strexpr_median 51.0 ns 51.0 ns 10 +Find concat three strexpr_stddev 2.58 ns 2.58 ns 10 +Find concat three strexpr_cv 5.05 % 5.05 % 10 +Find concat three simstr_mean 19.6 ns 19.6 ns 10 +Find concat three simstr_median 19.7 ns 19.7 ns 10 +Find concat three simstr_stddev 0.770 ns 0.770 ns 10 +Find concat three simstr_cv 3.93 % 3.93 % 10 +----- Build Type Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +BuildTypeNameStr 0/0_mean 7.64 ns 7.64 ns 10 +BuildTypeNameStr 0/0_median 7.63 ns 7.63 ns 10 +BuildTypeNameStr 0/0_stddev 0.241 ns 0.241 ns 10 +BuildTypeNameStr 0/0_cv 3.16 % 3.16 % 10 +BuildTypeNameExp 0/0_mean 6.52 ns 6.52 ns 10 +BuildTypeNameExp 0/0_median 6.54 ns 6.54 ns 10 +BuildTypeNameExp 0/0_stddev 0.149 ns 0.149 ns 10 +BuildTypeNameExp 0/0_cv 2.29 % 2.29 % 10 +BuildTypeNameSim 0/0_mean 4.99 ns 4.99 ns 10 +BuildTypeNameSim 0/0_median 4.92 ns 4.92 ns 10 +BuildTypeNameSim 0/0_stddev 0.280 ns 0.280 ns 10 +BuildTypeNameSim 0/0_cv 5.62 % 5.62 % 10 +BuildTypeNameStr 10/10_mean 56.8 ns 56.8 ns 10 +BuildTypeNameStr 10/10_median 57.0 ns 57.0 ns 10 +BuildTypeNameStr 10/10_stddev 1.62 ns 1.62 ns 10 +BuildTypeNameStr 10/10_cv 2.86 % 2.86 % 10 +BuildTypeNameExp 10/10_mean 30.5 ns 30.5 ns 10 +BuildTypeNameExp 10/10_median 30.3 ns 30.3 ns 10 +BuildTypeNameExp 10/10_stddev 0.808 ns 0.808 ns 10 +BuildTypeNameExp 10/10_cv 2.65 % 2.65 % 10 +BuildTypeNameSim 10/10_mean 22.7 ns 22.7 ns 10 +BuildTypeNameSim 10/10_median 22.6 ns 22.6 ns 10 +BuildTypeNameSim 10/10_stddev 0.330 ns 0.330 ns 10 +BuildTypeNameSim 10/10_cv 1.45 % 1.45 % 10 +----- Replace string by copy -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat with replace str_mean 207 ns 207 ns 10 +Concat with replace str_median 203 ns 203 ns 10 +Concat with replace str_stddev 11.4 ns 11.4 ns 10 +Concat with replace str_cv 5.52 % 5.52 % 10 +Concat with replace exp_mean 149 ns 149 ns 10 +Concat with replace exp_median 148 ns 148 ns 10 +Concat with replace exp_stddev 4.78 ns 4.78 ns 10 +Concat with replace exp_cv 3.20 % 3.20 % 10 ----- Create Empty Str ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e;_mean 1.11 ns 1.11 ns 10 +std::string e;_mean 1.12 ns 1.12 ns 10 std::string e;_median 1.12 ns 1.12 ns 10 -std::string e;_stddev 0.017 ns 0.017 ns 10 -std::string e;_cv 1.53 % 1.53 % 10 -std::string_view e;_mean 0.369 ns 0.369 ns 10 +std::string e;_stddev 0.022 ns 0.022 ns 10 +std::string e;_cv 1.96 % 1.96 % 10 +std::string_view e;_mean 0.373 ns 0.373 ns 10 std::string_view e;_median 0.369 ns 0.369 ns 10 -std::string_view e;_stddev 0.005 ns 0.005 ns 10 -std::string_view e;_cv 1.43 % 1.43 % 10 -ssa e;_mean 0.369 ns 0.369 ns 10 -ssa e;_median 0.366 ns 0.366 ns 10 -ssa e;_stddev 0.011 ns 0.011 ns 10 -ssa e;_cv 2.92 % 2.92 % 10 -stringa e;_mean 0.742 ns 0.742 ns 10 -stringa e;_median 0.744 ns 0.744 ns 10 -stringa e;_stddev 0.013 ns 0.013 ns 10 -stringa e;_cv 1.75 % 1.75 % 10 +std::string_view e;_stddev 0.012 ns 0.012 ns 10 +std::string_view e;_cv 3.14 % 3.14 % 10 +ssa e;_mean 0.367 ns 0.367 ns 10 +ssa e;_median 0.367 ns 0.367 ns 10 +ssa e;_stddev 0.006 ns 0.006 ns 10 +ssa e;_cv 1.54 % 1.54 % 10 +stringa e;_mean 0.753 ns 0.753 ns 10 +stringa e;_median 0.748 ns 0.748 ns 10 +stringa e;_stddev 0.024 ns 0.024 ns 10 +stringa e;_cv 3.14 % 3.14 % 10 lstringa<20> e;_mean 1.13 ns 1.13 ns 10 -lstringa<20> e;_median 1.13 ns 1.13 ns 10 -lstringa<20> e;_stddev 0.046 ns 0.046 ns 10 -lstringa<20> e;_cv 4.10 % 4.10 % 10 +lstringa<20> e;_median 1.12 ns 1.12 ns 10 +lstringa<20> e;_stddev 0.027 ns 0.027 ns 10 +lstringa<20> e;_cv 2.42 % 2.42 % 10 lstringa<40> e;_mean 1.13 ns 1.13 ns 10 -lstringa<40> e;_median 1.14 ns 1.14 ns 10 -lstringa<40> e;_stddev 0.025 ns 0.025 ns 10 -lstringa<40> e;_cv 2.23 % 2.23 % 10 +lstringa<40> e;_median 1.12 ns 1.12 ns 10 +lstringa<40> e;_stddev 0.029 ns 0.029 ns 10 +lstringa<40> e;_cv 2.53 % 2.53 % 10 ----- Create Str from short literal (9 symbols) --------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text";_mean 1.91 ns 1.91 ns 10 -std::string e = "Test text";_median 1.90 ns 1.90 ns 10 -std::string e = "Test text";_stddev 0.098 ns 0.098 ns 10 -std::string e = "Test text";_cv 5.10 % 5.10 % 10 -std::string_view e = "Test text";_mean 0.748 ns 0.748 ns 10 -std::string_view e = "Test text";_median 0.751 ns 0.751 ns 10 -std::string_view e = "Test text";_stddev 0.012 ns 0.012 ns 10 -std::string_view e = "Test text";_cv 1.56 % 1.56 % 10 -ssa e = "Test text";_mean 0.374 ns 0.374 ns 10 -ssa e = "Test text";_median 0.373 ns 0.373 ns 10 -ssa e = "Test text";_stddev 0.008 ns 0.008 ns 10 -ssa e = "Test text";_cv 2.18 % 2.18 % 10 -stringa e = "Test text";_mean 1.11 ns 1.11 ns 10 -stringa e = "Test text";_median 1.11 ns 1.11 ns 10 -stringa e = "Test text";_stddev 0.045 ns 0.045 ns 10 -stringa e = "Test text";_cv 4.03 % 4.03 % 10 -lstringa<20> e = "Test text";_mean 1.88 ns 1.88 ns 10 -lstringa<20> e = "Test text";_median 1.87 ns 1.87 ns 10 -lstringa<20> e = "Test text";_stddev 0.034 ns 0.034 ns 10 -lstringa<20> e = "Test text";_cv 1.79 % 1.79 % 10 -lstringa<40> e = "Test text";_mean 1.86 ns 1.86 ns 10 -lstringa<40> e = "Test text";_median 1.86 ns 1.86 ns 10 -lstringa<40> e = "Test text";_stddev 0.045 ns 0.045 ns 10 -lstringa<40> e = "Test text";_cv 2.41 % 2.41 % 10 +std::string e = "Test text";_mean 1.84 ns 1.84 ns 10 +std::string e = "Test text";_median 1.84 ns 1.84 ns 10 +std::string e = "Test text";_stddev 0.037 ns 0.037 ns 10 +std::string e = "Test text";_cv 2.03 % 2.03 % 10 +std::string_view e = "Test text";_mean 0.750 ns 0.750 ns 10 +std::string_view e = "Test text";_median 0.734 ns 0.734 ns 10 +std::string_view e = "Test text";_stddev 0.030 ns 0.030 ns 10 +std::string_view e = "Test text";_cv 3.99 % 3.99 % 10 +ssa e = "Test text";_mean 0.381 ns 0.381 ns 10 +ssa e = "Test text";_median 0.380 ns 0.380 ns 10 +ssa e = "Test text";_stddev 0.019 ns 0.019 ns 10 +ssa e = "Test text";_cv 5.10 % 5.10 % 10 +stringa e = "Test text";_mean 1.85 ns 1.85 ns 10 +stringa e = "Test text";_median 1.83 ns 1.83 ns 10 +stringa e = "Test text";_stddev 0.058 ns 0.058 ns 10 +stringa e = "Test text";_cv 3.16 % 3.16 % 10 +lstringa<20> e = "Test text";_mean 1.87 ns 1.87 ns 10 +lstringa<20> e = "Test text";_median 1.84 ns 1.84 ns 10 +lstringa<20> e = "Test text";_stddev 0.068 ns 0.068 ns 10 +lstringa<20> e = "Test text";_cv 3.63 % 3.63 % 10 +lstringa<40> e = "Test text";_mean 1.85 ns 1.85 ns 10 +lstringa<40> e = "Test text";_median 1.83 ns 1.83 ns 10 +lstringa<40> e = "Test text";_stddev 0.052 ns 0.052 ns 10 +lstringa<40> e = "Test text";_cv 2.81 % 2.81 % 10 ----- Create Str from long literal (30 symbols) ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 std::string e = "123456789012345678901234567890";_mean 18.8 ns 18.8 ns 10 -std::string e = "123456789012345678901234567890";_median 18.8 ns 18.8 ns 10 -std::string e = "123456789012345678901234567890";_stddev 0.316 ns 0.316 ns 10 -std::string e = "123456789012345678901234567890";_cv 1.68 % 1.68 % 10 +std::string e = "123456789012345678901234567890";_median 18.6 ns 18.6 ns 10 +std::string e = "123456789012345678901234567890";_stddev 0.658 ns 0.658 ns 10 +std::string e = "123456789012345678901234567890";_cv 3.50 % 3.50 % 10 std::string_view e = "123456789012345678901234567890";_mean 0.747 ns 0.747 ns 10 -std::string_view e = "123456789012345678901234567890";_median 0.747 ns 0.747 ns 10 -std::string_view e = "123456789012345678901234567890";_stddev 0.009 ns 0.009 ns 10 -std::string_view e = "123456789012345678901234567890";_cv 1.14 % 1.14 % 10 -ssa e = "123456789012345678901234567890";_mean 0.373 ns 0.373 ns 10 -ssa e = "123456789012345678901234567890";_median 0.375 ns 0.375 ns 10 -ssa e = "123456789012345678901234567890";_stddev 0.004 ns 0.004 ns 10 -ssa e = "123456789012345678901234567890";_cv 1.18 % 1.18 % 10 -stringa e = "123456789012345678901234567890";_mean 1.13 ns 1.13 ns 10 -stringa e = "123456789012345678901234567890";_median 1.12 ns 1.12 ns 10 -stringa e = "123456789012345678901234567890";_stddev 0.024 ns 0.024 ns 10 -stringa e = "123456789012345678901234567890";_cv 2.12 % 2.12 % 10 -lstringa<20> e = "123456789012345678901234567890";_mean 21.2 ns 21.2 ns 10 -lstringa<20> e = "123456789012345678901234567890";_median 21.1 ns 21.1 ns 10 -lstringa<20> e = "123456789012345678901234567890";_stddev 0.428 ns 0.418 ns 10 -lstringa<20> e = "123456789012345678901234567890";_cv 2.02 % 1.98 % 10 -lstringa<40> e = "123456789012345678901234567890";_mean 2.57 ns 2.57 ns 10 -lstringa<40> e = "123456789012345678901234567890";_median 2.56 ns 2.56 ns 10 -lstringa<40> e = "123456789012345678901234567890";_stddev 0.051 ns 0.051 ns 10 -lstringa<40> e = "123456789012345678901234567890";_cv 1.98 % 1.98 % 10 +std::string_view e = "123456789012345678901234567890";_median 0.738 ns 0.738 ns 10 +std::string_view e = "123456789012345678901234567890";_stddev 0.027 ns 0.027 ns 10 +std::string_view e = "123456789012345678901234567890";_cv 3.58 % 3.58 % 10 +ssa e = "123456789012345678901234567890";_mean 0.370 ns 0.370 ns 10 +ssa e = "123456789012345678901234567890";_median 0.366 ns 0.366 ns 10 +ssa e = "123456789012345678901234567890";_stddev 0.010 ns 0.010 ns 10 +ssa e = "123456789012345678901234567890";_cv 2.71 % 2.71 % 10 +stringa e = "123456789012345678901234567890";_mean 1.88 ns 1.88 ns 10 +stringa e = "123456789012345678901234567890";_median 1.87 ns 1.87 ns 10 +stringa e = "123456789012345678901234567890";_stddev 0.057 ns 0.057 ns 10 +stringa e = "123456789012345678901234567890";_cv 3.02 % 3.02 % 10 +lstringa<20> e = "123456789012345678901234567890";_mean 21.0 ns 21.0 ns 10 +lstringa<20> e = "123456789012345678901234567890";_median 21.0 ns 21.0 ns 10 +lstringa<20> e = "123456789012345678901234567890";_stddev 0.876 ns 0.876 ns 10 +lstringa<20> e = "123456789012345678901234567890";_cv 4.17 % 4.17 % 10 +lstringa<40> e = "123456789012345678901234567890";_mean 2.55 ns 2.55 ns 10 +lstringa<40> e = "123456789012345678901234567890";_median 2.54 ns 2.54 ns 10 +lstringa<40> e = "123456789012345678901234567890";_stddev 0.042 ns 0.042 ns 10 +lstringa<40> e = "123456789012345678901234567890";_cv 1.63 % 1.63 % 10 ----- Create copy of Str with 9 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text"; auto c{e};_mean 4.98 ns 4.98 ns 10 -std::string e = "Test text"; auto c{e};_median 4.98 ns 4.98 ns 10 -std::string e = "Test text"; auto c{e};_stddev 0.126 ns 0.126 ns 10 -std::string e = "Test text"; auto c{e};_cv 2.53 % 2.53 % 10 -std::string_view e = "Test text"; auto c{e};_mean 0.373 ns 0.373 ns 10 -std::string_view e = "Test text"; auto c{e};_median 0.373 ns 0.373 ns 10 -std::string_view e = "Test text"; auto c{e};_stddev 0.004 ns 0.004 ns 10 -std::string_view e = "Test text"; auto c{e};_cv 1.20 % 1.20 % 10 -ssa e = "Test text"; auto c{e};_mean 0.376 ns 0.376 ns 10 -ssa e = "Test text"; auto c{e};_median 0.373 ns 0.373 ns 10 -ssa e = "Test text"; auto c{e};_stddev 0.017 ns 0.017 ns 10 -ssa e = "Test text"; auto c{e};_cv 4.60 % 4.60 % 10 -stringa e = "Test text"; auto c{e};_mean 1.13 ns 1.13 ns 10 -stringa e = "Test text"; auto c{e};_median 1.13 ns 1.13 ns 10 -stringa e = "Test text"; auto c{e};_stddev 0.048 ns 0.048 ns 10 -stringa e = "Test text"; auto c{e};_cv 4.29 % 4.29 % 10 -lstringa<20> e = "Test text"; auto c{e};_mean 4.84 ns 4.84 ns 10 -lstringa<20> e = "Test text"; auto c{e};_median 4.85 ns 4.85 ns 10 -lstringa<20> e = "Test text"; auto c{e};_stddev 0.070 ns 0.070 ns 10 -lstringa<20> e = "Test text"; auto c{e};_cv 1.44 % 1.44 % 10 -lstringa<40> e = "Test text"; auto c{e};_mean 4.53 ns 4.53 ns 10 -lstringa<40> e = "Test text"; auto c{e};_median 4.51 ns 4.51 ns 10 -lstringa<40> e = "Test text"; auto c{e};_stddev 0.109 ns 0.109 ns 10 -lstringa<40> e = "Test text"; auto c{e};_cv 2.41 % 2.41 % 10 +std::string e = "Test text"; auto c{e};_mean 4.83 ns 4.83 ns 10 +std::string e = "Test text"; auto c{e};_median 4.80 ns 4.80 ns 10 +std::string e = "Test text"; auto c{e};_stddev 0.091 ns 0.091 ns 10 +std::string e = "Test text"; auto c{e};_cv 1.89 % 1.89 % 10 +std::string_view e = "Test text"; auto c{e};_mean 0.377 ns 0.377 ns 10 +std::string_view e = "Test text"; auto c{e};_median 0.376 ns 0.376 ns 10 +std::string_view e = "Test text"; auto c{e};_stddev 0.010 ns 0.010 ns 10 +std::string_view e = "Test text"; auto c{e};_cv 2.62 % 2.62 % 10 +ssa e = "Test text"; auto c{e};_mean 0.368 ns 0.368 ns 10 +ssa e = "Test text"; auto c{e};_median 0.367 ns 0.367 ns 10 +ssa e = "Test text"; auto c{e};_stddev 0.007 ns 0.007 ns 10 +ssa e = "Test text"; auto c{e};_cv 1.99 % 1.99 % 10 +stringa e = "Test text"; auto c{e};_mean 1.11 ns 1.11 ns 10 +stringa e = "Test text"; auto c{e};_median 1.11 ns 1.11 ns 10 +stringa e = "Test text"; auto c{e};_stddev 0.025 ns 0.025 ns 10 +stringa e = "Test text"; auto c{e};_cv 2.29 % 2.29 % 10 +lstringa<20> e = "Test text"; auto c{e};_mean 4.18 ns 4.18 ns 10 +lstringa<20> e = "Test text"; auto c{e};_median 4.15 ns 4.15 ns 10 +lstringa<20> e = "Test text"; auto c{e};_stddev 0.134 ns 0.134 ns 10 +lstringa<20> e = "Test text"; auto c{e};_cv 3.20 % 3.20 % 10 +lstringa<40> e = "Test text"; auto c{e};_mean 4.47 ns 4.47 ns 10 +lstringa<40> e = "Test text"; auto c{e};_median 4.39 ns 4.39 ns 10 +lstringa<40> e = "Test text"; auto c{e};_stddev 0.381 ns 0.381 ns 10 +lstringa<40> e = "Test text"; auto c{e};_cv 8.52 % 8.52 % 10 ----- Create copy of Str with 30 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "123456789012345678901234567890"; auto c{e};_mean 19.6 ns 19.6 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_median 19.7 ns 19.7 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_stddev 0.423 ns 0.423 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_cv 2.16 % 2.16 % 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 0.748 ns 0.748 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_median 0.740 ns 0.740 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.022 ns 0.022 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 2.88 % 2.88 % 10 -ssa e = "123456789012345678901234567890"; auto c{e};_mean 0.373 ns 0.373 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_mean 19.8 ns 19.8 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_median 19.4 ns 19.4 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_stddev 0.903 ns 0.903 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_cv 4.56 % 4.56 % 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 0.752 ns 0.752 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_median 0.744 ns 0.744 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.024 ns 0.024 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 3.23 % 3.23 % 10 +ssa e = "123456789012345678901234567890"; auto c{e};_mean 0.375 ns 0.375 ns 10 ssa e = "123456789012345678901234567890"; auto c{e};_median 0.371 ns 0.371 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.007 ns 0.007 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_cv 2.00 % 2.00 % 10 -stringa e = "123456789012345678901234567890"; auto c{e};_mean 1.13 ns 1.13 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_median 1.13 ns 1.13 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.024 ns 0.024 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_cv 2.10 % 2.10 % 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 20.0 ns 20.0 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 20.1 ns 20.1 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 0.383 ns 0.383 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 1.91 % 1.91 % 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 5.40 ns 5.40 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 5.43 ns 5.43 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 0.065 ns 0.065 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 1.20 % 1.20 % 10 +ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.010 ns 0.010 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_cv 2.67 % 2.67 % 10 +stringa e = "123456789012345678901234567890"; auto c{e};_mean 1.89 ns 1.89 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_median 1.89 ns 1.89 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.049 ns 0.049 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_cv 2.60 % 2.60 % 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 21.0 ns 21.0 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 21.2 ns 21.2 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 0.965 ns 0.965 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 4.60 % 4.60 % 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 4.53 ns 4.53 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 4.49 ns 4.49 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 0.118 ns 0.118 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 2.60 % 2.60 % 10 ----- Find 9 symbols text in end of 99 symbols text ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string::find;_mean 6.87 ns 6.86 ns 10 -std::string::find;_median 6.86 ns 6.85 ns 10 -std::string::find;_stddev 0.076 ns 0.077 ns 10 -std::string::find;_cv 1.11 % 1.12 % 10 -std::string_view::find;_mean 7.75 ns 7.75 ns 10 -std::string_view::find;_median 7.71 ns 7.71 ns 10 -std::string_view::find;_stddev 0.370 ns 0.370 ns 10 -std::string_view::find;_cv 4.77 % 4.77 % 10 -ssa::find;_mean 6.96 ns 6.96 ns 10 -ssa::find;_median 6.82 ns 6.82 ns 10 -ssa::find;_stddev 0.484 ns 0.484 ns 10 -ssa::find;_cv 6.96 % 6.96 % 10 -stringa::find;_mean 7.38 ns 7.38 ns 10 -stringa::find;_median 7.33 ns 7.33 ns 10 -stringa::find;_stddev 0.301 ns 0.301 ns 10 -stringa::find;_cv 4.08 % 4.08 % 10 -lstringa<20>::find;_mean 6.90 ns 6.90 ns 10 -lstringa<20>::find;_median 6.84 ns 6.84 ns 10 -lstringa<20>::find;_stddev 0.269 ns 0.269 ns 10 -lstringa<20>::find;_cv 3.90 % 3.90 % 10 -lstringa<40>::find;_mean 6.83 ns 6.83 ns 10 -lstringa<40>::find;_median 6.84 ns 6.84 ns 10 -lstringa<40>::find;_stddev 0.127 ns 0.127 ns 10 -lstringa<40>::find;_cv 1.86 % 1.86 % 10 +std::string::find;_mean 7.86 ns 7.86 ns 10 +std::string::find;_median 7.80 ns 7.80 ns 10 +std::string::find;_stddev 0.292 ns 0.292 ns 10 +std::string::find;_cv 3.72 % 3.72 % 10 +std::string_view::find;_mean 7.36 ns 7.36 ns 10 +std::string_view::find;_median 7.15 ns 7.15 ns 10 +std::string_view::find;_stddev 0.780 ns 0.780 ns 10 +std::string_view::find;_cv 10.60 % 10.60 % 10 +ssa::find;_mean 7.03 ns 7.03 ns 10 +ssa::find;_median 7.02 ns 7.02 ns 10 +ssa::find;_stddev 0.355 ns 0.355 ns 10 +ssa::find;_cv 5.06 % 5.06 % 10 +stringa::find;_mean 7.17 ns 7.17 ns 10 +stringa::find;_median 7.16 ns 7.16 ns 10 +stringa::find;_stddev 0.148 ns 0.148 ns 10 +stringa::find;_cv 2.06 % 2.06 % 10 +lstringa<20>::find;_mean 6.43 ns 6.43 ns 10 +lstringa<20>::find;_median 6.42 ns 6.42 ns 10 +lstringa<20>::find;_stddev 0.163 ns 0.163 ns 10 +lstringa<20>::find;_cv 2.53 % 2.53 % 10 +lstringa<40>::find;_mean 6.56 ns 6.56 ns 10 +lstringa<40>::find;_median 6.31 ns 6.31 ns 10 +lstringa<40>::find;_stddev 0.479 ns 0.479 ns 10 +lstringa<40>::find;_cv 7.30 % 7.30 % 10 ------- Copy not literal Str with N symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string copy{str_with_len_N};/15_mean 4.90 ns 4.90 ns 10 -std::string copy{str_with_len_N};/15_median 4.90 ns 4.90 ns 10 -std::string copy{str_with_len_N};/15_stddev 0.110 ns 0.110 ns 10 -std::string copy{str_with_len_N};/15_cv 2.23 % 2.23 % 10 -std::string copy{str_with_len_N};/16_mean 23.1 ns 23.1 ns 10 -std::string copy{str_with_len_N};/16_median 22.8 ns 22.8 ns 10 -std::string copy{str_with_len_N};/16_stddev 2.01 ns 2.01 ns 10 -std::string copy{str_with_len_N};/16_cv 8.69 % 8.69 % 10 -std::string copy{str_with_len_N};/23_mean 23.2 ns 23.2 ns 10 -std::string copy{str_with_len_N};/23_median 22.9 ns 22.9 ns 10 -std::string copy{str_with_len_N};/23_stddev 1.15 ns 1.15 ns 10 -std::string copy{str_with_len_N};/23_cv 4.94 % 4.94 % 10 -std::string copy{str_with_len_N};/24_mean 22.3 ns 22.3 ns 10 -std::string copy{str_with_len_N};/24_median 22.2 ns 22.2 ns 10 -std::string copy{str_with_len_N};/24_stddev 0.521 ns 0.521 ns 10 -std::string copy{str_with_len_N};/24_cv 2.33 % 2.33 % 10 -std::string copy{str_with_len_N};/32_mean 22.2 ns 22.2 ns 10 -std::string copy{str_with_len_N};/32_median 22.0 ns 22.0 ns 10 -std::string copy{str_with_len_N};/32_stddev 0.529 ns 0.529 ns 10 -std::string copy{str_with_len_N};/32_cv 2.39 % 2.39 % 10 -std::string copy{str_with_len_N};/64_mean 22.6 ns 22.6 ns 10 -std::string copy{str_with_len_N};/64_median 22.4 ns 22.4 ns 10 -std::string copy{str_with_len_N};/64_stddev 0.917 ns 0.917 ns 10 -std::string copy{str_with_len_N};/64_cv 4.05 % 4.05 % 10 -std::string copy{str_with_len_N};/128_mean 26.2 ns 26.2 ns 10 -std::string copy{str_with_len_N};/128_median 26.1 ns 26.1 ns 10 -std::string copy{str_with_len_N};/128_stddev 0.553 ns 0.553 ns 10 -std::string copy{str_with_len_N};/128_cv 2.11 % 2.11 % 10 -std::string copy{str_with_len_N};/256_mean 27.3 ns 27.3 ns 10 -std::string copy{str_with_len_N};/256_median 27.3 ns 27.3 ns 10 -std::string copy{str_with_len_N};/256_stddev 0.472 ns 0.471 ns 10 -std::string copy{str_with_len_N};/256_cv 1.73 % 1.73 % 10 -std::string copy{str_with_len_N};/512_mean 28.3 ns 28.3 ns 10 -std::string copy{str_with_len_N};/512_median 28.1 ns 28.1 ns 10 -std::string copy{str_with_len_N};/512_stddev 0.553 ns 0.553 ns 10 -std::string copy{str_with_len_N};/512_cv 1.95 % 1.95 % 10 -std::string copy{str_with_len_N};/1024_mean 39.6 ns 39.6 ns 10 -std::string copy{str_with_len_N};/1024_median 39.6 ns 39.6 ns 10 -std::string copy{str_with_len_N};/1024_stddev 0.393 ns 0.393 ns 10 -std::string copy{str_with_len_N};/1024_cv 0.99 % 0.99 % 10 -std::string copy{str_with_len_N};/2048_mean 81.3 ns 81.3 ns 10 -std::string copy{str_with_len_N};/2048_median 79.9 ns 79.9 ns 10 -std::string copy{str_with_len_N};/2048_stddev 7.71 ns 7.71 ns 10 -std::string copy{str_with_len_N};/2048_cv 9.48 % 9.48 % 10 -std::string copy{str_with_len_N};/4096_mean 117 ns 117 ns 10 -std::string copy{str_with_len_N};/4096_median 117 ns 117 ns 10 -std::string copy{str_with_len_N};/4096_stddev 4.59 ns 4.59 ns 10 -std::string copy{str_with_len_N};/4096_cv 3.91 % 3.91 % 10 -stringa copy{str_with_len_N};/15_mean 1.13 ns 1.13 ns 10 -stringa copy{str_with_len_N};/15_median 1.12 ns 1.12 ns 10 -stringa copy{str_with_len_N};/15_stddev 0.027 ns 0.027 ns 10 -stringa copy{str_with_len_N};/15_cv 2.39 % 2.39 % 10 -stringa copy{str_with_len_N};/16_mean 1.12 ns 1.12 ns 10 -stringa copy{str_with_len_N};/16_median 1.12 ns 1.12 ns 10 -stringa copy{str_with_len_N};/16_stddev 0.011 ns 0.011 ns 10 -stringa copy{str_with_len_N};/16_cv 1.01 % 1.01 % 10 -stringa copy{str_with_len_N};/23_mean 1.11 ns 1.11 ns 10 -stringa copy{str_with_len_N};/23_median 1.11 ns 1.11 ns 10 -stringa copy{str_with_len_N};/23_stddev 0.023 ns 0.023 ns 10 -stringa copy{str_with_len_N};/23_cv 2.08 % 2.08 % 10 -stringa copy{str_with_len_N};/24_mean 16.6 ns 16.6 ns 10 -stringa copy{str_with_len_N};/24_median 16.3 ns 16.3 ns 10 -stringa copy{str_with_len_N};/24_stddev 1.15 ns 1.15 ns 10 -stringa copy{str_with_len_N};/24_cv 6.92 % 6.92 % 10 -stringa copy{str_with_len_N};/32_mean 16.2 ns 16.2 ns 10 -stringa copy{str_with_len_N};/32_median 16.2 ns 16.2 ns 10 -stringa copy{str_with_len_N};/32_stddev 0.182 ns 0.184 ns 10 -stringa copy{str_with_len_N};/32_cv 1.12 % 1.13 % 10 +std::string copy{str_with_len_N};/15_mean 5.69 ns 5.69 ns 10 +std::string copy{str_with_len_N};/15_median 5.60 ns 5.60 ns 10 +std::string copy{str_with_len_N};/15_stddev 0.168 ns 0.168 ns 10 +std::string copy{str_with_len_N};/15_cv 2.95 % 2.95 % 10 +std::string copy{str_with_len_N};/16_mean 23.6 ns 23.6 ns 10 +std::string copy{str_with_len_N};/16_median 23.2 ns 23.2 ns 10 +std::string copy{str_with_len_N};/16_stddev 0.963 ns 0.963 ns 10 +std::string copy{str_with_len_N};/16_cv 4.08 % 4.08 % 10 +std::string copy{str_with_len_N};/23_mean 24.0 ns 24.0 ns 10 +std::string copy{str_with_len_N};/23_median 23.9 ns 23.9 ns 10 +std::string copy{str_with_len_N};/23_stddev 0.815 ns 0.815 ns 10 +std::string copy{str_with_len_N};/23_cv 3.40 % 3.40 % 10 +std::string copy{str_with_len_N};/24_mean 23.3 ns 23.3 ns 10 +std::string copy{str_with_len_N};/24_median 23.1 ns 23.1 ns 10 +std::string copy{str_with_len_N};/24_stddev 0.657 ns 0.657 ns 10 +std::string copy{str_with_len_N};/24_cv 2.83 % 2.83 % 10 +std::string copy{str_with_len_N};/32_mean 23.2 ns 23.2 ns 10 +std::string copy{str_with_len_N};/32_median 23.0 ns 23.0 ns 10 +std::string copy{str_with_len_N};/32_stddev 0.736 ns 0.736 ns 10 +std::string copy{str_with_len_N};/32_cv 3.17 % 3.17 % 10 +std::string copy{str_with_len_N};/64_mean 23.3 ns 23.3 ns 10 +std::string copy{str_with_len_N};/64_median 23.1 ns 23.1 ns 10 +std::string copy{str_with_len_N};/64_stddev 0.632 ns 0.632 ns 10 +std::string copy{str_with_len_N};/64_cv 2.71 % 2.71 % 10 +std::string copy{str_with_len_N};/128_mean 25.2 ns 25.2 ns 10 +std::string copy{str_with_len_N};/128_median 25.3 ns 25.3 ns 10 +std::string copy{str_with_len_N};/128_stddev 0.448 ns 0.448 ns 10 +std::string copy{str_with_len_N};/128_cv 1.78 % 1.78 % 10 +std::string copy{str_with_len_N};/256_mean 25.4 ns 25.4 ns 10 +std::string copy{str_with_len_N};/256_median 25.1 ns 25.1 ns 10 +std::string copy{str_with_len_N};/256_stddev 0.854 ns 0.854 ns 10 +std::string copy{str_with_len_N};/256_cv 3.36 % 3.36 % 10 +std::string copy{str_with_len_N};/512_mean 29.9 ns 29.9 ns 10 +std::string copy{str_with_len_N};/512_median 29.5 ns 29.5 ns 10 +std::string copy{str_with_len_N};/512_stddev 1.73 ns 1.73 ns 10 +std::string copy{str_with_len_N};/512_cv 5.79 % 5.79 % 10 +std::string copy{str_with_len_N};/1024_mean 44.1 ns 44.1 ns 10 +std::string copy{str_with_len_N};/1024_median 44.1 ns 44.1 ns 10 +std::string copy{str_with_len_N};/1024_stddev 0.355 ns 0.355 ns 10 +std::string copy{str_with_len_N};/1024_cv 0.81 % 0.81 % 10 +std::string copy{str_with_len_N};/2048_mean 130 ns 130 ns 10 +std::string copy{str_with_len_N};/2048_median 132 ns 132 ns 10 +std::string copy{str_with_len_N};/2048_stddev 8.33 ns 8.33 ns 10 +std::string copy{str_with_len_N};/2048_cv 6.39 % 6.39 % 10 +std::string copy{str_with_len_N};/4096_mean 153 ns 153 ns 10 +std::string copy{str_with_len_N};/4096_median 154 ns 154 ns 10 +std::string copy{str_with_len_N};/4096_stddev 9.49 ns 9.49 ns 10 +std::string copy{str_with_len_N};/4096_cv 6.19 % 6.19 % 10 +stringa copy{str_with_len_N};/15_mean 1.10 ns 1.10 ns 10 +stringa copy{str_with_len_N};/15_median 1.09 ns 1.09 ns 10 +stringa copy{str_with_len_N};/15_stddev 0.023 ns 0.023 ns 10 +stringa copy{str_with_len_N};/15_cv 2.13 % 2.13 % 10 +stringa copy{str_with_len_N};/16_mean 1.10 ns 1.10 ns 10 +stringa copy{str_with_len_N};/16_median 1.10 ns 1.10 ns 10 +stringa copy{str_with_len_N};/16_stddev 0.021 ns 0.021 ns 10 +stringa copy{str_with_len_N};/16_cv 1.87 % 1.87 % 10 +stringa copy{str_with_len_N};/23_mean 1.10 ns 1.10 ns 10 +stringa copy{str_with_len_N};/23_median 1.10 ns 1.10 ns 10 +stringa copy{str_with_len_N};/23_stddev 0.020 ns 0.020 ns 10 +stringa copy{str_with_len_N};/23_cv 1.77 % 1.77 % 10 +stringa copy{str_with_len_N};/24_mean 16.7 ns 16.7 ns 10 +stringa copy{str_with_len_N};/24_median 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/24_stddev 2.22 ns 2.22 ns 10 +stringa copy{str_with_len_N};/24_cv 13.29 % 13.29 % 10 +stringa copy{str_with_len_N};/32_mean 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/32_median 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/32_stddev 0.274 ns 0.274 ns 10 +stringa copy{str_with_len_N};/32_cv 1.71 % 1.71 % 10 stringa copy{str_with_len_N};/64_mean 16.0 ns 16.0 ns 10 -stringa copy{str_with_len_N};/64_median 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/64_stddev 0.133 ns 0.133 ns 10 -stringa copy{str_with_len_N};/64_cv 0.83 % 0.83 % 10 -stringa copy{str_with_len_N};/128_mean 16.2 ns 16.2 ns 10 -stringa copy{str_with_len_N};/128_median 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/128_stddev 0.420 ns 0.420 ns 10 -stringa copy{str_with_len_N};/128_cv 2.60 % 2.60 % 10 +stringa copy{str_with_len_N};/64_median 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/64_stddev 0.140 ns 0.140 ns 10 +stringa copy{str_with_len_N};/64_cv 0.87 % 0.87 % 10 +stringa copy{str_with_len_N};/128_mean 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/128_median 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/128_stddev 0.101 ns 0.101 ns 10 +stringa copy{str_with_len_N};/128_cv 0.63 % 0.63 % 10 stringa copy{str_with_len_N};/256_mean 16.0 ns 16.0 ns 10 -stringa copy{str_with_len_N};/256_median 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/256_stddev 0.093 ns 0.093 ns 10 -stringa copy{str_with_len_N};/256_cv 0.58 % 0.58 % 10 +stringa copy{str_with_len_N};/256_median 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/256_stddev 0.199 ns 0.199 ns 10 +stringa copy{str_with_len_N};/256_cv 1.24 % 1.24 % 10 stringa copy{str_with_len_N};/512_mean 16.0 ns 16.0 ns 10 -stringa copy{str_with_len_N};/512_median 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/512_stddev 0.158 ns 0.158 ns 10 -stringa copy{str_with_len_N};/512_cv 0.98 % 0.98 % 10 -stringa copy{str_with_len_N};/1024_mean 16.4 ns 16.4 ns 10 -stringa copy{str_with_len_N};/1024_median 16.2 ns 16.2 ns 10 -stringa copy{str_with_len_N};/1024_stddev 0.353 ns 0.353 ns 10 -stringa copy{str_with_len_N};/1024_cv 2.16 % 2.16 % 10 +stringa copy{str_with_len_N};/512_median 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/512_stddev 0.116 ns 0.116 ns 10 +stringa copy{str_with_len_N};/512_cv 0.72 % 0.72 % 10 +stringa copy{str_with_len_N};/1024_mean 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/1024_median 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/1024_stddev 0.086 ns 0.086 ns 10 +stringa copy{str_with_len_N};/1024_cv 0.54 % 0.54 % 10 stringa copy{str_with_len_N};/2048_mean 16.1 ns 16.1 ns 10 stringa copy{str_with_len_N};/2048_median 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/2048_stddev 0.089 ns 0.089 ns 10 -stringa copy{str_with_len_N};/2048_cv 0.55 % 0.55 % 10 -stringa copy{str_with_len_N};/4096_mean 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/4096_median 16.0 ns 16.0 ns 10 -stringa copy{str_with_len_N};/4096_stddev 0.117 ns 0.117 ns 10 -stringa copy{str_with_len_N};/4096_cv 0.73 % 0.73 % 10 -lstringa<16> copy{str_with_len_N};/15_mean 5.08 ns 5.08 ns 10 -lstringa<16> copy{str_with_len_N};/15_median 5.03 ns 5.03 ns 10 -lstringa<16> copy{str_with_len_N};/15_stddev 0.271 ns 0.271 ns 10 -lstringa<16> copy{str_with_len_N};/15_cv 5.33 % 5.33 % 10 -lstringa<16> copy{str_with_len_N};/16_mean 4.97 ns 4.97 ns 10 -lstringa<16> copy{str_with_len_N};/16_median 4.89 ns 4.89 ns 10 -lstringa<16> copy{str_with_len_N};/16_stddev 0.234 ns 0.234 ns 10 -lstringa<16> copy{str_with_len_N};/16_cv 4.72 % 4.72 % 10 -lstringa<16> copy{str_with_len_N};/23_mean 4.90 ns 4.90 ns 10 -lstringa<16> copy{str_with_len_N};/23_median 4.89 ns 4.89 ns 10 -lstringa<16> copy{str_with_len_N};/23_stddev 0.093 ns 0.093 ns 10 -lstringa<16> copy{str_with_len_N};/23_cv 1.89 % 1.89 % 10 -lstringa<16> copy{str_with_len_N};/24_mean 24.2 ns 24.2 ns 10 -lstringa<16> copy{str_with_len_N};/24_median 24.3 ns 24.3 ns 10 -lstringa<16> copy{str_with_len_N};/24_stddev 0.377 ns 0.377 ns 10 -lstringa<16> copy{str_with_len_N};/24_cv 1.56 % 1.56 % 10 -lstringa<16> copy{str_with_len_N};/32_mean 24.1 ns 24.1 ns 10 -lstringa<16> copy{str_with_len_N};/32_median 24.2 ns 24.2 ns 10 -lstringa<16> copy{str_with_len_N};/32_stddev 0.406 ns 0.406 ns 10 -lstringa<16> copy{str_with_len_N};/32_cv 1.69 % 1.69 % 10 -lstringa<16> copy{str_with_len_N};/64_mean 25.6 ns 25.6 ns 10 -lstringa<16> copy{str_with_len_N};/64_median 25.7 ns 25.7 ns 10 -lstringa<16> copy{str_with_len_N};/64_stddev 0.473 ns 0.473 ns 10 -lstringa<16> copy{str_with_len_N};/64_cv 1.85 % 1.85 % 10 -lstringa<16> copy{str_with_len_N};/128_mean 27.3 ns 27.3 ns 10 -lstringa<16> copy{str_with_len_N};/128_median 27.3 ns 27.3 ns 10 -lstringa<16> copy{str_with_len_N};/128_stddev 0.298 ns 0.298 ns 10 -lstringa<16> copy{str_with_len_N};/128_cv 1.09 % 1.09 % 10 -lstringa<16> copy{str_with_len_N};/256_mean 27.6 ns 27.6 ns 10 -lstringa<16> copy{str_with_len_N};/256_median 27.5 ns 27.5 ns 10 -lstringa<16> copy{str_with_len_N};/256_stddev 1.23 ns 1.23 ns 10 -lstringa<16> copy{str_with_len_N};/256_cv 4.45 % 4.45 % 10 -lstringa<16> copy{str_with_len_N};/512_mean 30.4 ns 30.4 ns 10 -lstringa<16> copy{str_with_len_N};/512_median 30.5 ns 30.5 ns 10 -lstringa<16> copy{str_with_len_N};/512_stddev 1.54 ns 1.54 ns 10 -lstringa<16> copy{str_with_len_N};/512_cv 5.07 % 5.07 % 10 -lstringa<16> copy{str_with_len_N};/1024_mean 70.0 ns 70.0 ns 10 -lstringa<16> copy{str_with_len_N};/1024_median 67.8 ns 67.8 ns 10 -lstringa<16> copy{str_with_len_N};/1024_stddev 18.1 ns 18.1 ns 10 -lstringa<16> copy{str_with_len_N};/1024_cv 25.80 % 25.80 % 10 -lstringa<16> copy{str_with_len_N};/2048_mean 74.5 ns 74.5 ns 10 -lstringa<16> copy{str_with_len_N};/2048_median 74.1 ns 74.1 ns 10 -lstringa<16> copy{str_with_len_N};/2048_stddev 11.7 ns 11.7 ns 10 -lstringa<16> copy{str_with_len_N};/2048_cv 15.66 % 15.66 % 10 -lstringa<16> copy{str_with_len_N};/4096_mean 90.9 ns 90.9 ns 10 -lstringa<16> copy{str_with_len_N};/4096_median 88.7 ns 88.7 ns 10 -lstringa<16> copy{str_with_len_N};/4096_stddev 5.55 ns 5.55 ns 10 -lstringa<16> copy{str_with_len_N};/4096_cv 6.11 % 6.11 % 10 -lstringa<512> copy{str_with_len_N};/15_mean 5.14 ns 5.14 ns 10 -lstringa<512> copy{str_with_len_N};/15_median 5.06 ns 5.06 ns 10 -lstringa<512> copy{str_with_len_N};/15_stddev 0.297 ns 0.297 ns 10 -lstringa<512> copy{str_with_len_N};/15_cv 5.77 % 5.77 % 10 -lstringa<512> copy{str_with_len_N};/16_mean 4.86 ns 4.86 ns 10 -lstringa<512> copy{str_with_len_N};/16_median 4.85 ns 4.85 ns 10 -lstringa<512> copy{str_with_len_N};/16_stddev 0.077 ns 0.077 ns 10 -lstringa<512> copy{str_with_len_N};/16_cv 1.58 % 1.58 % 10 -lstringa<512> copy{str_with_len_N};/23_mean 4.91 ns 4.91 ns 10 -lstringa<512> copy{str_with_len_N};/23_median 4.91 ns 4.91 ns 10 -lstringa<512> copy{str_with_len_N};/23_stddev 0.088 ns 0.088 ns 10 -lstringa<512> copy{str_with_len_N};/23_cv 1.79 % 1.79 % 10 -lstringa<512> copy{str_with_len_N};/24_mean 4.99 ns 4.99 ns 10 -lstringa<512> copy{str_with_len_N};/24_median 4.96 ns 4.96 ns 10 -lstringa<512> copy{str_with_len_N};/24_stddev 0.209 ns 0.209 ns 10 -lstringa<512> copy{str_with_len_N};/24_cv 4.18 % 4.18 % 10 -lstringa<512> copy{str_with_len_N};/32_mean 4.58 ns 4.58 ns 10 -lstringa<512> copy{str_with_len_N};/32_median 4.54 ns 4.54 ns 10 -lstringa<512> copy{str_with_len_N};/32_stddev 0.159 ns 0.159 ns 10 -lstringa<512> copy{str_with_len_N};/32_cv 3.48 % 3.48 % 10 -lstringa<512> copy{str_with_len_N};/64_mean 6.06 ns 6.06 ns 10 -lstringa<512> copy{str_with_len_N};/64_median 6.04 ns 6.04 ns 10 -lstringa<512> copy{str_with_len_N};/64_stddev 0.100 ns 0.100 ns 10 -lstringa<512> copy{str_with_len_N};/64_cv 1.65 % 1.65 % 10 -lstringa<512> copy{str_with_len_N};/128_mean 6.44 ns 6.45 ns 10 -lstringa<512> copy{str_with_len_N};/128_median 6.47 ns 6.47 ns 10 -lstringa<512> copy{str_with_len_N};/128_stddev 0.092 ns 0.092 ns 10 -lstringa<512> copy{str_with_len_N};/128_cv 1.42 % 1.42 % 10 -lstringa<512> copy{str_with_len_N};/256_mean 8.00 ns 8.00 ns 10 -lstringa<512> copy{str_with_len_N};/256_median 7.96 ns 7.96 ns 10 -lstringa<512> copy{str_with_len_N};/256_stddev 0.177 ns 0.177 ns 10 -lstringa<512> copy{str_with_len_N};/256_cv 2.22 % 2.22 % 10 -lstringa<512> copy{str_with_len_N};/512_mean 10.7 ns 10.7 ns 10 -lstringa<512> copy{str_with_len_N};/512_median 10.6 ns 10.6 ns 10 -lstringa<512> copy{str_with_len_N};/512_stddev 0.188 ns 0.188 ns 10 -lstringa<512> copy{str_with_len_N};/512_cv 1.76 % 1.76 % 10 -lstringa<512> copy{str_with_len_N};/1024_mean 69.8 ns 69.8 ns 10 -lstringa<512> copy{str_with_len_N};/1024_median 65.9 ns 65.9 ns 10 -lstringa<512> copy{str_with_len_N};/1024_stddev 17.9 ns 17.9 ns 10 -lstringa<512> copy{str_with_len_N};/1024_cv 25.67 % 25.67 % 10 -lstringa<512> copy{str_with_len_N};/2048_mean 73.4 ns 73.4 ns 10 -lstringa<512> copy{str_with_len_N};/2048_median 72.8 ns 72.8 ns 10 -lstringa<512> copy{str_with_len_N};/2048_stddev 11.2 ns 11.2 ns 10 -lstringa<512> copy{str_with_len_N};/2048_cv 15.26 % 15.26 % 10 -lstringa<512> copy{str_with_len_N};/4096_mean 90.8 ns 90.8 ns 10 -lstringa<512> copy{str_with_len_N};/4096_median 88.1 ns 88.1 ns 10 -lstringa<512> copy{str_with_len_N};/4096_stddev 5.69 ns 5.69 ns 10 -lstringa<512> copy{str_with_len_N};/4096_cv 6.27 % 6.27 % 10 +stringa copy{str_with_len_N};/2048_stddev 0.231 ns 0.231 ns 10 +stringa copy{str_with_len_N};/2048_cv 1.43 % 1.43 % 10 +stringa copy{str_with_len_N};/4096_mean 16.0 ns 16.0 ns 10 +stringa copy{str_with_len_N};/4096_median 15.9 ns 15.9 ns 10 +stringa copy{str_with_len_N};/4096_stddev 0.137 ns 0.137 ns 10 +stringa copy{str_with_len_N};/4096_cv 0.86 % 0.86 % 10 +lstringa<16> copy{str_with_len_N};/15_mean 4.12 ns 4.12 ns 10 +lstringa<16> copy{str_with_len_N};/15_median 4.06 ns 4.06 ns 10 +lstringa<16> copy{str_with_len_N};/15_stddev 0.151 ns 0.151 ns 10 +lstringa<16> copy{str_with_len_N};/15_cv 3.68 % 3.68 % 10 +lstringa<16> copy{str_with_len_N};/16_mean 4.09 ns 4.09 ns 10 +lstringa<16> copy{str_with_len_N};/16_median 4.04 ns 4.04 ns 10 +lstringa<16> copy{str_with_len_N};/16_stddev 0.099 ns 0.099 ns 10 +lstringa<16> copy{str_with_len_N};/16_cv 2.42 % 2.42 % 10 +lstringa<16> copy{str_with_len_N};/23_mean 4.04 ns 4.04 ns 10 +lstringa<16> copy{str_with_len_N};/23_median 4.02 ns 4.02 ns 10 +lstringa<16> copy{str_with_len_N};/23_stddev 0.087 ns 0.087 ns 10 +lstringa<16> copy{str_with_len_N};/23_cv 2.16 % 2.16 % 10 +lstringa<16> copy{str_with_len_N};/24_mean 22.9 ns 22.9 ns 10 +lstringa<16> copy{str_with_len_N};/24_median 22.9 ns 22.9 ns 10 +lstringa<16> copy{str_with_len_N};/24_stddev 0.276 ns 0.276 ns 10 +lstringa<16> copy{str_with_len_N};/24_cv 1.20 % 1.20 % 10 +lstringa<16> copy{str_with_len_N};/32_mean 22.9 ns 22.9 ns 10 +lstringa<16> copy{str_with_len_N};/32_median 23.0 ns 23.0 ns 10 +lstringa<16> copy{str_with_len_N};/32_stddev 0.429 ns 0.429 ns 10 +lstringa<16> copy{str_with_len_N};/32_cv 1.87 % 1.87 % 10 +lstringa<16> copy{str_with_len_N};/64_mean 24.1 ns 24.1 ns 10 +lstringa<16> copy{str_with_len_N};/64_median 23.8 ns 23.8 ns 10 +lstringa<16> copy{str_with_len_N};/64_stddev 0.966 ns 0.966 ns 10 +lstringa<16> copy{str_with_len_N};/64_cv 4.01 % 4.01 % 10 +lstringa<16> copy{str_with_len_N};/128_mean 24.8 ns 24.8 ns 10 +lstringa<16> copy{str_with_len_N};/128_median 24.8 ns 24.8 ns 10 +lstringa<16> copy{str_with_len_N};/128_stddev 0.671 ns 0.671 ns 10 +lstringa<16> copy{str_with_len_N};/128_cv 2.70 % 2.70 % 10 +lstringa<16> copy{str_with_len_N};/256_mean 26.0 ns 26.0 ns 10 +lstringa<16> copy{str_with_len_N};/256_median 25.8 ns 25.8 ns 10 +lstringa<16> copy{str_with_len_N};/256_stddev 0.889 ns 0.889 ns 10 +lstringa<16> copy{str_with_len_N};/256_cv 3.42 % 3.42 % 10 +lstringa<16> copy{str_with_len_N};/512_mean 28.5 ns 28.5 ns 10 +lstringa<16> copy{str_with_len_N};/512_median 28.4 ns 28.4 ns 10 +lstringa<16> copy{str_with_len_N};/512_stddev 0.294 ns 0.294 ns 10 +lstringa<16> copy{str_with_len_N};/512_cv 1.03 % 1.03 % 10 +lstringa<16> copy{str_with_len_N};/1024_mean 93.2 ns 93.2 ns 10 +lstringa<16> copy{str_with_len_N};/1024_median 96.2 ns 96.2 ns 10 +lstringa<16> copy{str_with_len_N};/1024_stddev 10.7 ns 10.7 ns 10 +lstringa<16> copy{str_with_len_N};/1024_cv 11.44 % 11.44 % 10 +lstringa<16> copy{str_with_len_N};/2048_mean 113 ns 113 ns 10 +lstringa<16> copy{str_with_len_N};/2048_median 114 ns 114 ns 10 +lstringa<16> copy{str_with_len_N};/2048_stddev 12.1 ns 12.1 ns 10 +lstringa<16> copy{str_with_len_N};/2048_cv 10.70 % 10.70 % 10 +lstringa<16> copy{str_with_len_N};/4096_mean 127 ns 127 ns 10 +lstringa<16> copy{str_with_len_N};/4096_median 126 ns 126 ns 10 +lstringa<16> copy{str_with_len_N};/4096_stddev 8.40 ns 8.40 ns 10 +lstringa<16> copy{str_with_len_N};/4096_cv 6.63 % 6.63 % 10 +lstringa<512> copy{str_with_len_N};/15_mean 4.48 ns 4.48 ns 10 +lstringa<512> copy{str_with_len_N};/15_median 4.38 ns 4.38 ns 10 +lstringa<512> copy{str_with_len_N};/15_stddev 0.311 ns 0.311 ns 10 +lstringa<512> copy{str_with_len_N};/15_cv 6.94 % 6.94 % 10 +lstringa<512> copy{str_with_len_N};/16_mean 4.49 ns 4.49 ns 10 +lstringa<512> copy{str_with_len_N};/16_median 4.48 ns 4.48 ns 10 +lstringa<512> copy{str_with_len_N};/16_stddev 0.123 ns 0.123 ns 10 +lstringa<512> copy{str_with_len_N};/16_cv 2.75 % 2.75 % 10 +lstringa<512> copy{str_with_len_N};/23_mean 4.43 ns 4.43 ns 10 +lstringa<512> copy{str_with_len_N};/23_median 4.40 ns 4.40 ns 10 +lstringa<512> copy{str_with_len_N};/23_stddev 0.107 ns 0.107 ns 10 +lstringa<512> copy{str_with_len_N};/23_cv 2.42 % 2.42 % 10 +lstringa<512> copy{str_with_len_N};/24_mean 4.55 ns 4.55 ns 10 +lstringa<512> copy{str_with_len_N};/24_median 4.53 ns 4.53 ns 10 +lstringa<512> copy{str_with_len_N};/24_stddev 0.112 ns 0.112 ns 10 +lstringa<512> copy{str_with_len_N};/24_cv 2.47 % 2.47 % 10 +lstringa<512> copy{str_with_len_N};/32_mean 4.12 ns 4.12 ns 10 +lstringa<512> copy{str_with_len_N};/32_median 4.09 ns 4.09 ns 10 +lstringa<512> copy{str_with_len_N};/32_stddev 0.123 ns 0.123 ns 10 +lstringa<512> copy{str_with_len_N};/32_cv 3.00 % 3.00 % 10 +lstringa<512> copy{str_with_len_N};/64_mean 6.30 ns 6.30 ns 10 +lstringa<512> copy{str_with_len_N};/64_median 6.16 ns 6.16 ns 10 +lstringa<512> copy{str_with_len_N};/64_stddev 0.337 ns 0.337 ns 10 +lstringa<512> copy{str_with_len_N};/64_cv 5.35 % 5.35 % 10 +lstringa<512> copy{str_with_len_N};/128_mean 6.07 ns 6.07 ns 10 +lstringa<512> copy{str_with_len_N};/128_median 6.00 ns 6.00 ns 10 +lstringa<512> copy{str_with_len_N};/128_stddev 0.226 ns 0.226 ns 10 +lstringa<512> copy{str_with_len_N};/128_cv 3.73 % 3.73 % 10 +lstringa<512> copy{str_with_len_N};/256_mean 7.87 ns 7.87 ns 10 +lstringa<512> copy{str_with_len_N};/256_median 7.88 ns 7.88 ns 10 +lstringa<512> copy{str_with_len_N};/256_stddev 0.159 ns 0.159 ns 10 +lstringa<512> copy{str_with_len_N};/256_cv 2.02 % 2.02 % 10 +lstringa<512> copy{str_with_len_N};/512_mean 10.2 ns 10.2 ns 10 +lstringa<512> copy{str_with_len_N};/512_median 10.1 ns 10.1 ns 10 +lstringa<512> copy{str_with_len_N};/512_stddev 0.401 ns 0.401 ns 10 +lstringa<512> copy{str_with_len_N};/512_cv 3.95 % 3.95 % 10 +lstringa<512> copy{str_with_len_N};/1024_mean 95.5 ns 95.5 ns 10 +lstringa<512> copy{str_with_len_N};/1024_median 95.8 ns 95.8 ns 10 +lstringa<512> copy{str_with_len_N};/1024_stddev 10.0 ns 10.0 ns 10 +lstringa<512> copy{str_with_len_N};/1024_cv 10.48 % 10.48 % 10 +lstringa<512> copy{str_with_len_N};/2048_mean 116 ns 116 ns 10 +lstringa<512> copy{str_with_len_N};/2048_median 119 ns 119 ns 10 +lstringa<512> copy{str_with_len_N};/2048_stddev 12.9 ns 12.9 ns 10 +lstringa<512> copy{str_with_len_N};/2048_cv 11.09 % 11.09 % 10 +lstringa<512> copy{str_with_len_N};/4096_mean 130 ns 130 ns 10 +lstringa<512> copy{str_with_len_N};/4096_median 126 ns 126 ns 10 +lstringa<512> copy{str_with_len_N};/4096_stddev 13.5 ns 13.5 ns 10 +lstringa<512> copy{str_with_len_N};/4096_cv 10.37 % 10.37 % 10 ----- Convert to int '1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_mean 27.5 ns 27.5 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 27.4 ns 27.4 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 0.887 ns 0.887 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 3.23 % 3.23 % 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 15.8 ns 15.8 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 15.7 ns 15.7 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.845 ns 0.845 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 5.35 % 5.35 % 10 -stringa s = "123456789"; int res = s.to_int_mean 12.8 ns 12.8 ns 10 -stringa s = "123456789"; int res = s.to_int_median 12.7 ns 12.7 ns 10 -stringa s = "123456789"; int res = s.to_int_stddev 0.243 ns 0.243 ns 10 -stringa s = "123456789"; int res = s.to_int_cv 1.90 % 1.90 % 10 -ssa s = "123456789"; int res = s.to_int_mean 12.5 ns 12.5 ns 10 -ssa s = "123456789"; int res = s.to_int_median 12.5 ns 12.5 ns 10 -ssa s = "123456789"; int res = s.to_int_stddev 0.210 ns 0.210 ns 10 -ssa s = "123456789"; int res = s.to_int_cv 1.68 % 1.68 % 10 -lstringa<20> s = "123456789"; int res = s.to_int_mean 12.5 ns 12.5 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_median 12.5 ns 12.5 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_stddev 0.262 ns 0.262 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_cv 2.09 % 2.09 % 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 27.7 ns 27.7 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 1.02 ns 1.02 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 3.69 % 3.69 % 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 15.1 ns 15.1 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 15.1 ns 15.1 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.395 ns 0.395 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 2.62 % 2.62 % 10 +stringa s = "123456789"; int res = s.to_int_mean 12.4 ns 12.4 ns 10 +stringa s = "123456789"; int res = s.to_int_median 12.4 ns 12.4 ns 10 +stringa s = "123456789"; int res = s.to_int_stddev 0.134 ns 0.134 ns 10 +stringa s = "123456789"; int res = s.to_int_cv 1.08 % 1.08 % 10 +ssa s = "123456789"; int res = s.to_int_mean 12.2 ns 12.2 ns 10 +ssa s = "123456789"; int res = s.to_int_median 12.2 ns 12.2 ns 10 +ssa s = "123456789"; int res = s.to_int_stddev 0.135 ns 0.135 ns 10 +ssa s = "123456789"; int res = s.to_int_cv 1.11 % 1.11 % 10 +lstringa<20> s = "123456789"; int res = s.to_int_mean 12.4 ns 12.4 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_median 12.4 ns 12.4 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_stddev 0.212 ns 0.212 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_cv 1.71 % 1.71 % 10 ----- Convert to unsigned 'abcDef' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 23.9 ns 23.9 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 23.7 ns 23.7 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 0.615 ns 0.615 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 2.57 % 2.57 % 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 10.0 ns 10.0 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 9.83 ns 9.83 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 0.588 ns 0.588 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 5.87 % 5.87 % 10 -stringa s = "abcDef"; int res = s.to_int_mean 12.9 ns 12.9 ns 10 -stringa s = "abcDef"; int res = s.to_int_median 12.8 ns 12.8 ns 10 -stringa s = "abcDef"; int res = s.to_int_stddev 0.387 ns 0.387 ns 10 -stringa s = "abcDef"; int res = s.to_int_cv 3.00 % 3.00 % 10 -ssa s = "abcDef"; int res = s.to_int_mean 12.5 ns 12.5 ns 10 -ssa s = "abcDef"; int res = s.to_int_median 12.5 ns 12.5 ns 10 -ssa s = "abcDef"; int res = s.to_int_stddev 0.272 ns 0.272 ns 10 -ssa s = "abcDef"; int res = s.to_int_cv 2.17 % 2.17 % 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 24.1 ns 24.1 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 23.9 ns 23.9 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 0.739 ns 0.739 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 3.07 % 3.07 % 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 9.60 ns 9.60 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 9.56 ns 9.56 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 0.196 ns 0.196 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 2.05 % 2.05 % 10 +stringa s = "abcDef"; int res = s.to_int_mean 12.7 ns 12.7 ns 10 +stringa s = "abcDef"; int res = s.to_int_median 12.5 ns 12.5 ns 10 +stringa s = "abcDef"; int res = s.to_int_stddev 0.388 ns 0.388 ns 10 +stringa s = "abcDef"; int res = s.to_int_cv 3.05 % 3.05 % 10 +ssa s = "abcDef"; int res = s.to_int_mean 13.1 ns 13.1 ns 10 +ssa s = "abcDef"; int res = s.to_int_median 13.0 ns 13.0 ns 10 +ssa s = "abcDef"; int res = s.to_int_stddev 0.717 ns 0.717 ns 10 +ssa s = "abcDef"; int res = s.to_int_cv 5.46 % 5.46 % 10 lstringa<20> s = "abcDef"; int res = s.to_int_mean 12.7 ns 12.7 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_median 12.4 ns 12.4 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_stddev 0.542 ns 0.542 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_cv 4.28 % 4.28 % 10 +lstringa<20> s = "abcDef"; int res = s.to_int_median 12.6 ns 12.6 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_stddev 0.416 ns 0.416 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_cv 3.26 % 3.26 % 10 ----- Convert to int ' 1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_mean 28.9 ns 28.9 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 29.0 ns 29.0 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 0.673 ns 0.673 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 2.32 % 2.32 % 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 18.8 ns 18.8 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 18.8 ns 18.8 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 0.285 ns 0.285 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 1.52 % 1.52 % 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 16.1 ns 16.1 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 16.1 ns 16.1 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.269 ns 0.269 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 1.67 % 1.67 % 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 28.7 ns 28.7 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 0.802 ns 0.802 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 2.77 % 2.77 % 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 18.4 ns 18.4 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 18.4 ns 18.4 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 0.236 ns 0.236 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 1.28 % 1.28 % 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 15.3 ns 15.3 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 15.2 ns 15.2 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.387 ns 0.387 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 2.54 % 2.54 % 10 ----- Convert to double '1234.567e10' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 65.0 ns 65.0 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_median 65.2 ns 65.2 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 1.50 ns 1.50 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 2.30 % 2.30 % 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 24.2 ns 24.2 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 24.2 ns 24.2 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 0.504 ns 0.504 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 2.08 % 2.08 % 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 65.7 ns 65.7 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_median 64.6 ns 64.6 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 2.02 ns 2.02 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 3.08 % 3.08 % 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 24.6 ns 24.6 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 24.4 ns 24.4 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 0.496 ns 0.496 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 2.02 % 2.02 % 10 ssa s = "1234.567e10"; double res = *s.to_double()_mean 26.1 ns 26.1 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_median 26.0 ns 26.0 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_stddev 0.459 ns 0.459 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_cv 1.76 % 1.76 % 10 +ssa s = "1234.567e10"; double res = *s.to_double()_median 25.7 ns 25.7 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_stddev 0.780 ns 0.780 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_cv 2.99 % 2.99 % 10 -- Append const literal of 16 bytes 64 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << "abbaabbaabbaabba";_mean 1403 ns 1403 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_median 1392 ns 1392 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 56.2 ns 56.2 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_cv 4.01 % 4.01 % 10 -std::string str; ... str += "abbaabbaabbaabba";_mean 359 ns 359 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_median 363 ns 363 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_stddev 22.7 ns 22.7 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_cv 6.33 % 6.33 % 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 337 ns 337 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_median 332 ns 332 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 15.8 ns 15.8 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 4.69 % 4.69 % 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 242 ns 242 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_median 245 ns 245 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 10.9 ns 10.9 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 4.51 % 4.51 % 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 227 ns 227 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_median 226 ns 226 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 10.2 ns 10.2 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 4.48 % 4.48 % 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 138 ns 138 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_median 138 ns 138 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 2.87 ns 2.87 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_mean 1354 ns 1354 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_median 1341 ns 1341 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 34.1 ns 34.1 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_cv 2.52 % 2.52 % 10 +std::string str; ... str += "abbaabbaabbaabba";_mean 372 ns 372 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_median 375 ns 375 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_stddev 16.4 ns 16.4 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_cv 4.42 % 4.42 % 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 361 ns 361 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_median 364 ns 364 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 14.5 ns 14.5 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 4.02 % 4.02 % 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 272 ns 272 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_median 267 ns 267 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 13.2 ns 13.2 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 4.83 % 4.83 % 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 228 ns 228 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_median 221 ns 221 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 16.3 ns 16.3 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 7.16 % 7.16 % 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 136 ns 136 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_median 135 ns 135 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 2.82 ns 2.82 ns 10 lstringa<1024> str; ... str += "abbaabbaabbaabba";_cv 2.07 % 2.07 % 10 -- Append string of 16 bytes and const literal of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 1403 ns 1403 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 1376 ns 1376 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 95.9 ns 95.9 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 6.84 % 6.84 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 1296 ns 1296 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_median 1297 ns 1297 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 14.4 ns 14.4 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 1.11 % 1.11 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 431 ns 431 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 435 ns 435 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 22.8 ns 22.8 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.28 % 5.28 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 326 ns 326 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 330 ns 330 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 18.3 ns 18.3 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.61 % 5.61 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 312 ns 312 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 316 ns 316 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 11.6 ns 11.6 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 3.70 % 3.70 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 253 ns 253 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 243 ns 243 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 20.5 ns 20.5 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 8.10 % 8.10 % 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 1363 ns 1363 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 1349 ns 1349 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 40.2 ns 40.2 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 2.95 % 2.95 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 1282 ns 1282 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_median 1276 ns 1276 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 31.1 ns 31.1 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 2.43 % 2.43 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 445 ns 445 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 447 ns 447 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 15.1 ns 15.1 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 3.41 % 3.41 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 386 ns 386 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 380 ns 380 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 21.8 ns 21.8 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.66 % 5.66 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 323 ns 323 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 311 ns 311 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 23.3 ns 23.3 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 7.22 % 7.22 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 204 ns 204 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 202 ns 202 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 4.94 ns 4.94 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 2.42 % 2.42 % 10 -- Append string of 16 bytes and const literal of 16 bytes 2048 times, 65536 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 125727 ns 125726 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 125997 ns 125994 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 2545 ns 2545 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 2.02 % 2.02 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 77160 ns 77160 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 76892 ns 76892 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 1509 ns 1509 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 1.96 % 1.96 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 52479 ns 52479 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 52594 ns 52594 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 2170 ns 2170 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 4.14 % 4.14 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 28389 ns 28389 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 29270 ns 29270 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 3975 ns 3975 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 14.00 % 14.00 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 18137 ns 18137 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 15931 ns 15931 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 4628 ns 4628 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 25.52 % 25.52 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 15503 ns 15503 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 15576 ns 15576 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 298 ns 298 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 1.92 % 1.92 % 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 76544 ns 76545 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 75664 ns 75664 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 2769 ns 2769 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 3.62 % 3.62 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 72458 ns 72459 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 72032 ns 72033 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 2580 ns 2580 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.56 % 3.56 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 19689 ns 19689 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 19666 ns 19666 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 596 ns 596 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.03 % 3.03 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 15956 ns 15956 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 15932 ns 15933 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 321 ns 321 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.01 % 2.01 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 15837 ns 15837 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 15670 ns 15670 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 366 ns 366 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.31 % 2.31 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 17811 ns 17812 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 17760 ns 17760 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 344 ns 344 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 1.93 % 1.93 % 10 -- Append 2 string of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var1 << str_var2;_mean 1369 ns 1369 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_median 1355 ns 1355 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_stddev 50.3 ns 50.3 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_cv 3.68 % 3.68 % 10 -std::string str; ... str += str_var1 + str_var2;_mean 1396 ns 1396 ns 10 -std::string str; ... str += str_var1 + str_var2;_median 1376 ns 1376 ns 10 -std::string str; ... str += str_var1 + str_var2;_stddev 67.2 ns 67.2 ns 10 -std::string str; ... str += str_var1 + str_var2;_cv 4.81 % 4.81 % 10 -lstringa<16> str; ... str += str_var1 + str_var2;_mean 523 ns 523 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_median 492 ns 492 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_stddev 62.1 ns 62.1 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_cv 11.86 % 11.86 % 10 -lstringa<128> str; ... str += str_var1 + str_var2;_mean 419 ns 419 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_median 418 ns 418 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_stddev 11.5 ns 11.5 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_cv 2.74 % 2.74 % 10 -lstringa<512> str; ... str += str_var1 + str_var2;_mean 395 ns 395 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_median 379 ns 379 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_stddev 32.8 ns 32.8 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_cv 8.30 % 8.30 % 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_mean 311 ns 311 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_median 307 ns 307 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 20.7 ns 20.7 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_cv 6.68 % 6.68 % 10 +std::stringstream str; ... str << str_var1 << str_var2;_mean 1397 ns 1397 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_median 1390 ns 1390 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_stddev 58.0 ns 58.0 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_cv 4.15 % 4.15 % 10 +std::string str; ... str += str_var1 + str_var2;_mean 1354 ns 1354 ns 10 +std::string str; ... str += str_var1 + str_var2;_median 1353 ns 1353 ns 10 +std::string str; ... str += str_var1 + str_var2;_stddev 19.0 ns 19.0 ns 10 +std::string str; ... str += str_var1 + str_var2;_cv 1.41 % 1.41 % 10 +lstringa<16> str; ... str += str_var1 + str_var2;_mean 524 ns 524 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_median 522 ns 522 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_stddev 37.6 ns 37.6 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_cv 7.18 % 7.18 % 10 +lstringa<128> str; ... str += str_var1 + str_var2;_mean 449 ns 449 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_median 445 ns 445 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_stddev 20.3 ns 20.3 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_cv 4.52 % 4.52 % 10 +lstringa<512> str; ... str += str_var1 + str_var2;_mean 385 ns 385 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_median 387 ns 387 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_stddev 15.8 ns 15.8 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_cv 4.11 % 4.11 % 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_mean 305 ns 305 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_median 303 ns 303 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 7.25 ns 7.25 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_cv 2.38 % 2.38 % 10 -- Append text, number, text --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; str << "test = " << k << " times";_mean 3149 ns 3149 ns 10 -std::stringstream str; str << "test = " << k << " times";_median 3141 ns 3141 ns 10 -std::stringstream str; str << "test = " << k << " times";_stddev 163 ns 163 ns 10 -std::stringstream str; str << "test = " << k << " times";_cv 5.18 % 5.18 % 10 -std::string str = "test = " + std::to_string(k) + " times";_mean 482 ns 482 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_median 479 ns 479 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_stddev 10.3 ns 10.3 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_cv 2.14 % 2.14 % 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 1416 ns 1416 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 1403 ns 1403 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 56.8 ns 56.8 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 4.01 % 4.01 % 10 -std::string str = std::format("test = {} times", k);_mean 1134 ns 1134 ns 10 -std::string str = std::format("test = {} times", k);_median 1131 ns 1131 ns 10 -std::string str = std::format("test = {} times", k);_stddev 22.6 ns 22.6 ns 10 -std::string str = std::format("test = {} times", k);_cv 1.99 % 1.99 % 10 -lstringa<8> str; str.format("test = {} times", k);_mean 1390 ns 1390 ns 10 -lstringa<8> str; str.format("test = {} times", k);_median 1382 ns 1382 ns 10 -lstringa<8> str; str.format("test = {} times", k);_stddev 31.5 ns 31.5 ns 10 -lstringa<8> str; str.format("test = {} times", k);_cv 2.27 % 2.27 % 10 -lstringa<32> str; str.format("test = {} times", k);_mean 963 ns 963 ns 10 -lstringa<32> str; str.format("test = {} times", k);_median 968 ns 968 ns 10 -lstringa<32> str; str.format("test = {} times", k);_stddev 25.6 ns 25.6 ns 10 -lstringa<32> str; str.format("test = {} times", k);_cv 2.66 % 2.66 % 10 -lstringa<8> str = "test = " + k + " times";_mean 290 ns 290 ns 10 -lstringa<8> str = "test = " + k + " times";_median 288 ns 288 ns 10 -lstringa<8> str = "test = " + k + " times";_stddev 7.48 ns 7.49 ns 10 -lstringa<8> str = "test = " + k + " times";_cv 2.58 % 2.58 % 10 -lstringa<32> str = "test = " + k + " times";_mean 157 ns 157 ns 10 -lstringa<32> str = "test = " + k + " times";_median 156 ns 156 ns 10 -lstringa<32> str = "test = " + k + " times";_stddev 10.2 ns 10.2 ns 10 -lstringa<32> str = "test = " + k + " times";_cv 6.49 % 6.49 % 10 -stringa str = "test = " + k + " times";_mean 149 ns 149 ns 10 +std::stringstream str; str << "test = " << k << " times";_mean 3102 ns 3102 ns 10 +std::stringstream str; str << "test = " << k << " times";_median 3021 ns 3021 ns 10 +std::stringstream str; str << "test = " << k << " times";_stddev 206 ns 206 ns 10 +std::stringstream str; str << "test = " << k << " times";_cv 6.65 % 6.65 % 10 +std::string str = "test = " + std::to_string(k) + " times";_mean 471 ns 471 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_median 468 ns 468 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_stddev 14.6 ns 14.6 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_cv 3.10 % 3.10 % 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 1395 ns 1395 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 1384 ns 1384 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 43.0 ns 43.0 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 3.08 % 3.08 % 10 +std::string str = std::format("test = {} times", k);_mean 1205 ns 1205 ns 10 +std::string str = std::format("test = {} times", k);_median 1179 ns 1179 ns 10 +std::string str = std::format("test = {} times", k);_stddev 86.3 ns 86.3 ns 10 +std::string str = std::format("test = {} times", k);_cv 7.16 % 7.16 % 10 +lstringa<8> str; str.format("test = {} times", k);_mean 1377 ns 1377 ns 10 +lstringa<8> str; str.format("test = {} times", k);_median 1348 ns 1348 ns 10 +lstringa<8> str; str.format("test = {} times", k);_stddev 75.8 ns 75.8 ns 10 +lstringa<8> str; str.format("test = {} times", k);_cv 5.51 % 5.51 % 10 +lstringa<32> str; str.format("test = {} times", k);_mean 979 ns 979 ns 10 +lstringa<32> str; str.format("test = {} times", k);_median 969 ns 969 ns 10 +lstringa<32> str; str.format("test = {} times", k);_stddev 25.7 ns 25.7 ns 10 +lstringa<32> str; str.format("test = {} times", k);_cv 2.62 % 2.62 % 10 +lstringa<8> str = "test = " + k + " times";_mean 295 ns 295 ns 10 +lstringa<8> str = "test = " + k + " times";_median 292 ns 292 ns 10 +lstringa<8> str = "test = " + k + " times";_stddev 9.63 ns 9.63 ns 10 +lstringa<8> str = "test = " + k + " times";_cv 3.26 % 3.26 % 10 +lstringa<32> str = "test = " + k + " times";_mean 152 ns 152 ns 10 +lstringa<32> str = "test = " + k + " times";_median 152 ns 152 ns 10 +lstringa<32> str = "test = " + k + " times";_stddev 3.23 ns 3.23 ns 10 +lstringa<32> str = "test = " + k + " times";_cv 2.12 % 2.12 % 10 +stringa str = "test = " + k + " times";_mean 150 ns 150 ns 10 stringa str = "test = " + k + " times";_median 149 ns 149 ns 10 -stringa str = "test = " + k + " times";_stddev 2.52 ns 2.52 ns 10 -stringa str = "test = " + k + " times";_cv 1.69 % 1.69 % 10 +stringa str = "test = " + k + " times";_stddev 3.69 ns 3.69 ns 10 +stringa str = "test = " + k + " times";_cv 2.46 % 2.46 % 10 -- Split text and convert to int --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string::find + substr + std::strtol_mean 276 ns 276 ns 10 -std::string::find + substr + std::strtol_median 279 ns 279 ns 10 -std::string::find + substr + std::strtol_stddev 9.35 ns 9.35 ns 10 -std::string::find + substr + std::strtol_cv 3.39 % 3.39 % 10 +std::string::find + substr + std::strtol_mean 270 ns 270 ns 10 +std::string::find + substr + std::strtol_median 268 ns 268 ns 10 +std::string::find + substr + std::strtol_stddev 7.74 ns 7.74 ns 10 +std::string::find + substr + std::strtol_cv 2.86 % 2.86 % 10 ssa::splitter + ssa::as_int_mean 154 ns 154 ns 10 ssa::splitter + ssa::as_int_median 153 ns 153 ns 10 -ssa::splitter + ssa::as_int_stddev 4.66 ns 4.66 ns 10 -ssa::splitter + ssa::as_int_cv 3.03 % 3.03 % 10 -ssa::splitf + functor_mean 214 ns 214 ns 10 -ssa::splitf + functor_median 215 ns 215 ns 10 -ssa::splitf + functor_stddev 3.91 ns 3.91 ns 10 -ssa::splitf + functor_cv 1.83 % 1.83 % 10 +ssa::splitter + ssa::as_int_stddev 4.53 ns 4.53 ns 10 +ssa::splitter + ssa::as_int_cv 2.94 % 2.94 % 10 +ssa::splitf + functor_mean 212 ns 212 ns 10 +ssa::splitf + functor_median 212 ns 212 ns 10 +ssa::splitf + functor_stddev 6.59 ns 6.59 ns 10 +ssa::splitf + functor_cv 3.11 % 3.11 % 10 -- Replace symbols in text ~400 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Naive (and wrong) replace symbols with std::string find + replace_mean 852 ns 852 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_median 849 ns 849 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_stddev 13.8 ns 13.8 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_cv 1.62 % 1.62 % 10 -replace symbols with std::string find_first_of + replace_mean 2510 ns 2510 ns 10 -replace symbols with std::string find_first_of + replace_median 2491 ns 2491 ns 10 -replace symbols with std::string find_first_of + replace_stddev 65.3 ns 65.3 ns 10 -replace symbols with std::string find_first_of + replace_cv 2.60 % 2.60 % 10 -replace symbols with std::string_view find_first_of + copy_mean 1110 ns 1110 ns 10 -replace symbols with std::string_view find_first_of + copy_median 1106 ns 1106 ns 10 -replace symbols with std::string_view find_first_of + copy_stddev 36.3 ns 36.3 ns 10 -replace symbols with std::string_view find_first_of + copy_cv 3.27 % 3.27 % 10 -replace runtime symbols with string expressions and without remembering all search results_mean 1235 ns 1235 ns 10 -replace runtime symbols with string expressions and without remembering all search results_median 1213 ns 1213 ns 10 -replace runtime symbols with string expressions and without remembering all search results_stddev 58.0 ns 58.0 ns 10 -replace runtime symbols with string expressions and without remembering all search results_cv 4.69 % 4.69 % 10 -replace runtime symbols with simstr and memorization of all search results_mean 1069 ns 1069 ns 10 -replace runtime symbols with simstr and memorization of all search results_median 1025 ns 1025 ns 10 -replace runtime symbols with simstr and memorization of all search results_stddev 100 ns 100 ns 10 -replace runtime symbols with simstr and memorization of all search results_cv 9.38 % 9.38 % 10 -replace const symbols with string expressions and without remembering all search results_mean 1084 ns 1084 ns 10 -replace const symbols with string expressions and without remembering all search results_median 1053 ns 1053 ns 10 -replace const symbols with string expressions and without remembering all search results_stddev 91.1 ns 91.1 ns 10 -replace const symbols with string expressions and without remembering all search results_cv 8.40 % 8.40 % 10 -replace const symbols with string expressions and memorization of all search results_mean 862 ns 862 ns 10 -replace const symbols with string expressions and memorization of all search results_median 865 ns 865 ns 10 -replace const symbols with string expressions and memorization of all search results_stddev 22.9 ns 22.9 ns 10 -replace const symbols with string expressions and memorization of all search results_cv 2.66 % 2.66 % 10 +Naive (and wrong) replace symbols with std::string find + replace_mean 865 ns 865 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_median 867 ns 867 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_stddev 28.3 ns 28.3 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_cv 3.27 % 3.27 % 10 +replace symbols with std::string find_first_of + replace_mean 2400 ns 2400 ns 10 +replace symbols with std::string find_first_of + replace_median 2390 ns 2390 ns 10 +replace symbols with std::string find_first_of + replace_stddev 57.5 ns 57.5 ns 10 +replace symbols with std::string find_first_of + replace_cv 2.39 % 2.39 % 10 +replace symbols with std::string_view find_first_of + copy_mean 1100 ns 1100 ns 10 +replace symbols with std::string_view find_first_of + copy_median 1099 ns 1099 ns 10 +replace symbols with std::string_view find_first_of + copy_stddev 22.3 ns 22.3 ns 10 +replace symbols with std::string_view find_first_of + copy_cv 2.03 % 2.03 % 10 +replace runtime symbols with string expressions and without remembering all search results_mean 1290 ns 1290 ns 10 +replace runtime symbols with string expressions and without remembering all search results_median 1279 ns 1279 ns 10 +replace runtime symbols with string expressions and without remembering all search results_stddev 41.5 ns 41.5 ns 10 +replace runtime symbols with string expressions and without remembering all search results_cv 3.22 % 3.22 % 10 +replace runtime symbols with simstr and memorization of all search results_mean 1039 ns 1039 ns 10 +replace runtime symbols with simstr and memorization of all search results_median 1037 ns 1037 ns 10 +replace runtime symbols with simstr and memorization of all search results_stddev 18.2 ns 18.2 ns 10 +replace runtime symbols with simstr and memorization of all search results_cv 1.75 % 1.75 % 10 +replace const symbols with string expressions and without remembering all search results_mean 1034 ns 1034 ns 10 +replace const symbols with string expressions and without remembering all search results_median 1019 ns 1019 ns 10 +replace const symbols with string expressions and without remembering all search results_stddev 35.2 ns 35.2 ns 10 +replace const symbols with string expressions and without remembering all search results_cv 3.40 % 3.40 % 10 +replace const symbols with string expressions and memorization of all search results_mean 892 ns 892 ns 10 +replace const symbols with string expressions and memorization of all search results_median 878 ns 878 ns 10 +replace const symbols with string expressions and memorization of all search results_stddev 24.3 ns 24.3 ns 10 +replace const symbols with string expressions and memorization of all search results_cv 2.72 % 2.72 % 10 -- Replace symbols in text ~40 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Short Naive (and wrong) replace symbols with std::string find + replace_mean 170 ns 170 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_median 169 ns 169 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_stddev 2.55 ns 2.55 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_cv 1.50 % 1.50 % 10 -Short replace symbols with std::string find_first_of + replace_mean 310 ns 310 ns 10 -Short replace symbols with std::string find_first_of + replace_median 309 ns 309 ns 10 -Short replace symbols with std::string find_first_of + replace_stddev 8.39 ns 8.39 ns 10 -Short replace symbols with std::string find_first_of + replace_cv 2.71 % 2.71 % 10 -Short replace symbols with std::string_view find_first_of + copy_mean 165 ns 165 ns 10 -Short replace symbols with std::string_view find_first_of + copy_median 164 ns 164 ns 10 -Short replace symbols with std::string_view find_first_of + copy_stddev 3.77 ns 3.77 ns 10 -Short replace symbols with std::string_view find_first_of + copy_cv 2.29 % 2.29 % 10 -Short replace runtime symbols with string expressions and without remembering all search results_mean 167 ns 167 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_median 167 ns 167 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_stddev 2.92 ns 2.92 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_cv 1.75 % 1.75 % 10 -Short replace runtime symbols with simstr and memorization of all search results_mean 176 ns 176 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_median 175 ns 175 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_stddev 6.46 ns 6.46 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_cv 3.66 % 3.66 % 10 -Short replace const symbols with string expressions and without remembering all search results_mean 142 ns 142 ns 10 -Short replace const symbols with string expressions and without remembering all search results_median 138 ns 138 ns 10 -Short replace const symbols with string expressions and without remembering all search results_stddev 9.85 ns 9.85 ns 10 -Short replace const symbols with string expressions and without remembering all search results_cv 6.94 % 6.94 % 10 -Short replace const symbols with string expressions and memorization of all search results_mean 157 ns 157 ns 10 -Short replace const symbols with string expressions and memorization of all search results_median 154 ns 154 ns 10 -Short replace const symbols with string expressions and memorization of all search results_stddev 9.03 ns 9.03 ns 10 -Short replace const symbols with string expressions and memorization of all search results_cv 5.77 % 5.77 % 10 +Short Naive (and wrong) replace symbols with std::string find + replace_mean 156 ns 156 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_median 157 ns 157 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_stddev 3.45 ns 3.45 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_cv 2.21 % 2.21 % 10 +Short replace symbols with std::string find_first_of + replace_mean 343 ns 343 ns 10 +Short replace symbols with std::string find_first_of + replace_median 348 ns 348 ns 10 +Short replace symbols with std::string find_first_of + replace_stddev 23.7 ns 23.7 ns 10 +Short replace symbols with std::string find_first_of + replace_cv 6.91 % 6.91 % 10 +Short replace symbols with std::string_view find_first_of + copy_mean 167 ns 167 ns 10 +Short replace symbols with std::string_view find_first_of + copy_median 165 ns 165 ns 10 +Short replace symbols with std::string_view find_first_of + copy_stddev 6.66 ns 6.66 ns 10 +Short replace symbols with std::string_view find_first_of + copy_cv 3.98 % 3.98 % 10 +Short replace runtime symbols with string expressions and without remembering all search results_mean 191 ns 191 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_median 189 ns 189 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_stddev 7.06 ns 7.06 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_cv 3.70 % 3.70 % 10 +Short replace runtime symbols with simstr and memorization of all search results_mean 185 ns 185 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_median 183 ns 183 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_stddev 5.32 ns 5.32 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_cv 2.88 % 2.88 % 10 +Short replace const symbols with string expressions and without remembering all search results_mean 132 ns 132 ns 10 +Short replace const symbols with string expressions and without remembering all search results_median 130 ns 130 ns 10 +Short replace const symbols with string expressions and without remembering all search results_stddev 4.94 ns 4.94 ns 10 +Short replace const symbols with string expressions and without remembering all search results_cv 3.73 % 3.73 % 10 +Short replace const symbols with string expressions and memorization of all search results_mean 149 ns 149 ns 10 +Short replace const symbols with string expressions and memorization of all search results_median 148 ns 148 ns 10 +Short replace const symbols with string expressions and memorization of all search results_stddev 3.65 ns 3.65 ns 10 +Short replace const symbols with string expressions and memorization of all search results_cv 2.46 % 2.46 % 10 ----- Replace All Str To Longer Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to ---- in std::string|64_mean 164 ns 164 ns 10 -replace bb to ---- in std::string|64_median 163 ns 163 ns 10 -replace bb to ---- in std::string|64_stddev 5.14 ns 5.14 ns 10 -replace bb to ---- in std::string|64_cv 3.14 % 3.14 % 10 -replace bb to ---- in std::string|256_mean 531 ns 531 ns 10 -replace bb to ---- in std::string|256_median 523 ns 523 ns 10 -replace bb to ---- in std::string|256_stddev 22.7 ns 22.7 ns 10 -replace bb to ---- in std::string|256_cv 4.28 % 4.28 % 10 -replace bb to ---- in std::string|512_mean 1217 ns 1217 ns 10 -replace bb to ---- in std::string|512_median 1212 ns 1212 ns 10 -replace bb to ---- in std::string|512_stddev 24.5 ns 24.5 ns 10 -replace bb to ---- in std::string|512_cv 2.01 % 2.01 % 10 -replace bb to ---- in std::string|1024_mean 2374 ns 2374 ns 10 -replace bb to ---- in std::string|1024_median 2360 ns 2360 ns 10 -replace bb to ---- in std::string|1024_stddev 144 ns 144 ns 10 -replace bb to ---- in std::string|1024_cv 6.06 % 6.06 % 10 -replace bb to ---- in std::string|2048_mean 5735 ns 5735 ns 10 -replace bb to ---- in std::string|2048_median 5662 ns 5662 ns 10 -replace bb to ---- in std::string|2048_stddev 211 ns 211 ns 10 -replace bb to ---- in std::string|2048_cv 3.67 % 3.67 % 10 -replace bb to ---- in lstringa<8>|64_mean 145 ns 145 ns 10 -replace bb to ---- in lstringa<8>|64_median 145 ns 145 ns 10 -replace bb to ---- in lstringa<8>|64_stddev 3.55 ns 3.55 ns 10 -replace bb to ---- in lstringa<8>|64_cv 2.44 % 2.44 % 10 -replace bb to ---- in lstringa<8>|256_mean 435 ns 435 ns 10 -replace bb to ---- in lstringa<8>|256_median 435 ns 435 ns 10 -replace bb to ---- in lstringa<8>|256_stddev 8.39 ns 8.39 ns 10 -replace bb to ---- in lstringa<8>|256_cv 1.93 % 1.93 % 10 -replace bb to ---- in lstringa<8>|512_mean 825 ns 825 ns 10 -replace bb to ---- in lstringa<8>|512_median 800 ns 800 ns 10 -replace bb to ---- in lstringa<8>|512_stddev 67.4 ns 67.4 ns 10 -replace bb to ---- in lstringa<8>|512_cv 8.17 % 8.17 % 10 -replace bb to ---- in lstringa<8>|1024_mean 1713 ns 1713 ns 10 -replace bb to ---- in lstringa<8>|1024_median 1679 ns 1679 ns 10 -replace bb to ---- in lstringa<8>|1024_stddev 76.5 ns 76.5 ns 10 -replace bb to ---- in lstringa<8>|1024_cv 4.47 % 4.47 % 10 -replace bb to ---- in lstringa<8>|2048_mean 3055 ns 3055 ns 10 -replace bb to ---- in lstringa<8>|2048_median 3001 ns 3001 ns 10 -replace bb to ---- in lstringa<8>|2048_stddev 214 ns 214 ns 10 -replace bb to ---- in lstringa<8>|2048_cv 7.00 % 7.00 % 10 -replace bb to ---- by init stringa|64_mean 117 ns 117 ns 10 -replace bb to ---- by init stringa|64_median 116 ns 116 ns 10 -replace bb to ---- by init stringa|64_stddev 1.72 ns 1.72 ns 10 -replace bb to ---- by init stringa|64_cv 1.47 % 1.47 % 10 -replace bb to ---- by init stringa|256_mean 398 ns 398 ns 10 -replace bb to ---- by init stringa|256_median 398 ns 398 ns 10 -replace bb to ---- by init stringa|256_stddev 7.04 ns 7.04 ns 10 -replace bb to ---- by init stringa|256_cv 1.77 % 1.77 % 10 -replace bb to ---- by init stringa|512_mean 803 ns 803 ns 10 -replace bb to ---- by init stringa|512_median 802 ns 802 ns 10 -replace bb to ---- by init stringa|512_stddev 9.50 ns 9.50 ns 10 -replace bb to ---- by init stringa|512_cv 1.18 % 1.18 % 10 -replace bb to ---- by init stringa|1024_mean 1624 ns 1624 ns 10 -replace bb to ---- by init stringa|1024_median 1636 ns 1636 ns 10 -replace bb to ---- by init stringa|1024_stddev 31.9 ns 31.9 ns 10 -replace bb to ---- by init stringa|1024_cv 1.96 % 1.96 % 10 -replace bb to ---- by init stringa|2048_mean 3156 ns 3156 ns 10 -replace bb to ---- by init stringa|2048_median 3138 ns 3138 ns 10 -replace bb to ---- by init stringa|2048_stddev 89.9 ns 89.9 ns 10 -replace bb to ---- by init stringa|2048_cv 2.85 % 2.85 % 10 +replace bb to ---- in std::string|64_mean 161 ns 161 ns 10 +replace bb to ---- in std::string|64_median 160 ns 160 ns 10 +replace bb to ---- in std::string|64_stddev 5.40 ns 5.40 ns 10 +replace bb to ---- in std::string|64_cv 3.36 % 3.36 % 10 +replace bb to ---- in std::string|256_mean 543 ns 543 ns 10 +replace bb to ---- in std::string|256_median 529 ns 529 ns 10 +replace bb to ---- in std::string|256_stddev 35.9 ns 35.9 ns 10 +replace bb to ---- in std::string|256_cv 6.61 % 6.61 % 10 +replace bb to ---- in std::string|512_mean 1041 ns 1041 ns 10 +replace bb to ---- in std::string|512_median 1042 ns 1042 ns 10 +replace bb to ---- in std::string|512_stddev 16.1 ns 16.1 ns 10 +replace bb to ---- in std::string|512_cv 1.55 % 1.55 % 10 +replace bb to ---- in std::string|1024_mean 2329 ns 2329 ns 10 +replace bb to ---- in std::string|1024_median 2239 ns 2239 ns 10 +replace bb to ---- in std::string|1024_stddev 205 ns 205 ns 10 +replace bb to ---- in std::string|1024_cv 8.81 % 8.81 % 10 +replace bb to ---- in std::string|2048_mean 5815 ns 5815 ns 10 +replace bb to ---- in std::string|2048_median 5657 ns 5657 ns 10 +replace bb to ---- in std::string|2048_stddev 338 ns 338 ns 10 +replace bb to ---- in std::string|2048_cv 5.82 % 5.82 % 10 +replace bb to ---- in lstringa<8>|64_mean 143 ns 143 ns 10 +replace bb to ---- in lstringa<8>|64_median 142 ns 142 ns 10 +replace bb to ---- in lstringa<8>|64_stddev 3.02 ns 3.02 ns 10 +replace bb to ---- in lstringa<8>|64_cv 2.12 % 2.12 % 10 +replace bb to ---- in lstringa<8>|256_mean 439 ns 439 ns 10 +replace bb to ---- in lstringa<8>|256_median 437 ns 437 ns 10 +replace bb to ---- in lstringa<8>|256_stddev 9.49 ns 9.49 ns 10 +replace bb to ---- in lstringa<8>|256_cv 2.16 % 2.16 % 10 +replace bb to ---- in lstringa<8>|512_mean 833 ns 833 ns 10 +replace bb to ---- in lstringa<8>|512_median 839 ns 839 ns 10 +replace bb to ---- in lstringa<8>|512_stddev 25.8 ns 25.8 ns 10 +replace bb to ---- in lstringa<8>|512_cv 3.10 % 3.10 % 10 +replace bb to ---- in lstringa<8>|1024_mean 1669 ns 1669 ns 10 +replace bb to ---- in lstringa<8>|1024_median 1646 ns 1646 ns 10 +replace bb to ---- in lstringa<8>|1024_stddev 54.6 ns 54.6 ns 10 +replace bb to ---- in lstringa<8>|1024_cv 3.27 % 3.27 % 10 +replace bb to ---- in lstringa<8>|2048_mean 3123 ns 3123 ns 10 +replace bb to ---- in lstringa<8>|2048_median 3111 ns 3111 ns 10 +replace bb to ---- in lstringa<8>|2048_stddev 54.4 ns 54.4 ns 10 +replace bb to ---- in lstringa<8>|2048_cv 1.74 % 1.74 % 10 +replace bb to ---- by init stringa|64_mean 98.9 ns 98.9 ns 10 +replace bb to ---- by init stringa|64_median 98.0 ns 98.0 ns 10 +replace bb to ---- by init stringa|64_stddev 3.52 ns 3.52 ns 10 +replace bb to ---- by init stringa|64_cv 3.56 % 3.56 % 10 +replace bb to ---- by init stringa|256_mean 300 ns 300 ns 10 +replace bb to ---- by init stringa|256_median 298 ns 298 ns 10 +replace bb to ---- by init stringa|256_stddev 6.55 ns 6.55 ns 10 +replace bb to ---- by init stringa|256_cv 2.18 % 2.18 % 10 +replace bb to ---- by init stringa|512_mean 706 ns 706 ns 10 +replace bb to ---- by init stringa|512_median 701 ns 701 ns 10 +replace bb to ---- by init stringa|512_stddev 17.5 ns 17.5 ns 10 +replace bb to ---- by init stringa|512_cv 2.47 % 2.47 % 10 +replace bb to ---- by init stringa|1024_mean 1511 ns 1512 ns 10 +replace bb to ---- by init stringa|1024_median 1510 ns 1510 ns 10 +replace bb to ---- by init stringa|1024_stddev 22.4 ns 22.4 ns 10 +replace bb to ---- by init stringa|1024_cv 1.48 % 1.48 % 10 +replace bb to ---- by init stringa|2048_mean 3078 ns 3078 ns 10 +replace bb to ---- by init stringa|2048_median 3038 ns 3038 ns 10 +replace bb to ---- by init stringa|2048_stddev 113 ns 113 ns 10 +replace bb to ---- by init stringa|2048_cv 3.68 % 3.68 % 10 ----- Replace All Str To Same Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to -- in std::string|64_mean 119 ns 119 ns 10 -replace bb to -- in std::string|64_median 118 ns 118 ns 10 -replace bb to -- in std::string|64_stddev 2.56 ns 2.56 ns 10 -replace bb to -- in std::string|64_cv 2.16 % 2.16 % 10 -replace bb to -- in std::string|256_mean 415 ns 415 ns 10 -replace bb to -- in std::string|256_median 413 ns 413 ns 10 -replace bb to -- in std::string|256_stddev 9.74 ns 9.74 ns 10 -replace bb to -- in std::string|256_cv 2.35 % 2.35 % 10 -replace bb to -- in std::string|512_mean 783 ns 783 ns 10 -replace bb to -- in std::string|512_median 782 ns 782 ns 10 -replace bb to -- in std::string|512_stddev 20.7 ns 20.7 ns 10 -replace bb to -- in std::string|512_cv 2.65 % 2.65 % 10 -replace bb to -- in std::string|1024_mean 1499 ns 1499 ns 10 -replace bb to -- in std::string|1024_median 1501 ns 1501 ns 10 -replace bb to -- in std::string|1024_stddev 35.8 ns 35.8 ns 10 -replace bb to -- in std::string|1024_cv 2.39 % 2.39 % 10 -replace bb to -- in std::string|2048_mean 2960 ns 2960 ns 10 -replace bb to -- in std::string|2048_median 2974 ns 2974 ns 10 -replace bb to -- in std::string|2048_stddev 58.4 ns 58.4 ns 10 -replace bb to -- in std::string|2048_cv 1.97 % 1.97 % 10 -replace bb to -- in lstringa<8>|64_mean 101 ns 101 ns 10 -replace bb to -- in lstringa<8>|64_median 101 ns 101 ns 10 -replace bb to -- in lstringa<8>|64_stddev 2.76 ns 2.76 ns 10 -replace bb to -- in lstringa<8>|64_cv 2.73 % 2.73 % 10 -replace bb to -- in lstringa<8>|256_mean 326 ns 326 ns 10 -replace bb to -- in lstringa<8>|256_median 306 ns 306 ns 10 -replace bb to -- in lstringa<8>|256_stddev 41.2 ns 41.2 ns 10 -replace bb to -- in lstringa<8>|256_cv 12.61 % 12.61 % 10 -replace bb to -- in lstringa<8>|512_mean 569 ns 569 ns 10 -replace bb to -- in lstringa<8>|512_median 566 ns 566 ns 10 -replace bb to -- in lstringa<8>|512_stddev 18.1 ns 18.1 ns 10 -replace bb to -- in lstringa<8>|512_cv 3.17 % 3.18 % 10 -replace bb to -- in lstringa<8>|1024_mean 1128 ns 1128 ns 10 -replace bb to -- in lstringa<8>|1024_median 1132 ns 1132 ns 10 -replace bb to -- in lstringa<8>|1024_stddev 30.4 ns 30.4 ns 10 -replace bb to -- in lstringa<8>|1024_cv 2.70 % 2.70 % 10 -replace bb to -- in lstringa<8>|2048_mean 2155 ns 2155 ns 10 -replace bb to -- in lstringa<8>|2048_median 2125 ns 2125 ns 10 -replace bb to -- in lstringa<8>|2048_stddev 101 ns 101 ns 10 -replace bb to -- in lstringa<8>|2048_cv 4.68 % 4.68 % 10 -replace bb to -- by init stringa|64_mean 86.9 ns 86.9 ns 10 -replace bb to -- by init stringa|64_median 85.6 ns 85.6 ns 10 -replace bb to -- by init stringa|64_stddev 4.43 ns 4.43 ns 10 -replace bb to -- by init stringa|64_cv 5.10 % 5.10 % 10 -replace bb to -- by init stringa|256_mean 232 ns 232 ns 10 -replace bb to -- by init stringa|256_median 231 ns 231 ns 10 -replace bb to -- by init stringa|256_stddev 5.61 ns 5.61 ns 10 -replace bb to -- by init stringa|256_cv 2.42 % 2.42 % 10 -replace bb to -- by init stringa|512_mean 441 ns 441 ns 10 -replace bb to -- by init stringa|512_median 441 ns 441 ns 10 -replace bb to -- by init stringa|512_stddev 6.71 ns 6.71 ns 10 -replace bb to -- by init stringa|512_cv 1.52 % 1.52 % 10 -replace bb to -- by init stringa|1024_mean 883 ns 883 ns 10 -replace bb to -- by init stringa|1024_median 877 ns 877 ns 10 -replace bb to -- by init stringa|1024_stddev 19.7 ns 19.7 ns 10 -replace bb to -- by init stringa|1024_cv 2.23 % 2.23 % 10 -replace bb to -- by init stringa|2048_mean 1670 ns 1670 ns 10 -replace bb to -- by init stringa|2048_median 1659 ns 1659 ns 10 -replace bb to -- by init stringa|2048_stddev 34.1 ns 34.1 ns 10 -replace bb to -- by init stringa|2048_cv 2.04 % 2.04 % 10 +replace bb to -- in std::string|64_mean 121 ns 121 ns 10 +replace bb to -- in std::string|64_median 119 ns 119 ns 10 +replace bb to -- in std::string|64_stddev 4.36 ns 4.36 ns 10 +replace bb to -- in std::string|64_cv 3.62 % 3.62 % 10 +replace bb to -- in std::string|256_mean 411 ns 411 ns 10 +replace bb to -- in std::string|256_median 411 ns 411 ns 10 +replace bb to -- in std::string|256_stddev 23.4 ns 23.4 ns 10 +replace bb to -- in std::string|256_cv 5.69 % 5.69 % 10 +replace bb to -- in std::string|512_mean 759 ns 759 ns 10 +replace bb to -- in std::string|512_median 760 ns 760 ns 10 +replace bb to -- in std::string|512_stddev 19.8 ns 19.8 ns 10 +replace bb to -- in std::string|512_cv 2.60 % 2.60 % 10 +replace bb to -- in std::string|1024_mean 1460 ns 1460 ns 10 +replace bb to -- in std::string|1024_median 1449 ns 1449 ns 10 +replace bb to -- in std::string|1024_stddev 54.1 ns 54.1 ns 10 +replace bb to -- in std::string|1024_cv 3.70 % 3.70 % 10 +replace bb to -- in std::string|2048_mean 3052 ns 3052 ns 10 +replace bb to -- in std::string|2048_median 3033 ns 3033 ns 10 +replace bb to -- in std::string|2048_stddev 74.6 ns 74.6 ns 10 +replace bb to -- in std::string|2048_cv 2.44 % 2.44 % 10 +replace bb to -- in lstringa<8>|64_mean 99.0 ns 99.0 ns 10 +replace bb to -- in lstringa<8>|64_median 98.1 ns 98.1 ns 10 +replace bb to -- in lstringa<8>|64_stddev 2.91 ns 2.91 ns 10 +replace bb to -- in lstringa<8>|64_cv 2.94 % 2.94 % 10 +replace bb to -- in lstringa<8>|256_mean 300 ns 300 ns 10 +replace bb to -- in lstringa<8>|256_median 299 ns 299 ns 10 +replace bb to -- in lstringa<8>|256_stddev 13.2 ns 13.2 ns 10 +replace bb to -- in lstringa<8>|256_cv 4.39 % 4.39 % 10 +replace bb to -- in lstringa<8>|512_mean 552 ns 552 ns 10 +replace bb to -- in lstringa<8>|512_median 551 ns 551 ns 10 +replace bb to -- in lstringa<8>|512_stddev 12.0 ns 12.0 ns 10 +replace bb to -- in lstringa<8>|512_cv 2.17 % 2.17 % 10 +replace bb to -- in lstringa<8>|1024_mean 1147 ns 1147 ns 10 +replace bb to -- in lstringa<8>|1024_median 1154 ns 1154 ns 10 +replace bb to -- in lstringa<8>|1024_stddev 30.5 ns 30.5 ns 10 +replace bb to -- in lstringa<8>|1024_cv 2.66 % 2.66 % 10 +replace bb to -- in lstringa<8>|2048_mean 2183 ns 2183 ns 10 +replace bb to -- in lstringa<8>|2048_median 2167 ns 2167 ns 10 +replace bb to -- in lstringa<8>|2048_stddev 65.9 ns 65.9 ns 10 +replace bb to -- in lstringa<8>|2048_cv 3.02 % 3.02 % 10 +replace bb to -- by init stringa|64_mean 82.4 ns 82.4 ns 10 +replace bb to -- by init stringa|64_median 81.8 ns 81.8 ns 10 +replace bb to -- by init stringa|64_stddev 2.20 ns 2.20 ns 10 +replace bb to -- by init stringa|64_cv 2.67 % 2.67 % 10 +replace bb to -- by init stringa|256_mean 244 ns 244 ns 10 +replace bb to -- by init stringa|256_median 240 ns 240 ns 10 +replace bb to -- by init stringa|256_stddev 11.1 ns 11.1 ns 10 +replace bb to -- by init stringa|256_cv 4.53 % 4.53 % 10 +replace bb to -- by init stringa|512_mean 444 ns 444 ns 10 +replace bb to -- by init stringa|512_median 444 ns 444 ns 10 +replace bb to -- by init stringa|512_stddev 18.2 ns 18.2 ns 10 +replace bb to -- by init stringa|512_cv 4.11 % 4.11 % 10 +replace bb to -- by init stringa|1024_mean 886 ns 886 ns 10 +replace bb to -- by init stringa|1024_median 868 ns 868 ns 10 +replace bb to -- by init stringa|1024_stddev 32.1 ns 32.1 ns 10 +replace bb to -- by init stringa|1024_cv 3.62 % 3.62 % 10 +replace bb to -- by init stringa|2048_mean 1707 ns 1707 ns 10 +replace bb to -- by init stringa|2048_median 1696 ns 1696 ns 10 +replace bb to -- by init stringa|2048_stddev 55.5 ns 55.5 ns 10 +replace bb to -- by init stringa|2048_cv 3.25 % 3.25 % 10 ----- Hash Map insert and find ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -hashStrMapA emplace & find stringa;_mean 3565051 ns 3565054 ns 10 -hashStrMapA emplace & find stringa;_median 3563645 ns 3563657 ns 10 -hashStrMapA emplace & find stringa;_stddev 60616 ns 60600 ns 10 -hashStrMapA emplace & find stringa;_cv 1.70 % 1.70 % 10 -std::unordered_map emplace & find std::string;_mean 3504581 ns 3504582 ns 10 -std::unordered_map emplace & find std::string;_median 3492374 ns 3492358 ns 10 -std::unordered_map emplace & find std::string;_stddev 67478 ns 67484 ns 10 -std::unordered_map emplace & find std::string;_cv 1.93 % 1.93 % 10 -hashStrMapA emplace & find ssa;_mean 3648733 ns 3648738 ns 10 -hashStrMapA emplace & find ssa;_median 3643789 ns 3643806 ns 10 -hashStrMapA emplace & find ssa;_stddev 46557 ns 46567 ns 10 -hashStrMapA emplace & find ssa;_cv 1.28 % 1.28 % 10 -std::unordered_map emplace & find std::string_view;_mean 4252438 ns 4252417 ns 10 -std::unordered_map emplace & find std::string_view;_median 4162735 ns 4162699 ns 10 -std::unordered_map emplace & find std::string_view;_stddev 274815 ns 274779 ns 10 -std::unordered_map emplace & find std::string_view;_cv 6.46 % 6.46 % 10 +hashStrMapA emplace & find stringa;_mean 3625242 ns 3625255 ns 10 +hashStrMapA emplace & find stringa;_median 3613086 ns 3613099 ns 10 +hashStrMapA emplace & find stringa;_stddev 56566 ns 56566 ns 10 +hashStrMapA emplace & find stringa;_cv 1.56 % 1.56 % 10 +std::unordered_map emplace & find std::string;_mean 3517784 ns 3517795 ns 10 +std::unordered_map emplace & find std::string;_median 3487503 ns 3487513 ns 10 +std::unordered_map emplace & find std::string;_stddev 77853 ns 77854 ns 10 +std::unordered_map emplace & find std::string;_cv 2.21 % 2.21 % 10 +hashStrMapA emplace & find ssa;_mean 3618716 ns 3618730 ns 10 +hashStrMapA emplace & find ssa;_median 3594424 ns 3594438 ns 10 +hashStrMapA emplace & find ssa;_stddev 62317 ns 62318 ns 10 +hashStrMapA emplace & find ssa;_cv 1.72 % 1.72 % 10 +std::unordered_map emplace & find std::string_view;_mean 4166457 ns 4166472 ns 10 +std::unordered_map emplace & find std::string_view;_median 4166618 ns 4166634 ns 10 +std::unordered_map emplace & find std::string_view;_stddev 80853 ns 80854 ns 10 +std::unordered_map emplace & find std::string_view;_cv 1.94 % 1.94 % 10 ----- Build Full Func Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -Build func full name std::string;_mean 733 ns 733 ns 10 -Build func full name std::string;_median 737 ns 737 ns 10 -Build func full name std::string;_stddev 22.0 ns 22.0 ns 10 -Build func full name std::string;_cv 3.01 % 3.01 % 10 -Build func full name std::string 1;_mean 829 ns 829 ns 10 -Build func full name std::string 1;_median 823 ns 823 ns 10 -Build func full name std::string 1;_stddev 16.9 ns 16.9 ns 10 -Build func full name std::string 1;_cv 2.04 % 2.03 % 10 -Build func full name std::stream;_mean 2554 ns 2554 ns 10 -Build func full name std::stream;_median 2564 ns 2564 ns 10 -Build func full name std::stream;_stddev 25.0 ns 25.0 ns 10 -Build func full name std::stream;_cv 0.98 % 0.98 % 10 -Build func full name stringa;_mean 525 ns 525 ns 10 -Build func full name stringa;_median 525 ns 525 ns 10 -Build func full name stringa;_stddev 12.0 ns 12.0 ns 10 -Build func full name stringa;_cv 2.28 % 2.28 % 10 -Build func full name stringa 1;_mean 672 ns 672 ns 10 -Build func full name stringa 1;_median 664 ns 664 ns 10 -Build func full name stringa 1;_stddev 20.5 ns 20.5 ns 10 -Build func full name stringa 1;_cv 3.06 % 3.06 % 10 +Build func full name std::string;_mean 708 ns 708 ns 10 +Build func full name std::string;_median 710 ns 710 ns 10 +Build func full name std::string;_stddev 23.6 ns 23.6 ns 10 +Build func full name std::string;_cv 3.33 % 3.33 % 10 +Build func full name std::string 1;_mean 846 ns 846 ns 10 +Build func full name std::string 1;_median 834 ns 834 ns 10 +Build func full name std::string 1;_stddev 26.7 ns 26.7 ns 10 +Build func full name std::string 1;_cv 3.15 % 3.15 % 10 +Build func full name std::stream;_mean 2571 ns 2571 ns 10 +Build func full name std::stream;_median 2542 ns 2542 ns 10 +Build func full name std::stream;_stddev 73.7 ns 73.7 ns 10 +Build func full name std::stream;_cv 2.87 % 2.87 % 10 +Build func full name stringa;_mean 508 ns 508 ns 10 +Build func full name stringa;_median 504 ns 504 ns 10 +Build func full name stringa;_stddev 22.6 ns 22.6 ns 10 +Build func full name stringa;_cv 4.45 % 4.45 % 10 +Build func full name stringa 1;_mean 648 ns 648 ns 10 +Build func full name stringa 1;_median 642 ns 642 ns 10 +Build func full name stringa 1;_stddev 15.7 ns 15.7 ns 10 +Build func full name stringa 1;_cv 2.43 % 2.43 % 10 diff --git a/bench/results/001-Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13.txt b/bench/results/001-Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13.txt index bc65f89..a769187 100644 --- a/bench/results/001-Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13.txt +++ b/bench/results/001-Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13.txt @@ -1,4 +1,4 @@ -2025-11-26T18:09:34+03:00 +2026-01-21T07:11:34+03:00 Running ./benchStr Run on (32 X 2494.22 MHz CPU s) CPU Caches: @@ -6,786 +6,873 @@ CPU Caches: L1 Instruction 32 KiB (x16) L2 Unified 256 KiB (x16) L3 Unified 40960 KiB (x1) -Load Average: 0.02, 0.05, 0.12 +Load Average: 0.00, 0.00, 0.00 +***WARNING*** ASLR is enabled, the results may have unreproducible noise in them. -------------------------------------------------------------------------------------------------------------------------------------------------------- Benchmark Time CPU Iterations -------------------------------------------------------------------------------------------------------------------------------------------------------- +----- Concatenate string + Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and number by std to std::string_mean 207 ns 207 ns 10 +Concat std::string and number by std to std::string_median 205 ns 205 ns 10 +Concat std::string and number by std to std::string_stddev 7.79 ns 7.79 ns 10 +Concat std::string and number by std to std::string_cv 3.77 % 3.77 % 10 +Concat std::string and number by StrExpr to std::string_mean 102 ns 102 ns 10 +Concat std::string and number by StrExpr to std::string_median 101 ns 101 ns 10 +Concat std::string and number by StrExpr to std::string_stddev 2.95 ns 2.95 ns 10 +Concat std::string and number by StrExpr to std::string_cv 2.90 % 2.90 % 10 +Concat stringa and number by StrExpr to simstr::stringa_mean 70.4 ns 70.4 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_median 69.3 ns 69.3 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_stddev 3.12 ns 3.12 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_cv 4.43 % 4.43 % 10 +----- Concatenate string + Hex Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and hex number by std to std::string_mean 668 ns 668 ns 10 +Concat std::string and hex number by std to std::string_median 665 ns 665 ns 10 +Concat std::string and hex number by std to std::string_stddev 21.8 ns 21.8 ns 10 +Concat std::string and hex number by std to std::string_cv 3.27 % 3.27 % 10 +Concat std::string and hex number by StrExpr to std::string_mean 65.9 ns 65.9 ns 10 +Concat std::string and hex number by StrExpr to std::string_median 65.3 ns 65.3 ns 10 +Concat std::string and hex number by StrExpr to std::string_stddev 2.24 ns 2.24 ns 10 +Concat std::string and hex number by StrExpr to std::string_cv 3.39 % 3.39 % 10 +Concat stringa and hex number by StrExpr to simstr::stringa_mean 68.2 ns 68.2 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_median 67.9 ns 67.9 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_stddev 1.59 ns 1.59 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_cv 2.33 % 2.33 % 10 +----- Concatenate string + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string by std to std::string_mean 44.7 ns 44.7 ns 10 +Concat std::string by std to std::string_median 43.5 ns 43.5 ns 10 +Concat std::string by std to std::string_stddev 2.51 ns 2.51 ns 10 +Concat std::string by std to std::string_cv 5.61 % 5.61 % 10 +Concat std::string by StrExpr to std::string_mean 35.9 ns 35.9 ns 10 +Concat std::string by StrExpr to std::string_median 35.8 ns 35.8 ns 10 +Concat std::string by StrExpr to std::string_stddev 1.12 ns 1.12 ns 10 +Concat std::string by StrExpr to std::string_cv 3.12 % 3.12 % 10 +Concat stringa by StrExpr to stringa_mean 25.9 ns 25.9 ns 10 +Concat stringa by StrExpr to stringa_median 25.7 ns 25.7 ns 10 +Concat stringa by StrExpr to stringa_stddev 0.700 ns 0.700 ns 10 +Concat stringa by StrExpr to stringa_cv 2.71 % 2.71 % 10 +----- Find three concatenated string in string_view -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Find concat three std::string_mean 130 ns 130 ns 10 +Find concat three std::string_median 128 ns 128 ns 10 +Find concat three std::string_stddev 4.71 ns 4.71 ns 10 +Find concat three std::string_cv 3.62 % 3.62 % 10 +Find concat three strexpr_mean 39.8 ns 39.8 ns 10 +Find concat three strexpr_median 39.1 ns 39.1 ns 10 +Find concat three strexpr_stddev 2.02 ns 2.02 ns 10 +Find concat three strexpr_cv 5.08 % 5.08 % 10 +Find concat three simstr_mean 20.2 ns 20.2 ns 10 +Find concat three simstr_median 20.2 ns 20.2 ns 10 +Find concat three simstr_stddev 0.739 ns 0.739 ns 10 +Find concat three simstr_cv 3.66 % 3.66 % 10 +----- Build Type Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +BuildTypeNameStr 0/0_mean 10.7 ns 10.7 ns 10 +BuildTypeNameStr 0/0_median 10.6 ns 10.6 ns 10 +BuildTypeNameStr 0/0_stddev 0.506 ns 0.506 ns 10 +BuildTypeNameStr 0/0_cv 4.74 % 4.74 % 10 +BuildTypeNameExp 0/0_mean 6.63 ns 6.63 ns 10 +BuildTypeNameExp 0/0_median 6.61 ns 6.61 ns 10 +BuildTypeNameExp 0/0_stddev 0.061 ns 0.061 ns 10 +BuildTypeNameExp 0/0_cv 0.92 % 0.92 % 10 +BuildTypeNameSim 0/0_mean 5.23 ns 5.23 ns 10 +BuildTypeNameSim 0/0_median 5.16 ns 5.16 ns 10 +BuildTypeNameSim 0/0_stddev 0.156 ns 0.156 ns 10 +BuildTypeNameSim 0/0_cv 2.98 % 2.98 % 10 +BuildTypeNameStr 10/10_mean 91.9 ns 91.9 ns 10 +BuildTypeNameStr 10/10_median 91.8 ns 91.8 ns 10 +BuildTypeNameStr 10/10_stddev 7.70 ns 7.70 ns 10 +BuildTypeNameStr 10/10_cv 8.38 % 8.38 % 10 +BuildTypeNameExp 10/10_mean 25.3 ns 25.3 ns 10 +BuildTypeNameExp 10/10_median 24.6 ns 24.6 ns 10 +BuildTypeNameExp 10/10_stddev 1.31 ns 1.31 ns 10 +BuildTypeNameExp 10/10_cv 5.17 % 5.17 % 10 +BuildTypeNameSim 10/10_mean 22.7 ns 22.7 ns 10 +BuildTypeNameSim 10/10_median 22.5 ns 22.5 ns 10 +BuildTypeNameSim 10/10_stddev 0.865 ns 0.865 ns 10 +BuildTypeNameSim 10/10_cv 3.81 % 3.81 % 10 +----- Replace string by copy -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat with replace str_mean 242 ns 242 ns 10 +Concat with replace str_median 240 ns 240 ns 10 +Concat with replace str_stddev 10.6 ns 10.6 ns 10 +Concat with replace str_cv 4.39 % 4.39 % 10 +Concat with replace exp_mean 135 ns 135 ns 10 +Concat with replace exp_median 132 ns 132 ns 10 +Concat with replace exp_stddev 8.05 ns 8.05 ns 10 +Concat with replace exp_cv 5.95 % 5.95 % 10 ----- Create Empty Str ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e;_mean 1.15 ns 1.15 ns 10 -std::string e;_median 1.14 ns 1.14 ns 10 -std::string e;_stddev 0.057 ns 0.057 ns 10 -std::string e;_cv 4.91 % 4.91 % 10 -std::string_view e;_mean 0.743 ns 0.743 ns 10 -std::string_view e;_median 0.743 ns 0.743 ns 10 -std::string_view e;_stddev 0.009 ns 0.009 ns 10 -std::string_view e;_cv 1.16 % 1.16 % 10 -ssa e;_mean 0.185 ns 0.185 ns 10 +std::string e;_mean 1.12 ns 1.12 ns 10 +std::string e;_median 1.12 ns 1.12 ns 10 +std::string e;_stddev 0.032 ns 0.032 ns 10 +std::string e;_cv 2.87 % 2.87 % 10 +std::string_view e;_mean 0.737 ns 0.737 ns 10 +std::string_view e;_median 0.735 ns 0.735 ns 10 +std::string_view e;_stddev 0.012 ns 0.012 ns 10 +std::string_view e;_cv 1.59 % 1.59 % 10 +ssa e;_mean 0.182 ns 0.182 ns 10 ssa e;_median 0.182 ns 0.182 ns 10 -ssa e;_stddev 0.005 ns 0.005 ns 10 -ssa e;_cv 2.95 % 2.95 % 10 -stringa e;_mean 0.759 ns 0.759 ns 10 -stringa e;_median 0.753 ns 0.753 ns 10 -stringa e;_stddev 0.020 ns 0.020 ns 10 -stringa e;_cv 2.63 % 2.63 % 10 -lstringa<20> e;_mean 1.13 ns 1.13 ns 10 +ssa e;_stddev 0.002 ns 0.002 ns 10 +ssa e;_cv 1.19 % 1.19 % 10 +stringa e;_mean 0.751 ns 0.751 ns 10 +stringa e;_median 0.735 ns 0.735 ns 10 +stringa e;_stddev 0.030 ns 0.030 ns 10 +stringa e;_cv 3.95 % 3.95 % 10 +lstringa<20> e;_mean 1.12 ns 1.12 ns 10 lstringa<20> e;_median 1.12 ns 1.12 ns 10 -lstringa<20> e;_stddev 0.032 ns 0.032 ns 10 -lstringa<20> e;_cv 2.83 % 2.83 % 10 -lstringa<40> e;_mean 1.13 ns 1.13 ns 10 -lstringa<40> e;_median 1.12 ns 1.12 ns 10 -lstringa<40> e;_stddev 0.024 ns 0.024 ns 10 -lstringa<40> e;_cv 2.17 % 2.17 % 10 +lstringa<20> e;_stddev 0.023 ns 0.023 ns 10 +lstringa<20> e;_cv 2.10 % 2.10 % 10 +lstringa<40> e;_mean 1.11 ns 1.11 ns 10 +lstringa<40> e;_median 1.10 ns 1.10 ns 10 +lstringa<40> e;_stddev 0.011 ns 0.011 ns 10 +lstringa<40> e;_cv 1.01 % 1.01 % 10 ----- Create Str from short literal (9 symbols) --------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text";_mean 1.85 ns 1.85 ns 10 -std::string e = "Test text";_median 1.84 ns 1.84 ns 10 -std::string e = "Test text";_stddev 0.026 ns 0.026 ns 10 -std::string e = "Test text";_cv 1.43 % 1.43 % 10 -std::string_view e = "Test text";_mean 0.751 ns 0.751 ns 10 -std::string_view e = "Test text";_median 0.748 ns 0.748 ns 10 -std::string_view e = "Test text";_stddev 0.011 ns 0.011 ns 10 -std::string_view e = "Test text";_cv 1.48 % 1.48 % 10 -ssa e = "Test text";_mean 0.781 ns 0.781 ns 10 -ssa e = "Test text";_median 0.753 ns 0.753 ns 10 -ssa e = "Test text";_stddev 0.062 ns 0.062 ns 10 -ssa e = "Test text";_cv 7.88 % 7.88 % 10 -stringa e = "Test text";_mean 1.13 ns 1.13 ns 10 -stringa e = "Test text";_median 1.12 ns 1.12 ns 10 -stringa e = "Test text";_stddev 0.030 ns 0.030 ns 10 -stringa e = "Test text";_cv 2.62 % 2.62 % 10 -lstringa<20> e = "Test text";_mean 1.86 ns 1.86 ns 10 -lstringa<20> e = "Test text";_median 1.87 ns 1.87 ns 10 -lstringa<20> e = "Test text";_stddev 0.030 ns 0.030 ns 10 -lstringa<20> e = "Test text";_cv 1.62 % 1.62 % 10 -lstringa<40> e = "Test text";_mean 1.88 ns 1.88 ns 10 -lstringa<40> e = "Test text";_median 1.86 ns 1.86 ns 10 -lstringa<40> e = "Test text";_stddev 0.052 ns 0.052 ns 10 -lstringa<40> e = "Test text";_cv 2.78 % 2.78 % 10 +std::string e = "Test text";_mean 1.87 ns 1.87 ns 10 +std::string e = "Test text";_median 1.83 ns 1.83 ns 10 +std::string e = "Test text";_stddev 0.097 ns 0.097 ns 10 +std::string e = "Test text";_cv 5.21 % 5.21 % 10 +std::string_view e = "Test text";_mean 0.730 ns 0.730 ns 10 +std::string_view e = "Test text";_median 0.729 ns 0.729 ns 10 +std::string_view e = "Test text";_stddev 0.006 ns 0.006 ns 10 +std::string_view e = "Test text";_cv 0.89 % 0.89 % 10 +ssa e = "Test text";_mean 0.736 ns 0.736 ns 10 +ssa e = "Test text";_median 0.733 ns 0.733 ns 10 +ssa e = "Test text";_stddev 0.016 ns 0.016 ns 10 +ssa e = "Test text";_cv 2.14 % 2.14 % 10 +stringa e = "Test text";_mean 1.12 ns 1.12 ns 10 +stringa e = "Test text";_median 1.11 ns 1.11 ns 10 +stringa e = "Test text";_stddev 0.028 ns 0.028 ns 10 +stringa e = "Test text";_cv 2.53 % 2.53 % 10 +lstringa<20> e = "Test text";_mean 1.87 ns 1.87 ns 10 +lstringa<20> e = "Test text";_median 1.85 ns 1.85 ns 10 +lstringa<20> e = "Test text";_stddev 0.074 ns 0.074 ns 10 +lstringa<20> e = "Test text";_cv 3.93 % 3.93 % 10 +lstringa<40> e = "Test text";_mean 1.89 ns 1.89 ns 10 +lstringa<40> e = "Test text";_median 1.89 ns 1.89 ns 10 +lstringa<40> e = "Test text";_stddev 0.056 ns 0.056 ns 10 +lstringa<40> e = "Test text";_cv 2.95 % 2.95 % 10 ----- Create Str from long literal (30 symbols) ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "123456789012345678901234567890";_mean 19.9 ns 19.9 ns 10 -std::string e = "123456789012345678901234567890";_median 19.6 ns 19.6 ns 10 -std::string e = "123456789012345678901234567890";_stddev 0.953 ns 0.953 ns 10 -std::string e = "123456789012345678901234567890";_cv 4.79 % 4.79 % 10 -std::string_view e = "123456789012345678901234567890";_mean 0.808 ns 0.808 ns 10 -std::string_view e = "123456789012345678901234567890";_median 0.833 ns 0.833 ns 10 -std::string_view e = "123456789012345678901234567890";_stddev 0.047 ns 0.047 ns 10 -std::string_view e = "123456789012345678901234567890";_cv 5.78 % 5.78 % 10 -ssa e = "123456789012345678901234567890";_mean 0.754 ns 0.754 ns 10 -ssa e = "123456789012345678901234567890";_median 0.753 ns 0.753 ns 10 -ssa e = "123456789012345678901234567890";_stddev 0.013 ns 0.013 ns 10 -ssa e = "123456789012345678901234567890";_cv 1.68 % 1.68 % 10 +std::string e = "123456789012345678901234567890";_mean 19.3 ns 19.3 ns 10 +std::string e = "123456789012345678901234567890";_median 19.1 ns 19.1 ns 10 +std::string e = "123456789012345678901234567890";_stddev 0.662 ns 0.662 ns 10 +std::string e = "123456789012345678901234567890";_cv 3.44 % 3.44 % 10 +std::string_view e = "123456789012345678901234567890";_mean 0.744 ns 0.744 ns 10 +std::string_view e = "123456789012345678901234567890";_median 0.737 ns 0.737 ns 10 +std::string_view e = "123456789012345678901234567890";_stddev 0.021 ns 0.021 ns 10 +std::string_view e = "123456789012345678901234567890";_cv 2.80 % 2.80 % 10 +ssa e = "123456789012345678901234567890";_mean 0.735 ns 0.735 ns 10 +ssa e = "123456789012345678901234567890";_median 0.734 ns 0.734 ns 10 +ssa e = "123456789012345678901234567890";_stddev 0.011 ns 0.011 ns 10 +ssa e = "123456789012345678901234567890";_cv 1.50 % 1.50 % 10 stringa e = "123456789012345678901234567890";_mean 1.12 ns 1.12 ns 10 -stringa e = "123456789012345678901234567890";_median 1.13 ns 1.13 ns 10 -stringa e = "123456789012345678901234567890";_stddev 0.020 ns 0.020 ns 10 -stringa e = "123456789012345678901234567890";_cv 1.77 % 1.77 % 10 -lstringa<20> e = "123456789012345678901234567890";_mean 19.6 ns 19.6 ns 10 -lstringa<20> e = "123456789012345678901234567890";_median 19.6 ns 19.6 ns 10 -lstringa<20> e = "123456789012345678901234567890";_stddev 0.348 ns 0.348 ns 10 -lstringa<20> e = "123456789012345678901234567890";_cv 1.77 % 1.77 % 10 -lstringa<40> e = "123456789012345678901234567890";_mean 1.86 ns 1.86 ns 10 -lstringa<40> e = "123456789012345678901234567890";_median 1.86 ns 1.86 ns 10 -lstringa<40> e = "123456789012345678901234567890";_stddev 0.027 ns 0.027 ns 10 -lstringa<40> e = "123456789012345678901234567890";_cv 1.46 % 1.46 % 10 +stringa e = "123456789012345678901234567890";_median 1.09 ns 1.09 ns 10 +stringa e = "123456789012345678901234567890";_stddev 0.042 ns 0.042 ns 10 +stringa e = "123456789012345678901234567890";_cv 3.73 % 3.73 % 10 +lstringa<20> e = "123456789012345678901234567890";_mean 20.0 ns 20.0 ns 10 +lstringa<20> e = "123456789012345678901234567890";_median 20.1 ns 20.1 ns 10 +lstringa<20> e = "123456789012345678901234567890";_stddev 0.301 ns 0.301 ns 10 +lstringa<20> e = "123456789012345678901234567890";_cv 1.50 % 1.50 % 10 +lstringa<40> e = "123456789012345678901234567890";_mean 1.84 ns 1.84 ns 10 +lstringa<40> e = "123456789012345678901234567890";_median 1.83 ns 1.83 ns 10 +lstringa<40> e = "123456789012345678901234567890";_stddev 0.034 ns 0.034 ns 10 +lstringa<40> e = "123456789012345678901234567890";_cv 1.83 % 1.83 % 10 ----- Create copy of Str with 9 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text"; auto c{e};_mean 4.95 ns 4.95 ns 10 -std::string e = "Test text"; auto c{e};_median 4.95 ns 4.95 ns 10 -std::string e = "Test text"; auto c{e};_stddev 0.102 ns 0.102 ns 10 -std::string e = "Test text"; auto c{e};_cv 2.06 % 2.06 % 10 -std::string_view e = "Test text"; auto c{e};_mean 0.381 ns 0.381 ns 10 -std::string_view e = "Test text"; auto c{e};_median 0.381 ns 0.381 ns 10 -std::string_view e = "Test text"; auto c{e};_stddev 0.005 ns 0.005 ns 10 -std::string_view e = "Test text"; auto c{e};_cv 1.28 % 1.28 % 10 -ssa e = "Test text"; auto c{e};_mean 0.377 ns 0.377 ns 10 -ssa e = "Test text"; auto c{e};_median 0.376 ns 0.376 ns 10 -ssa e = "Test text"; auto c{e};_stddev 0.009 ns 0.009 ns 10 -ssa e = "Test text"; auto c{e};_cv 2.46 % 2.46 % 10 -stringa e = "Test text"; auto c{e};_mean 1.35 ns 1.35 ns 10 -stringa e = "Test text"; auto c{e};_median 1.34 ns 1.34 ns 10 -stringa e = "Test text"; auto c{e};_stddev 0.055 ns 0.055 ns 10 -stringa e = "Test text"; auto c{e};_cv 4.07 % 4.07 % 10 -lstringa<20> e = "Test text"; auto c{e};_mean 4.49 ns 4.49 ns 10 -lstringa<20> e = "Test text"; auto c{e};_median 4.49 ns 4.49 ns 10 -lstringa<20> e = "Test text"; auto c{e};_stddev 0.043 ns 0.043 ns 10 -lstringa<20> e = "Test text"; auto c{e};_cv 0.95 % 0.95 % 10 -lstringa<40> e = "Test text"; auto c{e};_mean 4.93 ns 4.93 ns 10 -lstringa<40> e = "Test text"; auto c{e};_median 4.92 ns 4.92 ns 10 -lstringa<40> e = "Test text"; auto c{e};_stddev 0.083 ns 0.083 ns 10 -lstringa<40> e = "Test text"; auto c{e};_cv 1.68 % 1.68 % 10 +std::string e = "Test text"; auto c{e};_mean 4.80 ns 4.80 ns 10 +std::string e = "Test text"; auto c{e};_median 4.79 ns 4.79 ns 10 +std::string e = "Test text"; auto c{e};_stddev 0.056 ns 0.056 ns 10 +std::string e = "Test text"; auto c{e};_cv 1.16 % 1.16 % 10 +std::string_view e = "Test text"; auto c{e};_mean 0.373 ns 0.373 ns 10 +std::string_view e = "Test text"; auto c{e};_median 0.373 ns 0.373 ns 10 +std::string_view e = "Test text"; auto c{e};_stddev 0.004 ns 0.004 ns 10 +std::string_view e = "Test text"; auto c{e};_cv 1.21 % 1.21 % 10 +ssa e = "Test text"; auto c{e};_mean 0.376 ns 0.376 ns 10 +ssa e = "Test text"; auto c{e};_median 0.371 ns 0.371 ns 10 +ssa e = "Test text"; auto c{e};_stddev 0.021 ns 0.021 ns 10 +ssa e = "Test text"; auto c{e};_cv 5.50 % 5.50 % 10 +stringa e = "Test text"; auto c{e};_mean 1.37 ns 1.37 ns 10 +stringa e = "Test text"; auto c{e};_median 1.31 ns 1.31 ns 10 +stringa e = "Test text"; auto c{e};_stddev 0.102 ns 0.102 ns 10 +stringa e = "Test text"; auto c{e};_cv 7.45 % 7.45 % 10 +lstringa<20> e = "Test text"; auto c{e};_mean 4.43 ns 4.43 ns 10 +lstringa<20> e = "Test text"; auto c{e};_median 4.40 ns 4.40 ns 10 +lstringa<20> e = "Test text"; auto c{e};_stddev 0.101 ns 0.101 ns 10 +lstringa<20> e = "Test text"; auto c{e};_cv 2.27 % 2.27 % 10 +lstringa<40> e = "Test text"; auto c{e};_mean 4.49 ns 4.49 ns 10 +lstringa<40> e = "Test text"; auto c{e};_median 4.48 ns 4.48 ns 10 +lstringa<40> e = "Test text"; auto c{e};_stddev 0.127 ns 0.127 ns 10 +lstringa<40> e = "Test text"; auto c{e};_cv 2.84 % 2.84 % 10 ----- Create copy of Str with 30 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "123456789012345678901234567890"; auto c{e};_mean 24.2 ns 24.2 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_mean 24.3 ns 24.3 ns 10 std::string e = "123456789012345678901234567890"; auto c{e};_median 24.1 ns 24.1 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_stddev 0.503 ns 0.503 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_cv 2.08 % 2.08 % 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 0.747 ns 0.747 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_median 0.748 ns 0.748 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.006 ns 0.006 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 0.77 % 0.77 % 10 -ssa e = "123456789012345678901234567890"; auto c{e};_mean 0.746 ns 0.746 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_median 0.744 ns 0.744 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.012 ns 0.012 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_cv 1.68 % 1.68 % 10 -stringa e = "123456789012345678901234567890"; auto c{e};_mean 1.13 ns 1.13 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_median 1.13 ns 1.13 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.013 ns 0.013 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_cv 1.18 % 1.18 % 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 24.4 ns 24.4 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 24.0 ns 24.0 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 1.02 ns 1.02 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 4.17 % 4.17 % 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 4.61 ns 4.61 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 4.56 ns 4.56 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 0.154 ns 0.154 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 3.35 % 3.35 % 10 +std::string e = "123456789012345678901234567890"; auto c{e};_stddev 0.599 ns 0.599 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_cv 2.46 % 2.46 % 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 0.724 ns 0.724 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_median 0.724 ns 0.724 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.007 ns 0.007 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 0.91 % 0.91 % 10 +ssa e = "123456789012345678901234567890"; auto c{e};_mean 0.752 ns 0.752 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_median 0.751 ns 0.751 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.024 ns 0.024 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_cv 3.21 % 3.21 % 10 +stringa e = "123456789012345678901234567890"; auto c{e};_mean 1.11 ns 1.11 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_median 1.11 ns 1.11 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.028 ns 0.028 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_cv 2.48 % 2.48 % 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 20.1 ns 20.1 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 20.0 ns 20.0 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 0.428 ns 0.428 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 2.13 % 2.13 % 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 4.52 ns 4.52 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 4.49 ns 4.49 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 0.115 ns 0.115 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 2.54 % 2.54 % 10 ----- Find 9 symbols text in end of 99 symbols text ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string::find;_mean 6.87 ns 6.87 ns 10 -std::string::find;_median 6.78 ns 6.78 ns 10 -std::string::find;_stddev 0.324 ns 0.324 ns 10 -std::string::find;_cv 4.71 % 4.71 % 10 -std::string_view::find;_mean 7.39 ns 7.39 ns 10 -std::string_view::find;_median 7.29 ns 7.29 ns 10 -std::string_view::find;_stddev 0.225 ns 0.225 ns 10 -std::string_view::find;_cv 3.05 % 3.05 % 10 -ssa::find;_mean 6.93 ns 6.93 ns 10 -ssa::find;_median 6.85 ns 6.85 ns 10 -ssa::find;_stddev 0.311 ns 0.311 ns 10 -ssa::find;_cv 4.49 % 4.49 % 10 -stringa::find;_mean 8.00 ns 8.00 ns 10 -stringa::find;_median 7.71 ns 7.71 ns 10 -stringa::find;_stddev 0.857 ns 0.857 ns 10 -stringa::find;_cv 10.72 % 10.72 % 10 -lstringa<20>::find;_mean 6.92 ns 6.93 ns 10 -lstringa<20>::find;_median 6.91 ns 6.91 ns 10 -lstringa<20>::find;_stddev 0.187 ns 0.187 ns 10 -lstringa<20>::find;_cv 2.71 % 2.71 % 10 -lstringa<40>::find;_mean 6.87 ns 6.87 ns 10 -lstringa<40>::find;_median 6.84 ns 6.84 ns 10 -lstringa<40>::find;_stddev 0.208 ns 0.208 ns 10 -lstringa<40>::find;_cv 3.03 % 3.03 % 10 +std::string::find;_mean 7.33 ns 7.33 ns 10 +std::string::find;_median 7.15 ns 7.15 ns 10 +std::string::find;_stddev 0.514 ns 0.513 ns 10 +std::string::find;_cv 7.00 % 7.00 % 10 +std::string_view::find;_mean 6.78 ns 6.78 ns 10 +std::string_view::find;_median 6.74 ns 6.74 ns 10 +std::string_view::find;_stddev 0.241 ns 0.241 ns 10 +std::string_view::find;_cv 3.56 % 3.56 % 10 +ssa::find;_mean 6.32 ns 6.32 ns 10 +ssa::find;_median 6.27 ns 6.27 ns 10 +ssa::find;_stddev 0.136 ns 0.136 ns 10 +ssa::find;_cv 2.16 % 2.16 % 10 +stringa::find;_mean 6.77 ns 6.77 ns 10 +stringa::find;_median 6.75 ns 6.75 ns 10 +stringa::find;_stddev 0.152 ns 0.152 ns 10 +stringa::find;_cv 2.25 % 2.25 % 10 +lstringa<20>::find;_mean 6.33 ns 6.33 ns 10 +lstringa<20>::find;_median 6.26 ns 6.26 ns 10 +lstringa<20>::find;_stddev 0.205 ns 0.205 ns 10 +lstringa<20>::find;_cv 3.24 % 3.24 % 10 +lstringa<40>::find;_mean 6.43 ns 6.43 ns 10 +lstringa<40>::find;_median 6.36 ns 6.36 ns 10 +lstringa<40>::find;_stddev 0.307 ns 0.307 ns 10 +lstringa<40>::find;_cv 4.77 % 4.77 % 10 ------- Copy not literal Str with N symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string copy{str_with_len_N};/15_mean 5.07 ns 5.07 ns 10 -std::string copy{str_with_len_N};/15_median 4.96 ns 4.96 ns 10 -std::string copy{str_with_len_N};/15_stddev 0.277 ns 0.277 ns 10 -std::string copy{str_with_len_N};/15_cv 5.46 % 5.46 % 10 -std::string copy{str_with_len_N};/16_mean 23.7 ns 23.7 ns 10 -std::string copy{str_with_len_N};/16_median 23.5 ns 23.5 ns 10 -std::string copy{str_with_len_N};/16_stddev 0.591 ns 0.591 ns 10 -std::string copy{str_with_len_N};/16_cv 2.50 % 2.50 % 10 -std::string copy{str_with_len_N};/23_mean 23.9 ns 23.9 ns 10 -std::string copy{str_with_len_N};/23_median 23.7 ns 23.7 ns 10 -std::string copy{str_with_len_N};/23_stddev 1.15 ns 1.15 ns 10 -std::string copy{str_with_len_N};/23_cv 4.82 % 4.82 % 10 -std::string copy{str_with_len_N};/24_mean 24.9 ns 24.9 ns 10 -std::string copy{str_with_len_N};/24_median 25.0 ns 25.0 ns 10 -std::string copy{str_with_len_N};/24_stddev 1.92 ns 1.92 ns 10 -std::string copy{str_with_len_N};/24_cv 7.72 % 7.72 % 10 -std::string copy{str_with_len_N};/32_mean 22.6 ns 22.6 ns 10 -std::string copy{str_with_len_N};/32_median 22.6 ns 22.6 ns 10 -std::string copy{str_with_len_N};/32_stddev 0.319 ns 0.319 ns 10 -std::string copy{str_with_len_N};/32_cv 1.41 % 1.41 % 10 -std::string copy{str_with_len_N};/64_mean 22.9 ns 22.9 ns 10 -std::string copy{str_with_len_N};/64_median 22.8 ns 22.8 ns 10 -std::string copy{str_with_len_N};/64_stddev 0.582 ns 0.582 ns 10 -std::string copy{str_with_len_N};/64_cv 2.54 % 2.54 % 10 -std::string copy{str_with_len_N};/128_mean 24.2 ns 24.2 ns 10 -std::string copy{str_with_len_N};/128_median 24.2 ns 24.2 ns 10 -std::string copy{str_with_len_N};/128_stddev 0.560 ns 0.560 ns 10 -std::string copy{str_with_len_N};/128_cv 2.31 % 2.31 % 10 -std::string copy{str_with_len_N};/256_mean 25.5 ns 25.5 ns 10 -std::string copy{str_with_len_N};/256_median 25.2 ns 25.2 ns 10 -std::string copy{str_with_len_N};/256_stddev 0.554 ns 0.554 ns 10 -std::string copy{str_with_len_N};/256_cv 2.18 % 2.18 % 10 -std::string copy{str_with_len_N};/512_mean 29.2 ns 29.2 ns 10 -std::string copy{str_with_len_N};/512_median 29.3 ns 29.3 ns 10 -std::string copy{str_with_len_N};/512_stddev 0.352 ns 0.352 ns 10 -std::string copy{str_with_len_N};/512_cv 1.21 % 1.21 % 10 -std::string copy{str_with_len_N};/1024_mean 37.2 ns 37.2 ns 10 -std::string copy{str_with_len_N};/1024_median 36.8 ns 36.8 ns 10 -std::string copy{str_with_len_N};/1024_stddev 1.63 ns 1.63 ns 10 -std::string copy{str_with_len_N};/1024_cv 4.38 % 4.38 % 10 -std::string copy{str_with_len_N};/2048_mean 81.5 ns 81.5 ns 10 -std::string copy{str_with_len_N};/2048_median 78.4 ns 78.4 ns 10 -std::string copy{str_with_len_N};/2048_stddev 8.26 ns 8.26 ns 10 -std::string copy{str_with_len_N};/2048_cv 10.14 % 10.14 % 10 -std::string copy{str_with_len_N};/4096_mean 118 ns 118 ns 10 -std::string copy{str_with_len_N};/4096_median 116 ns 116 ns 10 -std::string copy{str_with_len_N};/4096_stddev 7.18 ns 7.18 ns 10 -std::string copy{str_with_len_N};/4096_cv 6.11 % 6.11 % 10 -stringa copy{str_with_len_N};/15_mean 1.13 ns 1.13 ns 10 -stringa copy{str_with_len_N};/15_median 1.14 ns 1.14 ns 10 -stringa copy{str_with_len_N};/15_stddev 0.026 ns 0.026 ns 10 -stringa copy{str_with_len_N};/15_cv 2.33 % 2.33 % 10 -stringa copy{str_with_len_N};/16_mean 1.14 ns 1.14 ns 10 -stringa copy{str_with_len_N};/16_median 1.13 ns 1.13 ns 10 -stringa copy{str_with_len_N};/16_stddev 0.039 ns 0.039 ns 10 -stringa copy{str_with_len_N};/16_cv 3.39 % 3.39 % 10 -stringa copy{str_with_len_N};/23_mean 1.20 ns 1.20 ns 10 -stringa copy{str_with_len_N};/23_median 1.18 ns 1.18 ns 10 -stringa copy{str_with_len_N};/23_stddev 0.088 ns 0.088 ns 10 -stringa copy{str_with_len_N};/23_cv 7.37 % 7.37 % 10 -stringa copy{str_with_len_N};/24_mean 16.3 ns 16.3 ns 10 -stringa copy{str_with_len_N};/24_median 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/24_stddev 0.461 ns 0.461 ns 10 -stringa copy{str_with_len_N};/24_cv 2.83 % 2.83 % 10 -stringa copy{str_with_len_N};/32_mean 16.2 ns 16.2 ns 10 -stringa copy{str_with_len_N};/32_median 16.0 ns 16.0 ns 10 -stringa copy{str_with_len_N};/32_stddev 0.434 ns 0.434 ns 10 -stringa copy{str_with_len_N};/32_cv 2.68 % 2.68 % 10 -stringa copy{str_with_len_N};/64_mean 16.2 ns 16.2 ns 10 -stringa copy{str_with_len_N};/64_median 16.2 ns 16.2 ns 10 -stringa copy{str_with_len_N};/64_stddev 0.167 ns 0.167 ns 10 -stringa copy{str_with_len_N};/64_cv 1.03 % 1.03 % 10 -stringa copy{str_with_len_N};/128_mean 16.3 ns 16.3 ns 10 -stringa copy{str_with_len_N};/128_median 16.3 ns 16.3 ns 10 -stringa copy{str_with_len_N};/128_stddev 0.223 ns 0.223 ns 10 -stringa copy{str_with_len_N};/128_cv 1.37 % 1.37 % 10 +std::string copy{str_with_len_N};/15_mean 5.20 ns 5.20 ns 10 +std::string copy{str_with_len_N};/15_median 5.18 ns 5.18 ns 10 +std::string copy{str_with_len_N};/15_stddev 0.124 ns 0.124 ns 10 +std::string copy{str_with_len_N};/15_cv 2.39 % 2.39 % 10 +std::string copy{str_with_len_N};/16_mean 23.6 ns 23.6 ns 10 +std::string copy{str_with_len_N};/16_median 23.7 ns 23.7 ns 10 +std::string copy{str_with_len_N};/16_stddev 0.628 ns 0.628 ns 10 +std::string copy{str_with_len_N};/16_cv 2.66 % 2.66 % 10 +std::string copy{str_with_len_N};/23_mean 23.0 ns 23.0 ns 10 +std::string copy{str_with_len_N};/23_median 23.0 ns 23.0 ns 10 +std::string copy{str_with_len_N};/23_stddev 0.156 ns 0.156 ns 10 +std::string copy{str_with_len_N};/23_cv 0.68 % 0.68 % 10 +std::string copy{str_with_len_N};/24_mean 23.1 ns 23.1 ns 10 +std::string copy{str_with_len_N};/24_median 23.1 ns 23.1 ns 10 +std::string copy{str_with_len_N};/24_stddev 0.362 ns 0.362 ns 10 +std::string copy{str_with_len_N};/24_cv 1.57 % 1.57 % 10 +std::string copy{str_with_len_N};/32_mean 23.4 ns 23.4 ns 10 +std::string copy{str_with_len_N};/32_median 23.3 ns 23.3 ns 10 +std::string copy{str_with_len_N};/32_stddev 0.533 ns 0.533 ns 10 +std::string copy{str_with_len_N};/32_cv 2.28 % 2.28 % 10 +std::string copy{str_with_len_N};/64_mean 24.0 ns 24.0 ns 10 +std::string copy{str_with_len_N};/64_median 23.9 ns 23.9 ns 10 +std::string copy{str_with_len_N};/64_stddev 1.21 ns 1.21 ns 10 +std::string copy{str_with_len_N};/64_cv 5.03 % 5.03 % 10 +std::string copy{str_with_len_N};/128_mean 24.5 ns 24.5 ns 10 +std::string copy{str_with_len_N};/128_median 24.4 ns 24.4 ns 10 +std::string copy{str_with_len_N};/128_stddev 0.331 ns 0.331 ns 10 +std::string copy{str_with_len_N};/128_cv 1.35 % 1.35 % 10 +std::string copy{str_with_len_N};/256_mean 25.1 ns 25.1 ns 10 +std::string copy{str_with_len_N};/256_median 24.8 ns 24.8 ns 10 +std::string copy{str_with_len_N};/256_stddev 0.922 ns 0.922 ns 10 +std::string copy{str_with_len_N};/256_cv 3.67 % 3.67 % 10 +std::string copy{str_with_len_N};/512_mean 29.0 ns 29.0 ns 10 +std::string copy{str_with_len_N};/512_median 29.0 ns 29.0 ns 10 +std::string copy{str_with_len_N};/512_stddev 0.576 ns 0.576 ns 10 +std::string copy{str_with_len_N};/512_cv 1.99 % 1.99 % 10 +std::string copy{str_with_len_N};/1024_mean 44.3 ns 44.3 ns 10 +std::string copy{str_with_len_N};/1024_median 44.1 ns 44.1 ns 10 +std::string copy{str_with_len_N};/1024_stddev 0.821 ns 0.821 ns 10 +std::string copy{str_with_len_N};/1024_cv 1.86 % 1.86 % 10 +std::string copy{str_with_len_N};/2048_mean 130 ns 130 ns 10 +std::string copy{str_with_len_N};/2048_median 131 ns 131 ns 10 +std::string copy{str_with_len_N};/2048_stddev 8.66 ns 8.66 ns 10 +std::string copy{str_with_len_N};/2048_cv 6.66 % 6.66 % 10 +std::string copy{str_with_len_N};/4096_mean 157 ns 157 ns 10 +std::string copy{str_with_len_N};/4096_median 158 ns 158 ns 10 +std::string copy{str_with_len_N};/4096_stddev 10.6 ns 10.6 ns 10 +std::string copy{str_with_len_N};/4096_cv 6.77 % 6.77 % 10 +stringa copy{str_with_len_N};/15_mean 1.14 ns 1.14 ns 10 +stringa copy{str_with_len_N};/15_median 1.13 ns 1.13 ns 10 +stringa copy{str_with_len_N};/15_stddev 0.042 ns 0.042 ns 10 +stringa copy{str_with_len_N};/15_cv 3.67 % 3.67 % 10 +stringa copy{str_with_len_N};/16_mean 1.10 ns 1.10 ns 10 +stringa copy{str_with_len_N};/16_median 1.10 ns 1.10 ns 10 +stringa copy{str_with_len_N};/16_stddev 0.017 ns 0.017 ns 10 +stringa copy{str_with_len_N};/16_cv 1.50 % 1.50 % 10 +stringa copy{str_with_len_N};/23_mean 1.11 ns 1.11 ns 10 +stringa copy{str_with_len_N};/23_median 1.11 ns 1.11 ns 10 +stringa copy{str_with_len_N};/23_stddev 0.016 ns 0.016 ns 10 +stringa copy{str_with_len_N};/23_cv 1.44 % 1.44 % 10 +stringa copy{str_with_len_N};/24_mean 16.2 ns 16.2 ns 10 +stringa copy{str_with_len_N};/24_median 16.2 ns 16.2 ns 10 +stringa copy{str_with_len_N};/24_stddev 0.215 ns 0.215 ns 10 +stringa copy{str_with_len_N};/24_cv 1.33 % 1.33 % 10 +stringa copy{str_with_len_N};/32_mean 16.3 ns 16.3 ns 10 +stringa copy{str_with_len_N};/32_median 16.2 ns 16.2 ns 10 +stringa copy{str_with_len_N};/32_stddev 0.264 ns 0.264 ns 10 +stringa copy{str_with_len_N};/32_cv 1.62 % 1.62 % 10 +stringa copy{str_with_len_N};/64_mean 16.5 ns 16.5 ns 10 +stringa copy{str_with_len_N};/64_median 16.5 ns 16.5 ns 10 +stringa copy{str_with_len_N};/64_stddev 0.299 ns 0.299 ns 10 +stringa copy{str_with_len_N};/64_cv 1.81 % 1.81 % 10 +stringa copy{str_with_len_N};/128_mean 16.4 ns 16.4 ns 10 +stringa copy{str_with_len_N};/128_median 16.5 ns 16.5 ns 10 +stringa copy{str_with_len_N};/128_stddev 0.327 ns 0.327 ns 10 +stringa copy{str_with_len_N};/128_cv 1.99 % 1.99 % 10 stringa copy{str_with_len_N};/256_mean 16.2 ns 16.2 ns 10 stringa copy{str_with_len_N};/256_median 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/256_stddev 0.245 ns 0.245 ns 10 -stringa copy{str_with_len_N};/256_cv 1.52 % 1.52 % 10 -stringa copy{str_with_len_N};/512_mean 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/512_median 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/512_stddev 0.071 ns 0.071 ns 10 -stringa copy{str_with_len_N};/512_cv 0.44 % 0.44 % 10 -stringa copy{str_with_len_N};/1024_mean 16.5 ns 16.5 ns 10 -stringa copy{str_with_len_N};/1024_median 16.5 ns 16.5 ns 10 -stringa copy{str_with_len_N};/1024_stddev 0.232 ns 0.232 ns 10 -stringa copy{str_with_len_N};/1024_cv 1.41 % 1.41 % 10 -stringa copy{str_with_len_N};/2048_mean 16.3 ns 16.3 ns 10 -stringa copy{str_with_len_N};/2048_median 16.5 ns 16.5 ns 10 -stringa copy{str_with_len_N};/2048_stddev 0.290 ns 0.290 ns 10 -stringa copy{str_with_len_N};/2048_cv 1.78 % 1.78 % 10 -stringa copy{str_with_len_N};/4096_mean 16.2 ns 16.2 ns 10 -stringa copy{str_with_len_N};/4096_median 16.1 ns 16.1 ns 10 -stringa copy{str_with_len_N};/4096_stddev 0.246 ns 0.246 ns 10 -stringa copy{str_with_len_N};/4096_cv 1.52 % 1.52 % 10 -lstringa<16> copy{str_with_len_N};/15_mean 4.88 ns 4.88 ns 10 -lstringa<16> copy{str_with_len_N};/15_median 4.88 ns 4.88 ns 10 -lstringa<16> copy{str_with_len_N};/15_stddev 0.134 ns 0.134 ns 10 -lstringa<16> copy{str_with_len_N};/15_cv 2.76 % 2.76 % 10 -lstringa<16> copy{str_with_len_N};/16_mean 4.89 ns 4.89 ns 10 -lstringa<16> copy{str_with_len_N};/16_median 4.89 ns 4.89 ns 10 -lstringa<16> copy{str_with_len_N};/16_stddev 0.071 ns 0.071 ns 10 -lstringa<16> copy{str_with_len_N};/16_cv 1.44 % 1.44 % 10 -lstringa<16> copy{str_with_len_N};/23_mean 5.01 ns 5.01 ns 10 -lstringa<16> copy{str_with_len_N};/23_median 4.95 ns 4.95 ns 10 -lstringa<16> copy{str_with_len_N};/23_stddev 0.265 ns 0.265 ns 10 -lstringa<16> copy{str_with_len_N};/23_cv 5.30 % 5.30 % 10 -lstringa<16> copy{str_with_len_N};/24_mean 25.0 ns 25.0 ns 10 -lstringa<16> copy{str_with_len_N};/24_median 24.9 ns 24.9 ns 10 -lstringa<16> copy{str_with_len_N};/24_stddev 0.874 ns 0.874 ns 10 -lstringa<16> copy{str_with_len_N};/24_cv 3.49 % 3.49 % 10 -lstringa<16> copy{str_with_len_N};/32_mean 24.5 ns 24.5 ns 10 -lstringa<16> copy{str_with_len_N};/32_median 24.6 ns 24.6 ns 10 -lstringa<16> copy{str_with_len_N};/32_stddev 0.286 ns 0.286 ns 10 -lstringa<16> copy{str_with_len_N};/32_cv 1.17 % 1.17 % 10 -lstringa<16> copy{str_with_len_N};/64_mean 25.9 ns 25.9 ns 10 -lstringa<16> copy{str_with_len_N};/64_median 25.6 ns 25.6 ns 10 -lstringa<16> copy{str_with_len_N};/64_stddev 0.706 ns 0.706 ns 10 -lstringa<16> copy{str_with_len_N};/64_cv 2.73 % 2.73 % 10 -lstringa<16> copy{str_with_len_N};/128_mean 26.5 ns 26.5 ns 10 -lstringa<16> copy{str_with_len_N};/128_median 26.2 ns 26.2 ns 10 -lstringa<16> copy{str_with_len_N};/128_stddev 1.21 ns 1.21 ns 10 -lstringa<16> copy{str_with_len_N};/128_cv 4.56 % 4.56 % 10 -lstringa<16> copy{str_with_len_N};/256_mean 29.6 ns 29.6 ns 10 -lstringa<16> copy{str_with_len_N};/256_median 28.5 ns 28.5 ns 10 -lstringa<16> copy{str_with_len_N};/256_stddev 2.76 ns 2.76 ns 10 -lstringa<16> copy{str_with_len_N};/256_cv 9.32 % 9.32 % 10 -lstringa<16> copy{str_with_len_N};/512_mean 30.9 ns 30.9 ns 10 -lstringa<16> copy{str_with_len_N};/512_median 30.5 ns 30.5 ns 10 -lstringa<16> copy{str_with_len_N};/512_stddev 1.06 ns 1.06 ns 10 -lstringa<16> copy{str_with_len_N};/512_cv 3.42 % 3.42 % 10 -lstringa<16> copy{str_with_len_N};/1024_mean 71.7 ns 71.7 ns 10 -lstringa<16> copy{str_with_len_N};/1024_median 69.8 ns 69.8 ns 10 -lstringa<16> copy{str_with_len_N};/1024_stddev 16.9 ns 16.9 ns 10 -lstringa<16> copy{str_with_len_N};/1024_cv 23.58 % 23.58 % 10 -lstringa<16> copy{str_with_len_N};/2048_mean 74.3 ns 74.3 ns 10 -lstringa<16> copy{str_with_len_N};/2048_median 76.4 ns 76.4 ns 10 -lstringa<16> copy{str_with_len_N};/2048_stddev 9.26 ns 9.26 ns 10 -lstringa<16> copy{str_with_len_N};/2048_cv 12.45 % 12.45 % 10 -lstringa<16> copy{str_with_len_N};/4096_mean 93.3 ns 93.3 ns 10 -lstringa<16> copy{str_with_len_N};/4096_median 91.2 ns 91.2 ns 10 -lstringa<16> copy{str_with_len_N};/4096_stddev 6.20 ns 6.20 ns 10 -lstringa<16> copy{str_with_len_N};/4096_cv 6.65 % 6.65 % 10 -lstringa<512> copy{str_with_len_N};/15_mean 4.93 ns 4.93 ns 10 -lstringa<512> copy{str_with_len_N};/15_median 4.96 ns 4.96 ns 10 -lstringa<512> copy{str_with_len_N};/15_stddev 0.123 ns 0.123 ns 10 -lstringa<512> copy{str_with_len_N};/15_cv 2.50 % 2.50 % 10 -lstringa<512> copy{str_with_len_N};/16_mean 4.97 ns 4.97 ns 10 -lstringa<512> copy{str_with_len_N};/16_median 4.93 ns 4.93 ns 10 -lstringa<512> copy{str_with_len_N};/16_stddev 0.183 ns 0.183 ns 10 -lstringa<512> copy{str_with_len_N};/16_cv 3.68 % 3.68 % 10 -lstringa<512> copy{str_with_len_N};/23_mean 4.94 ns 4.94 ns 10 -lstringa<512> copy{str_with_len_N};/23_median 4.90 ns 4.90 ns 10 -lstringa<512> copy{str_with_len_N};/23_stddev 0.160 ns 0.160 ns 10 -lstringa<512> copy{str_with_len_N};/23_cv 3.23 % 3.23 % 10 -lstringa<512> copy{str_with_len_N};/24_mean 4.90 ns 4.90 ns 10 -lstringa<512> copy{str_with_len_N};/24_median 4.89 ns 4.89 ns 10 -lstringa<512> copy{str_with_len_N};/24_stddev 0.069 ns 0.069 ns 10 -lstringa<512> copy{str_with_len_N};/24_cv 1.40 % 1.40 % 10 -lstringa<512> copy{str_with_len_N};/32_mean 5.03 ns 5.03 ns 10 -lstringa<512> copy{str_with_len_N};/32_median 4.97 ns 4.97 ns 10 -lstringa<512> copy{str_with_len_N};/32_stddev 0.452 ns 0.452 ns 10 -lstringa<512> copy{str_with_len_N};/32_cv 8.99 % 8.99 % 10 -lstringa<512> copy{str_with_len_N};/64_mean 6.12 ns 6.12 ns 10 -lstringa<512> copy{str_with_len_N};/64_median 6.06 ns 6.06 ns 10 -lstringa<512> copy{str_with_len_N};/64_stddev 0.221 ns 0.221 ns 10 -lstringa<512> copy{str_with_len_N};/64_cv 3.61 % 3.61 % 10 -lstringa<512> copy{str_with_len_N};/128_mean 7.87 ns 7.87 ns 10 -lstringa<512> copy{str_with_len_N};/128_median 7.80 ns 7.80 ns 10 -lstringa<512> copy{str_with_len_N};/128_stddev 0.269 ns 0.269 ns 10 -lstringa<512> copy{str_with_len_N};/128_cv 3.42 % 3.42 % 10 -lstringa<512> copy{str_with_len_N};/256_mean 8.70 ns 8.70 ns 10 -lstringa<512> copy{str_with_len_N};/256_median 8.80 ns 8.80 ns 10 -lstringa<512> copy{str_with_len_N};/256_stddev 0.343 ns 0.343 ns 10 -lstringa<512> copy{str_with_len_N};/256_cv 3.94 % 3.94 % 10 -lstringa<512> copy{str_with_len_N};/512_mean 10.6 ns 10.6 ns 10 -lstringa<512> copy{str_with_len_N};/512_median 10.6 ns 10.6 ns 10 -lstringa<512> copy{str_with_len_N};/512_stddev 0.291 ns 0.291 ns 10 -lstringa<512> copy{str_with_len_N};/512_cv 2.75 % 2.75 % 10 -lstringa<512> copy{str_with_len_N};/1024_mean 71.4 ns 71.4 ns 10 -lstringa<512> copy{str_with_len_N};/1024_median 71.5 ns 71.5 ns 10 -lstringa<512> copy{str_with_len_N};/1024_stddev 17.3 ns 17.3 ns 10 -lstringa<512> copy{str_with_len_N};/1024_cv 24.23 % 24.23 % 10 -lstringa<512> copy{str_with_len_N};/2048_mean 77.5 ns 77.5 ns 10 -lstringa<512> copy{str_with_len_N};/2048_median 75.1 ns 75.1 ns 10 -lstringa<512> copy{str_with_len_N};/2048_stddev 10.9 ns 10.9 ns 10 -lstringa<512> copy{str_with_len_N};/2048_cv 14.01 % 14.01 % 10 -lstringa<512> copy{str_with_len_N};/4096_mean 93.4 ns 93.4 ns 10 -lstringa<512> copy{str_with_len_N};/4096_median 90.8 ns 90.8 ns 10 -lstringa<512> copy{str_with_len_N};/4096_stddev 11.0 ns 11.0 ns 10 -lstringa<512> copy{str_with_len_N};/4096_cv 11.77 % 11.77 % 10 +stringa copy{str_with_len_N};/256_stddev 0.261 ns 0.261 ns 10 +stringa copy{str_with_len_N};/256_cv 1.61 % 1.61 % 10 +stringa copy{str_with_len_N};/512_mean 16.3 ns 16.3 ns 10 +stringa copy{str_with_len_N};/512_median 16.2 ns 16.2 ns 10 +stringa copy{str_with_len_N};/512_stddev 0.272 ns 0.272 ns 10 +stringa copy{str_with_len_N};/512_cv 1.67 % 1.67 % 10 +stringa copy{str_with_len_N};/1024_mean 16.3 ns 16.3 ns 10 +stringa copy{str_with_len_N};/1024_median 16.1 ns 16.1 ns 10 +stringa copy{str_with_len_N};/1024_stddev 0.357 ns 0.357 ns 10 +stringa copy{str_with_len_N};/1024_cv 2.19 % 2.19 % 10 +stringa copy{str_with_len_N};/2048_mean 16.4 ns 16.4 ns 10 +stringa copy{str_with_len_N};/2048_median 16.2 ns 16.2 ns 10 +stringa copy{str_with_len_N};/2048_stddev 0.371 ns 0.371 ns 10 +stringa copy{str_with_len_N};/2048_cv 2.26 % 2.26 % 10 +stringa copy{str_with_len_N};/4096_mean 16.5 ns 16.5 ns 10 +stringa copy{str_with_len_N};/4096_median 16.4 ns 16.4 ns 10 +stringa copy{str_with_len_N};/4096_stddev 0.427 ns 0.427 ns 10 +stringa copy{str_with_len_N};/4096_cv 2.59 % 2.59 % 10 +lstringa<16> copy{str_with_len_N};/15_mean 4.51 ns 4.51 ns 10 +lstringa<16> copy{str_with_len_N};/15_median 4.49 ns 4.49 ns 10 +lstringa<16> copy{str_with_len_N};/15_stddev 0.147 ns 0.147 ns 10 +lstringa<16> copy{str_with_len_N};/15_cv 3.26 % 3.26 % 10 +lstringa<16> copy{str_with_len_N};/16_mean 4.50 ns 4.50 ns 10 +lstringa<16> copy{str_with_len_N};/16_median 4.46 ns 4.46 ns 10 +lstringa<16> copy{str_with_len_N};/16_stddev 0.131 ns 0.131 ns 10 +lstringa<16> copy{str_with_len_N};/16_cv 2.91 % 2.91 % 10 +lstringa<16> copy{str_with_len_N};/23_mean 4.56 ns 4.56 ns 10 +lstringa<16> copy{str_with_len_N};/23_median 4.57 ns 4.57 ns 10 +lstringa<16> copy{str_with_len_N};/23_stddev 0.126 ns 0.126 ns 10 +lstringa<16> copy{str_with_len_N};/23_cv 2.77 % 2.77 % 10 +lstringa<16> copy{str_with_len_N};/24_mean 24.2 ns 24.2 ns 10 +lstringa<16> copy{str_with_len_N};/24_median 24.0 ns 24.0 ns 10 +lstringa<16> copy{str_with_len_N};/24_stddev 0.622 ns 0.622 ns 10 +lstringa<16> copy{str_with_len_N};/24_cv 2.57 % 2.57 % 10 +lstringa<16> copy{str_with_len_N};/32_mean 23.7 ns 23.7 ns 10 +lstringa<16> copy{str_with_len_N};/32_median 23.6 ns 23.6 ns 10 +lstringa<16> copy{str_with_len_N};/32_stddev 0.525 ns 0.525 ns 10 +lstringa<16> copy{str_with_len_N};/32_cv 2.22 % 2.22 % 10 +lstringa<16> copy{str_with_len_N};/64_mean 25.4 ns 25.4 ns 10 +lstringa<16> copy{str_with_len_N};/64_median 25.2 ns 25.2 ns 10 +lstringa<16> copy{str_with_len_N};/64_stddev 0.675 ns 0.675 ns 10 +lstringa<16> copy{str_with_len_N};/64_cv 2.65 % 2.65 % 10 +lstringa<16> copy{str_with_len_N};/128_mean 26.8 ns 26.8 ns 10 +lstringa<16> copy{str_with_len_N};/128_median 26.6 ns 26.6 ns 10 +lstringa<16> copy{str_with_len_N};/128_stddev 0.702 ns 0.702 ns 10 +lstringa<16> copy{str_with_len_N};/128_cv 2.62 % 2.62 % 10 +lstringa<16> copy{str_with_len_N};/256_mean 27.8 ns 27.8 ns 10 +lstringa<16> copy{str_with_len_N};/256_median 27.7 ns 27.7 ns 10 +lstringa<16> copy{str_with_len_N};/256_stddev 1.06 ns 1.06 ns 10 +lstringa<16> copy{str_with_len_N};/256_cv 3.79 % 3.79 % 10 +lstringa<16> copy{str_with_len_N};/512_mean 31.9 ns 31.9 ns 10 +lstringa<16> copy{str_with_len_N};/512_median 31.2 ns 31.2 ns 10 +lstringa<16> copy{str_with_len_N};/512_stddev 1.63 ns 1.63 ns 10 +lstringa<16> copy{str_with_len_N};/512_cv 5.11 % 5.11 % 10 +lstringa<16> copy{str_with_len_N};/1024_mean 96.9 ns 96.9 ns 10 +lstringa<16> copy{str_with_len_N};/1024_median 97.0 ns 97.0 ns 10 +lstringa<16> copy{str_with_len_N};/1024_stddev 12.0 ns 12.0 ns 10 +lstringa<16> copy{str_with_len_N};/1024_cv 12.35 % 12.35 % 10 +lstringa<16> copy{str_with_len_N};/2048_mean 117 ns 117 ns 10 +lstringa<16> copy{str_with_len_N};/2048_median 118 ns 118 ns 10 +lstringa<16> copy{str_with_len_N};/2048_stddev 9.38 ns 9.38 ns 10 +lstringa<16> copy{str_with_len_N};/2048_cv 8.05 % 8.05 % 10 +lstringa<16> copy{str_with_len_N};/4096_mean 130 ns 130 ns 10 +lstringa<16> copy{str_with_len_N};/4096_median 129 ns 129 ns 10 +lstringa<16> copy{str_with_len_N};/4096_stddev 7.81 ns 7.81 ns 10 +lstringa<16> copy{str_with_len_N};/4096_cv 6.02 % 6.02 % 10 +lstringa<512> copy{str_with_len_N};/15_mean 5.23 ns 5.23 ns 10 +lstringa<512> copy{str_with_len_N};/15_median 5.21 ns 5.21 ns 10 +lstringa<512> copy{str_with_len_N};/15_stddev 0.125 ns 0.125 ns 10 +lstringa<512> copy{str_with_len_N};/15_cv 2.39 % 2.39 % 10 +lstringa<512> copy{str_with_len_N};/16_mean 11.5 ns 11.5 ns 10 +lstringa<512> copy{str_with_len_N};/16_median 11.5 ns 11.5 ns 10 +lstringa<512> copy{str_with_len_N};/16_stddev 0.133 ns 0.133 ns 10 +lstringa<512> copy{str_with_len_N};/16_cv 1.15 % 1.15 % 10 +lstringa<512> copy{str_with_len_N};/23_mean 11.7 ns 11.7 ns 10 +lstringa<512> copy{str_with_len_N};/23_median 11.6 ns 11.6 ns 10 +lstringa<512> copy{str_with_len_N};/23_stddev 0.425 ns 0.425 ns 10 +lstringa<512> copy{str_with_len_N};/23_cv 3.62 % 3.62 % 10 +lstringa<512> copy{str_with_len_N};/24_mean 11.6 ns 11.6 ns 10 +lstringa<512> copy{str_with_len_N};/24_median 11.7 ns 11.7 ns 10 +lstringa<512> copy{str_with_len_N};/24_stddev 0.208 ns 0.208 ns 10 +lstringa<512> copy{str_with_len_N};/24_cv 1.79 % 1.79 % 10 +lstringa<512> copy{str_with_len_N};/32_mean 20.0 ns 20.0 ns 10 +lstringa<512> copy{str_with_len_N};/32_median 19.9 ns 19.9 ns 10 +lstringa<512> copy{str_with_len_N};/32_stddev 0.297 ns 0.297 ns 10 +lstringa<512> copy{str_with_len_N};/32_cv 1.48 % 1.48 % 10 +lstringa<512> copy{str_with_len_N};/64_mean 20.8 ns 20.8 ns 10 +lstringa<512> copy{str_with_len_N};/64_median 20.7 ns 20.7 ns 10 +lstringa<512> copy{str_with_len_N};/64_stddev 0.253 ns 0.253 ns 10 +lstringa<512> copy{str_with_len_N};/64_cv 1.22 % 1.22 % 10 +lstringa<512> copy{str_with_len_N};/128_mean 23.4 ns 23.4 ns 10 +lstringa<512> copy{str_with_len_N};/128_median 23.1 ns 23.1 ns 10 +lstringa<512> copy{str_with_len_N};/128_stddev 0.736 ns 0.736 ns 10 +lstringa<512> copy{str_with_len_N};/128_cv 3.14 % 3.14 % 10 +lstringa<512> copy{str_with_len_N};/256_mean 18.1 ns 18.1 ns 10 +lstringa<512> copy{str_with_len_N};/256_median 18.2 ns 18.2 ns 10 +lstringa<512> copy{str_with_len_N};/256_stddev 0.391 ns 0.391 ns 10 +lstringa<512> copy{str_with_len_N};/256_cv 2.16 % 2.16 % 10 +lstringa<512> copy{str_with_len_N};/512_mean 20.6 ns 20.6 ns 10 +lstringa<512> copy{str_with_len_N};/512_median 20.6 ns 20.6 ns 10 +lstringa<512> copy{str_with_len_N};/512_stddev 0.288 ns 0.288 ns 10 +lstringa<512> copy{str_with_len_N};/512_cv 1.39 % 1.39 % 10 +lstringa<512> copy{str_with_len_N};/1024_mean 96.9 ns 96.9 ns 10 +lstringa<512> copy{str_with_len_N};/1024_median 95.5 ns 95.5 ns 10 +lstringa<512> copy{str_with_len_N};/1024_stddev 11.7 ns 11.7 ns 10 +lstringa<512> copy{str_with_len_N};/1024_cv 12.11 % 12.11 % 10 +lstringa<512> copy{str_with_len_N};/2048_mean 118 ns 118 ns 10 +lstringa<512> copy{str_with_len_N};/2048_median 121 ns 121 ns 10 +lstringa<512> copy{str_with_len_N};/2048_stddev 13.4 ns 13.4 ns 10 +lstringa<512> copy{str_with_len_N};/2048_cv 11.31 % 11.31 % 10 +lstringa<512> copy{str_with_len_N};/4096_mean 134 ns 134 ns 10 +lstringa<512> copy{str_with_len_N};/4096_median 133 ns 133 ns 10 +lstringa<512> copy{str_with_len_N};/4096_stddev 11.5 ns 11.5 ns 10 +lstringa<512> copy{str_with_len_N};/4096_cv 8.58 % 8.58 % 10 ----- Convert to int '1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_mean 27.0 ns 27.0 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 26.8 ns 26.8 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 0.637 ns 0.637 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 2.36 % 2.36 % 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 12.3 ns 12.3 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 12.3 ns 12.3 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.086 ns 0.086 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 0.70 % 0.70 % 10 -stringa s = "123456789"; int res = s.to_int_mean 8.38 ns 8.38 ns 10 -stringa s = "123456789"; int res = s.to_int_median 8.33 ns 8.33 ns 10 -stringa s = "123456789"; int res = s.to_int_stddev 0.220 ns 0.220 ns 10 -stringa s = "123456789"; int res = s.to_int_cv 2.62 % 2.62 % 10 -ssa s = "123456789"; int res = s.to_int_mean 8.48 ns 8.48 ns 10 -ssa s = "123456789"; int res = s.to_int_median 8.36 ns 8.36 ns 10 -ssa s = "123456789"; int res = s.to_int_stddev 0.427 ns 0.427 ns 10 -ssa s = "123456789"; int res = s.to_int_cv 5.03 % 5.03 % 10 -lstringa<20> s = "123456789"; int res = s.to_int_mean 8.36 ns 8.36 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_median 8.29 ns 8.29 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_stddev 0.338 ns 0.338 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_cv 4.04 % 4.04 % 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_mean 27.4 ns 27.4 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 27.4 ns 27.4 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 0.497 ns 0.497 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 1.81 % 1.81 % 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 12.5 ns 12.5 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 12.6 ns 12.6 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.308 ns 0.308 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 2.46 % 2.46 % 10 +stringa s = "123456789"; int res = s.to_int_mean 8.24 ns 8.24 ns 10 +stringa s = "123456789"; int res = s.to_int_median 8.16 ns 8.16 ns 10 +stringa s = "123456789"; int res = s.to_int_stddev 0.298 ns 0.298 ns 10 +stringa s = "123456789"; int res = s.to_int_cv 3.62 % 3.62 % 10 +ssa s = "123456789"; int res = s.to_int_mean 7.94 ns 7.94 ns 10 +ssa s = "123456789"; int res = s.to_int_median 7.86 ns 7.86 ns 10 +ssa s = "123456789"; int res = s.to_int_stddev 0.327 ns 0.327 ns 10 +ssa s = "123456789"; int res = s.to_int_cv 4.12 % 4.12 % 10 +lstringa<20> s = "123456789"; int res = s.to_int_mean 8.34 ns 8.34 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_median 8.14 ns 8.14 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_stddev 0.501 ns 0.501 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_cv 6.01 % 6.01 % 10 ----- Convert to unsigned 'abcDef' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 24.3 ns 24.3 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 23.7 ns 23.7 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 1.18 ns 1.18 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 4.86 % 4.86 % 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 15.0 ns 15.0 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 15.0 ns 15.0 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 0.265 ns 0.265 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 1.77 % 1.77 % 10 -stringa s = "abcDef"; int res = s.to_int_mean 8.57 ns 8.57 ns 10 -stringa s = "abcDef"; int res = s.to_int_median 8.53 ns 8.53 ns 10 -stringa s = "abcDef"; int res = s.to_int_stddev 0.154 ns 0.154 ns 10 -stringa s = "abcDef"; int res = s.to_int_cv 1.80 % 1.80 % 10 -ssa s = "abcDef"; int res = s.to_int_mean 7.90 ns 7.90 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 23.7 ns 23.7 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 23.6 ns 23.6 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 0.678 ns 0.678 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 2.86 % 2.86 % 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 9.81 ns 9.81 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 9.67 ns 9.67 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 0.410 ns 0.410 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 4.18 % 4.18 % 10 +stringa s = "abcDef"; int res = s.to_int_mean 8.30 ns 8.30 ns 10 +stringa s = "abcDef"; int res = s.to_int_median 8.31 ns 8.31 ns 10 +stringa s = "abcDef"; int res = s.to_int_stddev 0.239 ns 0.239 ns 10 +stringa s = "abcDef"; int res = s.to_int_cv 2.88 % 2.88 % 10 +ssa s = "abcDef"; int res = s.to_int_mean 7.86 ns 7.86 ns 10 ssa s = "abcDef"; int res = s.to_int_median 7.88 ns 7.88 ns 10 -ssa s = "abcDef"; int res = s.to_int_stddev 0.135 ns 0.135 ns 10 -ssa s = "abcDef"; int res = s.to_int_cv 1.71 % 1.71 % 10 -lstringa<20> s = "abcDef"; int res = s.to_int_mean 7.94 ns 7.94 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_median 7.94 ns 7.94 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_stddev 0.121 ns 0.121 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_cv 1.52 % 1.52 % 10 +ssa s = "abcDef"; int res = s.to_int_stddev 0.104 ns 0.104 ns 10 +ssa s = "abcDef"; int res = s.to_int_cv 1.32 % 1.32 % 10 +lstringa<20> s = "abcDef"; int res = s.to_int_mean 8.11 ns 8.11 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_median 8.11 ns 8.11 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_stddev 0.057 ns 0.057 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_cv 0.71 % 0.71 % 10 ----- Convert to int ' 1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_mean 28.7 ns 28.7 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 28.5 ns 28.5 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 1.26 ns 1.26 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 4.39 % 4.39 % 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 15.7 ns 15.7 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 15.4 ns 15.4 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 1.09 ns 1.09 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 6.91 % 6.91 % 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 10.9 ns 10.9 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 10.9 ns 10.9 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.309 ns 0.309 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 2.83 % 2.83 % 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_mean 29.3 ns 29.3 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 29.0 ns 29.0 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 1.04 ns 1.04 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 3.54 % 3.54 % 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 15.1 ns 15.1 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 15.0 ns 15.0 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 0.585 ns 0.585 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 3.88 % 3.88 % 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 10.8 ns 10.8 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 10.7 ns 10.7 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.242 ns 0.242 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 2.25 % 2.25 % 10 ----- Convert to double '1234.567e10' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 65.0 ns 65.0 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 65.1 ns 65.1 ns 10 std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_median 64.8 ns 64.8 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 2.42 ns 2.42 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 3.72 % 3.72 % 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 23.9 ns 23.9 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 24.0 ns 24.0 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 0.476 ns 0.476 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 1.99 % 1.99 % 10 -ssa s = "1234.567e10"; double res = *s.to_double()_mean 24.3 ns 24.3 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_median 24.4 ns 24.4 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_stddev 0.473 ns 0.458 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_cv 1.94 % 1.88 % 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 2.37 ns 2.37 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 3.64 % 3.64 % 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 24.4 ns 24.4 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 24.3 ns 24.3 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 1.03 ns 1.03 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 4.20 % 4.20 % 10 +ssa s = "1234.567e10"; double res = *s.to_double()_mean 24.7 ns 24.7 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_median 24.2 ns 24.2 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_stddev 0.927 ns 0.927 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_cv 3.76 % 3.76 % 10 -- Append const literal of 16 bytes 64 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << "abbaabbaabbaabba";_mean 1513 ns 1513 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_median 1490 ns 1490 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 105 ns 105 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_cv 6.95 % 6.95 % 10 -std::string str; ... str += "abbaabbaabbaabba";_mean 346 ns 346 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_median 343 ns 343 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_stddev 20.3 ns 20.3 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_cv 5.86 % 5.86 % 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 371 ns 371 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_median 367 ns 367 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 25.3 ns 25.3 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 6.82 % 6.82 % 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 264 ns 264 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_median 261 ns 261 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 17.6 ns 17.6 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 6.67 % 6.67 % 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 239 ns 239 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_median 239 ns 239 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 14.3 ns 14.3 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 5.96 % 5.96 % 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 141 ns 141 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_mean 1395 ns 1395 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_median 1401 ns 1401 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 46.8 ns 46.8 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_cv 3.35 % 3.35 % 10 +std::string str; ... str += "abbaabbaabbaabba";_mean 377 ns 377 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_median 381 ns 381 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_stddev 20.6 ns 20.6 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_cv 5.45 % 5.45 % 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 407 ns 407 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_median 401 ns 401 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 28.3 ns 28.3 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 6.96 % 6.96 % 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 267 ns 267 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_median 268 ns 268 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 13.6 ns 13.6 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 5.09 % 5.09 % 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 240 ns 240 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_median 232 ns 232 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 15.7 ns 15.7 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 6.55 % 6.55 % 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 142 ns 142 ns 10 lstringa<1024> str; ... str += "abbaabbaabbaabba";_median 140 ns 140 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 2.88 ns 2.88 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_cv 2.04 % 2.04 % 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 6.01 ns 6.01 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_cv 4.24 % 4.24 % 10 -- Append string of 16 bytes and const literal of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 1456 ns 1456 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 1460 ns 1460 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 25.6 ns 25.6 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 1.76 % 1.76 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 1276 ns 1276 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_median 1277 ns 1277 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 23.7 ns 23.7 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 1.86 % 1.86 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 420 ns 420 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 417 ns 417 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 18.9 ns 18.9 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 4.50 % 4.50 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 355 ns 355 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 354 ns 354 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 14.0 ns 14.0 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 3.94 % 3.94 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 310 ns 310 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 313 ns 313 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 12.0 ns 12.0 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 3.86 % 3.86 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 253 ns 253 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 249 ns 249 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 13.3 ns 13.3 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.27 % 5.27 % 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 1404 ns 1404 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 1381 ns 1381 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 56.4 ns 56.4 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 4.02 % 4.02 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 1265 ns 1265 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_median 1258 ns 1258 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 41.9 ns 41.9 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 3.31 % 3.31 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 442 ns 442 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 445 ns 445 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 22.2 ns 22.2 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.03 % 5.03 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 376 ns 376 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 367 ns 367 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 19.4 ns 19.4 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.15 % 5.15 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 316 ns 316 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 309 ns 309 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 15.6 ns 15.6 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 4.93 % 4.93 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 247 ns 247 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 246 ns 246 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 5.64 ns 5.64 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 2.28 % 2.28 % 10 -- Append string of 16 bytes and const literal of 16 bytes 2048 times, 65536 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 132670 ns 132669 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 132572 ns 132570 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 3449 ns 3449 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 2.60 % 2.60 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 74369 ns 74369 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 74079 ns 74079 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 1365 ns 1365 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 1.84 % 1.84 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 55191 ns 55191 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 55808 ns 55808 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 2053 ns 2053 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.72 % 3.72 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 28835 ns 28835 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 29915 ns 29915 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 4393 ns 4393 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 15.23 % 15.23 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 19500 ns 19500 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 17304 ns 17304 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 4582 ns 4582 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 23.50 % 23.50 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 18108 ns 18108 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 17806 ns 17806 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 1267 ns 1267 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 7.00 % 7.00 % 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 75371 ns 75372 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 75158 ns 75158 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 1425 ns 1425 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 1.89 % 1.89 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 73091 ns 73091 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 72172 ns 72172 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 1892 ns 1892 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.59 % 2.59 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 20644 ns 20645 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 20542 ns 20542 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 581 ns 581 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.81 % 2.81 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 17277 ns 17278 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 17153 ns 17154 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 267 ns 267 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 1.55 % 1.55 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 17504 ns 17504 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 17286 ns 17286 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 614 ns 614 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.51 % 3.51 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 17482 ns 17482 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 17354 ns 17354 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 463 ns 463 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.65 % 2.65 % 10 -- Append 2 string of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var1 << str_var2;_mean 1425 ns 1425 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_median 1418 ns 1418 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_stddev 26.1 ns 26.1 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_cv 1.83 % 1.83 % 10 -std::string str; ... str += str_var1 + str_var2;_mean 1392 ns 1392 ns 10 -std::string str; ... str += str_var1 + str_var2;_median 1359 ns 1359 ns 10 -std::string str; ... str += str_var1 + str_var2;_stddev 80.1 ns 80.1 ns 10 -std::string str; ... str += str_var1 + str_var2;_cv 5.76 % 5.76 % 10 -lstringa<16> str; ... str += str_var1 + str_var2;_mean 630 ns 630 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_median 609 ns 609 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_stddev 57.4 ns 57.4 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_cv 9.11 % 9.11 % 10 -lstringa<128> str; ... str += str_var1 + str_var2;_mean 534 ns 534 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_median 534 ns 534 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_stddev 13.8 ns 13.8 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_cv 2.59 % 2.59 % 10 -lstringa<512> str; ... str += str_var1 + str_var2;_mean 470 ns 470 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_median 470 ns 470 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_stddev 8.82 ns 8.82 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_cv 1.88 % 1.88 % 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_mean 434 ns 434 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_median 434 ns 434 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 5.85 ns 5.85 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_cv 1.35 % 1.35 % 10 +std::stringstream str; ... str << str_var1 << str_var2;_mean 1414 ns 1414 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_median 1404 ns 1404 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_stddev 37.7 ns 37.7 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_cv 2.66 % 2.66 % 10 +std::string str; ... str += str_var1 + str_var2;_mean 1409 ns 1409 ns 10 +std::string str; ... str += str_var1 + str_var2;_median 1404 ns 1404 ns 10 +std::string str; ... str += str_var1 + str_var2;_stddev 33.7 ns 33.7 ns 10 +std::string str; ... str += str_var1 + str_var2;_cv 2.39 % 2.39 % 10 +lstringa<16> str; ... str += str_var1 + str_var2;_mean 544 ns 544 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_median 536 ns 536 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_stddev 37.1 ns 37.1 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_cv 6.82 % 6.82 % 10 +lstringa<128> str; ... str += str_var1 + str_var2;_mean 433 ns 433 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_median 427 ns 427 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_stddev 14.5 ns 14.5 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_cv 3.34 % 3.34 % 10 +lstringa<512> str; ... str += str_var1 + str_var2;_mean 417 ns 417 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_median 403 ns 403 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_stddev 34.3 ns 34.3 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_cv 8.23 % 8.23 % 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_mean 316 ns 316 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_median 313 ns 313 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 6.83 ns 6.83 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_cv 2.16 % 2.16 % 10 -- Append text, number, text --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; str << "test = " << k << " times";_mean 3106 ns 3106 ns 10 -std::stringstream str; str << "test = " << k << " times";_median 3081 ns 3081 ns 10 -std::stringstream str; str << "test = " << k << " times";_stddev 58.7 ns 58.7 ns 10 -std::stringstream str; str << "test = " << k << " times";_cv 1.89 % 1.89 % 10 -std::string str = "test = " + std::to_string(k) + " times";_mean 448 ns 448 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_median 447 ns 447 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_stddev 8.40 ns 8.40 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_cv 1.87 % 1.87 % 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 1526 ns 1526 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 1523 ns 1523 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 37.9 ns 37.9 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 2.48 % 2.48 % 10 -std::string str = std::format("test = {} times", k);_mean 1271 ns 1271 ns 10 -std::string str = std::format("test = {} times", k);_median 1268 ns 1268 ns 10 -std::string str = std::format("test = {} times", k);_stddev 36.9 ns 36.9 ns 10 -std::string str = std::format("test = {} times", k);_cv 2.90 % 2.90 % 10 -lstringa<8> str; str.format("test = {} times", k);_mean 1674 ns 1674 ns 10 -lstringa<8> str; str.format("test = {} times", k);_median 1655 ns 1655 ns 10 -lstringa<8> str; str.format("test = {} times", k);_stddev 54.6 ns 54.6 ns 10 -lstringa<8> str; str.format("test = {} times", k);_cv 3.26 % 3.26 % 10 -lstringa<32> str; str.format("test = {} times", k);_mean 1138 ns 1138 ns 10 -lstringa<32> str; str.format("test = {} times", k);_median 1122 ns 1122 ns 10 -lstringa<32> str; str.format("test = {} times", k);_stddev 51.3 ns 51.3 ns 10 -lstringa<32> str; str.format("test = {} times", k);_cv 4.51 % 4.51 % 10 -lstringa<8> str = "test = " + k + " times";_mean 317 ns 317 ns 10 -lstringa<8> str = "test = " + k + " times";_median 315 ns 315 ns 10 -lstringa<8> str = "test = " + k + " times";_stddev 9.00 ns 9.00 ns 10 -lstringa<8> str = "test = " + k + " times";_cv 2.84 % 2.84 % 10 -lstringa<32> str = "test = " + k + " times";_mean 154 ns 154 ns 10 -lstringa<32> str = "test = " + k + " times";_median 154 ns 154 ns 10 -lstringa<32> str = "test = " + k + " times";_stddev 3.15 ns 3.15 ns 10 -lstringa<32> str = "test = " + k + " times";_cv 2.04 % 2.04 % 10 -stringa str = "test = " + k + " times";_mean 170 ns 170 ns 10 -stringa str = "test = " + k + " times";_median 168 ns 168 ns 10 -stringa str = "test = " + k + " times";_stddev 5.97 ns 5.97 ns 10 -stringa str = "test = " + k + " times";_cv 3.52 % 3.52 % 10 +std::stringstream str; str << "test = " << k << " times";_mean 2998 ns 2998 ns 10 +std::stringstream str; str << "test = " << k << " times";_median 2967 ns 2967 ns 10 +std::stringstream str; str << "test = " << k << " times";_stddev 81.6 ns 81.6 ns 10 +std::stringstream str; str << "test = " << k << " times";_cv 2.72 % 2.72 % 10 +std::string str = "test = " + std::to_string(k) + " times";_mean 456 ns 456 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_median 454 ns 454 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_stddev 19.8 ns 19.8 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_cv 4.34 % 4.34 % 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 1527 ns 1527 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 1514 ns 1514 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 90.1 ns 90.1 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 5.90 % 5.90 % 10 +std::string str = std::format("test = {} times", k);_mean 1266 ns 1266 ns 10 +std::string str = std::format("test = {} times", k);_median 1265 ns 1265 ns 10 +std::string str = std::format("test = {} times", k);_stddev 42.0 ns 42.0 ns 10 +std::string str = std::format("test = {} times", k);_cv 3.32 % 3.32 % 10 +lstringa<8> str; str.format("test = {} times", k);_mean 1633 ns 1633 ns 10 +lstringa<8> str; str.format("test = {} times", k);_median 1607 ns 1607 ns 10 +lstringa<8> str; str.format("test = {} times", k);_stddev 70.5 ns 70.5 ns 10 +lstringa<8> str; str.format("test = {} times", k);_cv 4.31 % 4.31 % 10 +lstringa<32> str; str.format("test = {} times", k);_mean 1117 ns 1117 ns 10 +lstringa<32> str; str.format("test = {} times", k);_median 1107 ns 1107 ns 10 +lstringa<32> str; str.format("test = {} times", k);_stddev 44.8 ns 44.8 ns 10 +lstringa<32> str; str.format("test = {} times", k);_cv 4.01 % 4.01 % 10 +lstringa<8> str = "test = " + k + " times";_mean 313 ns 313 ns 10 +lstringa<8> str = "test = " + k + " times";_median 307 ns 307 ns 10 +lstringa<8> str = "test = " + k + " times";_stddev 16.3 ns 16.3 ns 10 +lstringa<8> str = "test = " + k + " times";_cv 5.19 % 5.19 % 10 +lstringa<32> str = "test = " + k + " times";_mean 153 ns 153 ns 10 +lstringa<32> str = "test = " + k + " times";_median 153 ns 153 ns 10 +lstringa<32> str = "test = " + k + " times";_stddev 5.19 ns 5.19 ns 10 +lstringa<32> str = "test = " + k + " times";_cv 3.40 % 3.40 % 10 +stringa str = "test = " + k + " times";_mean 162 ns 162 ns 10 +stringa str = "test = " + k + " times";_median 160 ns 160 ns 10 +stringa str = "test = " + k + " times";_stddev 5.01 ns 5.01 ns 10 +stringa str = "test = " + k + " times";_cv 3.10 % 3.10 % 10 -- Split text and convert to int --/repeats:1 0.000 ns 0.000 ns 1000000000000 std::string::find + substr + std::strtol_mean 273 ns 273 ns 10 -std::string::find + substr + std::strtol_median 271 ns 271 ns 10 -std::string::find + substr + std::strtol_stddev 5.77 ns 5.77 ns 10 -std::string::find + substr + std::strtol_cv 2.12 % 2.12 % 10 -ssa::splitter + ssa::as_int_mean 137 ns 137 ns 10 -ssa::splitter + ssa::as_int_median 136 ns 136 ns 10 -ssa::splitter + ssa::as_int_stddev 3.41 ns 3.41 ns 10 -ssa::splitter + ssa::as_int_cv 2.49 % 2.49 % 10 -ssa::splitf + functor_mean 130 ns 130 ns 10 -ssa::splitf + functor_median 130 ns 130 ns 10 -ssa::splitf + functor_stddev 1.63 ns 1.63 ns 10 -ssa::splitf + functor_cv 1.26 % 1.26 % 10 +std::string::find + substr + std::strtol_median 270 ns 270 ns 10 +std::string::find + substr + std::strtol_stddev 9.80 ns 9.80 ns 10 +std::string::find + substr + std::strtol_cv 3.59 % 3.59 % 10 +ssa::splitter + ssa::as_int_mean 135 ns 135 ns 10 +ssa::splitter + ssa::as_int_median 134 ns 134 ns 10 +ssa::splitter + ssa::as_int_stddev 3.01 ns 3.01 ns 10 +ssa::splitter + ssa::as_int_cv 2.23 % 2.23 % 10 +ssa::splitf + functor_mean 131 ns 131 ns 10 +ssa::splitf + functor_median 131 ns 131 ns 10 +ssa::splitf + functor_stddev 2.28 ns 2.28 ns 10 +ssa::splitf + functor_cv 1.74 % 1.74 % 10 -- Replace symbols in text ~400 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Naive (and wrong) replace symbols with std::string find + replace_mean 851 ns 851 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_median 856 ns 856 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_stddev 18.6 ns 18.6 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_cv 2.19 % 2.19 % 10 -replace symbols with std::string find_first_of + replace_mean 2496 ns 2496 ns 10 -replace symbols with std::string find_first_of + replace_median 2428 ns 2428 ns 10 -replace symbols with std::string find_first_of + replace_stddev 225 ns 225 ns 10 -replace symbols with std::string find_first_of + replace_cv 9.03 % 9.03 % 10 -replace symbols with std::string_view find_first_of + copy_mean 973 ns 973 ns 10 -replace symbols with std::string_view find_first_of + copy_median 971 ns 971 ns 10 -replace symbols with std::string_view find_first_of + copy_stddev 18.8 ns 18.8 ns 10 -replace symbols with std::string_view find_first_of + copy_cv 1.93 % 1.93 % 10 -replace runtime symbols with string expressions and without remembering all search results_mean 1508 ns 1508 ns 10 -replace runtime symbols with string expressions and without remembering all search results_median 1511 ns 1511 ns 10 -replace runtime symbols with string expressions and without remembering all search results_stddev 24.9 ns 24.9 ns 10 -replace runtime symbols with string expressions and without remembering all search results_cv 1.65 % 1.65 % 10 -replace runtime symbols with simstr and memorization of all search results_mean 1172 ns 1172 ns 10 -replace runtime symbols with simstr and memorization of all search results_median 1177 ns 1177 ns 10 -replace runtime symbols with simstr and memorization of all search results_stddev 13.5 ns 13.5 ns 10 -replace runtime symbols with simstr and memorization of all search results_cv 1.15 % 1.15 % 10 -replace const symbols with string expressions and without remembering all search results_mean 1253 ns 1253 ns 10 -replace const symbols with string expressions and without remembering all search results_median 1254 ns 1254 ns 10 -replace const symbols with string expressions and without remembering all search results_stddev 19.3 ns 19.3 ns 10 -replace const symbols with string expressions and without remembering all search results_cv 1.54 % 1.54 % 10 -replace const symbols with string expressions and memorization of all search results_mean 874 ns 874 ns 10 -replace const symbols with string expressions and memorization of all search results_median 875 ns 875 ns 10 -replace const symbols with string expressions and memorization of all search results_stddev 23.8 ns 23.8 ns 10 -replace const symbols with string expressions and memorization of all search results_cv 2.73 % 2.73 % 10 +Naive (and wrong) replace symbols with std::string find + replace_mean 852 ns 852 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_median 850 ns 850 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_stddev 20.9 ns 20.9 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_cv 2.45 % 2.45 % 10 +replace symbols with std::string find_first_of + replace_mean 2378 ns 2378 ns 10 +replace symbols with std::string find_first_of + replace_median 2379 ns 2379 ns 10 +replace symbols with std::string find_first_of + replace_stddev 38.1 ns 38.1 ns 10 +replace symbols with std::string find_first_of + replace_cv 1.60 % 1.60 % 10 +replace symbols with std::string_view find_first_of + copy_mean 1037 ns 1037 ns 10 +replace symbols with std::string_view find_first_of + copy_median 1021 ns 1021 ns 10 +replace symbols with std::string_view find_first_of + copy_stddev 35.1 ns 35.1 ns 10 +replace symbols with std::string_view find_first_of + copy_cv 3.38 % 3.38 % 10 +replace runtime symbols with string expressions and without remembering all search results_mean 1465 ns 1465 ns 10 +replace runtime symbols with string expressions and without remembering all search results_median 1452 ns 1452 ns 10 +replace runtime symbols with string expressions and without remembering all search results_stddev 43.1 ns 43.1 ns 10 +replace runtime symbols with string expressions and without remembering all search results_cv 2.95 % 2.95 % 10 +replace runtime symbols with simstr and memorization of all search results_mean 1035 ns 1035 ns 10 +replace runtime symbols with simstr and memorization of all search results_median 1039 ns 1039 ns 10 +replace runtime symbols with simstr and memorization of all search results_stddev 13.7 ns 13.7 ns 10 +replace runtime symbols with simstr and memorization of all search results_cv 1.32 % 1.32 % 10 +replace const symbols with string expressions and without remembering all search results_mean 1231 ns 1231 ns 10 +replace const symbols with string expressions and without remembering all search results_median 1217 ns 1217 ns 10 +replace const symbols with string expressions and without remembering all search results_stddev 51.2 ns 51.2 ns 10 +replace const symbols with string expressions and without remembering all search results_cv 4.16 % 4.16 % 10 +replace const symbols with string expressions and memorization of all search results_mean 919 ns 919 ns 10 +replace const symbols with string expressions and memorization of all search results_median 918 ns 918 ns 10 +replace const symbols with string expressions and memorization of all search results_stddev 54.4 ns 54.5 ns 10 +replace const symbols with string expressions and memorization of all search results_cv 5.93 % 5.93 % 10 -- Replace symbols in text ~40 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Short Naive (and wrong) replace symbols with std::string find + replace_mean 161 ns 161 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_median 161 ns 161 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_stddev 3.28 ns 3.28 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_cv 2.04 % 2.04 % 10 -Short replace symbols with std::string find_first_of + replace_mean 321 ns 321 ns 10 -Short replace symbols with std::string find_first_of + replace_median 315 ns 315 ns 10 -Short replace symbols with std::string find_first_of + replace_stddev 12.9 ns 12.9 ns 10 -Short replace symbols with std::string find_first_of + replace_cv 4.02 % 4.02 % 10 -Short replace symbols with std::string_view find_first_of + copy_mean 155 ns 155 ns 10 -Short replace symbols with std::string_view find_first_of + copy_median 154 ns 154 ns 10 -Short replace symbols with std::string_view find_first_of + copy_stddev 4.84 ns 4.84 ns 10 -Short replace symbols with std::string_view find_first_of + copy_cv 3.13 % 3.13 % 10 -Short replace runtime symbols with string expressions and without remembering all search results_mean 192 ns 192 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_median 190 ns 190 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_stddev 7.47 ns 7.47 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_cv 3.89 % 3.89 % 10 -Short replace runtime symbols with simstr and memorization of all search results_mean 190 ns 190 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_median 189 ns 189 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_stddev 2.96 ns 2.96 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_cv 1.56 % 1.56 % 10 -Short replace const symbols with string expressions and without remembering all search results_mean 159 ns 159 ns 10 -Short replace const symbols with string expressions and without remembering all search results_median 159 ns 159 ns 10 -Short replace const symbols with string expressions and without remembering all search results_stddev 3.16 ns 3.16 ns 10 -Short replace const symbols with string expressions and without remembering all search results_cv 1.99 % 1.99 % 10 -Short replace const symbols with string expressions and memorization of all search results_mean 149 ns 149 ns 10 -Short replace const symbols with string expressions and memorization of all search results_median 149 ns 149 ns 10 -Short replace const symbols with string expressions and memorization of all search results_stddev 3.86 ns 3.86 ns 10 -Short replace const symbols with string expressions and memorization of all search results_cv 2.59 % 2.59 % 10 +Short Naive (and wrong) replace symbols with std::string find + replace_mean 159 ns 159 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_median 158 ns 158 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_stddev 4.68 ns 4.68 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_cv 2.94 % 2.94 % 10 +Short replace symbols with std::string find_first_of + replace_mean 319 ns 319 ns 10 +Short replace symbols with std::string find_first_of + replace_median 318 ns 318 ns 10 +Short replace symbols with std::string find_first_of + replace_stddev 6.49 ns 6.49 ns 10 +Short replace symbols with std::string find_first_of + replace_cv 2.03 % 2.03 % 10 +Short replace symbols with std::string_view find_first_of + copy_mean 166 ns 166 ns 10 +Short replace symbols with std::string_view find_first_of + copy_median 165 ns 165 ns 10 +Short replace symbols with std::string_view find_first_of + copy_stddev 6.26 ns 6.26 ns 10 +Short replace symbols with std::string_view find_first_of + copy_cv 3.77 % 3.77 % 10 +Short replace runtime symbols with string expressions and without remembering all search results_mean 196 ns 196 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_median 194 ns 194 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_stddev 6.79 ns 6.79 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_cv 3.46 % 3.46 % 10 +Short replace runtime symbols with simstr and memorization of all search results_mean 211 ns 211 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_median 211 ns 211 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_stddev 8.49 ns 8.49 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_cv 4.03 % 4.03 % 10 +Short replace const symbols with string expressions and without remembering all search results_mean 153 ns 153 ns 10 +Short replace const symbols with string expressions and without remembering all search results_median 151 ns 151 ns 10 +Short replace const symbols with string expressions and without remembering all search results_stddev 4.63 ns 4.63 ns 10 +Short replace const symbols with string expressions and without remembering all search results_cv 3.04 % 3.04 % 10 +Short replace const symbols with string expressions and memorization of all search results_mean 146 ns 146 ns 10 +Short replace const symbols with string expressions and memorization of all search results_median 144 ns 144 ns 10 +Short replace const symbols with string expressions and memorization of all search results_stddev 4.77 ns 4.77 ns 10 +Short replace const symbols with string expressions and memorization of all search results_cv 3.26 % 3.26 % 10 ----- Replace All Str To Longer Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to ---- in std::string|64_mean 174 ns 174 ns 10 -replace bb to ---- in std::string|64_median 166 ns 166 ns 10 -replace bb to ---- in std::string|64_stddev 16.4 ns 16.4 ns 10 -replace bb to ---- in std::string|64_cv 9.46 % 9.46 % 10 -replace bb to ---- in std::string|256_mean 511 ns 511 ns 10 -replace bb to ---- in std::string|256_median 498 ns 498 ns 10 -replace bb to ---- in std::string|256_stddev 28.1 ns 28.1 ns 10 -replace bb to ---- in std::string|256_cv 5.50 % 5.50 % 10 -replace bb to ---- in std::string|512_mean 1180 ns 1180 ns 10 -replace bb to ---- in std::string|512_median 1173 ns 1173 ns 10 -replace bb to ---- in std::string|512_stddev 20.5 ns 20.5 ns 10 -replace bb to ---- in std::string|512_cv 1.74 % 1.74 % 10 -replace bb to ---- in std::string|1024_mean 2244 ns 2244 ns 10 -replace bb to ---- in std::string|1024_median 2253 ns 2253 ns 10 -replace bb to ---- in std::string|1024_stddev 92.2 ns 92.2 ns 10 -replace bb to ---- in std::string|1024_cv 4.11 % 4.11 % 10 -replace bb to ---- in std::string|2048_mean 6009 ns 6009 ns 10 -replace bb to ---- in std::string|2048_median 5918 ns 5918 ns 10 -replace bb to ---- in std::string|2048_stddev 398 ns 398 ns 10 -replace bb to ---- in std::string|2048_cv 6.62 % 6.62 % 10 -replace bb to ---- in lstringa<8>|64_mean 154 ns 154 ns 10 -replace bb to ---- in lstringa<8>|64_median 154 ns 154 ns 10 -replace bb to ---- in lstringa<8>|64_stddev 3.85 ns 3.85 ns 10 -replace bb to ---- in lstringa<8>|64_cv 2.50 % 2.50 % 10 -replace bb to ---- in lstringa<8>|256_mean 459 ns 459 ns 10 +replace bb to ---- in std::string|64_mean 172 ns 172 ns 10 +replace bb to ---- in std::string|64_median 170 ns 170 ns 10 +replace bb to ---- in std::string|64_stddev 9.48 ns 9.48 ns 10 +replace bb to ---- in std::string|64_cv 5.52 % 5.52 % 10 +replace bb to ---- in std::string|256_mean 510 ns 510 ns 10 +replace bb to ---- in std::string|256_median 509 ns 509 ns 10 +replace bb to ---- in std::string|256_stddev 18.2 ns 18.2 ns 10 +replace bb to ---- in std::string|256_cv 3.57 % 3.57 % 10 +replace bb to ---- in std::string|512_mean 989 ns 989 ns 10 +replace bb to ---- in std::string|512_median 975 ns 975 ns 10 +replace bb to ---- in std::string|512_stddev 34.2 ns 34.2 ns 10 +replace bb to ---- in std::string|512_cv 3.46 % 3.46 % 10 +replace bb to ---- in std::string|1024_mean 2308 ns 2308 ns 10 +replace bb to ---- in std::string|1024_median 2290 ns 2290 ns 10 +replace bb to ---- in std::string|1024_stddev 157 ns 157 ns 10 +replace bb to ---- in std::string|1024_cv 6.79 % 6.79 % 10 +replace bb to ---- in std::string|2048_mean 5824 ns 5824 ns 10 +replace bb to ---- in std::string|2048_median 5566 ns 5566 ns 10 +replace bb to ---- in std::string|2048_stddev 463 ns 463 ns 10 +replace bb to ---- in std::string|2048_cv 7.94 % 7.94 % 10 +replace bb to ---- in lstringa<8>|64_mean 161 ns 161 ns 10 +replace bb to ---- in lstringa<8>|64_median 162 ns 162 ns 10 +replace bb to ---- in lstringa<8>|64_stddev 7.73 ns 7.73 ns 10 +replace bb to ---- in lstringa<8>|64_cv 4.78 % 4.78 % 10 +replace bb to ---- in lstringa<8>|256_mean 462 ns 462 ns 10 replace bb to ---- in lstringa<8>|256_median 461 ns 461 ns 10 -replace bb to ---- in lstringa<8>|256_stddev 9.64 ns 9.64 ns 10 -replace bb to ---- in lstringa<8>|256_cv 2.10 % 2.10 % 10 -replace bb to ---- in lstringa<8>|512_mean 850 ns 850 ns 10 -replace bb to ---- in lstringa<8>|512_median 855 ns 855 ns 10 -replace bb to ---- in lstringa<8>|512_stddev 16.0 ns 16.0 ns 10 -replace bb to ---- in lstringa<8>|512_cv 1.88 % 1.88 % 10 -replace bb to ---- in lstringa<8>|1024_mean 1775 ns 1775 ns 10 -replace bb to ---- in lstringa<8>|1024_median 1779 ns 1779 ns 10 -replace bb to ---- in lstringa<8>|1024_stddev 74.7 ns 74.7 ns 10 -replace bb to ---- in lstringa<8>|1024_cv 4.21 % 4.21 % 10 -replace bb to ---- in lstringa<8>|2048_mean 3322 ns 3322 ns 10 -replace bb to ---- in lstringa<8>|2048_median 3322 ns 3322 ns 10 -replace bb to ---- in lstringa<8>|2048_stddev 95.3 ns 95.4 ns 10 -replace bb to ---- in lstringa<8>|2048_cv 2.87 % 2.87 % 10 -replace bb to ---- by init stringa|64_mean 124 ns 124 ns 10 -replace bb to ---- by init stringa|64_median 124 ns 124 ns 10 -replace bb to ---- by init stringa|64_stddev 2.40 ns 2.40 ns 10 -replace bb to ---- by init stringa|64_cv 1.93 % 1.93 % 10 -replace bb to ---- by init stringa|256_mean 483 ns 483 ns 10 -replace bb to ---- by init stringa|256_median 481 ns 481 ns 10 -replace bb to ---- by init stringa|256_stddev 21.5 ns 21.5 ns 10 -replace bb to ---- by init stringa|256_cv 4.44 % 4.44 % 10 -replace bb to ---- by init stringa|512_mean 888 ns 888 ns 10 -replace bb to ---- by init stringa|512_median 884 ns 884 ns 10 -replace bb to ---- by init stringa|512_stddev 16.3 ns 16.3 ns 10 -replace bb to ---- by init stringa|512_cv 1.83 % 1.83 % 10 -replace bb to ---- by init stringa|1024_mean 1787 ns 1787 ns 10 -replace bb to ---- by init stringa|1024_median 1788 ns 1788 ns 10 -replace bb to ---- by init stringa|1024_stddev 35.7 ns 35.7 ns 10 -replace bb to ---- by init stringa|1024_cv 2.00 % 2.00 % 10 -replace bb to ---- by init stringa|2048_mean 3741 ns 3741 ns 10 -replace bb to ---- by init stringa|2048_median 3653 ns 3653 ns 10 -replace bb to ---- by init stringa|2048_stddev 217 ns 217 ns 10 -replace bb to ---- by init stringa|2048_cv 5.80 % 5.80 % 10 +replace bb to ---- in lstringa<8>|256_stddev 12.7 ns 12.7 ns 10 +replace bb to ---- in lstringa<8>|256_cv 2.75 % 2.75 % 10 +replace bb to ---- in lstringa<8>|512_mean 882 ns 882 ns 10 +replace bb to ---- in lstringa<8>|512_median 876 ns 876 ns 10 +replace bb to ---- in lstringa<8>|512_stddev 33.2 ns 33.2 ns 10 +replace bb to ---- in lstringa<8>|512_cv 3.77 % 3.77 % 10 +replace bb to ---- in lstringa<8>|1024_mean 1827 ns 1827 ns 10 +replace bb to ---- in lstringa<8>|1024_median 1824 ns 1824 ns 10 +replace bb to ---- in lstringa<8>|1024_stddev 87.4 ns 87.4 ns 10 +replace bb to ---- in lstringa<8>|1024_cv 4.78 % 4.78 % 10 +replace bb to ---- in lstringa<8>|2048_mean 3363 ns 3363 ns 10 +replace bb to ---- in lstringa<8>|2048_median 3353 ns 3353 ns 10 +replace bb to ---- in lstringa<8>|2048_stddev 123 ns 123 ns 10 +replace bb to ---- in lstringa<8>|2048_cv 3.65 % 3.65 % 10 +replace bb to ---- by init stringa|64_mean 104 ns 104 ns 10 +replace bb to ---- by init stringa|64_median 103 ns 103 ns 10 +replace bb to ---- by init stringa|64_stddev 3.90 ns 3.90 ns 10 +replace bb to ---- by init stringa|64_cv 3.75 % 3.75 % 10 +replace bb to ---- by init stringa|256_mean 299 ns 299 ns 10 +replace bb to ---- by init stringa|256_median 299 ns 299 ns 10 +replace bb to ---- by init stringa|256_stddev 10.9 ns 10.9 ns 10 +replace bb to ---- by init stringa|256_cv 3.65 % 3.65 % 10 +replace bb to ---- by init stringa|512_mean 733 ns 733 ns 10 +replace bb to ---- by init stringa|512_median 732 ns 732 ns 10 +replace bb to ---- by init stringa|512_stddev 19.5 ns 19.5 ns 10 +replace bb to ---- by init stringa|512_cv 2.66 % 2.66 % 10 +replace bb to ---- by init stringa|1024_mean 1625 ns 1625 ns 10 +replace bb to ---- by init stringa|1024_median 1616 ns 1616 ns 10 +replace bb to ---- by init stringa|1024_stddev 31.3 ns 31.3 ns 10 +replace bb to ---- by init stringa|1024_cv 1.92 % 1.92 % 10 +replace bb to ---- by init stringa|2048_mean 3339 ns 3339 ns 10 +replace bb to ---- by init stringa|2048_median 3303 ns 3304 ns 10 +replace bb to ---- by init stringa|2048_stddev 111 ns 111 ns 10 +replace bb to ---- by init stringa|2048_cv 3.33 % 3.33 % 10 ----- Replace All Str To Same Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to -- in std::string|64_mean 118 ns 118 ns 10 -replace bb to -- in std::string|64_median 117 ns 117 ns 10 -replace bb to -- in std::string|64_stddev 4.91 ns 4.91 ns 10 -replace bb to -- in std::string|64_cv 4.16 % 4.16 % 10 -replace bb to -- in std::string|256_mean 370 ns 370 ns 10 -replace bb to -- in std::string|256_median 370 ns 370 ns 10 -replace bb to -- in std::string|256_stddev 10.4 ns 10.4 ns 10 -replace bb to -- in std::string|256_cv 2.81 % 2.81 % 10 -replace bb to -- in std::string|512_mean 739 ns 739 ns 10 -replace bb to -- in std::string|512_median 737 ns 737 ns 10 -replace bb to -- in std::string|512_stddev 11.5 ns 11.5 ns 10 -replace bb to -- in std::string|512_cv 1.56 % 1.56 % 10 -replace bb to -- in std::string|1024_mean 1423 ns 1423 ns 10 -replace bb to -- in std::string|1024_median 1416 ns 1416 ns 10 -replace bb to -- in std::string|1024_stddev 42.4 ns 42.4 ns 10 -replace bb to -- in std::string|1024_cv 2.98 % 2.98 % 10 -replace bb to -- in std::string|2048_mean 2898 ns 2898 ns 10 -replace bb to -- in std::string|2048_median 2873 ns 2873 ns 10 -replace bb to -- in std::string|2048_stddev 126 ns 126 ns 10 -replace bb to -- in std::string|2048_cv 4.36 % 4.36 % 10 -replace bb to -- in lstringa<8>|64_mean 99.1 ns 99.1 ns 10 -replace bb to -- in lstringa<8>|64_median 98.8 ns 98.8 ns 10 -replace bb to -- in lstringa<8>|64_stddev 1.97 ns 1.97 ns 10 -replace bb to -- in lstringa<8>|64_cv 1.99 % 1.99 % 10 -replace bb to -- in lstringa<8>|256_mean 301 ns 301 ns 10 -replace bb to -- in lstringa<8>|256_median 296 ns 296 ns 10 -replace bb to -- in lstringa<8>|256_stddev 11.4 ns 11.4 ns 10 -replace bb to -- in lstringa<8>|256_cv 3.78 % 3.78 % 10 -replace bb to -- in lstringa<8>|512_mean 566 ns 566 ns 10 -replace bb to -- in lstringa<8>|512_median 563 ns 563 ns 10 -replace bb to -- in lstringa<8>|512_stddev 8.23 ns 8.23 ns 10 -replace bb to -- in lstringa<8>|512_cv 1.45 % 1.45 % 10 -replace bb to -- in lstringa<8>|1024_mean 1104 ns 1104 ns 10 -replace bb to -- in lstringa<8>|1024_median 1112 ns 1112 ns 10 -replace bb to -- in lstringa<8>|1024_stddev 26.7 ns 26.7 ns 10 -replace bb to -- in lstringa<8>|1024_cv 2.42 % 2.42 % 10 -replace bb to -- in lstringa<8>|2048_mean 2088 ns 2088 ns 10 -replace bb to -- in lstringa<8>|2048_median 2078 ns 2078 ns 10 -replace bb to -- in lstringa<8>|2048_stddev 49.4 ns 49.4 ns 10 -replace bb to -- in lstringa<8>|2048_cv 2.37 % 2.37 % 10 -replace bb to -- by init stringa|64_mean 99.6 ns 99.6 ns 10 -replace bb to -- by init stringa|64_median 98.7 ns 98.7 ns 10 -replace bb to -- by init stringa|64_stddev 5.18 ns 5.18 ns 10 -replace bb to -- by init stringa|64_cv 5.20 % 5.20 % 10 -replace bb to -- by init stringa|256_mean 274 ns 274 ns 10 -replace bb to -- by init stringa|256_median 275 ns 275 ns 10 -replace bb to -- by init stringa|256_stddev 6.18 ns 6.18 ns 10 -replace bb to -- by init stringa|256_cv 2.26 % 2.26 % 10 -replace bb to -- by init stringa|512_mean 527 ns 527 ns 10 -replace bb to -- by init stringa|512_median 516 ns 516 ns 10 -replace bb to -- by init stringa|512_stddev 29.0 ns 29.0 ns 10 -replace bb to -- by init stringa|512_cv 5.50 % 5.50 % 10 -replace bb to -- by init stringa|1024_mean 1029 ns 1029 ns 10 -replace bb to -- by init stringa|1024_median 1029 ns 1029 ns 10 -replace bb to -- by init stringa|1024_stddev 14.0 ns 14.0 ns 10 -replace bb to -- by init stringa|1024_cv 1.36 % 1.36 % 10 -replace bb to -- by init stringa|2048_mean 2041 ns 2041 ns 10 -replace bb to -- by init stringa|2048_median 2041 ns 2041 ns 10 -replace bb to -- by init stringa|2048_stddev 41.6 ns 41.6 ns 10 -replace bb to -- by init stringa|2048_cv 2.04 % 2.04 % 10 +replace bb to -- in std::string|64_mean 115 ns 115 ns 10 +replace bb to -- in std::string|64_median 114 ns 114 ns 10 +replace bb to -- in std::string|64_stddev 3.33 ns 3.33 ns 10 +replace bb to -- in std::string|64_cv 2.88 % 2.88 % 10 +replace bb to -- in std::string|256_mean 367 ns 367 ns 10 +replace bb to -- in std::string|256_median 361 ns 361 ns 10 +replace bb to -- in std::string|256_stddev 14.7 ns 14.7 ns 10 +replace bb to -- in std::string|256_cv 4.01 % 4.01 % 10 +replace bb to -- in std::string|512_mean 733 ns 733 ns 10 +replace bb to -- in std::string|512_median 728 ns 728 ns 10 +replace bb to -- in std::string|512_stddev 15.0 ns 15.0 ns 10 +replace bb to -- in std::string|512_cv 2.04 % 2.04 % 10 +replace bb to -- in std::string|1024_mean 1409 ns 1409 ns 10 +replace bb to -- in std::string|1024_median 1378 ns 1378 ns 10 +replace bb to -- in std::string|1024_stddev 79.1 ns 79.1 ns 10 +replace bb to -- in std::string|1024_cv 5.61 % 5.61 % 10 +replace bb to -- in std::string|2048_mean 2902 ns 2902 ns 10 +replace bb to -- in std::string|2048_median 2875 ns 2875 ns 10 +replace bb to -- in std::string|2048_stddev 125 ns 125 ns 10 +replace bb to -- in std::string|2048_cv 4.32 % 4.32 % 10 +replace bb to -- in lstringa<8>|64_mean 103 ns 103 ns 10 +replace bb to -- in lstringa<8>|64_median 105 ns 105 ns 10 +replace bb to -- in lstringa<8>|64_stddev 4.91 ns 4.91 ns 10 +replace bb to -- in lstringa<8>|64_cv 4.76 % 4.76 % 10 +replace bb to -- in lstringa<8>|256_mean 299 ns 299 ns 10 +replace bb to -- in lstringa<8>|256_median 297 ns 297 ns 10 +replace bb to -- in lstringa<8>|256_stddev 9.27 ns 9.27 ns 10 +replace bb to -- in lstringa<8>|256_cv 3.10 % 3.10 % 10 +replace bb to -- in lstringa<8>|512_mean 548 ns 548 ns 10 +replace bb to -- in lstringa<8>|512_median 540 ns 540 ns 10 +replace bb to -- in lstringa<8>|512_stddev 16.4 ns 16.4 ns 10 +replace bb to -- in lstringa<8>|512_cv 3.00 % 3.00 % 10 +replace bb to -- in lstringa<8>|1024_mean 1133 ns 1133 ns 10 +replace bb to -- in lstringa<8>|1024_median 1117 ns 1117 ns 10 +replace bb to -- in lstringa<8>|1024_stddev 48.3 ns 48.3 ns 10 +replace bb to -- in lstringa<8>|1024_cv 4.26 % 4.26 % 10 +replace bb to -- in lstringa<8>|2048_mean 2150 ns 2150 ns 10 +replace bb to -- in lstringa<8>|2048_median 2140 ns 2140 ns 10 +replace bb to -- in lstringa<8>|2048_stddev 62.9 ns 62.9 ns 10 +replace bb to -- in lstringa<8>|2048_cv 2.93 % 2.93 % 10 +replace bb to -- by init stringa|64_mean 93.9 ns 93.9 ns 10 +replace bb to -- by init stringa|64_median 93.1 ns 93.1 ns 10 +replace bb to -- by init stringa|64_stddev 2.83 ns 2.83 ns 10 +replace bb to -- by init stringa|64_cv 3.01 % 3.01 % 10 +replace bb to -- by init stringa|256_mean 275 ns 275 ns 10 +replace bb to -- by init stringa|256_median 278 ns 278 ns 10 +replace bb to -- by init stringa|256_stddev 5.58 ns 5.58 ns 10 +replace bb to -- by init stringa|256_cv 2.03 % 2.03 % 10 +replace bb to -- by init stringa|512_mean 498 ns 498 ns 10 +replace bb to -- by init stringa|512_median 496 ns 496 ns 10 +replace bb to -- by init stringa|512_stddev 9.03 ns 9.03 ns 10 +replace bb to -- by init stringa|512_cv 1.81 % 1.81 % 10 +replace bb to -- by init stringa|1024_mean 1033 ns 1033 ns 10 +replace bb to -- by init stringa|1024_median 1031 ns 1031 ns 10 +replace bb to -- by init stringa|1024_stddev 17.6 ns 17.6 ns 10 +replace bb to -- by init stringa|1024_cv 1.70 % 1.70 % 10 +replace bb to -- by init stringa|2048_mean 1981 ns 1981 ns 10 +replace bb to -- by init stringa|2048_median 1976 ns 1976 ns 10 +replace bb to -- by init stringa|2048_stddev 41.8 ns 41.8 ns 10 +replace bb to -- by init stringa|2048_cv 2.11 % 2.11 % 10 ----- Hash Map insert and find ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -hashStrMapA emplace & find stringa;_mean 3720924 ns 3720931 ns 10 -hashStrMapA emplace & find stringa;_median 3710051 ns 3710034 ns 10 -hashStrMapA emplace & find stringa;_stddev 41589 ns 41593 ns 10 -hashStrMapA emplace & find stringa;_cv 1.12 % 1.12 % 10 -std::unordered_map emplace & find std::string;_mean 3624563 ns 3624558 ns 10 -std::unordered_map emplace & find std::string;_median 3613358 ns 3613332 ns 10 -std::unordered_map emplace & find std::string;_stddev 57870 ns 57855 ns 10 -std::unordered_map emplace & find std::string;_cv 1.60 % 1.60 % 10 -hashStrMapA emplace & find ssa;_mean 3730268 ns 3730281 ns 10 -hashStrMapA emplace & find ssa;_median 3700358 ns 3700373 ns 10 -hashStrMapA emplace & find ssa;_stddev 105448 ns 105449 ns 10 -hashStrMapA emplace & find ssa;_cv 2.83 % 2.83 % 10 -std::unordered_map emplace & find std::string_view;_mean 4036697 ns 4036676 ns 10 -std::unordered_map emplace & find std::string_view;_median 4029808 ns 4029818 ns 10 -std::unordered_map emplace & find std::string_view;_stddev 57315 ns 57303 ns 10 -std::unordered_map emplace & find std::string_view;_cv 1.42 % 1.42 % 10 +hashStrMapA emplace & find stringa;_mean 3750693 ns 3750707 ns 10 +hashStrMapA emplace & find stringa;_median 3737012 ns 3737025 ns 10 +hashStrMapA emplace & find stringa;_stddev 75686 ns 75686 ns 10 +hashStrMapA emplace & find stringa;_cv 2.02 % 2.02 % 10 +std::unordered_map emplace & find std::string;_mean 3625926 ns 3625926 ns 10 +std::unordered_map emplace & find std::string;_median 3622724 ns 3622735 ns 10 +std::unordered_map emplace & find std::string;_stddev 84320 ns 84319 ns 10 +std::unordered_map emplace & find std::string;_cv 2.33 % 2.33 % 10 +hashStrMapA emplace & find ssa;_mean 3687972 ns 3687966 ns 10 +hashStrMapA emplace & find ssa;_median 3673688 ns 3673702 ns 10 +hashStrMapA emplace & find ssa;_stddev 47692 ns 47693 ns 10 +hashStrMapA emplace & find ssa;_cv 1.29 % 1.29 % 10 +std::unordered_map emplace & find std::string_view;_mean 3937773 ns 3937779 ns 10 +std::unordered_map emplace & find std::string_view;_median 3921638 ns 3921649 ns 10 +std::unordered_map emplace & find std::string_view;_stddev 90680 ns 90669 ns 10 +std::unordered_map emplace & find std::string_view;_cv 2.30 % 2.30 % 10 ----- Build Full Func Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -Build func full name std::string;_mean 1031 ns 1031 ns 10 -Build func full name std::string;_median 951 ns 951 ns 10 -Build func full name std::string;_stddev 117 ns 117 ns 10 -Build func full name std::string;_cv 11.31 % 11.31 % 10 -Build func full name std::string 1;_mean 999 ns 999 ns 10 -Build func full name std::string 1;_median 1003 ns 1003 ns 10 -Build func full name std::string 1;_stddev 17.0 ns 17.0 ns 10 -Build func full name std::string 1;_cv 1.70 % 1.70 % 10 -Build func full name std::stream;_mean 2626 ns 2626 ns 10 -Build func full name std::stream;_median 2620 ns 2620 ns 10 -Build func full name std::stream;_stddev 58.5 ns 58.5 ns 10 -Build func full name std::stream;_cv 2.23 % 2.23 % 10 -Build func full name stringa;_mean 602 ns 602 ns 10 -Build func full name stringa;_median 588 ns 588 ns 10 -Build func full name stringa;_stddev 33.5 ns 33.5 ns 10 -Build func full name stringa;_cv 5.57 % 5.57 % 10 -Build func full name stringa 1;_mean 674 ns 674 ns 10 -Build func full name stringa 1;_median 667 ns 667 ns 10 -Build func full name stringa 1;_stddev 29.9 ns 29.9 ns 10 -Build func full name stringa 1;_cv 4.43 % 4.43 % 10 +Build func full name std::string;_mean 966 ns 966 ns 10 +Build func full name std::string;_median 965 ns 965 ns 10 +Build func full name std::string;_stddev 18.9 ns 18.9 ns 10 +Build func full name std::string;_cv 1.96 % 1.96 % 10 +Build func full name std::string 1;_mean 1010 ns 1010 ns 10 +Build func full name std::string 1;_median 1001 ns 1001 ns 10 +Build func full name std::string 1;_stddev 28.9 ns 28.9 ns 10 +Build func full name std::string 1;_cv 2.86 % 2.86 % 10 +Build func full name std::stream;_mean 2613 ns 2613 ns 10 +Build func full name std::stream;_median 2577 ns 2578 ns 10 +Build func full name std::stream;_stddev 69.2 ns 69.2 ns 10 +Build func full name std::stream;_cv 2.65 % 2.65 % 10 +Build func full name stringa;_mean 465 ns 465 ns 10 +Build func full name stringa;_median 460 ns 460 ns 10 +Build func full name stringa;_stddev 16.9 ns 16.9 ns 10 +Build func full name stringa;_cv 3.64 % 3.64 % 10 +Build func full name stringa 1;_mean 682 ns 682 ns 10 +Build func full name stringa 1;_median 677 ns 677 ns 10 +Build func full name stringa 1;_stddev 17.3 ns 17.3 ns 10 +Build func full name stringa 1;_cv 2.54 % 2.54 % 10 diff --git a/bench/results/002-Xeon E5-2682 v4, Windows 10, Clang-19.txt b/bench/results/002-Xeon E5-2682 v4, Windows 10, Clang-19.txt index 72ccbba..5ab6d8c 100644 --- a/bench/results/002-Xeon E5-2682 v4, Windows 10, Clang-19.txt +++ b/bench/results/002-Xeon E5-2682 v4, Windows 10, Clang-19.txt @@ -1,4 +1,4 @@ -2025-11-26T18:59:15+03:00 +2026-01-21T00:24:03+03:00 Running benchStr.exe Run on (32 X 2494 MHz CPU s) CPU Caches: @@ -9,782 +9,868 @@ CPU Caches: -------------------------------------------------------------------------------------------------------------------------------------------------------- Benchmark Time CPU Iterations -------------------------------------------------------------------------------------------------------------------------------------------------------- +----- Concatenate string + Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and number by std to std::string_mean 266 ns 265 ns 10 +Concat std::string and number by std to std::string_median 265 ns 265 ns 10 +Concat std::string and number by std to std::string_stddev 6.17 ns 4.74 ns 10 +Concat std::string and number by std to std::string_cv 2.32 % 1.79 % 10 +Concat std::string and number by StrExpr to std::string_mean 157 ns 156 ns 10 +Concat std::string and number by StrExpr to std::string_median 157 ns 157 ns 10 +Concat std::string and number by StrExpr to std::string_stddev 5.39 ns 6.16 ns 10 +Concat std::string and number by StrExpr to std::string_cv 3.43 % 3.95 % 10 +Concat stringa and number by StrExpr to simstr::stringa_mean 66.4 ns 66.3 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_median 66.7 ns 67.0 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_stddev 1.30 ns 1.77 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_cv 1.96 % 2.67 % 10 +----- Concatenate string + Hex Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and hex number by std to std::string_mean 777 ns 766 ns 10 +Concat std::string and hex number by std to std::string_median 773 ns 750 ns 10 +Concat std::string and hex number by std to std::string_stddev 30.7 ns 35.3 ns 10 +Concat std::string and hex number by std to std::string_cv 3.95 % 4.61 % 10 +Concat std::string and hex number by StrExpr to std::string_mean 76.6 ns 76.5 ns 10 +Concat std::string and hex number by StrExpr to std::string_median 76.2 ns 76.0 ns 10 +Concat std::string and hex number by StrExpr to std::string_stddev 1.72 ns 1.71 ns 10 +Concat std::string and hex number by StrExpr to std::string_cv 2.25 % 2.24 % 10 +Concat stringa and hex number by StrExpr to simstr::stringa_mean 67.9 ns 67.8 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_median 67.4 ns 67.0 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_stddev 1.81 ns 1.64 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_cv 2.67 % 2.42 % 10 +----- Concatenate string + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string by std to std::string_mean 39.8 ns 39.4 ns 10 +Concat std::string by std to std::string_median 39.8 ns 39.9 ns 10 +Concat std::string by std to std::string_stddev 1.29 ns 1.07 ns 10 +Concat std::string by std to std::string_cv 3.25 % 2.71 % 10 +Concat std::string by StrExpr to std::string_mean 39.1 ns 39.0 ns 10 +Concat std::string by StrExpr to std::string_median 39.1 ns 38.5 ns 10 +Concat std::string by StrExpr to std::string_stddev 1.05 ns 0.900 ns 10 +Concat std::string by StrExpr to std::string_cv 2.69 % 2.31 % 10 +Concat stringa by StrExpr to stringa_mean 29.2 ns 29.1 ns 10 +Concat stringa by StrExpr to stringa_median 28.7 ns 28.5 ns 10 +Concat stringa by StrExpr to stringa_stddev 1.18 ns 1.22 ns 10 +Concat stringa by StrExpr to stringa_cv 4.04 % 4.19 % 10 +----- Find three concatenated string in string_view -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Find concat three std::string_mean 208 ns 206 ns 10 +Find concat three std::string_median 205 ns 206 ns 10 +Find concat three std::string_stddev 6.54 ns 5.76 ns 10 +Find concat three std::string_cv 3.15 % 2.79 % 10 +Find concat three strexpr_mean 116 ns 115 ns 10 +Find concat three strexpr_median 115 ns 114 ns 10 +Find concat three strexpr_stddev 3.41 ns 3.45 ns 10 +Find concat three strexpr_cv 2.95 % 3.01 % 10 +Find concat three simstr_mean 22.2 ns 22.0 ns 10 +Find concat three simstr_median 22.2 ns 22.0 ns 10 +Find concat three simstr_stddev 0.690 ns 0.537 ns 10 +Find concat three simstr_cv 3.11 % 2.44 % 10 +----- Build Type Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +BuildTypeNameStr 0/0_mean 8.25 ns 8.14 ns 10 +BuildTypeNameStr 0/0_median 8.21 ns 8.11 ns 10 +BuildTypeNameStr 0/0_stddev 0.223 ns 0.273 ns 10 +BuildTypeNameStr 0/0_cv 2.71 % 3.36 % 10 +BuildTypeNameExp 0/0_mean 7.50 ns 7.50 ns 10 +BuildTypeNameExp 0/0_median 7.41 ns 7.41 ns 10 +BuildTypeNameExp 0/0_stddev 0.221 ns 0.247 ns 10 +BuildTypeNameExp 0/0_cv 2.95 % 3.29 % 10 +BuildTypeNameSim 0/0_mean 8.35 ns 8.25 ns 10 +BuildTypeNameSim 0/0_median 8.40 ns 8.37 ns 10 +BuildTypeNameSim 0/0_stddev 0.229 ns 0.218 ns 10 +BuildTypeNameSim 0/0_cv 2.75 % 2.65 % 10 +BuildTypeNameStr 10/10_mean 59.5 ns 59.1 ns 10 +BuildTypeNameStr 10/10_median 59.3 ns 59.3 ns 10 +BuildTypeNameStr 10/10_stddev 1.54 ns 1.73 ns 10 +BuildTypeNameStr 10/10_cv 2.59 % 2.93 % 10 +BuildTypeNameExp 10/10_mean 34.2 ns 34.1 ns 10 +BuildTypeNameExp 10/10_median 34.2 ns 34.1 ns 10 +BuildTypeNameExp 10/10_stddev 0.848 ns 0.708 ns 10 +BuildTypeNameExp 10/10_cv 2.48 % 2.07 % 10 +BuildTypeNameSim 10/10_mean 26.4 ns 26.0 ns 10 +BuildTypeNameSim 10/10_median 26.5 ns 26.1 ns 10 +BuildTypeNameSim 10/10_stddev 1.13 ns 1.27 ns 10 +BuildTypeNameSim 10/10_cv 4.27 % 4.91 % 10 +----- Replace string by copy -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat with replace str_mean 318 ns 316 ns 10 +Concat with replace str_median 316 ns 314 ns 10 +Concat with replace str_stddev 11.9 ns 10.4 ns 10 +Concat with replace str_cv 3.73 % 3.30 % 10 +Concat with replace exp_mean 224 ns 223 ns 10 +Concat with replace exp_median 220 ns 220 ns 10 +Concat with replace exp_stddev 8.19 ns 8.32 ns 10 +Concat with replace exp_cv 3.66 % 3.73 % 10 ----- Create Empty Str ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e;_mean 1.11 ns 1.11 ns 10 -std::string e;_median 1.11 ns 1.10 ns 10 -std::string e;_stddev 0.029 ns 0.026 ns 10 -std::string e;_cv 2.61 % 2.37 % 10 -std::string_view e;_mean 0.368 ns 0.368 ns 10 -std::string_view e;_median 0.365 ns 0.367 ns 10 -std::string_view e;_stddev 0.012 ns 0.012 ns 10 -std::string_view e;_cv 3.19 % 3.29 % 10 -ssa e;_mean 0.361 ns 0.361 ns 10 -ssa e;_median 0.360 ns 0.360 ns 10 -ssa e;_stddev 0.006 ns 0.006 ns 10 -ssa e;_cv 1.55 % 1.71 % 10 -stringa e;_mean 0.736 ns 0.732 ns 10 -stringa e;_median 0.736 ns 0.732 ns 10 -stringa e;_stddev 0.011 ns 0.016 ns 10 -stringa e;_cv 1.51 % 2.24 % 10 +std::string e;_mean 1.11 ns 1.10 ns 10 +std::string e;_median 1.10 ns 1.07 ns 10 +std::string e;_stddev 0.035 ns 0.035 ns 10 +std::string e;_cv 3.16 % 3.23 % 10 +std::string_view e;_mean 0.372 ns 0.368 ns 10 +std::string_view e;_median 0.367 ns 0.365 ns 10 +std::string_view e;_stddev 0.013 ns 0.009 ns 10 +std::string_view e;_cv 3.56 % 2.40 % 10 +ssa e;_mean 0.364 ns 0.361 ns 10 +ssa e;_median 0.365 ns 0.361 ns 10 +ssa e;_stddev 0.007 ns 0.008 ns 10 +ssa e;_cv 2.04 % 2.34 % 10 +stringa e;_mean 0.757 ns 0.749 ns 10 +stringa e;_median 0.754 ns 0.746 ns 10 +stringa e;_stddev 0.027 ns 0.021 ns 10 +stringa e;_cv 3.61 % 2.78 % 10 lstringa<20> e;_mean 1.12 ns 1.11 ns 10 -lstringa<20> e;_median 1.12 ns 1.12 ns 10 -lstringa<20> e;_stddev 0.016 ns 0.013 ns 10 -lstringa<20> e;_cv 1.39 % 1.13 % 10 -lstringa<40> e;_mean 1.13 ns 1.12 ns 10 -lstringa<40> e;_median 1.14 ns 1.12 ns 10 -lstringa<40> e;_stddev 0.027 ns 0.022 ns 10 -lstringa<40> e;_cv 2.40 % 1.96 % 10 +lstringa<20> e;_median 1.11 ns 1.12 ns 10 +lstringa<20> e;_stddev 0.035 ns 0.036 ns 10 +lstringa<20> e;_cv 3.12 % 3.22 % 10 +lstringa<40> e;_mean 1.15 ns 1.14 ns 10 +lstringa<40> e;_median 1.13 ns 1.13 ns 10 +lstringa<40> e;_stddev 0.072 ns 0.079 ns 10 +lstringa<40> e;_cv 6.27 % 6.90 % 10 ----- Create Str from short literal (9 symbols) --------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text";_mean 1.87 ns 1.86 ns 10 -std::string e = "Test text";_median 1.85 ns 1.84 ns 10 -std::string e = "Test text";_stddev 0.065 ns 0.056 ns 10 -std::string e = "Test text";_cv 3.47 % 3.04 % 10 -std::string_view e = "Test text";_mean 0.727 ns 0.722 ns 10 -std::string_view e = "Test text";_median 0.725 ns 0.715 ns 10 -std::string_view e = "Test text";_stddev 0.009 ns 0.015 ns 10 -std::string_view e = "Test text";_cv 1.26 % 2.04 % 10 -ssa e = "Test text";_mean 0.364 ns 0.363 ns 10 -ssa e = "Test text";_median 0.365 ns 0.365 ns 10 -ssa e = "Test text";_stddev 0.004 ns 0.007 ns 10 -ssa e = "Test text";_cv 1.20 % 2.03 % 10 -stringa e = "Test text";_mean 1.10 ns 1.09 ns 10 -stringa e = "Test text";_median 1.10 ns 1.10 ns 10 -stringa e = "Test text";_stddev 0.015 ns 0.016 ns 10 -stringa e = "Test text";_cv 1.36 % 1.51 % 10 -lstringa<20> e = "Test text";_mean 1.85 ns 1.85 ns 10 -lstringa<20> e = "Test text";_median 1.85 ns 1.84 ns 10 -lstringa<20> e = "Test text";_stddev 0.029 ns 0.042 ns 10 -lstringa<20> e = "Test text";_cv 1.55 % 2.25 % 10 -lstringa<40> e = "Test text";_mean 1.84 ns 1.83 ns 10 -lstringa<40> e = "Test text";_median 1.84 ns 1.82 ns 10 -lstringa<40> e = "Test text";_stddev 0.023 ns 0.034 ns 10 -lstringa<40> e = "Test text";_cv 1.26 % 1.88 % 10 +std::string e = "Test text";_mean 1.85 ns 1.82 ns 10 +std::string e = "Test text";_median 1.82 ns 1.84 ns 10 +std::string e = "Test text";_stddev 0.086 ns 0.049 ns 10 +std::string e = "Test text";_cv 4.67 % 2.69 % 10 +std::string_view e = "Test text";_mean 0.728 ns 0.722 ns 10 +std::string_view e = "Test text";_median 0.721 ns 0.724 ns 10 +std::string_view e = "Test text";_stddev 0.020 ns 0.020 ns 10 +std::string_view e = "Test text";_cv 2.79 % 2.84 % 10 +ssa e = "Test text";_mean 0.370 ns 0.367 ns 10 +ssa e = "Test text";_median 0.372 ns 0.369 ns 10 +ssa e = "Test text";_stddev 0.010 ns 0.010 ns 10 +ssa e = "Test text";_cv 2.79 % 2.68 % 10 +stringa e = "Test text";_mean 1.85 ns 1.83 ns 10 +stringa e = "Test text";_median 1.87 ns 1.82 ns 10 +stringa e = "Test text";_stddev 0.053 ns 0.044 ns 10 +stringa e = "Test text";_cv 2.84 % 2.42 % 10 +lstringa<20> e = "Test text";_mean 1.89 ns 1.86 ns 10 +lstringa<20> e = "Test text";_median 1.89 ns 1.86 ns 10 +lstringa<20> e = "Test text";_stddev 0.067 ns 0.085 ns 10 +lstringa<20> e = "Test text";_cv 3.55 % 4.60 % 10 +lstringa<40> e = "Test text";_mean 1.91 ns 1.90 ns 10 +lstringa<40> e = "Test text";_median 1.87 ns 1.86 ns 10 +lstringa<40> e = "Test text";_stddev 0.083 ns 0.082 ns 10 +lstringa<40> e = "Test text";_cv 4.36 % 4.34 % 10 ----- Create Str from long literal (30 symbols) ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "123456789012345678901234567890";_mean 78.5 ns 77.8 ns 10 -std::string e = "123456789012345678901234567890";_median 78.6 ns 78.5 ns 10 -std::string e = "123456789012345678901234567890";_stddev 0.991 ns 1.47 ns 10 -std::string e = "123456789012345678901234567890";_cv 1.26 % 1.89 % 10 -std::string_view e = "123456789012345678901234567890";_mean 0.731 ns 0.729 ns 10 -std::string_view e = "123456789012345678901234567890";_median 0.731 ns 0.724 ns 10 -std::string_view e = "123456789012345678901234567890";_stddev 0.009 ns 0.018 ns 10 -std::string_view e = "123456789012345678901234567890";_cv 1.26 % 2.47 % 10 -ssa e = "123456789012345678901234567890";_mean 0.371 ns 0.371 ns 10 -ssa e = "123456789012345678901234567890";_median 0.368 ns 0.369 ns 10 -ssa e = "123456789012345678901234567890";_stddev 0.010 ns 0.010 ns 10 -ssa e = "123456789012345678901234567890";_cv 2.79 % 2.66 % 10 -stringa e = "123456789012345678901234567890";_mean 1.12 ns 1.12 ns 10 -stringa e = "123456789012345678901234567890";_median 1.11 ns 1.12 ns 10 -stringa e = "123456789012345678901234567890";_stddev 0.014 ns 0.015 ns 10 -stringa e = "123456789012345678901234567890";_cv 1.24 % 1.31 % 10 -lstringa<20> e = "123456789012345678901234567890";_mean 80.1 ns 79.3 ns 10 -lstringa<20> e = "123456789012345678901234567890";_median 79.9 ns 79.5 ns 10 -lstringa<20> e = "123456789012345678901234567890";_stddev 1.77 ns 2.30 ns 10 -lstringa<20> e = "123456789012345678901234567890";_cv 2.21 % 2.90 % 10 -lstringa<40> e = "123456789012345678901234567890";_mean 2.53 ns 2.53 ns 10 -lstringa<40> e = "123456789012345678901234567890";_median 2.53 ns 2.55 ns 10 -lstringa<40> e = "123456789012345678901234567890";_stddev 0.016 ns 0.031 ns 10 -lstringa<40> e = "123456789012345678901234567890";_cv 0.64 % 1.21 % 10 +std::string e = "123456789012345678901234567890";_mean 74.9 ns 74.3 ns 10 +std::string e = "123456789012345678901234567890";_median 75.2 ns 75.3 ns 10 +std::string e = "123456789012345678901234567890";_stddev 2.40 ns 2.03 ns 10 +std::string e = "123456789012345678901234567890";_cv 3.20 % 2.74 % 10 +std::string_view e = "123456789012345678901234567890";_mean 0.736 ns 0.732 ns 10 +std::string_view e = "123456789012345678901234567890";_median 0.732 ns 0.732 ns 10 +std::string_view e = "123456789012345678901234567890";_stddev 0.024 ns 0.022 ns 10 +std::string_view e = "123456789012345678901234567890";_cv 3.20 % 2.97 % 10 +ssa e = "123456789012345678901234567890";_mean 0.365 ns 0.363 ns 10 +ssa e = "123456789012345678901234567890";_median 0.366 ns 0.361 ns 10 +ssa e = "123456789012345678901234567890";_stddev 0.005 ns 0.005 ns 10 +ssa e = "123456789012345678901234567890";_cv 1.27 % 1.40 % 10 +stringa e = "123456789012345678901234567890";_mean 1.85 ns 1.84 ns 10 +stringa e = "123456789012345678901234567890";_median 1.84 ns 1.84 ns 10 +stringa e = "123456789012345678901234567890";_stddev 0.051 ns 0.042 ns 10 +stringa e = "123456789012345678901234567890";_cv 2.75 % 2.30 % 10 +lstringa<20> e = "123456789012345678901234567890";_mean 76.8 ns 75.9 ns 10 +lstringa<20> e = "123456789012345678901234567890";_median 76.5 ns 76.7 ns 10 +lstringa<20> e = "123456789012345678901234567890";_stddev 1.85 ns 1.23 ns 10 +lstringa<20> e = "123456789012345678901234567890";_cv 2.40 % 1.63 % 10 +lstringa<40> e = "123456789012345678901234567890";_mean 2.53 ns 2.52 ns 10 +lstringa<40> e = "123456789012345678901234567890";_median 2.53 ns 2.51 ns 10 +lstringa<40> e = "123456789012345678901234567890";_stddev 0.065 ns 0.055 ns 10 +lstringa<40> e = "123456789012345678901234567890";_cv 2.58 % 2.20 % 10 ----- Create copy of Str with 9 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text"; auto c{e};_mean 1.85 ns 1.84 ns 10 -std::string e = "Test text"; auto c{e};_median 1.85 ns 1.84 ns 10 -std::string e = "Test text"; auto c{e};_stddev 0.023 ns 0.031 ns 10 -std::string e = "Test text"; auto c{e};_cv 1.26 % 1.68 % 10 -std::string_view e = "Test text"; auto c{e};_mean 0.370 ns 0.368 ns 10 -std::string_view e = "Test text"; auto c{e};_median 0.371 ns 0.368 ns 10 -std::string_view e = "Test text"; auto c{e};_stddev 0.006 ns 0.007 ns 10 -std::string_view e = "Test text"; auto c{e};_cv 1.65 % 1.86 % 10 -ssa e = "Test text"; auto c{e};_mean 0.370 ns 0.369 ns 10 -ssa e = "Test text"; auto c{e};_median 0.369 ns 0.369 ns 10 -ssa e = "Test text"; auto c{e};_stddev 0.003 ns 0.004 ns 10 -ssa e = "Test text"; auto c{e};_cv 0.80 % 1.02 % 10 -stringa e = "Test text"; auto c{e};_mean 1.30 ns 1.30 ns 10 -stringa e = "Test text"; auto c{e};_median 1.30 ns 1.29 ns 10 -stringa e = "Test text"; auto c{e};_stddev 0.016 ns 0.021 ns 10 -stringa e = "Test text"; auto c{e};_cv 1.22 % 1.63 % 10 -lstringa<20> e = "Test text"; auto c{e};_mean 5.25 ns 5.23 ns 10 -lstringa<20> e = "Test text"; auto c{e};_median 5.26 ns 5.23 ns 10 -lstringa<20> e = "Test text"; auto c{e};_stddev 0.108 ns 0.133 ns 10 -lstringa<20> e = "Test text"; auto c{e};_cv 2.06 % 2.54 % 10 -lstringa<40> e = "Test text"; auto c{e};_mean 5.36 ns 5.34 ns 10 -lstringa<40> e = "Test text"; auto c{e};_median 5.22 ns 5.16 ns 10 -lstringa<40> e = "Test text"; auto c{e};_stddev 0.303 ns 0.336 ns 10 -lstringa<40> e = "Test text"; auto c{e};_cv 5.65 % 6.29 % 10 +std::string e = "Test text"; auto c{e};_mean 1.87 ns 1.83 ns 10 +std::string e = "Test text"; auto c{e};_median 1.86 ns 1.81 ns 10 +std::string e = "Test text"; auto c{e};_stddev 0.059 ns 0.064 ns 10 +std::string e = "Test text"; auto c{e};_cv 3.17 % 3.52 % 10 +std::string_view e = "Test text"; auto c{e};_mean 0.368 ns 0.367 ns 10 +std::string_view e = "Test text"; auto c{e};_median 0.365 ns 0.361 ns 10 +std::string_view e = "Test text"; auto c{e};_stddev 0.010 ns 0.010 ns 10 +std::string_view e = "Test text"; auto c{e};_cv 2.64 % 2.68 % 10 +ssa e = "Test text"; auto c{e};_mean 0.375 ns 0.367 ns 10 +ssa e = "Test text"; auto c{e};_median 0.372 ns 0.360 ns 10 +ssa e = "Test text"; auto c{e};_stddev 0.017 ns 0.014 ns 10 +ssa e = "Test text"; auto c{e};_cv 4.40 % 3.85 % 10 +stringa e = "Test text"; auto c{e};_mean 1.32 ns 1.31 ns 10 +stringa e = "Test text"; auto c{e};_median 1.33 ns 1.29 ns 10 +stringa e = "Test text"; auto c{e};_stddev 0.042 ns 0.047 ns 10 +stringa e = "Test text"; auto c{e};_cv 3.17 % 3.62 % 10 +lstringa<20> e = "Test text"; auto c{e};_mean 5.30 ns 5.17 ns 10 +lstringa<20> e = "Test text"; auto c{e};_median 5.33 ns 5.16 ns 10 +lstringa<20> e = "Test text"; auto c{e};_stddev 0.187 ns 0.226 ns 10 +lstringa<20> e = "Test text"; auto c{e};_cv 3.53 % 4.38 % 10 +lstringa<40> e = "Test text"; auto c{e};_mean 5.22 ns 5.14 ns 10 +lstringa<40> e = "Test text"; auto c{e};_median 5.26 ns 5.16 ns 10 +lstringa<40> e = "Test text"; auto c{e};_stddev 0.140 ns 0.137 ns 10 +lstringa<40> e = "Test text"; auto c{e};_cv 2.68 % 2.66 % 10 ----- Create copy of Str with 30 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "123456789012345678901234567890"; auto c{e};_mean 81.7 ns 81.5 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_median 79.6 ns 79.5 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_stddev 4.61 ns 4.42 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_cv 5.64 % 5.43 % 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 0.741 ns 0.739 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_median 0.739 ns 0.741 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.013 ns 0.012 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 1.79 % 1.65 % 10 -ssa e = "123456789012345678901234567890"; auto c{e};_mean 0.368 ns 0.366 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_median 0.367 ns 0.368 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.005 ns 0.006 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_cv 1.32 % 1.54 % 10 -stringa e = "123456789012345678901234567890"; auto c{e};_mean 1.86 ns 1.85 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_median 1.85 ns 1.88 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.043 ns 0.048 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_cv 2.34 % 2.59 % 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 79.3 ns 78.8 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 79.0 ns 78.5 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 2.06 ns 2.44 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 2.60 % 3.09 % 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 4.94 ns 4.89 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 4.94 ns 4.87 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 0.150 ns 0.133 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 3.04 % 2.72 % 10 +std::string e = "123456789012345678901234567890"; auto c{e};_mean 81.3 ns 79.9 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_median 80.5 ns 78.5 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_stddev 5.02 ns 5.50 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_cv 6.17 % 6.89 % 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 0.741 ns 0.732 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_median 0.739 ns 0.725 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.016 ns 0.015 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 2.18 % 2.06 % 10 +ssa e = "123456789012345678901234567890"; auto c{e};_mean 0.362 ns 0.359 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_median 0.357 ns 0.360 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.011 ns 0.006 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_cv 2.95 % 1.72 % 10 +stringa e = "123456789012345678901234567890"; auto c{e};_mean 1.83 ns 1.81 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_median 1.81 ns 1.80 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.044 ns 0.040 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_cv 2.41 % 2.19 % 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 76.1 ns 75.9 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 75.8 ns 75.9 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 2.87 ns 3.21 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 3.77 % 4.23 % 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 4.38 ns 4.36 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 4.36 ns 4.39 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 0.073 ns 0.050 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 1.67 % 1.16 % 10 ----- Find 9 symbols text in end of 99 symbols text ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string::find;_mean 39.5 ns 39.1 ns 10 -std::string::find;_median 39.5 ns 39.2 ns 10 -std::string::find;_stddev 0.887 ns 0.867 ns 10 -std::string::find;_cv 2.24 % 2.21 % 10 -std::string_view::find;_mean 40.0 ns 39.7 ns 10 -std::string_view::find;_median 39.3 ns 39.2 ns 10 -std::string_view::find;_stddev 1.48 ns 1.25 ns 10 -std::string_view::find;_cv 3.70 % 3.15 % 10 -ssa::find;_mean 18.1 ns 18.0 ns 10 -ssa::find;_median 18.2 ns 18.0 ns 10 -ssa::find;_stddev 0.464 ns 0.543 ns 10 -ssa::find;_cv 2.56 % 3.01 % 10 -stringa::find;_mean 19.4 ns 19.4 ns 10 -stringa::find;_median 19.3 ns 19.3 ns 10 -stringa::find;_stddev 0.580 ns 0.560 ns 10 -stringa::find;_cv 2.99 % 2.89 % 10 -lstringa<20>::find;_mean 18.1 ns 18.0 ns 10 -lstringa<20>::find;_median 18.1 ns 18.0 ns 10 -lstringa<20>::find;_stddev 0.375 ns 0.382 ns 10 -lstringa<20>::find;_cv 2.08 % 2.12 % 10 -lstringa<40>::find;_mean 18.1 ns 18.0 ns 10 -lstringa<40>::find;_median 17.9 ns 17.9 ns 10 -lstringa<40>::find;_stddev 0.797 ns 0.860 ns 10 -lstringa<40>::find;_cv 4.41 % 4.79 % 10 +std::string::find;_mean 38.3 ns 38.0 ns 10 +std::string::find;_median 38.3 ns 37.7 ns 10 +std::string::find;_stddev 0.476 ns 0.585 ns 10 +std::string::find;_cv 1.24 % 1.54 % 10 +std::string_view::find;_mean 38.1 ns 37.5 ns 10 +std::string_view::find;_median 37.9 ns 37.7 ns 10 +std::string_view::find;_stddev 0.751 ns 0.660 ns 10 +std::string_view::find;_cv 1.97 % 1.76 % 10 +ssa::find;_mean 18.3 ns 18.1 ns 10 +ssa::find;_median 18.1 ns 18.0 ns 10 +ssa::find;_stddev 0.297 ns 0.345 ns 10 +ssa::find;_cv 1.63 % 1.90 % 10 +stringa::find;_mean 19.8 ns 19.6 ns 10 +stringa::find;_median 19.4 ns 19.5 ns 10 +stringa::find;_stddev 0.845 ns 0.648 ns 10 +stringa::find;_cv 4.27 % 3.31 % 10 +lstringa<20>::find;_mean 17.6 ns 17.5 ns 10 +lstringa<20>::find;_median 17.5 ns 17.4 ns 10 +lstringa<20>::find;_stddev 0.545 ns 0.397 ns 10 +lstringa<20>::find;_cv 3.10 % 2.28 % 10 +lstringa<40>::find;_mean 17.8 ns 17.5 ns 10 +lstringa<40>::find;_median 17.9 ns 17.3 ns 10 +lstringa<40>::find;_stddev 0.432 ns 0.324 ns 10 +lstringa<40>::find;_cv 2.42 % 1.85 % 10 ------- Copy not literal Str with N symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string copy{str_with_len_N};/15_mean 1.86 ns 1.86 ns 10 -std::string copy{str_with_len_N};/15_median 1.84 ns 1.84 ns 10 -std::string copy{str_with_len_N};/15_stddev 0.043 ns 0.053 ns 10 -std::string copy{str_with_len_N};/15_cv 2.33 % 2.85 % 10 -std::string copy{str_with_len_N};/16_mean 81.6 ns 81.6 ns 10 -std::string copy{str_with_len_N};/16_median 81.9 ns 82.0 ns 10 -std::string copy{str_with_len_N};/16_stddev 2.14 ns 1.98 ns 10 -std::string copy{str_with_len_N};/16_cv 2.62 % 2.43 % 10 -std::string copy{str_with_len_N};/23_mean 79.8 ns 79.5 ns 10 -std::string copy{str_with_len_N};/23_median 79.5 ns 79.5 ns 10 -std::string copy{str_with_len_N};/23_stddev 1.04 ns 1.71 ns 10 -std::string copy{str_with_len_N};/23_cv 1.31 % 2.15 % 10 -std::string copy{str_with_len_N};/24_mean 80.5 ns 80.2 ns 10 -std::string copy{str_with_len_N};/24_median 80.2 ns 80.2 ns 10 -std::string copy{str_with_len_N};/24_stddev 1.94 ns 1.84 ns 10 -std::string copy{str_with_len_N};/24_cv 2.41 % 2.29 % 10 -std::string copy{str_with_len_N};/32_mean 86.2 ns 85.8 ns 10 -std::string copy{str_with_len_N};/32_median 85.4 ns 85.4 ns 10 -std::string copy{str_with_len_N};/32_stddev 5.54 ns 4.99 ns 10 -std::string copy{str_with_len_N};/32_cv 6.43 % 5.81 % 10 -std::string copy{str_with_len_N};/64_mean 79.3 ns 79.0 ns 10 -std::string copy{str_with_len_N};/64_median 78.5 ns 78.5 ns 10 -std::string copy{str_with_len_N};/64_stddev 4.18 ns 3.49 ns 10 -std::string copy{str_with_len_N};/64_cv 5.27 % 4.42 % 10 -std::string copy{str_with_len_N};/128_mean 85.0 ns 84.8 ns 10 -std::string copy{str_with_len_N};/128_median 84.1 ns 83.7 ns 10 -std::string copy{str_with_len_N};/128_stddev 2.42 ns 2.47 ns 10 -std::string copy{str_with_len_N};/128_cv 2.84 % 2.91 % 10 -std::string copy{str_with_len_N};/256_mean 84.4 ns 84.4 ns 10 -std::string copy{str_with_len_N};/256_median 84.6 ns 84.6 ns 10 -std::string copy{str_with_len_N};/256_stddev 1.10 ns 1.22 ns 10 -std::string copy{str_with_len_N};/256_cv 1.30 % 1.44 % 10 -std::string copy{str_with_len_N};/512_mean 86.6 ns 86.2 ns 10 -std::string copy{str_with_len_N};/512_median 86.3 ns 85.8 ns 10 -std::string copy{str_with_len_N};/512_stddev 2.26 ns 1.92 ns 10 -std::string copy{str_with_len_N};/512_cv 2.61 % 2.23 % 10 -std::string copy{str_with_len_N};/1024_mean 95.3 ns 94.8 ns 10 -std::string copy{str_with_len_N};/1024_median 95.3 ns 95.2 ns 10 -std::string copy{str_with_len_N};/1024_stddev 2.25 ns 2.80 ns 10 -std::string copy{str_with_len_N};/1024_cv 2.36 % 2.95 % 10 -std::string copy{str_with_len_N};/2048_mean 127 ns 126 ns 10 -std::string copy{str_with_len_N};/2048_median 126 ns 126 ns 10 -std::string copy{str_with_len_N};/2048_stddev 3.19 ns 2.98 ns 10 -std::string copy{str_with_len_N};/2048_cv 2.51 % 2.35 % 10 -std::string copy{str_with_len_N};/4096_mean 176 ns 176 ns 10 -std::string copy{str_with_len_N};/4096_median 176 ns 176 ns 10 -std::string copy{str_with_len_N};/4096_stddev 2.80 ns 2.83 ns 10 -std::string copy{str_with_len_N};/4096_cv 1.59 % 1.61 % 10 -stringa copy{str_with_len_N};/15_mean 1.34 ns 1.31 ns 10 -stringa copy{str_with_len_N};/15_median 1.31 ns 1.30 ns 10 -stringa copy{str_with_len_N};/15_stddev 0.075 ns 0.037 ns 10 -stringa copy{str_with_len_N};/15_cv 5.62 % 2.84 % 10 -stringa copy{str_with_len_N};/16_mean 1.35 ns 1.34 ns 10 -stringa copy{str_with_len_N};/16_median 1.32 ns 1.31 ns 10 -stringa copy{str_with_len_N};/16_stddev 0.059 ns 0.058 ns 10 -stringa copy{str_with_len_N};/16_cv 4.38 % 4.32 % 10 -stringa copy{str_with_len_N};/23_mean 1.35 ns 1.34 ns 10 -stringa copy{str_with_len_N};/23_median 1.32 ns 1.33 ns 10 -stringa copy{str_with_len_N};/23_stddev 0.097 ns 0.102 ns 10 -stringa copy{str_with_len_N};/23_cv 7.18 % 7.62 % 10 -stringa copy{str_with_len_N};/24_mean 15.8 ns 15.8 ns 10 -stringa copy{str_with_len_N};/24_median 15.8 ns 15.7 ns 10 -stringa copy{str_with_len_N};/24_stddev 0.075 ns 0.147 ns 10 -stringa copy{str_with_len_N};/24_cv 0.47 % 0.93 % 10 -stringa copy{str_with_len_N};/32_mean 15.8 ns 15.8 ns 10 -stringa copy{str_with_len_N};/32_median 15.8 ns 15.7 ns 10 -stringa copy{str_with_len_N};/32_stddev 0.088 ns 0.168 ns 10 -stringa copy{str_with_len_N};/32_cv 0.56 % 1.07 % 10 -stringa copy{str_with_len_N};/64_mean 16.0 ns 16.0 ns 10 -stringa copy{str_with_len_N};/64_median 15.9 ns 16.1 ns 10 -stringa copy{str_with_len_N};/64_stddev 0.299 ns 0.198 ns 10 -stringa copy{str_with_len_N};/64_cv 1.87 % 1.24 % 10 -stringa copy{str_with_len_N};/128_mean 15.8 ns 15.8 ns 10 -stringa copy{str_with_len_N};/128_median 15.8 ns 15.7 ns 10 -stringa copy{str_with_len_N};/128_stddev 0.079 ns 0.235 ns 10 -stringa copy{str_with_len_N};/128_cv 0.50 % 1.49 % 10 -stringa copy{str_with_len_N};/256_mean 15.8 ns 15.8 ns 10 -stringa copy{str_with_len_N};/256_median 15.8 ns 15.7 ns 10 -stringa copy{str_with_len_N};/256_stddev 0.056 ns 0.180 ns 10 -stringa copy{str_with_len_N};/256_cv 0.35 % 1.14 % 10 -stringa copy{str_with_len_N};/512_mean 16.0 ns 15.9 ns 10 -stringa copy{str_with_len_N};/512_median 15.9 ns 16.0 ns 10 -stringa copy{str_with_len_N};/512_stddev 0.154 ns 0.235 ns 10 -stringa copy{str_with_len_N};/512_cv 0.96 % 1.48 % 10 -stringa copy{str_with_len_N};/1024_mean 15.9 ns 15.8 ns 10 -stringa copy{str_with_len_N};/1024_median 15.9 ns 15.7 ns 10 -stringa copy{str_with_len_N};/1024_stddev 0.181 ns 0.259 ns 10 -stringa copy{str_with_len_N};/1024_cv 1.14 % 1.63 % 10 -stringa copy{str_with_len_N};/2048_mean 16.0 ns 15.9 ns 10 -stringa copy{str_with_len_N};/2048_median 15.9 ns 16.0 ns 10 -stringa copy{str_with_len_N};/2048_stddev 0.156 ns 0.235 ns 10 -stringa copy{str_with_len_N};/2048_cv 0.98 % 1.48 % 10 +std::string copy{str_with_len_N};/15_mean 1.86 ns 1.82 ns 10 +std::string copy{str_with_len_N};/15_median 1.83 ns 1.82 ns 10 +std::string copy{str_with_len_N};/15_stddev 0.101 ns 0.052 ns 10 +std::string copy{str_with_len_N};/15_cv 5.42 % 2.85 % 10 +std::string copy{str_with_len_N};/16_mean 80.4 ns 80.0 ns 10 +std::string copy{str_with_len_N};/16_median 78.0 ns 78.5 ns 10 +std::string copy{str_with_len_N};/16_stddev 4.86 ns 5.36 ns 10 +std::string copy{str_with_len_N};/16_cv 6.04 % 6.69 % 10 +std::string copy{str_with_len_N};/23_mean 78.0 ns 77.3 ns 10 +std::string copy{str_with_len_N};/23_median 76.9 ns 76.7 ns 10 +std::string copy{str_with_len_N};/23_stddev 3.65 ns 2.73 ns 10 +std::string copy{str_with_len_N};/23_cv 4.68 % 3.54 % 10 +std::string copy{str_with_len_N};/24_mean 80.2 ns 79.3 ns 10 +std::string copy{str_with_len_N};/24_median 78.3 ns 78.5 ns 10 +std::string copy{str_with_len_N};/24_stddev 4.99 ns 5.59 ns 10 +std::string copy{str_with_len_N};/24_cv 6.22 % 7.05 % 10 +std::string copy{str_with_len_N};/32_mean 82.7 ns 82.1 ns 10 +std::string copy{str_with_len_N};/32_median 82.5 ns 82.0 ns 10 +std::string copy{str_with_len_N};/32_stddev 1.82 ns 1.29 ns 10 +std::string copy{str_with_len_N};/32_cv 2.20 % 1.57 % 10 +std::string copy{str_with_len_N};/64_mean 82.0 ns 81.6 ns 10 +std::string copy{str_with_len_N};/64_median 80.7 ns 80.2 ns 10 +std::string copy{str_with_len_N};/64_stddev 3.00 ns 2.94 ns 10 +std::string copy{str_with_len_N};/64_cv 3.66 % 3.60 % 10 +std::string copy{str_with_len_N};/128_mean 89.8 ns 87.7 ns 10 +std::string copy{str_with_len_N};/128_median 89.7 ns 87.9 ns 10 +std::string copy{str_with_len_N};/128_stddev 5.67 ns 4.46 ns 10 +std::string copy{str_with_len_N};/128_cv 6.32 % 5.09 % 10 +std::string copy{str_with_len_N};/256_mean 91.4 ns 90.5 ns 10 +std::string copy{str_with_len_N};/256_median 90.7 ns 90.7 ns 10 +std::string copy{str_with_len_N};/256_stddev 2.30 ns 1.92 ns 10 +std::string copy{str_with_len_N};/256_cv 2.52 % 2.12 % 10 +std::string copy{str_with_len_N};/512_mean 89.2 ns 88.2 ns 10 +std::string copy{str_with_len_N};/512_median 89.0 ns 87.2 ns 10 +std::string copy{str_with_len_N};/512_stddev 3.91 ns 3.41 ns 10 +std::string copy{str_with_len_N};/512_cv 4.38 % 3.86 % 10 +std::string copy{str_with_len_N};/1024_mean 96.8 ns 96.3 ns 10 +std::string copy{str_with_len_N};/1024_median 97.2 ns 96.3 ns 10 +std::string copy{str_with_len_N};/1024_stddev 3.59 ns 2.79 ns 10 +std::string copy{str_with_len_N};/1024_cv 3.71 % 2.90 % 10 +std::string copy{str_with_len_N};/2048_mean 130 ns 129 ns 10 +std::string copy{str_with_len_N};/2048_median 130 ns 128 ns 10 +std::string copy{str_with_len_N};/2048_stddev 3.80 ns 3.49 ns 10 +std::string copy{str_with_len_N};/2048_cv 2.92 % 2.70 % 10 +std::string copy{str_with_len_N};/4096_mean 178 ns 174 ns 10 +std::string copy{str_with_len_N};/4096_median 178 ns 176 ns 10 +std::string copy{str_with_len_N};/4096_stddev 5.34 ns 4.50 ns 10 +std::string copy{str_with_len_N};/4096_cv 3.01 % 2.59 % 10 +stringa copy{str_with_len_N};/15_mean 1.28 ns 1.27 ns 10 +stringa copy{str_with_len_N};/15_median 1.28 ns 1.28 ns 10 +stringa copy{str_with_len_N};/15_stddev 0.030 ns 0.033 ns 10 +stringa copy{str_with_len_N};/15_cv 2.32 % 2.57 % 10 +stringa copy{str_with_len_N};/16_mean 1.28 ns 1.28 ns 10 +stringa copy{str_with_len_N};/16_median 1.27 ns 1.27 ns 10 +stringa copy{str_with_len_N};/16_stddev 0.037 ns 0.048 ns 10 +stringa copy{str_with_len_N};/16_cv 2.87 % 3.73 % 10 +stringa copy{str_with_len_N};/23_mean 1.28 ns 1.28 ns 10 +stringa copy{str_with_len_N};/23_median 1.26 ns 1.26 ns 10 +stringa copy{str_with_len_N};/23_stddev 0.038 ns 0.035 ns 10 +stringa copy{str_with_len_N};/23_cv 3.01 % 2.74 % 10 +stringa copy{str_with_len_N};/24_mean 15.8 ns 15.6 ns 10 +stringa copy{str_with_len_N};/24_median 15.7 ns 15.7 ns 10 +stringa copy{str_with_len_N};/24_stddev 0.153 ns 0.168 ns 10 +stringa copy{str_with_len_N};/24_cv 0.97 % 1.08 % 10 +stringa copy{str_with_len_N};/32_mean 15.7 ns 15.7 ns 10 +stringa copy{str_with_len_N};/32_median 15.6 ns 15.7 ns 10 +stringa copy{str_with_len_N};/32_stddev 0.217 ns 0.233 ns 10 +stringa copy{str_with_len_N};/32_cv 1.38 % 1.48 % 10 +stringa copy{str_with_len_N};/64_mean 15.8 ns 15.7 ns 10 +stringa copy{str_with_len_N};/64_median 15.7 ns 15.7 ns 10 +stringa copy{str_with_len_N};/64_stddev 0.179 ns 0.233 ns 10 +stringa copy{str_with_len_N};/64_cv 1.13 % 1.48 % 10 +stringa copy{str_with_len_N};/128_mean 15.8 ns 15.7 ns 10 +stringa copy{str_with_len_N};/128_median 15.6 ns 15.7 ns 10 +stringa copy{str_with_len_N};/128_stddev 0.291 ns 0.233 ns 10 +stringa copy{str_with_len_N};/128_cv 1.84 % 1.48 % 10 +stringa copy{str_with_len_N};/256_mean 15.7 ns 15.7 ns 10 +stringa copy{str_with_len_N};/256_median 15.6 ns 15.7 ns 10 +stringa copy{str_with_len_N};/256_stddev 0.194 ns 0.257 ns 10 +stringa copy{str_with_len_N};/256_cv 1.23 % 1.64 % 10 +stringa copy{str_with_len_N};/512_mean 15.7 ns 15.7 ns 10 +stringa copy{str_with_len_N};/512_median 15.7 ns 15.7 ns 10 +stringa copy{str_with_len_N};/512_stddev 0.185 ns 0.198 ns 10 +stringa copy{str_with_len_N};/512_cv 1.17 % 1.26 % 10 +stringa copy{str_with_len_N};/1024_mean 15.7 ns 15.7 ns 10 +stringa copy{str_with_len_N};/1024_median 15.7 ns 15.7 ns 10 +stringa copy{str_with_len_N};/1024_stddev 0.207 ns 0.110 ns 10 +stringa copy{str_with_len_N};/1024_cv 1.32 % 0.70 % 10 +stringa copy{str_with_len_N};/2048_mean 15.9 ns 15.8 ns 10 +stringa copy{str_with_len_N};/2048_median 15.8 ns 15.7 ns 10 +stringa copy{str_with_len_N};/2048_stddev 0.321 ns 0.218 ns 10 +stringa copy{str_with_len_N};/2048_cv 2.02 % 1.38 % 10 stringa copy{str_with_len_N};/4096_mean 15.9 ns 15.8 ns 10 stringa copy{str_with_len_N};/4096_median 15.9 ns 15.7 ns 10 -stringa copy{str_with_len_N};/4096_stddev 0.074 ns 0.235 ns 10 -stringa copy{str_with_len_N};/4096_cv 0.47 % 1.49 % 10 -lstringa<16> copy{str_with_len_N};/15_mean 4.96 ns 4.94 ns 10 -lstringa<16> copy{str_with_len_N};/15_median 4.93 ns 4.92 ns 10 -lstringa<16> copy{str_with_len_N};/15_stddev 0.114 ns 0.138 ns 10 -lstringa<16> copy{str_with_len_N};/15_cv 2.29 % 2.79 % 10 -lstringa<16> copy{str_with_len_N};/16_mean 4.87 ns 4.85 ns 10 -lstringa<16> copy{str_with_len_N};/16_median 4.91 ns 4.87 ns 10 -lstringa<16> copy{str_with_len_N};/16_stddev 0.137 ns 0.108 ns 10 -lstringa<16> copy{str_with_len_N};/16_cv 2.81 % 2.21 % 10 -lstringa<16> copy{str_with_len_N};/23_mean 4.98 ns 4.96 ns 10 -lstringa<16> copy{str_with_len_N};/23_median 4.94 ns 4.97 ns 10 -lstringa<16> copy{str_with_len_N};/23_stddev 0.096 ns 0.129 ns 10 -lstringa<16> copy{str_with_len_N};/23_cv 1.93 % 2.61 % 10 -lstringa<16> copy{str_with_len_N};/24_mean 84.0 ns 83.9 ns 10 -lstringa<16> copy{str_with_len_N};/24_median 83.8 ns 83.7 ns 10 -lstringa<16> copy{str_with_len_N};/24_stddev 2.44 ns 1.53 ns 10 -lstringa<16> copy{str_with_len_N};/24_cv 2.91 % 1.82 % 10 -lstringa<16> copy{str_with_len_N};/32_mean 88.0 ns 87.2 ns 10 -lstringa<16> copy{str_with_len_N};/32_median 87.9 ns 87.2 ns 10 -lstringa<16> copy{str_with_len_N};/32_stddev 2.59 ns 2.01 ns 10 -lstringa<16> copy{str_with_len_N};/32_cv 2.94 % 2.31 % 10 -lstringa<16> copy{str_with_len_N};/64_mean 84.8 ns 84.6 ns 10 -lstringa<16> copy{str_with_len_N};/64_median 84.0 ns 83.7 ns 10 -lstringa<16> copy{str_with_len_N};/64_stddev 2.97 ns 2.76 ns 10 -lstringa<16> copy{str_with_len_N};/64_cv 3.50 % 3.26 % 10 -lstringa<16> copy{str_with_len_N};/128_mean 85.1 ns 84.4 ns 10 -lstringa<16> copy{str_with_len_N};/128_median 85.4 ns 83.7 ns 10 -lstringa<16> copy{str_with_len_N};/128_stddev 1.92 ns 1.87 ns 10 -lstringa<16> copy{str_with_len_N};/128_cv 2.25 % 2.22 % 10 -lstringa<16> copy{str_with_len_N};/256_mean 88.2 ns 87.3 ns 10 -lstringa<16> copy{str_with_len_N};/256_median 87.0 ns 85.8 ns 10 -lstringa<16> copy{str_with_len_N};/256_stddev 3.01 ns 2.62 ns 10 -lstringa<16> copy{str_with_len_N};/256_cv 3.41 % 3.00 % 10 -lstringa<16> copy{str_with_len_N};/512_mean 89.4 ns 89.1 ns 10 -lstringa<16> copy{str_with_len_N};/512_median 89.5 ns 88.9 ns 10 -lstringa<16> copy{str_with_len_N};/512_stddev 1.33 ns 1.53 ns 10 -lstringa<16> copy{str_with_len_N};/512_cv 1.48 % 1.71 % 10 -lstringa<16> copy{str_with_len_N};/1024_mean 101 ns 100 ns 10 -lstringa<16> copy{str_with_len_N};/1024_median 100 ns 99.4 ns 10 -lstringa<16> copy{str_with_len_N};/1024_stddev 4.92 ns 4.78 ns 10 -lstringa<16> copy{str_with_len_N};/1024_cv 4.89 % 4.77 % 10 -lstringa<16> copy{str_with_len_N};/2048_mean 131 ns 130 ns 10 -lstringa<16> copy{str_with_len_N};/2048_median 129 ns 129 ns 10 -lstringa<16> copy{str_with_len_N};/2048_stddev 5.79 ns 4.73 ns 10 -lstringa<16> copy{str_with_len_N};/2048_cv 4.42 % 3.64 % 10 -lstringa<16> copy{str_with_len_N};/4096_mean 194 ns 193 ns 10 -lstringa<16> copy{str_with_len_N};/4096_median 193 ns 190 ns 10 -lstringa<16> copy{str_with_len_N};/4096_stddev 8.46 ns 6.50 ns 10 -lstringa<16> copy{str_with_len_N};/4096_cv 4.35 % 3.37 % 10 -lstringa<512> copy{str_with_len_N};/15_mean 4.94 ns 4.89 ns 10 -lstringa<512> copy{str_with_len_N};/15_median 4.86 ns 4.84 ns 10 -lstringa<512> copy{str_with_len_N};/15_stddev 0.198 ns 0.105 ns 10 -lstringa<512> copy{str_with_len_N};/15_cv 4.00 % 2.16 % 10 -lstringa<512> copy{str_with_len_N};/16_mean 5.36 ns 5.36 ns 10 -lstringa<512> copy{str_with_len_N};/16_median 5.22 ns 5.23 ns 10 -lstringa<512> copy{str_with_len_N};/16_stddev 0.444 ns 0.442 ns 10 -lstringa<512> copy{str_with_len_N};/16_cv 8.29 % 8.25 % 10 -lstringa<512> copy{str_with_len_N};/23_mean 5.05 ns 5.05 ns 10 -lstringa<512> copy{str_with_len_N};/23_median 4.92 ns 4.87 ns 10 -lstringa<512> copy{str_with_len_N};/23_stddev 0.343 ns 0.371 ns 10 -lstringa<512> copy{str_with_len_N};/23_cv 6.79 % 7.35 % 10 -lstringa<512> copy{str_with_len_N};/24_mean 4.83 ns 4.79 ns 10 -lstringa<512> copy{str_with_len_N};/24_median 4.81 ns 4.74 ns 10 -lstringa<512> copy{str_with_len_N};/24_stddev 0.153 ns 0.162 ns 10 -lstringa<512> copy{str_with_len_N};/24_cv 3.17 % 3.38 % 10 -lstringa<512> copy{str_with_len_N};/32_mean 7.94 ns 7.85 ns 10 -lstringa<512> copy{str_with_len_N};/32_median 7.84 ns 7.85 ns 10 -lstringa<512> copy{str_with_len_N};/32_stddev 0.269 ns 0.201 ns 10 -lstringa<512> copy{str_with_len_N};/32_cv 3.38 % 2.57 % 10 -lstringa<512> copy{str_with_len_N};/64_mean 7.92 ns 7.90 ns 10 -lstringa<512> copy{str_with_len_N};/64_median 7.92 ns 7.85 ns 10 -lstringa<512> copy{str_with_len_N};/64_stddev 0.170 ns 0.202 ns 10 -lstringa<512> copy{str_with_len_N};/64_cv 2.15 % 2.56 % 10 -lstringa<512> copy{str_with_len_N};/128_mean 8.26 ns 8.20 ns 10 -lstringa<512> copy{str_with_len_N};/128_median 8.28 ns 8.20 ns 10 -lstringa<512> copy{str_with_len_N};/128_stddev 0.103 ns 0.164 ns 10 -lstringa<512> copy{str_with_len_N};/128_cv 1.24 % 2.01 % 10 -lstringa<512> copy{str_with_len_N};/256_mean 9.31 ns 9.25 ns 10 -lstringa<512> copy{str_with_len_N};/256_median 9.35 ns 9.21 ns 10 -lstringa<512> copy{str_with_len_N};/256_stddev 0.178 ns 0.165 ns 10 -lstringa<512> copy{str_with_len_N};/256_cv 1.91 % 1.78 % 10 -lstringa<512> copy{str_with_len_N};/512_mean 10.9 ns 10.9 ns 10 -lstringa<512> copy{str_with_len_N};/512_median 10.9 ns 11.0 ns 10 -lstringa<512> copy{str_with_len_N};/512_stddev 0.211 ns 0.206 ns 10 -lstringa<512> copy{str_with_len_N};/512_cv 1.93 % 1.89 % 10 -lstringa<512> copy{str_with_len_N};/1024_mean 99.0 ns 98.8 ns 10 -lstringa<512> copy{str_with_len_N};/1024_median 99.0 ns 98.4 ns 10 -lstringa<512> copy{str_with_len_N};/1024_stddev 2.55 ns 2.93 ns 10 -lstringa<512> copy{str_with_len_N};/1024_cv 2.58 % 2.96 % 10 -lstringa<512> copy{str_with_len_N};/2048_mean 131 ns 129 ns 10 -lstringa<512> copy{str_with_len_N};/2048_median 129 ns 128 ns 10 -lstringa<512> copy{str_with_len_N};/2048_stddev 4.28 ns 4.59 ns 10 -lstringa<512> copy{str_with_len_N};/2048_cv 3.27 % 3.55 % 10 -lstringa<512> copy{str_with_len_N};/4096_mean 191 ns 191 ns 10 -lstringa<512> copy{str_with_len_N};/4096_median 188 ns 188 ns 10 -lstringa<512> copy{str_with_len_N};/4096_stddev 9.77 ns 10.7 ns 10 -lstringa<512> copy{str_with_len_N};/4096_cv 5.12 % 5.59 % 10 +stringa copy{str_with_len_N};/4096_stddev 0.198 ns 0.331 ns 10 +stringa copy{str_with_len_N};/4096_cv 1.24 % 2.09 % 10 +lstringa<16> copy{str_with_len_N};/15_mean 4.88 ns 4.85 ns 10 +lstringa<16> copy{str_with_len_N};/15_median 4.77 ns 4.71 ns 10 +lstringa<16> copy{str_with_len_N};/15_stddev 0.247 ns 0.267 ns 10 +lstringa<16> copy{str_with_len_N};/15_cv 5.07 % 5.49 % 10 +lstringa<16> copy{str_with_len_N};/16_mean 4.78 ns 4.76 ns 10 +lstringa<16> copy{str_with_len_N};/16_median 4.74 ns 4.75 ns 10 +lstringa<16> copy{str_with_len_N};/16_stddev 0.183 ns 0.181 ns 10 +lstringa<16> copy{str_with_len_N};/16_cv 3.82 % 3.80 % 10 +lstringa<16> copy{str_with_len_N};/23_mean 4.80 ns 4.76 ns 10 +lstringa<16> copy{str_with_len_N};/23_median 4.73 ns 4.71 ns 10 +lstringa<16> copy{str_with_len_N};/23_stddev 0.159 ns 0.123 ns 10 +lstringa<16> copy{str_with_len_N};/23_cv 3.31 % 2.59 % 10 +lstringa<16> copy{str_with_len_N};/24_mean 76.9 ns 76.4 ns 10 +lstringa<16> copy{str_with_len_N};/24_median 75.5 ns 75.0 ns 10 +lstringa<16> copy{str_with_len_N};/24_stddev 2.76 ns 1.98 ns 10 +lstringa<16> copy{str_with_len_N};/24_cv 3.59 % 2.59 % 10 +lstringa<16> copy{str_with_len_N};/32_mean 80.5 ns 79.7 ns 10 +lstringa<16> copy{str_with_len_N};/32_median 80.5 ns 79.3 ns 10 +lstringa<16> copy{str_with_len_N};/32_stddev 4.29 ns 3.49 ns 10 +lstringa<16> copy{str_with_len_N};/32_cv 5.33 % 4.38 % 10 +lstringa<16> copy{str_with_len_N};/64_mean 81.7 ns 80.6 ns 10 +lstringa<16> copy{str_with_len_N};/64_median 81.0 ns 81.1 ns 10 +lstringa<16> copy{str_with_len_N};/64_stddev 3.42 ns 3.37 ns 10 +lstringa<16> copy{str_with_len_N};/64_cv 4.18 % 4.18 % 10 +lstringa<16> copy{str_with_len_N};/128_mean 81.6 ns 81.0 ns 10 +lstringa<16> copy{str_with_len_N};/128_median 81.4 ns 81.6 ns 10 +lstringa<16> copy{str_with_len_N};/128_stddev 3.00 ns 3.42 ns 10 +lstringa<16> copy{str_with_len_N};/128_cv 3.68 % 4.23 % 10 +lstringa<16> copy{str_with_len_N};/256_mean 83.0 ns 82.4 ns 10 +lstringa<16> copy{str_with_len_N};/256_median 82.3 ns 81.6 ns 10 +lstringa<16> copy{str_with_len_N};/256_stddev 3.27 ns 3.85 ns 10 +lstringa<16> copy{str_with_len_N};/256_cv 3.94 % 4.66 % 10 +lstringa<16> copy{str_with_len_N};/512_mean 87.0 ns 87.0 ns 10 +lstringa<16> copy{str_with_len_N};/512_median 85.9 ns 85.4 ns 10 +lstringa<16> copy{str_with_len_N};/512_stddev 3.56 ns 3.72 ns 10 +lstringa<16> copy{str_with_len_N};/512_cv 4.09 % 4.27 % 10 +lstringa<16> copy{str_with_len_N};/1024_mean 96.8 ns 95.8 ns 10 +lstringa<16> copy{str_with_len_N};/1024_median 95.4 ns 94.2 ns 10 +lstringa<16> copy{str_with_len_N};/1024_stddev 4.63 ns 4.61 ns 10 +lstringa<16> copy{str_with_len_N};/1024_cv 4.78 % 4.81 % 10 +lstringa<16> copy{str_with_len_N};/2048_mean 133 ns 132 ns 10 +lstringa<16> copy{str_with_len_N};/2048_median 132 ns 130 ns 10 +lstringa<16> copy{str_with_len_N};/2048_stddev 11.8 ns 10.4 ns 10 +lstringa<16> copy{str_with_len_N};/2048_cv 8.86 % 7.88 % 10 +lstringa<16> copy{str_with_len_N};/4096_mean 195 ns 193 ns 10 +lstringa<16> copy{str_with_len_N};/4096_median 196 ns 193 ns 10 +lstringa<16> copy{str_with_len_N};/4096_stddev 8.89 ns 9.82 ns 10 +lstringa<16> copy{str_with_len_N};/4096_cv 4.57 % 5.08 % 10 +lstringa<512> copy{str_with_len_N};/15_mean 5.12 ns 5.11 ns 10 +lstringa<512> copy{str_with_len_N};/15_median 5.09 ns 5.00 ns 10 +lstringa<512> copy{str_with_len_N};/15_stddev 0.139 ns 0.166 ns 10 +lstringa<512> copy{str_with_len_N};/15_cv 2.72 % 3.24 % 10 +lstringa<512> copy{str_with_len_N};/16_mean 5.09 ns 5.06 ns 10 +lstringa<512> copy{str_with_len_N};/16_median 5.05 ns 5.00 ns 10 +lstringa<512> copy{str_with_len_N};/16_stddev 0.123 ns 0.109 ns 10 +lstringa<512> copy{str_with_len_N};/16_cv 2.42 % 2.16 % 10 +lstringa<512> copy{str_with_len_N};/23_mean 5.25 ns 5.12 ns 10 +lstringa<512> copy{str_with_len_N};/23_median 5.12 ns 5.08 ns 10 +lstringa<512> copy{str_with_len_N};/23_stddev 0.292 ns 0.127 ns 10 +lstringa<512> copy{str_with_len_N};/23_cv 5.57 % 2.48 % 10 +lstringa<512> copy{str_with_len_N};/24_mean 5.15 ns 5.12 ns 10 +lstringa<512> copy{str_with_len_N};/24_median 5.09 ns 5.09 ns 10 +lstringa<512> copy{str_with_len_N};/24_stddev 0.157 ns 0.162 ns 10 +lstringa<512> copy{str_with_len_N};/24_cv 3.05 % 3.16 % 10 +lstringa<512> copy{str_with_len_N};/32_mean 7.92 ns 7.87 ns 10 +lstringa<512> copy{str_with_len_N};/32_median 7.92 ns 7.95 ns 10 +lstringa<512> copy{str_with_len_N};/32_stddev 0.109 ns 0.176 ns 10 +lstringa<512> copy{str_with_len_N};/32_cv 1.37 % 2.24 % 10 +lstringa<512> copy{str_with_len_N};/64_mean 7.99 ns 7.93 ns 10 +lstringa<512> copy{str_with_len_N};/64_median 7.92 ns 7.93 ns 10 +lstringa<512> copy{str_with_len_N};/64_stddev 0.222 ns 0.206 ns 10 +lstringa<512> copy{str_with_len_N};/64_cv 2.77 % 2.59 % 10 +lstringa<512> copy{str_with_len_N};/128_mean 8.43 ns 8.32 ns 10 +lstringa<512> copy{str_with_len_N};/128_median 8.35 ns 8.28 ns 10 +lstringa<512> copy{str_with_len_N};/128_stddev 0.256 ns 0.233 ns 10 +lstringa<512> copy{str_with_len_N};/128_cv 3.03 % 2.80 % 10 +lstringa<512> copy{str_with_len_N};/256_mean 9.40 ns 9.37 ns 10 +lstringa<512> copy{str_with_len_N};/256_median 9.36 ns 9.42 ns 10 +lstringa<512> copy{str_with_len_N};/256_stddev 0.193 ns 0.276 ns 10 +lstringa<512> copy{str_with_len_N};/256_cv 2.05 % 2.94 % 10 +lstringa<512> copy{str_with_len_N};/512_mean 12.3 ns 12.3 ns 10 +lstringa<512> copy{str_with_len_N};/512_median 12.1 ns 12.0 ns 10 +lstringa<512> copy{str_with_len_N};/512_stddev 1.24 ns 1.32 ns 10 +lstringa<512> copy{str_with_len_N};/512_cv 10.08 % 10.73 % 10 +lstringa<512> copy{str_with_len_N};/1024_mean 94.1 ns 94.0 ns 10 +lstringa<512> copy{str_with_len_N};/1024_median 94.1 ns 94.2 ns 10 +lstringa<512> copy{str_with_len_N};/1024_stddev 2.92 ns 3.48 ns 10 +lstringa<512> copy{str_with_len_N};/1024_cv 3.11 % 3.70 % 10 +lstringa<512> copy{str_with_len_N};/2048_mean 128 ns 127 ns 10 +lstringa<512> copy{str_with_len_N};/2048_median 127 ns 126 ns 10 +lstringa<512> copy{str_with_len_N};/2048_stddev 5.72 ns 5.14 ns 10 +lstringa<512> copy{str_with_len_N};/2048_cv 4.46 % 4.05 % 10 +lstringa<512> copy{str_with_len_N};/4096_mean 181 ns 180 ns 10 +lstringa<512> copy{str_with_len_N};/4096_median 180 ns 180 ns 10 +lstringa<512> copy{str_with_len_N};/4096_stddev 4.69 ns 3.66 ns 10 +lstringa<512> copy{str_with_len_N};/4096_cv 2.60 % 2.04 % 10 ----- Convert to int '1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_mean 31.7 ns 31.7 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 31.3 ns 31.4 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 0.742 ns 0.819 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 2.34 % 2.59 % 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 13.9 ns 13.9 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 14.0 ns 13.8 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.275 ns 0.212 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 1.97 % 1.52 % 10 -stringa s = "123456789"; int res = s.to_int_mean 14.3 ns 14.2 ns 10 -stringa s = "123456789"; int res = s.to_int_median 14.2 ns 14.1 ns 10 -stringa s = "123456789"; int res = s.to_int_stddev 0.300 ns 0.199 ns 10 -stringa s = "123456789"; int res = s.to_int_cv 2.09 % 1.40 % 10 -ssa s = "123456789"; int res = s.to_int_mean 13.0 ns 12.9 ns 10 -ssa s = "123456789"; int res = s.to_int_median 13.0 ns 13.1 ns 10 -ssa s = "123456789"; int res = s.to_int_stddev 0.259 ns 0.399 ns 10 -ssa s = "123456789"; int res = s.to_int_cv 1.99 % 3.08 % 10 -lstringa<20> s = "123456789"; int res = s.to_int_mean 13.4 ns 13.4 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_median 13.4 ns 13.4 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_stddev 0.213 ns 0.206 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_cv 1.59 % 1.54 % 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_mean 30.8 ns 30.7 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 30.6 ns 30.8 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 0.714 ns 0.877 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 2.32 % 2.86 % 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 13.5 ns 13.4 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 13.3 ns 13.3 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.465 ns 0.535 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 3.44 % 3.99 % 10 +stringa s = "123456789"; int res = s.to_int_mean 14.1 ns 14.1 ns 10 +stringa s = "123456789"; int res = s.to_int_median 14.1 ns 14.0 ns 10 +stringa s = "123456789"; int res = s.to_int_stddev 0.277 ns 0.328 ns 10 +stringa s = "123456789"; int res = s.to_int_cv 1.96 % 2.32 % 10 +ssa s = "123456789"; int res = s.to_int_mean 13.5 ns 13.4 ns 10 +ssa s = "123456789"; int res = s.to_int_median 13.3 ns 13.2 ns 10 +ssa s = "123456789"; int res = s.to_int_stddev 0.612 ns 0.607 ns 10 +ssa s = "123456789"; int res = s.to_int_cv 4.54 % 4.51 % 10 +lstringa<20> s = "123456789"; int res = s.to_int_mean 13.6 ns 13.6 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_median 13.3 ns 13.4 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_stddev 0.588 ns 0.706 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_cv 4.32 % 5.19 % 10 ----- Convert to unsigned 'abcDef' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 34.5 ns 34.4 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 34.3 ns 34.1 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 1.05 ns 1.09 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 3.05 % 3.17 % 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 8.49 ns 8.49 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 8.36 ns 8.37 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 0.358 ns 0.339 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 4.22 % 4.00 % 10 -stringa s = "abcDef"; int res = s.to_int_mean 12.3 ns 12.3 ns 10 -stringa s = "abcDef"; int res = s.to_int_median 12.3 ns 12.3 ns 10 -stringa s = "abcDef"; int res = s.to_int_stddev 0.225 ns 0.277 ns 10 -stringa s = "abcDef"; int res = s.to_int_cv 1.82 % 2.25 % 10 -ssa s = "abcDef"; int res = s.to_int_mean 12.0 ns 12.0 ns 10 -ssa s = "abcDef"; int res = s.to_int_median 12.0 ns 12.0 ns 10 -ssa s = "abcDef"; int res = s.to_int_stddev 0.244 ns 0.334 ns 10 -ssa s = "abcDef"; int res = s.to_int_cv 2.03 % 2.79 % 10 -lstringa<20> s = "abcDef"; int res = s.to_int_mean 11.8 ns 11.8 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_median 11.8 ns 11.7 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_stddev 0.236 ns 0.232 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_cv 2.00 % 1.96 % 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 33.5 ns 33.2 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 33.0 ns 33.0 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 0.985 ns 1.04 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 2.94 % 3.13 % 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 8.14 ns 8.06 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 8.04 ns 8.02 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 0.214 ns 0.160 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 2.62 % 1.99 % 10 +stringa s = "abcDef"; int res = s.to_int_mean 13.9 ns 13.8 ns 10 +stringa s = "abcDef"; int res = s.to_int_median 13.8 ns 13.8 ns 10 +stringa s = "abcDef"; int res = s.to_int_stddev 0.259 ns 0.362 ns 10 +stringa s = "abcDef"; int res = s.to_int_cv 1.86 % 2.62 % 10 +ssa s = "abcDef"; int res = s.to_int_mean 12.6 ns 12.5 ns 10 +ssa s = "abcDef"; int res = s.to_int_median 12.6 ns 12.6 ns 10 +ssa s = "abcDef"; int res = s.to_int_stddev 0.114 ns 0.256 ns 10 +ssa s = "abcDef"; int res = s.to_int_cv 0.90 % 2.05 % 10 +lstringa<20> s = "abcDef"; int res = s.to_int_mean 11.8 ns 11.7 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_median 11.8 ns 11.6 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_stddev 0.147 ns 0.152 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_cv 1.25 % 1.30 % 10 ----- Convert to int ' 1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_mean 44.1 ns 44.1 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 44.3 ns 44.3 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 0.602 ns 0.596 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 1.37 % 1.35 % 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 17.2 ns 17.1 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 17.1 ns 17.1 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 0.253 ns 0.384 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 1.48 % 2.24 % 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 16.6 ns 16.6 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 16.7 ns 16.7 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.317 ns 0.294 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 1.91 % 1.77 % 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_mean 43.6 ns 43.1 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 43.2 ns 42.8 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 1.36 ns 1.39 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 3.13 % 3.22 % 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 18.2 ns 18.1 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 18.3 ns 18.0 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 0.318 ns 0.432 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 1.74 % 2.39 % 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 16.2 ns 16.0 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 16.1 ns 15.9 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.478 ns 0.403 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 2.96 % 2.51 % 10 ----- Convert to double '1234.567e10' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 103 ns 103 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_median 102 ns 101 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 7.72 ns 7.23 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 7.50 % 7.03 % 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 62.8 ns 62.4 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 62.5 ns 62.8 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 1.33 ns 0.942 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 2.11 % 1.51 % 10 -ssa s = "1234.567e10"; double res = *s.to_double()_mean 35.7 ns 35.5 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_median 35.7 ns 35.3 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_stddev 0.654 ns 0.930 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_cv 1.83 % 2.62 % 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 98.3 ns 96.9 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_median 96.7 ns 97.7 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 4.06 ns 2.32 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 4.13 % 2.39 % 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 59.2 ns 58.6 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 58.5 ns 57.8 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 2.00 ns 1.69 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 3.38 % 2.88 % 10 +ssa s = "1234.567e10"; double res = *s.to_double()_mean 35.1 ns 34.9 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_median 34.6 ns 34.4 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_stddev 1.29 ns 0.980 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_cv 3.69 % 2.80 % 10 -- Append const literal of 16 bytes 64 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << "abbaabbaabbaabba";_mean 4774 ns 4764 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_median 4766 ns 4754 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 89.3 ns 111 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_cv 1.87 % 2.34 % 10 -std::string str; ... str += "abbaabbaabbaabba";_mean 1084 ns 1084 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_median 1077 ns 1074 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_stddev 40.2 ns 36.8 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_cv 3.71 % 3.39 % 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 767 ns 760 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_median 770 ns 767 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 14.5 ns 18.7 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 1.88 % 2.47 % 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 391 ns 388 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_median 391 ns 391 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 7.56 ns 8.65 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 1.93 % 2.23 % 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 246 ns 244 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_median 246 ns 246 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 3.78 ns 5.29 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 1.54 % 2.17 % 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 154 ns 154 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_median 155 ns 153 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 1.31 ns 2.75 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_cv 0.84 % 1.78 % 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_mean 4661 ns 4604 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_median 4646 ns 4604 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 86.0 ns 69.8 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_cv 1.85 % 1.52 % 10 +std::string str; ... str += "abbaabbaabbaabba";_mean 1070 ns 1062 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_median 1061 ns 1050 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_stddev 25.8 ns 20.7 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_cv 2.41 % 1.95 % 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 736 ns 727 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_median 739 ns 725 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 20.0 ns 13.9 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 2.72 % 1.91 % 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 396 ns 392 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_median 394 ns 392 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 11.0 ns 7.12 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 2.77 % 1.81 % 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 234 ns 233 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_median 233 ns 233 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 4.95 ns 4.45 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 2.11 % 1.91 % 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 155 ns 153 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_median 154 ns 153 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 2.64 ns 2.75 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_cv 1.71 % 1.80 % 10 -- Append string of 16 bytes and const literal of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 4816 ns 4792 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 4636 ns 4604 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 332 ns 330 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 6.89 % 6.89 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 3968 ns 3964 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_median 3901 ns 3908 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 208 ns 201 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 5.25 % 5.06 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 796 ns 795 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 784 ns 785 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 42.4 ns 41.3 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.33 % 5.19 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 492 ns 488 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 495 ns 497 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 12.2 ns 13.9 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 2.48 % 2.85 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 315 ns 313 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 312 ns 315 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 6.54 ns 8.32 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 2.08 % 2.65 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 216 ns 216 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 215 ns 213 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 6.84 ns 7.47 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 3.16 % 3.46 % 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 4793 ns 4734 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 4773 ns 4703 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 281 ns 277 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 5.87 % 5.86 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 3861 ns 3819 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_median 3863 ns 3749 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 133 ns 135 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 3.44 % 3.54 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 726 ns 713 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 720 ns 711 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 42.3 ns 18.0 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.83 % 2.52 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 440 ns 436 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 436 ns 439 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 12.2 ns 8.24 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 2.77 % 1.89 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 287 ns 285 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 284 ns 283 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 6.55 ns 4.39 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 2.28 % 1.54 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 183 ns 181 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 181 ns 180 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 3.10 ns 4.43 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 1.70 % 2.45 % 10 -- Append string of 16 bytes and const literal of 16 bytes 2048 times, 65536 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 219773 ns 219238 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 220812 ns 219727 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 3604 ns 4275 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 1.64 % 1.95 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 193770 ns 192540 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 193717 ns 192540 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 2500 ns 3418 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 1.29 % 1.77 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 19446 ns 19378 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 19194 ns 19043 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 875 ns 861 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 4.50 % 4.44 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 19410 ns 19088 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 19386 ns 19043 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 999 ns 543 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 5.15 % 2.84 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 18772 ns 18725 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 18677 ns 18589 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 425 ns 526 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.26 % 2.81 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 18557 ns 18492 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 18539 ns 18415 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 386 ns 566 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.08 % 3.06 % 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 221750 ns 219004 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 218930 ns 215377 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 12107 ns 12101 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 5.46 % 5.53 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 194313 ns 192252 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 189899 ns 190438 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 8351 ns 8865 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 4.30 % 4.61 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 17965 ns 17878 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 17710 ns 17648 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 662 ns 682 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.69 % 3.81 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 17021 ns 16919 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 16966 ns 16881 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 348 ns 494 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.05 % 2.92 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 16893 ns 16766 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 16799 ns 16881 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 703 ns 573 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 4.16 % 3.42 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 16257 ns 16183 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 16080 ns 16044 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 357 ns 441 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.20 % 2.73 % 10 -- Append 2 string of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var1 << str_var2;_mean 4503 ns 4489 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_median 4429 ns 4395 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_stddev 216 ns 234 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_cv 4.79 % 5.21 % 10 -std::string str; ... str += str_var1 + str_var2;_mean 4062 ns 4037 ns 10 -std::string str; ... str += str_var1 + str_var2;_median 4023 ns 4011 ns 10 -std::string str; ... str += str_var1 + str_var2;_stddev 89.1 ns 71.8 ns 10 -std::string str; ... str += str_var1 + str_var2;_cv 2.19 % 1.78 % 10 -lstringa<16> str; ... str += str_var1 + str_var2;_mean 842 ns 841 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_median 840 ns 837 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_stddev 16.3 ns 19.2 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_cv 1.94 % 2.29 % 10 -lstringa<128> str; ... str += str_var1 + str_var2;_mean 546 ns 543 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_median 539 ns 530 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_stddev 22.6 ns 22.3 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_cv 4.14 % 4.10 % 10 -lstringa<512> str; ... str += str_var1 + str_var2;_mean 416 ns 414 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_median 412 ns 417 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_stddev 13.2 ns 14.9 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_cv 3.18 % 3.61 % 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_mean 311 ns 308 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_median 312 ns 302 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 16.6 ns 16.9 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_cv 5.34 % 5.48 % 10 +std::stringstream str; ... str << str_var1 << str_var2;_mean 4399 ns 4336 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_median 4368 ns 4297 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_stddev 109 ns 105 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_cv 2.49 % 2.42 % 10 +std::string str; ... str += str_var1 + str_var2;_mean 3920 ns 3884 ns 10 +std::string str; ... str += str_var1 + str_var2;_median 3858 ns 3850 ns 10 +std::string str; ... str += str_var1 + str_var2;_stddev 188 ns 138 ns 10 +std::string str; ... str += str_var1 + str_var2;_cv 4.80 % 3.55 % 10 +lstringa<16> str; ... str += str_var1 + str_var2;_mean 817 ns 807 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_median 803 ns 802 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_stddev 38.0 ns 35.9 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_cv 4.65 % 4.44 % 10 +lstringa<128> str; ... str += str_var1 + str_var2;_mean 545 ns 542 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_median 545 ns 539 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_stddev 13.7 ns 12.9 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_cv 2.52 % 2.37 % 10 +lstringa<512> str; ... str += str_var1 + str_var2;_mean 381 ns 375 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_median 383 ns 369 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_stddev 12.9 ns 13.1 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_cv 3.39 % 3.50 % 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_mean 284 ns 277 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_median 284 ns 276 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 5.92 ns 7.52 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_cv 2.09 % 2.71 % 10 -- Append text, number, text --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; str << "test = " << k << " times";_mean 10976 ns 10938 ns 10 -std::stringstream str; str << "test = " << k << " times";_median 10884 ns 10882 ns 10 -std::stringstream str; str << "test = " << k << " times";_stddev 376 ns 412 ns 10 -std::stringstream str; str << "test = " << k << " times";_cv 3.43 % 3.76 % 10 -std::string str = "test = " + std::to_string(k) + " times";_mean 1131 ns 1116 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_median 1123 ns 1111 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_stddev 33.9 ns 25.9 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_cv 3.00 % 2.32 % 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 2941 ns 2900 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 2909 ns 2888 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 110 ns 64.8 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 3.75 % 2.24 % 10 -std::string str = std::format("test = {} times", k);_mean 2082 ns 1995 ns 10 -std::string str = std::format("test = {} times", k);_median 1996 ns 1976 ns 10 -std::string str = std::format("test = {} times", k);_stddev 203 ns 80.9 ns 10 -std::string str = std::format("test = {} times", k);_cv 9.77 % 4.05 % 10 -lstringa<8> str; str.format("test = {} times", k);_mean 2137 ns 2126 ns 10 -lstringa<8> str; str.format("test = {} times", k);_median 2118 ns 2131 ns 10 -lstringa<8> str; str.format("test = {} times", k);_stddev 54.9 ns 45.1 ns 10 -lstringa<8> str; str.format("test = {} times", k);_cv 2.57 % 2.12 % 10 -lstringa<32> str; str.format("test = {} times", k);_mean 1004 ns 994 ns 10 -lstringa<32> str; str.format("test = {} times", k);_median 994 ns 994 ns 10 -lstringa<32> str; str.format("test = {} times", k);_stddev 29.0 ns 17.8 ns 10 -lstringa<32> str; str.format("test = {} times", k);_cv 2.89 % 1.79 % 10 -lstringa<8> str = "test = " + k + " times";_mean 830 ns 830 ns 10 -lstringa<8> str = "test = " + k + " times";_median 828 ns 820 ns 10 -lstringa<8> str = "test = " + k + " times";_stddev 17.6 ns 18.7 ns 10 -lstringa<8> str = "test = " + k + " times";_cv 2.12 % 2.26 % 10 -lstringa<32> str = "test = " + k + " times";_mean 158 ns 159 ns 10 -lstringa<32> str = "test = " + k + " times";_median 157 ns 157 ns 10 -lstringa<32> str = "test = " + k + " times";_stddev 2.97 ns 2.96 ns 10 -lstringa<32> str = "test = " + k + " times";_cv 1.87 % 1.87 % 10 -stringa str = "test = " + k + " times";_mean 158 ns 157 ns 10 -stringa str = "test = " + k + " times";_median 156 ns 155 ns 10 -stringa str = "test = " + k + " times";_stddev 8.91 ns 8.17 ns 10 -stringa str = "test = " + k + " times";_cv 5.62 % 5.19 % 10 +std::stringstream str; str << "test = " << k << " times";_mean 11067 ns 10889 ns 10 +std::stringstream str; str << "test = " << k << " times";_median 11053 ns 10986 ns 10 +std::stringstream str; str << "test = " << k << " times";_stddev 367 ns 349 ns 10 +std::stringstream str; str << "test = " << k << " times";_cv 3.32 % 3.21 % 10 +std::string str = "test = " + std::to_string(k) + " times";_mean 1078 ns 1067 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_median 1072 ns 1046 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_stddev 32.9 ns 38.2 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_cv 3.05 % 3.58 % 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 2776 ns 2745 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 2756 ns 2727 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 72.0 ns 48.8 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 2.59 % 1.78 % 10 +std::string str = std::format("test = {} times", k);_mean 2001 ns 1992 ns 10 +std::string str = std::format("test = {} times", k);_median 2000 ns 2009 ns 10 +std::string str = std::format("test = {} times", k);_stddev 86.8 ns 74.3 ns 10 +std::string str = std::format("test = {} times", k);_cv 4.34 % 3.73 % 10 +lstringa<8> str; str.format("test = {} times", k);_mean 2076 ns 2054 ns 10 +lstringa<8> str; str.format("test = {} times", k);_median 2036 ns 2040 ns 10 +lstringa<8> str; str.format("test = {} times", k);_stddev 84.9 ns 56.8 ns 10 +lstringa<8> str; str.format("test = {} times", k);_cv 4.09 % 2.76 % 10 +lstringa<32> str; str.format("test = {} times", k);_mean 1004 ns 1000 ns 10 +lstringa<32> str; str.format("test = {} times", k);_median 990 ns 984 ns 10 +lstringa<32> str; str.format("test = {} times", k);_stddev 29.4 ns 32.4 ns 10 +lstringa<32> str; str.format("test = {} times", k);_cv 2.93 % 3.24 % 10 +lstringa<8> str = "test = " + k + " times";_mean 778 ns 774 ns 10 +lstringa<8> str = "test = " + k + " times";_median 775 ns 767 ns 10 +lstringa<8> str = "test = " + k + " times";_stddev 14.5 ns 22.1 ns 10 +lstringa<8> str = "test = " + k + " times";_cv 1.86 % 2.85 % 10 +lstringa<32> str = "test = " + k + " times";_mean 154 ns 153 ns 10 +lstringa<32> str = "test = " + k + " times";_median 152 ns 153 ns 10 +lstringa<32> str = "test = " + k + " times";_stddev 6.33 ns 6.37 ns 10 +lstringa<32> str = "test = " + k + " times";_cv 4.10 % 4.15 % 10 +stringa str = "test = " + k + " times";_mean 152 ns 150 ns 10 +stringa str = "test = " + k + " times";_median 151 ns 149 ns 10 +stringa str = "test = " + k + " times";_stddev 2.90 ns 3.45 ns 10 +stringa str = "test = " + k + " times";_cv 1.90 % 2.30 % 10 -- Split text and convert to int --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string::find + substr + std::strtol_mean 558 ns 557 ns 10 -std::string::find + substr + std::strtol_median 558 ns 558 ns 10 -std::string::find + substr + std::strtol_stddev 10.8 ns 13.9 ns 10 -std::string::find + substr + std::strtol_cv 1.94 % 2.49 % 10 -ssa::splitter + ssa::as_int_mean 171 ns 170 ns 10 -ssa::splitter + ssa::as_int_median 172 ns 171 ns 10 -ssa::splitter + ssa::as_int_stddev 2.80 ns 4.04 ns 10 -ssa::splitter + ssa::as_int_cv 1.64 % 2.38 % 10 -ssa::splitf + functor_mean 190 ns 190 ns 10 -ssa::splitf + functor_median 191 ns 190 ns 10 -ssa::splitf + functor_stddev 6.27 ns 6.91 ns 10 -ssa::splitf + functor_cv 3.30 % 3.64 % 10 +std::string::find + substr + std::strtol_mean 546 ns 533 ns 10 +std::string::find + substr + std::strtol_median 549 ns 530 ns 10 +std::string::find + substr + std::strtol_stddev 14.3 ns 11.0 ns 10 +std::string::find + substr + std::strtol_cv 2.61 % 2.06 % 10 +ssa::splitter + ssa::as_int_mean 170 ns 169 ns 10 +ssa::splitter + ssa::as_int_median 168 ns 169 ns 10 +ssa::splitter + ssa::as_int_stddev 5.45 ns 4.43 ns 10 +ssa::splitter + ssa::as_int_cv 3.21 % 2.62 % 10 +ssa::splitf + functor_mean 188 ns 186 ns 10 +ssa::splitf + functor_median 187 ns 186 ns 10 +ssa::splitf + functor_stddev 6.56 ns 6.41 ns 10 +ssa::splitf + functor_cv 3.49 % 3.45 % 10 -- Replace symbols in text ~400 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Naive (and wrong) replace symbols with std::string find + replace_mean 1171 ns 1165 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_median 1169 ns 1172 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_stddev 26.2 ns 23.2 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_cv 2.24 % 1.99 % 10 -replace symbols with std::string find_first_of + replace_mean 2063 ns 2049 ns 10 -replace symbols with std::string find_first_of + replace_median 2064 ns 2040 ns 10 -replace symbols with std::string find_first_of + replace_stddev 44.7 ns 46.8 ns 10 -replace symbols with std::string find_first_of + replace_cv 2.17 % 2.28 % 10 -replace symbols with std::string_view find_first_of + copy_mean 2410 ns 2407 ns 10 -replace symbols with std::string_view find_first_of + copy_median 2398 ns 2393 ns 10 -replace symbols with std::string_view find_first_of + copy_stddev 48.0 ns 56.6 ns 10 -replace symbols with std::string_view find_first_of + copy_cv 1.99 % 2.35 % 10 -replace runtime symbols with string expressions and without remembering all search results_mean 1441 ns 1440 ns 10 -replace runtime symbols with string expressions and without remembering all search results_median 1415 ns 1413 ns 10 -replace runtime symbols with string expressions and without remembering all search results_stddev 82.3 ns 80.6 ns 10 -replace runtime symbols with string expressions and without remembering all search results_cv 5.71 % 5.60 % 10 -replace runtime symbols with simstr and memorization of all search results_mean 1396 ns 1390 ns 10 -replace runtime symbols with simstr and memorization of all search results_median 1372 ns 1353 ns 10 -replace runtime symbols with simstr and memorization of all search results_stddev 109 ns 117 ns 10 -replace runtime symbols with simstr and memorization of all search results_cv 7.82 % 8.46 % 10 -replace const symbols with string expressions and without remembering all search results_mean 1209 ns 1205 ns 10 -replace const symbols with string expressions and without remembering all search results_median 1209 ns 1193 ns 10 -replace const symbols with string expressions and without remembering all search results_stddev 21.3 ns 33.7 ns 10 -replace const symbols with string expressions and without remembering all search results_cv 1.76 % 2.80 % 10 -replace const symbols with string expressions and memorization of all search results_mean 1206 ns 1196 ns 10 -replace const symbols with string expressions and memorization of all search results_median 1209 ns 1196 ns 10 -replace const symbols with string expressions and memorization of all search results_stddev 17.2 ns 25.7 ns 10 -replace const symbols with string expressions and memorization of all search results_cv 1.43 % 2.15 % 10 +Naive (and wrong) replace symbols with std::string find + replace_mean 1153 ns 1138 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_median 1128 ns 1116 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_stddev 64.4 ns 41.2 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_cv 5.58 % 3.62 % 10 +replace symbols with std::string find_first_of + replace_mean 2047 ns 2031 ns 10 +replace symbols with std::string find_first_of + replace_median 2017 ns 2018 ns 10 +replace symbols with std::string find_first_of + replace_stddev 98.2 ns 99.8 ns 10 +replace symbols with std::string find_first_of + replace_cv 4.80 % 4.91 % 10 +replace symbols with std::string_view find_first_of + copy_mean 2300 ns 2280 ns 10 +replace symbols with std::string_view find_first_of + copy_median 2286 ns 2295 ns 10 +replace symbols with std::string_view find_first_of + copy_stddev 58.4 ns 61.1 ns 10 +replace symbols with std::string_view find_first_of + copy_cv 2.54 % 2.68 % 10 +replace runtime symbols with string expressions and without remembering all search results_mean 1434 ns 1413 ns 10 +replace runtime symbols with string expressions and without remembering all search results_median 1428 ns 1397 ns 10 +replace runtime symbols with string expressions and without remembering all search results_stddev 48.8 ns 49.1 ns 10 +replace runtime symbols with string expressions and without remembering all search results_cv 3.40 % 3.47 % 10 +replace runtime symbols with simstr and memorization of all search results_mean 1349 ns 1334 ns 10 +replace runtime symbols with simstr and memorization of all search results_median 1339 ns 1350 ns 10 +replace runtime symbols with simstr and memorization of all search results_stddev 32.5 ns 39.8 ns 10 +replace runtime symbols with simstr and memorization of all search results_cv 2.41 % 2.99 % 10 +replace const symbols with string expressions and without remembering all search results_mean 1146 ns 1135 ns 10 +replace const symbols with string expressions and without remembering all search results_median 1137 ns 1147 ns 10 +replace const symbols with string expressions and without remembering all search results_stddev 29.7 ns 31.0 ns 10 +replace const symbols with string expressions and without remembering all search results_cv 2.59 % 2.73 % 10 +replace const symbols with string expressions and memorization of all search results_mean 1213 ns 1197 ns 10 +replace const symbols with string expressions and memorization of all search results_median 1200 ns 1186 ns 10 +replace const symbols with string expressions and memorization of all search results_stddev 35.7 ns 30.7 ns 10 +replace const symbols with string expressions and memorization of all search results_cv 2.94 % 2.57 % 10 -- Replace symbols in text ~40 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Short Naive (and wrong) replace symbols with std::string find + replace_mean 331 ns 330 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_median 330 ns 330 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_stddev 6.13 ns 5.98 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_cv 1.85 % 1.81 % 10 -Short replace symbols with std::string find_first_of + replace_mean 375 ns 375 ns 10 -Short replace symbols with std::string find_first_of + replace_median 377 ns 377 ns 10 -Short replace symbols with std::string find_first_of + replace_stddev 6.37 ns 9.30 ns 10 -Short replace symbols with std::string find_first_of + replace_cv 1.70 % 2.48 % 10 -Short replace symbols with std::string_view find_first_of + copy_mean 329 ns 325 ns 10 -Short replace symbols with std::string_view find_first_of + copy_median 327 ns 322 ns 10 -Short replace symbols with std::string_view find_first_of + copy_stddev 11.5 ns 10.5 ns 10 -Short replace symbols with std::string_view find_first_of + copy_cv 3.49 % 3.22 % 10 -Short replace runtime symbols with string expressions and without remembering all search results_mean 256 ns 254 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_median 257 ns 254 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_stddev 4.08 ns 3.90 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_cv 1.59 % 1.53 % 10 -Short replace runtime symbols with simstr and memorization of all search results_mean 369 ns 366 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_median 368 ns 360 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_stddev 8.65 ns 8.87 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_cv 2.35 % 2.42 % 10 -Short replace const symbols with string expressions and without remembering all search results_mean 223 ns 223 ns 10 -Short replace const symbols with string expressions and without remembering all search results_median 221 ns 222 ns 10 -Short replace const symbols with string expressions and without remembering all search results_stddev 6.17 ns 7.23 ns 10 -Short replace const symbols with string expressions and without remembering all search results_cv 2.76 % 3.25 % 10 -Short replace const symbols with string expressions and memorization of all search results_mean 310 ns 309 ns 10 -Short replace const symbols with string expressions and memorization of all search results_median 309 ns 305 ns 10 -Short replace const symbols with string expressions and memorization of all search results_stddev 6.82 ns 7.78 ns 10 -Short replace const symbols with string expressions and memorization of all search results_cv 2.20 % 2.52 % 10 +Short Naive (and wrong) replace symbols with std::string find + replace_mean 314 ns 312 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_median 315 ns 311 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_stddev 7.64 ns 9.08 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_cv 2.43 % 2.91 % 10 +Short replace symbols with std::string find_first_of + replace_mean 369 ns 367 ns 10 +Short replace symbols with std::string find_first_of + replace_median 363 ns 360 ns 10 +Short replace symbols with std::string find_first_of + replace_stddev 14.2 ns 16.9 ns 10 +Short replace symbols with std::string find_first_of + replace_cv 3.83 % 4.61 % 10 +Short replace symbols with std::string_view find_first_of + copy_mean 322 ns 321 ns 10 +Short replace symbols with std::string_view find_first_of + copy_median 321 ns 321 ns 10 +Short replace symbols with std::string_view find_first_of + copy_stddev 9.99 ns 9.98 ns 10 +Short replace symbols with std::string_view find_first_of + copy_cv 3.10 % 3.11 % 10 +Short replace runtime symbols with string expressions and without remembering all search results_mean 258 ns 257 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_median 259 ns 259 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_stddev 4.29 ns 6.43 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_cv 1.66 % 2.50 % 10 +Short replace runtime symbols with simstr and memorization of all search results_mean 344 ns 343 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_median 340 ns 339 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_stddev 11.9 ns 12.5 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_cv 3.46 % 3.64 % 10 +Short replace const symbols with string expressions and without remembering all search results_mean 213 ns 213 ns 10 +Short replace const symbols with string expressions and without remembering all search results_median 214 ns 213 ns 10 +Short replace const symbols with string expressions and without remembering all search results_stddev 4.05 ns 4.51 ns 10 +Short replace const symbols with string expressions and without remembering all search results_cv 1.90 % 2.12 % 10 +Short replace const symbols with string expressions and memorization of all search results_mean 303 ns 301 ns 10 +Short replace const symbols with string expressions and memorization of all search results_median 300 ns 298 ns 10 +Short replace const symbols with string expressions and memorization of all search results_stddev 8.35 ns 9.57 ns 10 +Short replace const symbols with string expressions and memorization of all search results_cv 2.75 % 3.18 % 10 ----- Replace All Str To Longer Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to ---- in std::string|64_mean 236 ns 235 ns 10 -replace bb to ---- in std::string|64_median 236 ns 235 ns 10 -replace bb to ---- in std::string|64_stddev 4.58 ns 3.86 ns 10 -replace bb to ---- in std::string|64_cv 1.94 % 1.64 % 10 -replace bb to ---- in std::string|256_mean 780 ns 776 ns 10 -replace bb to ---- in std::string|256_median 777 ns 774 ns 10 -replace bb to ---- in std::string|256_stddev 18.4 ns 25.1 ns 10 -replace bb to ---- in std::string|256_cv 2.36 % 3.23 % 10 -replace bb to ---- in std::string|512_mean 1449 ns 1447 ns 10 -replace bb to ---- in std::string|512_median 1454 ns 1465 ns 10 -replace bb to ---- in std::string|512_stddev 34.6 ns 44.3 ns 10 -replace bb to ---- in std::string|512_cv 2.39 % 3.06 % 10 -replace bb to ---- in std::string|1024_mean 3239 ns 3181 ns 10 -replace bb to ---- in std::string|1024_median 3214 ns 3174 ns 10 -replace bb to ---- in std::string|1024_stddev 121 ns 67.4 ns 10 -replace bb to ---- in std::string|1024_cv 3.73 % 2.12 % 10 -replace bb to ---- in std::string|2048_mean 8127 ns 8039 ns 10 -replace bb to ---- in std::string|2048_median 7982 ns 8022 ns 10 -replace bb to ---- in std::string|2048_stddev 355 ns 323 ns 10 -replace bb to ---- in std::string|2048_cv 4.36 % 4.02 % 10 -replace bb to ---- in lstringa<8>|64_mean 336 ns 333 ns 10 -replace bb to ---- in lstringa<8>|64_median 331 ns 330 ns 10 -replace bb to ---- in lstringa<8>|64_stddev 18.4 ns 17.0 ns 10 -replace bb to ---- in lstringa<8>|64_cv 5.48 % 5.10 % 10 -replace bb to ---- in lstringa<8>|256_mean 659 ns 657 ns 10 -replace bb to ---- in lstringa<8>|256_median 648 ns 642 ns 10 -replace bb to ---- in lstringa<8>|256_stddev 43.6 ns 46.7 ns 10 -replace bb to ---- in lstringa<8>|256_cv 6.62 % 7.11 % 10 -replace bb to ---- in lstringa<8>|512_mean 1091 ns 1085 ns 10 -replace bb to ---- in lstringa<8>|512_median 1089 ns 1088 ns 10 -replace bb to ---- in lstringa<8>|512_stddev 22.5 ns 20.6 ns 10 -replace bb to ---- in lstringa<8>|512_cv 2.06 % 1.90 % 10 -replace bb to ---- in lstringa<8>|1024_mean 1937 ns 1919 ns 10 -replace bb to ---- in lstringa<8>|1024_median 1939 ns 1929 ns 10 -replace bb to ---- in lstringa<8>|1024_stddev 27.5 ns 51.7 ns 10 -replace bb to ---- in lstringa<8>|1024_cv 1.42 % 2.70 % 10 -replace bb to ---- in lstringa<8>|2048_mean 3647 ns 3633 ns 10 -replace bb to ---- in lstringa<8>|2048_median 3640 ns 3599 ns 10 -replace bb to ---- in lstringa<8>|2048_stddev 64.1 ns 70.6 ns 10 -replace bb to ---- in lstringa<8>|2048_cv 1.76 % 1.94 % 10 -replace bb to ---- by init stringa|64_mean 212 ns 210 ns 10 -replace bb to ---- by init stringa|64_median 212 ns 209 ns 10 -replace bb to ---- by init stringa|64_stddev 3.40 ns 4.30 ns 10 -replace bb to ---- by init stringa|64_cv 1.60 % 2.05 % 10 -replace bb to ---- by init stringa|256_mean 559 ns 558 ns 10 -replace bb to ---- by init stringa|256_median 561 ns 562 ns 10 -replace bb to ---- by init stringa|256_stddev 10.8 ns 14.8 ns 10 -replace bb to ---- by init stringa|256_cv 1.93 % 2.66 % 10 -replace bb to ---- by init stringa|512_mean 1035 ns 1032 ns 10 -replace bb to ---- by init stringa|512_median 1022 ns 1025 ns 10 -replace bb to ---- by init stringa|512_stddev 78.3 ns 74.5 ns 10 -replace bb to ---- by init stringa|512_cv 7.56 % 7.22 % 10 -replace bb to ---- by init stringa|1024_mean 1850 ns 1842 ns 10 -replace bb to ---- by init stringa|1024_median 1849 ns 1842 ns 10 -replace bb to ---- by init stringa|1024_stddev 50.8 ns 51.2 ns 10 -replace bb to ---- by init stringa|1024_cv 2.75 % 2.78 % 10 -replace bb to ---- by init stringa|2048_mean 3423 ns 3409 ns 10 -replace bb to ---- by init stringa|2048_median 3423 ns 3369 ns 10 -replace bb to ---- by init stringa|2048_stddev 76.7 ns 86.6 ns 10 -replace bb to ---- by init stringa|2048_cv 2.24 % 2.54 % 10 +replace bb to ---- in std::string|64_mean 227 ns 223 ns 10 +replace bb to ---- in std::string|64_median 226 ns 222 ns 10 +replace bb to ---- in std::string|64_stddev 6.99 ns 4.02 ns 10 +replace bb to ---- in std::string|64_cv 3.08 % 1.80 % 10 +replace bb to ---- in std::string|256_mean 765 ns 760 ns 10 +replace bb to ---- in std::string|256_median 766 ns 753 ns 10 +replace bb to ---- in std::string|256_stddev 21.8 ns 20.0 ns 10 +replace bb to ---- in std::string|256_cv 2.85 % 2.63 % 10 +replace bb to ---- in std::string|512_mean 1465 ns 1456 ns 10 +replace bb to ---- in std::string|512_median 1468 ns 1451 ns 10 +replace bb to ---- in std::string|512_stddev 71.6 ns 73.0 ns 10 +replace bb to ---- in std::string|512_cv 4.89 % 5.01 % 10 +replace bb to ---- in std::string|1024_mean 3193 ns 3121 ns 10 +replace bb to ---- in std::string|1024_median 3207 ns 3181 ns 10 +replace bb to ---- in std::string|1024_stddev 145 ns 115 ns 10 +replace bb to ---- in std::string|1024_cv 4.53 % 3.67 % 10 +replace bb to ---- in std::string|2048_mean 7883 ns 7778 ns 10 +replace bb to ---- in std::string|2048_median 7810 ns 7673 ns 10 +replace bb to ---- in std::string|2048_stddev 224 ns 205 ns 10 +replace bb to ---- in std::string|2048_cv 2.84 % 2.63 % 10 +replace bb to ---- in lstringa<8>|64_mean 320 ns 314 ns 10 +replace bb to ---- in lstringa<8>|64_median 320 ns 315 ns 10 +replace bb to ---- in lstringa<8>|64_stddev 16.3 ns 11.2 ns 10 +replace bb to ---- in lstringa<8>|64_cv 5.11 % 3.55 % 10 +replace bb to ---- in lstringa<8>|256_mean 629 ns 621 ns 10 +replace bb to ---- in lstringa<8>|256_median 621 ns 614 ns 10 +replace bb to ---- in lstringa<8>|256_stddev 18.4 ns 13.6 ns 10 +replace bb to ---- in lstringa<8>|256_cv 2.92 % 2.18 % 10 +replace bb to ---- in lstringa<8>|512_mean 1065 ns 1057 ns 10 +replace bb to ---- in lstringa<8>|512_median 1056 ns 1050 ns 10 +replace bb to ---- in lstringa<8>|512_stddev 31.2 ns 30.6 ns 10 +replace bb to ---- in lstringa<8>|512_cv 2.93 % 2.89 % 10 +replace bb to ---- in lstringa<8>|1024_mean 1907 ns 1879 ns 10 +replace bb to ---- in lstringa<8>|1024_median 1880 ns 1883 ns 10 +replace bb to ---- in lstringa<8>|1024_stddev 61.4 ns 50.1 ns 10 +replace bb to ---- in lstringa<8>|1024_cv 3.22 % 2.67 % 10 +replace bb to ---- in lstringa<8>|2048_mean 3579 ns 3522 ns 10 +replace bb to ---- in lstringa<8>|2048_median 3524 ns 3530 ns 10 +replace bb to ---- in lstringa<8>|2048_stddev 95.4 ns 43.6 ns 10 +replace bb to ---- in lstringa<8>|2048_cv 2.67 % 1.24 % 10 +replace bb to ---- by init stringa|64_mean 172 ns 168 ns 10 +replace bb to ---- by init stringa|64_median 171 ns 164 ns 10 +replace bb to ---- by init stringa|64_stddev 9.74 ns 8.35 ns 10 +replace bb to ---- by init stringa|64_cv 5.68 % 4.97 % 10 +replace bb to ---- by init stringa|256_mean 377 ns 375 ns 10 +replace bb to ---- by init stringa|256_median 374 ns 372 ns 10 +replace bb to ---- by init stringa|256_stddev 8.32 ns 8.65 ns 10 +replace bb to ---- by init stringa|256_cv 2.21 % 2.31 % 10 +replace bb to ---- by init stringa|512_mean 813 ns 802 ns 10 +replace bb to ---- by init stringa|512_median 808 ns 802 ns 10 +replace bb to ---- by init stringa|512_stddev 20.4 ns 18.4 ns 10 +replace bb to ---- by init stringa|512_cv 2.51 % 2.29 % 10 +replace bb to ---- by init stringa|1024_mean 1637 ns 1625 ns 10 +replace bb to ---- by init stringa|1024_median 1614 ns 1604 ns 10 +replace bb to ---- by init stringa|1024_stddev 49.5 ns 52.5 ns 10 +replace bb to ---- by init stringa|1024_cv 3.02 % 3.23 % 10 +replace bb to ---- by init stringa|2048_mean 3090 ns 3062 ns 10 +replace bb to ---- by init stringa|2048_median 3057 ns 3048 ns 10 +replace bb to ---- by init stringa|2048_stddev 93.5 ns 68.4 ns 10 +replace bb to ---- by init stringa|2048_cv 3.03 % 2.24 % 10 ----- Replace All Str To Same Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to -- in std::string|64_mean 192 ns 192 ns 10 -replace bb to -- in std::string|64_median 192 ns 190 ns 10 -replace bb to -- in std::string|64_stddev 4.79 ns 5.39 ns 10 -replace bb to -- in std::string|64_cv 2.49 % 2.80 % 10 -replace bb to -- in std::string|256_mean 495 ns 495 ns 10 -replace bb to -- in std::string|256_median 494 ns 500 ns 10 -replace bb to -- in std::string|256_stddev 7.23 ns 10.5 ns 10 -replace bb to -- in std::string|256_cv 1.46 % 2.13 % 10 -replace bb to -- in std::string|512_mean 854 ns 853 ns 10 -replace bb to -- in std::string|512_median 846 ns 854 ns 10 -replace bb to -- in std::string|512_stddev 19.6 ns 23.9 ns 10 -replace bb to -- in std::string|512_cv 2.30 % 2.80 % 10 -replace bb to -- in std::string|1024_mean 1670 ns 1665 ns 10 -replace bb to -- in std::string|1024_median 1665 ns 1669 ns 10 -replace bb to -- in std::string|1024_stddev 21.3 ns 37.1 ns 10 -replace bb to -- in std::string|1024_cv 1.28 % 2.23 % 10 -replace bb to -- in std::string|2048_mean 3178 ns 3142 ns 10 -replace bb to -- in std::string|2048_median 3200 ns 3149 ns 10 -replace bb to -- in std::string|2048_stddev 71.4 ns 64.1 ns 10 -replace bb to -- in std::string|2048_cv 2.25 % 2.04 % 10 -replace bb to -- in lstringa<8>|64_mean 192 ns 191 ns 10 -replace bb to -- in lstringa<8>|64_median 190 ns 190 ns 10 -replace bb to -- in lstringa<8>|64_stddev 6.14 ns 5.56 ns 10 -replace bb to -- in lstringa<8>|64_cv 3.21 % 2.90 % 10 -replace bb to -- in lstringa<8>|256_mean 446 ns 442 ns 10 -replace bb to -- in lstringa<8>|256_median 449 ns 439 ns 10 -replace bb to -- in lstringa<8>|256_stddev 12.1 ns 12.2 ns 10 -replace bb to -- in lstringa<8>|256_cv 2.72 % 2.76 % 10 -replace bb to -- in lstringa<8>|512_mean 789 ns 785 ns 10 -replace bb to -- in lstringa<8>|512_median 790 ns 785 ns 10 -replace bb to -- in lstringa<8>|512_stddev 20.5 ns 21.7 ns 10 -replace bb to -- in lstringa<8>|512_cv 2.59 % 2.77 % 10 -replace bb to -- in lstringa<8>|1024_mean 1526 ns 1521 ns 10 -replace bb to -- in lstringa<8>|1024_median 1510 ns 1500 ns 10 -replace bb to -- in lstringa<8>|1024_stddev 92.5 ns 93.3 ns 10 -replace bb to -- in lstringa<8>|1024_cv 6.06 % 6.14 % 10 -replace bb to -- in lstringa<8>|2048_mean 2820 ns 2798 ns 10 -replace bb to -- in lstringa<8>|2048_median 2800 ns 2783 ns 10 -replace bb to -- in lstringa<8>|2048_stddev 105 ns 113 ns 10 -replace bb to -- in lstringa<8>|2048_cv 3.72 % 4.06 % 10 +replace bb to -- in std::string|64_mean 190 ns 190 ns 10 +replace bb to -- in std::string|64_median 190 ns 190 ns 10 +replace bb to -- in std::string|64_stddev 5.77 ns 7.18 ns 10 +replace bb to -- in std::string|64_cv 3.03 % 3.77 % 10 +replace bb to -- in std::string|256_mean 468 ns 466 ns 10 +replace bb to -- in std::string|256_median 465 ns 460 ns 10 +replace bb to -- in std::string|256_stddev 8.61 ns 10.2 ns 10 +replace bb to -- in std::string|256_cv 1.84 % 2.18 % 10 +replace bb to -- in std::string|512_mean 842 ns 833 ns 10 +replace bb to -- in std::string|512_median 835 ns 837 ns 10 +replace bb to -- in std::string|512_stddev 23.2 ns 19.2 ns 10 +replace bb to -- in std::string|512_cv 2.76 % 2.31 % 10 +replace bb to -- in std::string|1024_mean 1614 ns 1597 ns 10 +replace bb to -- in std::string|1024_median 1579 ns 1569 ns 10 +replace bb to -- in std::string|1024_stddev 65.9 ns 61.1 ns 10 +replace bb to -- in std::string|1024_cv 4.09 % 3.82 % 10 +replace bb to -- in std::string|2048_mean 3157 ns 3134 ns 10 +replace bb to -- in std::string|2048_median 3144 ns 3115 ns 10 +replace bb to -- in std::string|2048_stddev 79.0 ns 44.7 ns 10 +replace bb to -- in std::string|2048_cv 2.50 % 1.43 % 10 +replace bb to -- in lstringa<8>|64_mean 185 ns 184 ns 10 +replace bb to -- in lstringa<8>|64_median 184 ns 181 ns 10 +replace bb to -- in lstringa<8>|64_stddev 4.07 ns 6.14 ns 10 +replace bb to -- in lstringa<8>|64_cv 2.20 % 3.34 % 10 +replace bb to -- in lstringa<8>|256_mean 435 ns 429 ns 10 +replace bb to -- in lstringa<8>|256_median 431 ns 424 ns 10 +replace bb to -- in lstringa<8>|256_stddev 21.1 ns 20.0 ns 10 +replace bb to -- in lstringa<8>|256_cv 4.84 % 4.65 % 10 +replace bb to -- in lstringa<8>|512_mean 763 ns 753 ns 10 +replace bb to -- in lstringa<8>|512_median 760 ns 753 ns 10 +replace bb to -- in lstringa<8>|512_stddev 15.0 ns 13.2 ns 10 +replace bb to -- in lstringa<8>|512_cv 1.96 % 1.75 % 10 +replace bb to -- in lstringa<8>|1024_mean 1404 ns 1394 ns 10 +replace bb to -- in lstringa<8>|1024_median 1395 ns 1397 ns 10 +replace bb to -- in lstringa<8>|1024_stddev 42.3 ns 39.7 ns 10 +replace bb to -- in lstringa<8>|1024_cv 3.01 % 2.85 % 10 +replace bb to -- in lstringa<8>|2048_mean 2741 ns 2716 ns 10 +replace bb to -- in lstringa<8>|2048_median 2744 ns 2727 ns 10 +replace bb to -- in lstringa<8>|2048_stddev 76.5 ns 67.3 ns 10 +replace bb to -- in lstringa<8>|2048_cv 2.79 % 2.48 % 10 replace bb to -- by init stringa|64_mean 162 ns 161 ns 10 -replace bb to -- by init stringa|64_median 163 ns 161 ns 10 -replace bb to -- by init stringa|64_stddev 4.40 ns 4.59 ns 10 -replace bb to -- by init stringa|64_cv 2.72 % 2.86 % 10 -replace bb to -- by init stringa|256_mean 354 ns 352 ns 10 -replace bb to -- by init stringa|256_median 353 ns 353 ns 10 -replace bb to -- by init stringa|256_stddev 5.85 ns 7.63 ns 10 -replace bb to -- by init stringa|256_cv 1.65 % 2.17 % 10 -replace bb to -- by init stringa|512_mean 600 ns 596 ns 10 -replace bb to -- by init stringa|512_median 596 ns 586 ns 10 -replace bb to -- by init stringa|512_stddev 25.7 ns 22.8 ns 10 -replace bb to -- by init stringa|512_cv 4.29 % 3.83 % 10 -replace bb to -- by init stringa|1024_mean 1079 ns 1067 ns 10 -replace bb to -- by init stringa|1024_median 1070 ns 1062 ns 10 -replace bb to -- by init stringa|1024_stddev 29.7 ns 28.3 ns 10 -replace bb to -- by init stringa|1024_cv 2.75 % 2.65 % 10 -replace bb to -- by init stringa|2048_mean 2067 ns 2061 ns 10 -replace bb to -- by init stringa|2048_median 2060 ns 2051 ns 10 -replace bb to -- by init stringa|2048_stddev 50.6 ns 44.9 ns 10 -replace bb to -- by init stringa|2048_cv 2.45 % 2.18 % 10 +replace bb to -- by init stringa|64_median 164 ns 162 ns 10 +replace bb to -- by init stringa|64_stddev 4.13 ns 4.20 ns 10 +replace bb to -- by init stringa|64_cv 2.55 % 2.61 % 10 +replace bb to -- by init stringa|256_mean 357 ns 353 ns 10 +replace bb to -- by init stringa|256_median 358 ns 353 ns 10 +replace bb to -- by init stringa|256_stddev 11.8 ns 10.7 ns 10 +replace bb to -- by init stringa|256_cv 3.30 % 3.03 % 10 +replace bb to -- by init stringa|512_mean 580 ns 564 ns 10 +replace bb to -- by init stringa|512_median 577 ns 558 ns 10 +replace bb to -- by init stringa|512_stddev 23.9 ns 11.8 ns 10 +replace bb to -- by init stringa|512_cv 4.13 % 2.09 % 10 +replace bb to -- by init stringa|1024_mean 1091 ns 1077 ns 10 +replace bb to -- by init stringa|1024_median 1091 ns 1086 ns 10 +replace bb to -- by init stringa|1024_stddev 48.5 ns 38.9 ns 10 +replace bb to -- by init stringa|1024_cv 4.45 % 3.62 % 10 +replace bb to -- by init stringa|2048_mean 1998 ns 1972 ns 10 +replace bb to -- by init stringa|2048_median 2010 ns 1972 ns 10 +replace bb to -- by init stringa|2048_stddev 51.7 ns 49.0 ns 10 +replace bb to -- by init stringa|2048_cv 2.59 % 2.48 % 10 ----- Hash Map insert and find ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -hashStrMapA emplace & find stringa;_mean 3852886 ns 3824491 ns 10 -hashStrMapA emplace & find stringa;_median 3878020 ns 3860828 ns 10 -hashStrMapA emplace & find stringa;_stddev 176851 ns 168325 ns 10 -hashStrMapA emplace & find stringa;_cv 4.59 % 4.40 % 10 -std::unordered_map emplace & find std::string;_mean 5329837 ns 5281250 ns 10 -std::unordered_map emplace & find std::string;_median 5354391 ns 5312500 ns 10 -std::unordered_map emplace & find std::string;_stddev 95363 ns 161374 ns 10 -std::unordered_map emplace & find std::string;_cv 1.79 % 3.06 % 10 -hashStrMapA emplace & find ssa;_mean 3511046 ns 3477564 ns 10 -hashStrMapA emplace & find ssa;_median 3499198 ns 3445513 ns 10 -hashStrMapA emplace & find ssa;_stddev 74703 ns 67570 ns 10 -hashStrMapA emplace & find ssa;_cv 2.13 % 1.94 % 10 -std::unordered_map emplace & find std::string_view;_mean 6336347 ns 6333705 ns 10 -std::unordered_map emplace & find std::string_view;_median 6314743 ns 6277902 ns 10 -std::unordered_map emplace & find std::string_view;_stddev 87714 ns 97545 ns 10 -std::unordered_map emplace & find std::string_view;_cv 1.38 % 1.54 % 10 +hashStrMapA emplace & find stringa;_mean 3693883 ns 3674930 ns 10 +hashStrMapA emplace & find stringa;_median 3687852 ns 3666201 ns 10 +hashStrMapA emplace & find stringa;_stddev 226433 ns 207589 ns 10 +hashStrMapA emplace & find stringa;_cv 6.13 % 5.65 % 10 +std::unordered_map emplace & find std::string;_mean 5258881 ns 5231585 ns 10 +std::unordered_map emplace & find std::string;_median 5227104 ns 5161830 ns 10 +std::unordered_map emplace & find std::string;_stddev 147989 ns 135578 ns 10 +std::unordered_map emplace & find std::string;_cv 2.81 % 2.59 % 10 +hashStrMapA emplace & find ssa;_mean 3418166 ns 3416054 ns 10 +hashStrMapA emplace & find ssa;_median 3409800 ns 3408395 ns 10 +hashStrMapA emplace & find ssa;_stddev 67498 ns 73996 ns 10 +hashStrMapA emplace & find ssa;_cv 1.97 % 2.17 % 10 +std::unordered_map emplace & find std::string_view;_mean 6295014 ns 6277902 ns 10 +std::unordered_map emplace & find std::string_view;_median 6199714 ns 6138393 ns 10 +std::unordered_map emplace & find std::string_view;_stddev 245175 ns 263061 ns 10 +std::unordered_map emplace & find std::string_view;_cv 3.89 % 4.19 % 10 ----- Build Full Func Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -Build func full name std::string;_mean 1581 ns 1565 ns 10 -Build func full name std::string;_median 1578 ns 1573 ns 10 -Build func full name std::string;_stddev 17.3 ns 30.3 ns 10 -Build func full name std::string;_cv 1.10 % 1.93 % 10 -Build func full name std::string 1;_mean 1654 ns 1635 ns 10 -Build func full name std::string 1;_median 1646 ns 1632 ns 10 -Build func full name std::string 1;_stddev 62.7 ns 47.8 ns 10 -Build func full name std::string 1;_cv 3.79 % 2.92 % 10 -Build func full name std::stream;_mean 8195 ns 8179 ns 10 -Build func full name std::stream;_median 8225 ns 8196 ns 10 -Build func full name std::stream;_stddev 138 ns 192 ns 10 -Build func full name std::stream;_cv 1.69 % 2.35 % 10 -Build func full name stringa;_mean 859 ns 851 ns 10 -Build func full name stringa;_median 855 ns 854 ns 10 -Build func full name stringa;_stddev 12.6 ns 18.0 ns 10 -Build func full name stringa;_cv 1.47 % 2.12 % 10 -Build func full name stringa 1;_mean 1015 ns 1011 ns 10 -Build func full name stringa 1;_median 1014 ns 1001 ns 10 -Build func full name stringa 1;_stddev 28.4 ns 30.9 ns 10 -Build func full name stringa 1;_cv 2.79 % 3.06 % 10 +Build func full name std::string;_mean 1533 ns 1522 ns 10 +Build func full name std::string;_median 1513 ns 1491 ns 10 +Build func full name std::string;_stddev 58.1 ns 59.6 ns 10 +Build func full name std::string;_cv 3.79 % 3.92 % 10 +Build func full name std::string 1;_mean 1602 ns 1588 ns 10 +Build func full name std::string 1;_median 1581 ns 1573 ns 10 +Build func full name std::string 1;_stddev 71.7 ns 70.5 ns 10 +Build func full name std::string 1;_cv 4.48 % 4.44 % 10 +Build func full name std::stream;_mean 8228 ns 8161 ns 10 +Build func full name std::stream;_median 8257 ns 8109 ns 10 +Build func full name std::stream;_stddev 326 ns 305 ns 10 +Build func full name std::stream;_cv 3.96 % 3.74 % 10 +Build func full name stringa;_mean 818 ns 815 ns 10 +Build func full name stringa;_median 817 ns 816 ns 10 +Build func full name stringa;_stddev 22.1 ns 24.8 ns 10 +Build func full name stringa;_cv 2.70 % 3.04 % 10 +Build func full name stringa 1;_mean 959 ns 952 ns 10 +Build func full name stringa 1;_median 936 ns 940 ns 10 +Build func full name stringa 1;_stddev 50.6 ns 43.1 ns 10 +Build func full name stringa 1;_cv 5.27 % 4.52 % 10 diff --git a/bench/results/003-Xeon E5-2682 v4, Windows 10, MSVC-19.txt b/bench/results/003-Xeon E5-2682 v4, Windows 10, MSVC-19.txt index c14e87d..822f0e6 100644 --- a/bench/results/003-Xeon E5-2682 v4, Windows 10, MSVC-19.txt +++ b/bench/results/003-Xeon E5-2682 v4, Windows 10, MSVC-19.txt @@ -1,4 +1,4 @@ -2025-11-26T19:57:30+03:00 +2026-01-21T00:56:24+03:00 Running benchStr.exe Run on (32 X 2494 MHz CPU s) CPU Caches: @@ -9,782 +9,868 @@ CPU Caches: -------------------------------------------------------------------------------------------------------------------------------------------------------- Benchmark Time CPU Iterations -------------------------------------------------------------------------------------------------------------------------------------------------------- +----- Concatenate string + Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and number by std to std::string_mean 331 ns 330 ns 10 +Concat std::string and number by std to std::string_median 328 ns 328 ns 10 +Concat std::string and number by std to std::string_stddev 9.88 ns 8.73 ns 10 +Concat std::string and number by std to std::string_cv 2.98 % 2.65 % 10 +Concat std::string and number by StrExpr to std::string_mean 211 ns 207 ns 10 +Concat std::string and number by StrExpr to std::string_median 212 ns 206 ns 10 +Concat std::string and number by StrExpr to std::string_stddev 5.83 ns 5.26 ns 10 +Concat std::string and number by StrExpr to std::string_cv 2.77 % 2.54 % 10 +Concat stringa and number by StrExpr to simstr::stringa_mean 108 ns 107 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_median 108 ns 107 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_stddev 2.53 ns 2.24 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_cv 2.33 % 2.10 % 10 +----- Concatenate string + Hex Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and hex number by std to std::string_mean 1074 ns 1059 ns 10 +Concat std::string and hex number by std to std::string_median 1060 ns 1046 ns 10 +Concat std::string and hex number by std to std::string_stddev 38.0 ns 38.5 ns 10 +Concat std::string and hex number by std to std::string_cv 3.54 % 3.63 % 10 +Concat std::string and hex number by StrExpr to std::string_mean 136 ns 136 ns 10 +Concat std::string and hex number by StrExpr to std::string_median 137 ns 135 ns 10 +Concat std::string and hex number by StrExpr to std::string_stddev 4.05 ns 4.20 ns 10 +Concat std::string and hex number by StrExpr to std::string_cv 2.97 % 3.09 % 10 +Concat stringa and hex number by StrExpr to simstr::stringa_mean 101 ns 98.4 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_median 102 ns 97.7 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_stddev 4.57 ns 4.00 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_cv 4.50 % 4.06 % 10 +----- Concatenate string + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string by std to std::string_mean 55.4 ns 55.0 ns 10 +Concat std::string by std to std::string_median 54.8 ns 54.4 ns 10 +Concat std::string by std to std::string_stddev 1.60 ns 1.76 ns 10 +Concat std::string by std to std::string_cv 2.89 % 3.21 % 10 +Concat std::string by StrExpr to std::string_mean 77.9 ns 77.0 ns 10 +Concat std::string by StrExpr to std::string_median 77.6 ns 76.7 ns 10 +Concat std::string by StrExpr to std::string_stddev 1.39 ns 1.28 ns 10 +Concat std::string by StrExpr to std::string_cv 1.78 % 1.66 % 10 +Concat stringa by StrExpr to stringa_mean 52.5 ns 52.0 ns 10 +Concat stringa by StrExpr to stringa_median 51.6 ns 51.6 ns 10 +Concat stringa by StrExpr to stringa_stddev 1.34 ns 0.755 ns 10 +Concat stringa by StrExpr to stringa_cv 2.56 % 1.45 % 10 +----- Find three concatenated string in string_view -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Find concat three std::string_mean 225 ns 222 ns 10 +Find concat three std::string_median 223 ns 217 ns 10 +Find concat three std::string_stddev 9.31 ns 8.69 ns 10 +Find concat three std::string_cv 4.13 % 3.91 % 10 +Find concat three strexpr_mean 122 ns 121 ns 10 +Find concat three strexpr_median 122 ns 120 ns 10 +Find concat three strexpr_stddev 3.71 ns 3.68 ns 10 +Find concat three strexpr_cv 3.05 % 3.05 % 10 +Find concat three simstr_mean 28.4 ns 27.9 ns 10 +Find concat three simstr_median 28.2 ns 27.9 ns 10 +Find concat three simstr_stddev 0.873 ns 0.791 ns 10 +Find concat three simstr_cv 3.08 % 2.84 % 10 +----- Build Type Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +BuildTypeNameStr 0/0_mean 17.9 ns 17.7 ns 10 +BuildTypeNameStr 0/0_median 17.7 ns 17.6 ns 10 +BuildTypeNameStr 0/0_stddev 0.347 ns 0.353 ns 10 +BuildTypeNameStr 0/0_cv 1.94 % 1.99 % 10 +BuildTypeNameExp 0/0_mean 14.2 ns 14.1 ns 10 +BuildTypeNameExp 0/0_median 14.0 ns 14.1 ns 10 +BuildTypeNameExp 0/0_stddev 0.420 ns 0.391 ns 10 +BuildTypeNameExp 0/0_cv 2.96 % 2.77 % 10 +BuildTypeNameSim 0/0_mean 17.2 ns 17.1 ns 10 +BuildTypeNameSim 0/0_median 17.2 ns 17.3 ns 10 +BuildTypeNameSim 0/0_stddev 0.256 ns 0.185 ns 10 +BuildTypeNameSim 0/0_cv 1.49 % 1.08 % 10 +BuildTypeNameStr 10/10_mean 79.4 ns 79.2 ns 10 +BuildTypeNameStr 10/10_median 78.6 ns 78.5 ns 10 +BuildTypeNameStr 10/10_stddev 1.75 ns 1.22 ns 10 +BuildTypeNameStr 10/10_cv 2.20 % 1.54 % 10 +BuildTypeNameExp 10/10_mean 40.0 ns 40.0 ns 10 +BuildTypeNameExp 10/10_median 39.9 ns 40.1 ns 10 +BuildTypeNameExp 10/10_stddev 0.764 ns 0.643 ns 10 +BuildTypeNameExp 10/10_cv 1.91 % 1.61 % 10 +BuildTypeNameSim 10/10_mean 37.9 ns 37.8 ns 10 +BuildTypeNameSim 10/10_median 37.8 ns 37.5 ns 10 +BuildTypeNameSim 10/10_stddev 0.709 ns 0.718 ns 10 +BuildTypeNameSim 10/10_cv 1.87 % 1.90 % 10 +----- Replace string by copy -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat with replace str_mean 362 ns 351 ns 10 +Concat with replace str_median 364 ns 349 ns 10 +Concat with replace str_stddev 13.6 ns 10.6 ns 10 +Concat with replace str_cv 3.75 % 3.01 % 10 +Concat with replace exp_mean 223 ns 221 ns 10 +Concat with replace exp_median 222 ns 222 ns 10 +Concat with replace exp_stddev 5.40 ns 4.68 ns 10 +Concat with replace exp_cv 2.42 % 2.12 % 10 ----- Create Empty Str ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e;_mean 2.95 ns 2.92 ns 10 -std::string e;_median 2.90 ns 2.89 ns 10 -std::string e;_stddev 0.162 ns 0.108 ns 10 -std::string e;_cv 5.50 % 3.69 % 10 -std::string_view e;_mean 1.85 ns 1.85 ns 10 -std::string_view e;_median 1.86 ns 1.84 ns 10 -std::string_view e;_stddev 0.054 ns 0.064 ns 10 -std::string_view e;_cv 2.92 % 3.46 % 10 -ssa e;_mean 1.52 ns 1.50 ns 10 -ssa e;_median 1.51 ns 1.49 ns 10 -ssa e;_stddev 0.064 ns 0.050 ns 10 -ssa e;_cv 4.24 % 3.33 % 10 -stringa e;_mean 2.25 ns 2.24 ns 10 +std::string e;_mean 2.63 ns 2.57 ns 10 +std::string e;_median 2.61 ns 2.58 ns 10 +std::string e;_stddev 0.115 ns 0.093 ns 10 +std::string e;_cv 4.35 % 3.62 % 10 +std::string_view e;_mean 1.84 ns 1.83 ns 10 +std::string_view e;_median 1.82 ns 1.84 ns 10 +std::string_view e;_stddev 0.042 ns 0.028 ns 10 +std::string_view e;_cv 2.27 % 1.54 % 10 +ssa e;_mean 1.83 ns 1.82 ns 10 +ssa e;_median 1.83 ns 1.84 ns 10 +ssa e;_stddev 0.031 ns 0.041 ns 10 +ssa e;_cv 1.68 % 2.23 % 10 +stringa e;_mean 2.22 ns 2.20 ns 10 stringa e;_median 2.22 ns 2.20 ns 10 -stringa e;_stddev 0.093 ns 0.082 ns 10 -stringa e;_cv 4.14 % 3.68 % 10 -lstringa<20> e;_mean 2.58 ns 2.57 ns 10 -lstringa<20> e;_median 2.58 ns 2.57 ns 10 -lstringa<20> e;_stddev 0.065 ns 0.083 ns 10 -lstringa<20> e;_cv 2.51 % 3.24 % 10 -lstringa<40> e;_mean 2.59 ns 2.58 ns 10 -lstringa<40> e;_median 2.56 ns 2.57 ns 10 -lstringa<40> e;_stddev 0.067 ns 0.059 ns 10 -lstringa<40> e;_cv 2.60 % 2.29 % 10 +stringa e;_stddev 0.056 ns 0.046 ns 10 +stringa e;_cv 2.53 % 2.10 % 10 +lstringa<20> e;_mean 2.59 ns 2.57 ns 10 +lstringa<20> e;_median 2.56 ns 2.57 ns 10 +lstringa<20> e;_stddev 0.070 ns 0.051 ns 10 +lstringa<20> e;_cv 2.69 % 1.99 % 10 +lstringa<40> e;_mean 2.56 ns 2.54 ns 10 +lstringa<40> e;_median 2.55 ns 2.55 ns 10 +lstringa<40> e;_stddev 0.045 ns 0.044 ns 10 +lstringa<40> e;_cv 1.75 % 1.72 % 10 ----- Create Str from short literal (9 symbols) --------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text";_mean 2.58 ns 2.58 ns 10 -std::string e = "Test text";_median 2.58 ns 2.57 ns 10 -std::string e = "Test text";_stddev 0.045 ns 0.063 ns 10 -std::string e = "Test text";_cv 1.75 % 2.46 % 10 -std::string_view e = "Test text";_mean 1.90 ns 1.89 ns 10 -std::string_view e = "Test text";_median 1.86 ns 1.86 ns 10 -std::string_view e = "Test text";_stddev 0.110 ns 0.102 ns 10 -std::string_view e = "Test text";_cv 5.80 % 5.41 % 10 -ssa e = "Test text";_mean 1.85 ns 1.84 ns 10 -ssa e = "Test text";_median 1.84 ns 1.81 ns 10 -ssa e = "Test text";_stddev 0.064 ns 0.068 ns 10 -ssa e = "Test text";_cv 3.49 % 3.73 % 10 -stringa e = "Test text";_mean 2.92 ns 2.91 ns 10 -stringa e = "Test text";_median 2.87 ns 2.89 ns 10 -stringa e = "Test text";_stddev 0.100 ns 0.095 ns 10 -stringa e = "Test text";_cv 3.44 % 3.24 % 10 +std::string e = "Test text";_mean 2.64 ns 2.61 ns 10 +std::string e = "Test text";_median 2.63 ns 2.59 ns 10 +std::string e = "Test text";_stddev 0.074 ns 0.078 ns 10 +std::string e = "Test text";_cv 2.79 % 2.99 % 10 +std::string_view e = "Test text";_mean 1.85 ns 1.83 ns 10 +std::string_view e = "Test text";_median 1.84 ns 1.82 ns 10 +std::string_view e = "Test text";_stddev 0.038 ns 0.027 ns 10 +std::string_view e = "Test text";_cv 2.05 % 1.47 % 10 +ssa e = "Test text";_mean 1.83 ns 1.82 ns 10 +ssa e = "Test text";_median 1.83 ns 1.81 ns 10 +ssa e = "Test text";_stddev 0.022 ns 0.029 ns 10 +ssa e = "Test text";_cv 1.20 % 1.57 % 10 +stringa e = "Test text";_mean 2.20 ns 2.20 ns 10 +stringa e = "Test text";_median 2.19 ns 2.20 ns 10 +stringa e = "Test text";_stddev 0.053 ns 0.061 ns 10 +stringa e = "Test text";_cv 2.42 % 2.77 % 10 lstringa<20> e = "Test text";_mean 2.59 ns 2.57 ns 10 -lstringa<20> e = "Test text";_median 2.56 ns 2.54 ns 10 -lstringa<20> e = "Test text";_stddev 0.087 ns 0.083 ns 10 -lstringa<20> e = "Test text";_cv 3.35 % 3.24 % 10 -lstringa<40> e = "Test text";_mean 2.61 ns 2.58 ns 10 -lstringa<40> e = "Test text";_median 2.58 ns 2.57 ns 10 -lstringa<40> e = "Test text";_stddev 0.081 ns 0.065 ns 10 -lstringa<40> e = "Test text";_cv 3.12 % 2.50 % 10 +lstringa<20> e = "Test text";_median 2.60 ns 2.55 ns 10 +lstringa<20> e = "Test text";_stddev 0.033 ns 0.031 ns 10 +lstringa<20> e = "Test text";_cv 1.28 % 1.19 % 10 +lstringa<40> e = "Test text";_mean 2.58 ns 2.54 ns 10 +lstringa<40> e = "Test text";_median 2.57 ns 2.55 ns 10 +lstringa<40> e = "Test text";_stddev 0.082 ns 0.059 ns 10 +lstringa<40> e = "Test text";_cv 3.17 % 2.32 % 10 ----- Create Str from long literal (30 symbols) ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "123456789012345678901234567890";_mean 76.0 ns 75.9 ns 10 -std::string e = "123456789012345678901234567890";_median 76.2 ns 76.7 ns 10 -std::string e = "123456789012345678901234567890";_stddev 1.00 ns 1.23 ns 10 -std::string e = "123456789012345678901234567890";_cv 1.32 % 1.63 % 10 -std::string_view e = "123456789012345678901234567890";_mean 1.82 ns 1.82 ns 10 +std::string e = "123456789012345678901234567890";_mean 77.5 ns 77.2 ns 10 +std::string e = "123456789012345678901234567890";_median 77.1 ns 77.4 ns 10 +std::string e = "123456789012345678901234567890";_stddev 2.32 ns 2.51 ns 10 +std::string e = "123456789012345678901234567890";_cv 2.99 % 3.24 % 10 +std::string_view e = "123456789012345678901234567890";_mean 1.83 ns 1.81 ns 10 std::string_view e = "123456789012345678901234567890";_median 1.82 ns 1.80 ns 10 -std::string_view e = "123456789012345678901234567890";_stddev 0.029 ns 0.029 ns 10 -std::string_view e = "123456789012345678901234567890";_cv 1.58 % 1.61 % 10 -ssa e = "123456789012345678901234567890";_mean 1.82 ns 1.81 ns 10 -ssa e = "123456789012345678901234567890";_median 1.82 ns 1.80 ns 10 -ssa e = "123456789012345678901234567890";_stddev 0.018 ns 0.033 ns 10 -ssa e = "123456789012345678901234567890";_cv 1.00 % 1.83 % 10 -stringa e = "123456789012345678901234567890";_mean 2.58 ns 2.56 ns 10 -stringa e = "123456789012345678901234567890";_median 2.56 ns 2.54 ns 10 -stringa e = "123456789012345678901234567890";_stddev 0.042 ns 0.058 ns 10 -stringa e = "123456789012345678901234567890";_cv 1.62 % 2.26 % 10 -lstringa<20> e = "123456789012345678901234567890";_mean 76.8 ns 76.2 ns 10 -lstringa<20> e = "123456789012345678901234567890";_median 75.9 ns 76.7 ns 10 -lstringa<20> e = "123456789012345678901234567890";_stddev 2.22 ns 2.18 ns 10 -lstringa<20> e = "123456789012345678901234567890";_cv 2.89 % 2.86 % 10 -lstringa<40> e = "123456789012345678901234567890";_mean 3.33 ns 3.31 ns 10 -lstringa<40> e = "123456789012345678901234567890";_median 3.29 ns 3.30 ns 10 -lstringa<40> e = "123456789012345678901234567890";_stddev 0.163 ns 0.142 ns 10 -lstringa<40> e = "123456789012345678901234567890";_cv 4.90 % 4.30 % 10 +std::string_view e = "123456789012345678901234567890";_stddev 0.028 ns 0.028 ns 10 +std::string_view e = "123456789012345678901234567890";_cv 1.53 % 1.56 % 10 +ssa e = "123456789012345678901234567890";_mean 1.83 ns 1.83 ns 10 +ssa e = "123456789012345678901234567890";_median 1.83 ns 1.84 ns 10 +ssa e = "123456789012345678901234567890";_stddev 0.007 ns 0.019 ns 10 +ssa e = "123456789012345678901234567890";_cv 0.36 % 1.01 % 10 +stringa e = "123456789012345678901234567890";_mean 2.24 ns 2.23 ns 10 +stringa e = "123456789012345678901234567890";_median 2.22 ns 2.22 ns 10 +stringa e = "123456789012345678901234567890";_stddev 0.060 ns 0.047 ns 10 +stringa e = "123456789012345678901234567890";_cv 2.70 % 2.10 % 10 +lstringa<20> e = "123456789012345678901234567890";_mean 77.7 ns 77.1 ns 10 +lstringa<20> e = "123456789012345678901234567890";_median 76.7 ns 76.7 ns 10 +lstringa<20> e = "123456789012345678901234567890";_stddev 2.51 ns 2.57 ns 10 +lstringa<20> e = "123456789012345678901234567890";_cv 3.24 % 3.34 % 10 +lstringa<40> e = "123456789012345678901234567890";_mean 3.42 ns 3.40 ns 10 +lstringa<40> e = "123456789012345678901234567890";_median 3.36 ns 3.35 ns 10 +lstringa<40> e = "123456789012345678901234567890";_stddev 0.192 ns 0.168 ns 10 +lstringa<40> e = "123456789012345678901234567890";_cv 5.60 % 4.95 % 10 ----- Create copy of Str with 9 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text"; auto c{e};_mean 6.00 ns 5.95 ns 10 -std::string e = "Test text"; auto c{e};_median 5.93 ns 5.94 ns 10 -std::string e = "Test text"; auto c{e};_stddev 0.228 ns 0.260 ns 10 -std::string e = "Test text"; auto c{e};_cv 3.80 % 4.37 % 10 -std::string_view e = "Test text"; auto c{e};_mean 3.46 ns 3.46 ns 10 -std::string_view e = "Test text"; auto c{e};_median 3.46 ns 3.44 ns 10 -std::string_view e = "Test text"; auto c{e};_stddev 0.022 ns 0.046 ns 10 -std::string_view e = "Test text"; auto c{e};_cv 0.64 % 1.34 % 10 -ssa e = "Test text"; auto c{e};_mean 3.51 ns 3.50 ns 10 -ssa e = "Test text"; auto c{e};_median 3.49 ns 3.49 ns 10 -ssa e = "Test text"; auto c{e};_stddev 0.063 ns 0.054 ns 10 -ssa e = "Test text"; auto c{e};_cv 1.79 % 1.53 % 10 -stringa e = "Test text"; auto c{e};_mean 4.03 ns 4.03 ns 10 -stringa e = "Test text"; auto c{e};_median 4.01 ns 4.01 ns 10 -stringa e = "Test text"; auto c{e};_stddev 0.072 ns 0.069 ns 10 -stringa e = "Test text"; auto c{e};_cv 1.78 % 1.71 % 10 -lstringa<20> e = "Test text"; auto c{e};_mean 8.51 ns 8.48 ns 10 -lstringa<20> e = "Test text"; auto c{e};_median 8.55 ns 8.46 ns 10 -lstringa<20> e = "Test text"; auto c{e};_stddev 0.261 ns 0.221 ns 10 -lstringa<20> e = "Test text"; auto c{e};_cv 3.07 % 2.60 % 10 -lstringa<40> e = "Test text"; auto c{e};_mean 8.43 ns 8.35 ns 10 -lstringa<40> e = "Test text"; auto c{e};_median 8.38 ns 8.37 ns 10 -lstringa<40> e = "Test text"; auto c{e};_stddev 0.192 ns 0.230 ns 10 -lstringa<40> e = "Test text"; auto c{e};_cv 2.28 % 2.76 % 10 +std::string e = "Test text"; auto c{e};_mean 5.43 ns 5.37 ns 10 +std::string e = "Test text"; auto c{e};_median 5.37 ns 5.31 ns 10 +std::string e = "Test text"; auto c{e};_stddev 0.131 ns 0.132 ns 10 +std::string e = "Test text"; auto c{e};_cv 2.41 % 2.45 % 10 +std::string_view e = "Test text"; auto c{e};_mean 2.94 ns 2.93 ns 10 +std::string_view e = "Test text"; auto c{e};_median 2.94 ns 2.93 ns 10 +std::string_view e = "Test text"; auto c{e};_stddev 0.055 ns 0.066 ns 10 +std::string_view e = "Test text"; auto c{e};_cv 1.86 % 2.24 % 10 +ssa e = "Test text"; auto c{e};_mean 2.92 ns 2.90 ns 10 +ssa e = "Test text"; auto c{e};_median 2.90 ns 2.92 ns 10 +ssa e = "Test text"; auto c{e};_stddev 0.056 ns 0.070 ns 10 +ssa e = "Test text"; auto c{e};_cv 1.93 % 2.42 % 10 +stringa e = "Test text"; auto c{e};_mean 4.13 ns 4.09 ns 10 +stringa e = "Test text"; auto c{e};_median 4.08 ns 4.05 ns 10 +stringa e = "Test text"; auto c{e};_stddev 0.145 ns 0.104 ns 10 +stringa e = "Test text"; auto c{e};_cv 3.51 % 2.55 % 10 +lstringa<20> e = "Test text"; auto c{e};_mean 7.74 ns 7.60 ns 10 +lstringa<20> e = "Test text"; auto c{e};_median 7.65 ns 7.50 ns 10 +lstringa<20> e = "Test text"; auto c{e};_stddev 0.280 ns 0.187 ns 10 +lstringa<20> e = "Test text"; auto c{e};_cv 3.62 % 2.47 % 10 +lstringa<40> e = "Test text"; auto c{e};_mean 8.56 ns 8.46 ns 10 +lstringa<40> e = "Test text"; auto c{e};_median 8.52 ns 8.37 ns 10 +lstringa<40> e = "Test text"; auto c{e};_stddev 0.277 ns 0.276 ns 10 +lstringa<40> e = "Test text"; auto c{e};_cv 3.24 % 3.26 % 10 ----- Create copy of Str with 30 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "123456789012345678901234567890"; auto c{e};_mean 83.0 ns 82.5 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_median 82.5 ns 82.0 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_stddev 6.88 ns 6.68 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_cv 8.29 % 8.10 % 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 1.90 ns 1.88 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_median 1.87 ns 1.84 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.097 ns 0.104 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 5.13 % 5.53 % 10 -ssa e = "123456789012345678901234567890"; auto c{e};_mean 2.02 ns 2.02 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_median 2.01 ns 2.01 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.075 ns 0.073 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_cv 3.72 % 3.61 % 10 -stringa e = "123456789012345678901234567890"; auto c{e};_mean 3.41 ns 3.40 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_median 3.41 ns 3.38 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.160 ns 0.166 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_cv 4.68 % 4.88 % 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 90.4 ns 90.4 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 83.6 ns 83.7 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 13.9 ns 14.5 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 15.35 % 16.03 % 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 7.11 ns 7.07 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 6.99 ns 6.84 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 0.506 ns 0.530 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 7.11 % 7.50 % 10 +std::string e = "123456789012345678901234567890"; auto c{e};_mean 77.5 ns 76.6 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_median 77.6 ns 77.4 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_stddev 2.80 ns 2.50 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_cv 3.61 % 3.26 % 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 1.88 ns 1.85 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_median 1.84 ns 1.82 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.098 ns 0.086 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 5.20 % 4.64 % 10 +ssa e = "123456789012345678901234567890"; auto c{e};_mean 1.83 ns 1.82 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_median 1.82 ns 1.80 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.047 ns 0.045 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_cv 2.54 % 2.47 % 10 +stringa e = "123456789012345678901234567890"; auto c{e};_mean 3.02 ns 2.98 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_median 3.01 ns 2.98 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.093 ns 0.070 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_cv 3.09 % 2.34 % 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 79.3 ns 78.6 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 78.3 ns 78.5 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 2.18 ns 2.09 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 2.75 % 2.65 % 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 6.63 ns 6.63 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 6.60 ns 6.63 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 0.129 ns 0.151 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 1.95 % 2.27 % 10 ----- Find 9 symbols text in end of 99 symbols text ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string::find;_mean 45.0 ns 44.8 ns 10 -std::string::find;_median 45.0 ns 44.9 ns 10 -std::string::find;_stddev 1.20 ns 1.34 ns 10 -std::string::find;_cv 2.68 % 2.99 % 10 -std::string_view::find;_mean 44.2 ns 44.0 ns 10 -std::string_view::find;_median 44.1 ns 44.4 ns 10 -std::string_view::find;_stddev 1.41 ns 1.37 ns 10 -std::string_view::find;_cv 3.19 % 3.11 % 10 -ssa::find;_mean 21.8 ns 21.7 ns 10 -ssa::find;_median 21.1 ns 21.2 ns 10 -ssa::find;_stddev 1.70 ns 1.61 ns 10 -ssa::find;_cv 7.82 % 7.42 % 10 -stringa::find;_mean 31.0 ns 31.0 ns 10 -stringa::find;_median 31.3 ns 31.1 ns 10 -stringa::find;_stddev 1.29 ns 1.31 ns 10 -stringa::find;_cv 4.16 % 4.22 % 10 -lstringa<20>::find;_mean 26.3 ns 26.1 ns 10 -lstringa<20>::find;_median 26.4 ns 26.2 ns 10 -lstringa<20>::find;_stddev 1.00 ns 0.865 ns 10 -lstringa<20>::find;_cv 3.83 % 3.31 % 10 -lstringa<40>::find;_mean 24.9 ns 24.7 ns 10 -lstringa<40>::find;_median 25.0 ns 24.9 ns 10 -lstringa<40>::find;_stddev 2.48 ns 2.52 ns 10 -lstringa<40>::find;_cv 9.95 % 10.17 % 10 +std::string::find;_mean 40.7 ns 40.4 ns 10 +std::string::find;_median 40.6 ns 40.4 ns 10 +std::string::find;_stddev 0.887 ns 1.43 ns 10 +std::string::find;_cv 2.18 % 3.55 % 10 +std::string_view::find;_mean 40.8 ns 40.4 ns 10 +std::string_view::find;_median 40.7 ns 39.9 ns 10 +std::string_view::find;_stddev 0.671 ns 0.641 ns 10 +std::string_view::find;_cv 1.64 % 1.59 % 10 +ssa::find;_mean 22.6 ns 22.5 ns 10 +ssa::find;_median 22.6 ns 22.7 ns 10 +ssa::find;_stddev 0.634 ns 0.779 ns 10 +ssa::find;_cv 2.81 % 3.46 % 10 +stringa::find;_mean 28.4 ns 28.2 ns 10 +stringa::find;_median 28.5 ns 27.6 ns 10 +stringa::find;_stddev 1.42 ns 1.51 ns 10 +stringa::find;_cv 4.99 % 5.37 % 10 +lstringa<20>::find;_mean 23.2 ns 23.0 ns 10 +lstringa<20>::find;_median 23.1 ns 22.9 ns 10 +lstringa<20>::find;_stddev 0.720 ns 0.765 ns 10 +lstringa<20>::find;_cv 3.10 % 3.32 % 10 +lstringa<40>::find;_mean 21.3 ns 21.0 ns 10 +lstringa<40>::find;_median 20.9 ns 20.9 ns 10 +lstringa<40>::find;_stddev 0.840 ns 0.678 ns 10 +lstringa<40>::find;_cv 3.95 % 3.23 % 10 ------- Copy not literal Str with N symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string copy{str_with_len_N};/15_mean 4.45 ns 4.44 ns 10 -std::string copy{str_with_len_N};/15_median 4.43 ns 4.43 ns 10 -std::string copy{str_with_len_N};/15_stddev 0.086 ns 0.094 ns 10 -std::string copy{str_with_len_N};/15_cv 1.92 % 2.11 % 10 -std::string copy{str_with_len_N};/16_mean 94.0 ns 93.8 ns 10 -std::string copy{str_with_len_N};/16_median 95.6 ns 95.9 ns 10 -std::string copy{str_with_len_N};/16_stddev 6.54 ns 6.36 ns 10 -std::string copy{str_with_len_N};/16_cv 6.96 % 6.78 % 10 -std::string copy{str_with_len_N};/23_mean 94.8 ns 94.4 ns 10 -std::string copy{str_with_len_N};/23_median 96.5 ns 95.2 ns 10 -std::string copy{str_with_len_N};/23_stddev 5.33 ns 4.98 ns 10 -std::string copy{str_with_len_N};/23_cv 5.62 % 5.27 % 10 -std::string copy{str_with_len_N};/24_mean 97.7 ns 97.3 ns 10 -std::string copy{str_with_len_N};/24_median 95.9 ns 96.3 ns 10 -std::string copy{str_with_len_N};/24_stddev 9.75 ns 9.88 ns 10 -std::string copy{str_with_len_N};/24_cv 9.97 % 10.15 % 10 -std::string copy{str_with_len_N};/32_mean 95.8 ns 95.7 ns 10 -std::string copy{str_with_len_N};/32_median 94.1 ns 93.5 ns 10 -std::string copy{str_with_len_N};/32_stddev 8.79 ns 8.93 ns 10 -std::string copy{str_with_len_N};/32_cv 9.18 % 9.33 % 10 -std::string copy{str_with_len_N};/64_mean 94.1 ns 93.3 ns 10 -std::string copy{str_with_len_N};/64_median 95.5 ns 95.2 ns 10 -std::string copy{str_with_len_N};/64_stddev 8.50 ns 8.67 ns 10 -std::string copy{str_with_len_N};/64_cv 9.04 % 9.29 % 10 -std::string copy{str_with_len_N};/128_mean 103 ns 104 ns 10 -std::string copy{str_with_len_N};/128_median 106 ns 106 ns 10 -std::string copy{str_with_len_N};/128_stddev 6.50 ns 6.43 ns 10 -std::string copy{str_with_len_N};/128_cv 6.28 % 6.21 % 10 -std::string copy{str_with_len_N};/256_mean 105 ns 105 ns 10 -std::string copy{str_with_len_N};/256_median 107 ns 107 ns 10 -std::string copy{str_with_len_N};/256_stddev 5.83 ns 5.81 ns 10 -std::string copy{str_with_len_N};/256_cv 5.54 % 5.52 % 10 -std::string copy{str_with_len_N};/512_mean 97.1 ns 96.7 ns 10 -std::string copy{str_with_len_N};/512_median 94.0 ns 92.8 ns 10 -std::string copy{str_with_len_N};/512_stddev 8.76 ns 9.15 ns 10 -std::string copy{str_with_len_N};/512_cv 9.02 % 9.46 % 10 -std::string copy{str_with_len_N};/1024_mean 99.1 ns 98.8 ns 10 -std::string copy{str_with_len_N};/1024_median 97.8 ns 97.3 ns 10 -std::string copy{str_with_len_N};/1024_stddev 5.07 ns 5.39 ns 10 -std::string copy{str_with_len_N};/1024_cv 5.11 % 5.45 % 10 -std::string copy{str_with_len_N};/2048_mean 140 ns 139 ns 10 -std::string copy{str_with_len_N};/2048_median 139 ns 138 ns 10 -std::string copy{str_with_len_N};/2048_stddev 10.2 ns 10.6 ns 10 -std::string copy{str_with_len_N};/2048_cv 7.27 % 7.64 % 10 -std::string copy{str_with_len_N};/4096_mean 187 ns 186 ns 10 -std::string copy{str_with_len_N};/4096_median 186 ns 184 ns 10 -std::string copy{str_with_len_N};/4096_stddev 5.96 ns 7.18 ns 10 -std::string copy{str_with_len_N};/4096_cv 3.19 % 3.86 % 10 -stringa copy{str_with_len_N};/15_mean 4.03 ns 4.03 ns 10 -stringa copy{str_with_len_N};/15_median 4.03 ns 4.04 ns 10 -stringa copy{str_with_len_N};/15_stddev 0.040 ns 0.063 ns 10 -stringa copy{str_with_len_N};/15_cv 0.99 % 1.57 % 10 -stringa copy{str_with_len_N};/16_mean 4.09 ns 4.08 ns 10 -stringa copy{str_with_len_N};/16_median 4.08 ns 4.08 ns 10 -stringa copy{str_with_len_N};/16_stddev 0.074 ns 0.074 ns 10 -stringa copy{str_with_len_N};/16_cv 1.81 % 1.81 % 10 -stringa copy{str_with_len_N};/23_mean 4.06 ns 4.05 ns 10 -stringa copy{str_with_len_N};/23_median 4.04 ns 4.01 ns 10 -stringa copy{str_with_len_N};/23_stddev 0.085 ns 0.102 ns 10 -stringa copy{str_with_len_N};/23_cv 2.10 % 2.53 % 10 -stringa copy{str_with_len_N};/24_mean 18.7 ns 18.7 ns 10 -stringa copy{str_with_len_N};/24_median 18.6 ns 18.6 ns 10 -stringa copy{str_with_len_N};/24_stddev 0.551 ns 0.529 ns 10 -stringa copy{str_with_len_N};/24_cv 2.95 % 2.84 % 10 -stringa copy{str_with_len_N};/32_mean 18.6 ns 18.5 ns 10 +std::string copy{str_with_len_N};/15_mean 5.27 ns 5.17 ns 10 +std::string copy{str_with_len_N};/15_median 5.22 ns 5.16 ns 10 +std::string copy{str_with_len_N};/15_stddev 0.211 ns 0.155 ns 10 +std::string copy{str_with_len_N};/15_cv 4.00 % 3.00 % 10 +std::string copy{str_with_len_N};/16_mean 83.4 ns 83.2 ns 10 +std::string copy{str_with_len_N};/16_median 81.9 ns 82.0 ns 10 +std::string copy{str_with_len_N};/16_stddev 4.14 ns 4.20 ns 10 +std::string copy{str_with_len_N};/16_cv 4.96 % 5.04 % 10 +std::string copy{str_with_len_N};/23_mean 82.9 ns 82.3 ns 10 +std::string copy{str_with_len_N};/23_median 82.5 ns 81.1 ns 10 +std::string copy{str_with_len_N};/23_stddev 2.73 ns 2.94 ns 10 +std::string copy{str_with_len_N};/23_cv 3.30 % 3.57 % 10 +std::string copy{str_with_len_N};/24_mean 83.8 ns 82.4 ns 10 +std::string copy{str_with_len_N};/24_median 83.3 ns 81.6 ns 10 +std::string copy{str_with_len_N};/24_stddev 3.68 ns 3.30 ns 10 +std::string copy{str_with_len_N};/24_cv 4.39 % 4.00 % 10 +std::string copy{str_with_len_N};/32_mean 88.0 ns 87.7 ns 10 +std::string copy{str_with_len_N};/32_median 87.0 ns 87.9 ns 10 +std::string copy{str_with_len_N};/32_stddev 2.48 ns 2.30 ns 10 +std::string copy{str_with_len_N};/32_cv 2.82 % 2.63 % 10 +std::string copy{str_with_len_N};/64_mean 84.3 ns 83.5 ns 10 +std::string copy{str_with_len_N};/64_median 83.4 ns 83.7 ns 10 +std::string copy{str_with_len_N};/64_stddev 2.69 ns 2.51 ns 10 +std::string copy{str_with_len_N};/64_cv 3.19 % 3.00 % 10 +std::string copy{str_with_len_N};/128_mean 87.8 ns 87.5 ns 10 +std::string copy{str_with_len_N};/128_median 87.3 ns 87.9 ns 10 +std::string copy{str_with_len_N};/128_stddev 1.32 ns 1.65 ns 10 +std::string copy{str_with_len_N};/128_cv 1.51 % 1.89 % 10 +std::string copy{str_with_len_N};/256_mean 88.5 ns 88.1 ns 10 +std::string copy{str_with_len_N};/256_median 88.5 ns 87.9 ns 10 +std::string copy{str_with_len_N};/256_stddev 1.91 ns 2.30 ns 10 +std::string copy{str_with_len_N};/256_cv 2.16 % 2.61 % 10 +std::string copy{str_with_len_N};/512_mean 91.6 ns 91.0 ns 10 +std::string copy{str_with_len_N};/512_median 90.9 ns 90.0 ns 10 +std::string copy{str_with_len_N};/512_stddev 3.32 ns 3.31 ns 10 +std::string copy{str_with_len_N};/512_cv 3.63 % 3.63 % 10 +std::string copy{str_with_len_N};/1024_mean 99.9 ns 99.6 ns 10 +std::string copy{str_with_len_N};/1024_median 101 ns 99.4 ns 10 +std::string copy{str_with_len_N};/1024_stddev 2.94 ns 2.65 ns 10 +std::string copy{str_with_len_N};/1024_cv 2.95 % 2.66 % 10 +std::string copy{str_with_len_N};/2048_mean 129 ns 128 ns 10 +std::string copy{str_with_len_N};/2048_median 129 ns 126 ns 10 +std::string copy{str_with_len_N};/2048_stddev 4.47 ns 5.43 ns 10 +std::string copy{str_with_len_N};/2048_cv 3.46 % 4.26 % 10 +std::string copy{str_with_len_N};/4096_mean 177 ns 174 ns 10 +std::string copy{str_with_len_N};/4096_median 177 ns 174 ns 10 +std::string copy{str_with_len_N};/4096_stddev 3.85 ns 3.68 ns 10 +std::string copy{str_with_len_N};/4096_cv 2.17 % 2.11 % 10 +stringa copy{str_with_len_N};/15_mean 4.05 ns 4.02 ns 10 +stringa copy{str_with_len_N};/15_median 4.03 ns 4.01 ns 10 +stringa copy{str_with_len_N};/15_stddev 0.115 ns 0.104 ns 10 +stringa copy{str_with_len_N};/15_cv 2.85 % 2.60 % 10 +stringa copy{str_with_len_N};/16_mean 4.03 ns 4.02 ns 10 +stringa copy{str_with_len_N};/16_median 4.01 ns 4.00 ns 10 +stringa copy{str_with_len_N};/16_stddev 0.090 ns 0.109 ns 10 +stringa copy{str_with_len_N};/16_cv 2.22 % 2.72 % 10 +stringa copy{str_with_len_N};/23_mean 4.10 ns 4.04 ns 10 +stringa copy{str_with_len_N};/23_median 4.05 ns 4.04 ns 10 +stringa copy{str_with_len_N};/23_stddev 0.096 ns 0.048 ns 10 +stringa copy{str_with_len_N};/23_cv 2.34 % 1.18 % 10 +stringa copy{str_with_len_N};/24_mean 18.5 ns 18.4 ns 10 +stringa copy{str_with_len_N};/24_median 18.5 ns 18.4 ns 10 +stringa copy{str_with_len_N};/24_stddev 0.254 ns 0.218 ns 10 +stringa copy{str_with_len_N};/24_cv 1.37 % 1.19 % 10 +stringa copy{str_with_len_N};/32_mean 18.5 ns 18.4 ns 10 stringa copy{str_with_len_N};/32_median 18.5 ns 18.4 ns 10 -stringa copy{str_with_len_N};/32_stddev 0.450 ns 0.618 ns 10 -stringa copy{str_with_len_N};/32_cv 2.42 % 3.34 % 10 -stringa copy{str_with_len_N};/64_mean 18.9 ns 18.7 ns 10 -stringa copy{str_with_len_N};/64_median 18.4 ns 18.4 ns 10 -stringa copy{str_with_len_N};/64_stddev 0.854 ns 0.887 ns 10 -stringa copy{str_with_len_N};/64_cv 4.51 % 4.75 % 10 -stringa copy{str_with_len_N};/128_mean 18.4 ns 18.3 ns 10 -stringa copy{str_with_len_N};/128_median 18.3 ns 18.4 ns 10 -stringa copy{str_with_len_N};/128_stddev 0.179 ns 0.345 ns 10 -stringa copy{str_with_len_N};/128_cv 0.98 % 1.88 % 10 -stringa copy{str_with_len_N};/256_mean 18.6 ns 18.4 ns 10 -stringa copy{str_with_len_N};/256_median 18.4 ns 18.4 ns 10 -stringa copy{str_with_len_N};/256_stddev 0.484 ns 0.441 ns 10 -stringa copy{str_with_len_N};/256_cv 2.60 % 2.40 % 10 -stringa copy{str_with_len_N};/512_mean 19.5 ns 19.4 ns 10 -stringa copy{str_with_len_N};/512_median 19.7 ns 19.3 ns 10 -stringa copy{str_with_len_N};/512_stddev 1.11 ns 1.27 ns 10 -stringa copy{str_with_len_N};/512_cv 5.69 % 6.52 % 10 -stringa copy{str_with_len_N};/1024_mean 18.3 ns 18.2 ns 10 -stringa copy{str_with_len_N};/1024_median 18.3 ns 18.4 ns 10 -stringa copy{str_with_len_N};/1024_stddev 0.076 ns 0.293 ns 10 -stringa copy{str_with_len_N};/1024_cv 0.41 % 1.60 % 10 -stringa copy{str_with_len_N};/2048_mean 18.5 ns 18.3 ns 10 -stringa copy{str_with_len_N};/2048_median 18.4 ns 18.4 ns 10 -stringa copy{str_with_len_N};/2048_stddev 0.464 ns 0.324 ns 10 -stringa copy{str_with_len_N};/2048_cv 2.51 % 1.77 % 10 -stringa copy{str_with_len_N};/4096_mean 18.9 ns 18.8 ns 10 -stringa copy{str_with_len_N};/4096_median 18.5 ns 18.4 ns 10 -stringa copy{str_with_len_N};/4096_stddev 0.764 ns 0.878 ns 10 -stringa copy{str_with_len_N};/4096_cv 4.04 % 4.68 % 10 -lstringa<16> copy{str_with_len_N};/15_mean 7.85 ns 7.85 ns 10 -lstringa<16> copy{str_with_len_N};/15_median 7.76 ns 7.76 ns 10 -lstringa<16> copy{str_with_len_N};/15_stddev 0.249 ns 0.273 ns 10 -lstringa<16> copy{str_with_len_N};/15_cv 3.17 % 3.47 % 10 -lstringa<16> copy{str_with_len_N};/16_mean 8.07 ns 7.95 ns 10 -lstringa<16> copy{str_with_len_N};/16_median 7.84 ns 7.67 ns 10 -lstringa<16> copy{str_with_len_N};/16_stddev 0.878 ns 0.831 ns 10 -lstringa<16> copy{str_with_len_N};/16_cv 10.88 % 10.45 % 10 -lstringa<16> copy{str_with_len_N};/23_mean 7.94 ns 7.81 ns 10 -lstringa<16> copy{str_with_len_N};/23_median 7.84 ns 7.85 ns 10 -lstringa<16> copy{str_with_len_N};/23_stddev 0.303 ns 0.110 ns 10 -lstringa<16> copy{str_with_len_N};/23_cv 3.82 % 1.41 % 10 -lstringa<16> copy{str_with_len_N};/24_mean 82.8 ns 82.5 ns 10 -lstringa<16> copy{str_with_len_N};/24_median 82.6 ns 82.8 ns 10 -lstringa<16> copy{str_with_len_N};/24_stddev 1.55 ns 2.02 ns 10 -lstringa<16> copy{str_with_len_N};/24_cv 1.87 % 2.45 % 10 -lstringa<16> copy{str_with_len_N};/32_mean 85.5 ns 85.4 ns 10 -lstringa<16> copy{str_with_len_N};/32_median 85.5 ns 85.8 ns 10 -lstringa<16> copy{str_with_len_N};/32_stddev 1.49 ns 1.92 ns 10 -lstringa<16> copy{str_with_len_N};/32_cv 1.74 % 2.25 % 10 -lstringa<16> copy{str_with_len_N};/64_mean 85.1 ns 84.9 ns 10 -lstringa<16> copy{str_with_len_N};/64_median 84.2 ns 83.7 ns 10 -lstringa<16> copy{str_with_len_N};/64_stddev 2.49 ns 2.47 ns 10 -lstringa<16> copy{str_with_len_N};/64_cv 2.93 % 2.91 % 10 -lstringa<16> copy{str_with_len_N};/128_mean 89.8 ns 89.4 ns 10 -lstringa<16> copy{str_with_len_N};/128_median 89.0 ns 88.9 ns 10 -lstringa<16> copy{str_with_len_N};/128_stddev 2.82 ns 2.80 ns 10 -lstringa<16> copy{str_with_len_N};/128_cv 3.13 % 3.13 % 10 -lstringa<16> copy{str_with_len_N};/256_mean 655 ns 649 ns 10 -lstringa<16> copy{str_with_len_N};/256_median 653 ns 642 ns 10 -lstringa<16> copy{str_with_len_N};/256_stddev 12.4 ns 13.6 ns 10 -lstringa<16> copy{str_with_len_N};/256_cv 1.90 % 2.09 % 10 -lstringa<16> copy{str_with_len_N};/512_mean 92.5 ns 91.6 ns 10 -lstringa<16> copy{str_with_len_N};/512_median 92.8 ns 91.6 ns 10 -lstringa<16> copy{str_with_len_N};/512_stddev 3.03 ns 2.50 ns 10 -lstringa<16> copy{str_with_len_N};/512_cv 3.28 % 2.73 % 10 -lstringa<16> copy{str_with_len_N};/1024_mean 101 ns 98.9 ns 10 -lstringa<16> copy{str_with_len_N};/1024_median 99.0 ns 97.7 ns 10 -lstringa<16> copy{str_with_len_N};/1024_stddev 5.09 ns 5.55 ns 10 -lstringa<16> copy{str_with_len_N};/1024_cv 5.06 % 5.61 % 10 -lstringa<16> copy{str_with_len_N};/2048_mean 132 ns 131 ns 10 -lstringa<16> copy{str_with_len_N};/2048_median 131 ns 130 ns 10 -lstringa<16> copy{str_with_len_N};/2048_stddev 3.95 ns 4.45 ns 10 -lstringa<16> copy{str_with_len_N};/2048_cv 2.99 % 3.40 % 10 -lstringa<16> copy{str_with_len_N};/4096_mean 196 ns 194 ns 10 -lstringa<16> copy{str_with_len_N};/4096_median 197 ns 195 ns 10 -lstringa<16> copy{str_with_len_N};/4096_stddev 8.06 ns 8.83 ns 10 -lstringa<16> copy{str_with_len_N};/4096_cv 4.11 % 4.56 % 10 -lstringa<512> copy{str_with_len_N};/15_mean 8.62 ns 8.58 ns 10 -lstringa<512> copy{str_with_len_N};/15_median 8.51 ns 8.54 ns 10 -lstringa<512> copy{str_with_len_N};/15_stddev 0.324 ns 0.356 ns 10 -lstringa<512> copy{str_with_len_N};/15_cv 3.76 % 4.15 % 10 -lstringa<512> copy{str_with_len_N};/16_mean 8.94 ns 8.84 ns 10 -lstringa<512> copy{str_with_len_N};/16_median 8.65 ns 8.63 ns 10 -lstringa<512> copy{str_with_len_N};/16_stddev 0.625 ns 0.688 ns 10 -lstringa<512> copy{str_with_len_N};/16_cv 6.99 % 7.78 % 10 -lstringa<512> copy{str_with_len_N};/23_mean 8.67 ns 8.58 ns 10 -lstringa<512> copy{str_with_len_N};/23_median 8.53 ns 8.58 ns 10 -lstringa<512> copy{str_with_len_N};/23_stddev 0.469 ns 0.463 ns 10 -lstringa<512> copy{str_with_len_N};/23_cv 5.41 % 5.39 % 10 -lstringa<512> copy{str_with_len_N};/24_mean 8.44 ns 8.39 ns 10 -lstringa<512> copy{str_with_len_N};/24_median 8.45 ns 8.37 ns 10 -lstringa<512> copy{str_with_len_N};/24_stddev 0.183 ns 0.208 ns 10 -lstringa<512> copy{str_with_len_N};/24_cv 2.17 % 2.48 % 10 -lstringa<512> copy{str_with_len_N};/32_mean 12.0 ns 11.9 ns 10 -lstringa<512> copy{str_with_len_N};/32_median 11.9 ns 11.9 ns 10 -lstringa<512> copy{str_with_len_N};/32_stddev 0.246 ns 0.275 ns 10 -lstringa<512> copy{str_with_len_N};/32_cv 2.06 % 2.31 % 10 -lstringa<512> copy{str_with_len_N};/64_mean 12.1 ns 12.0 ns 10 -lstringa<512> copy{str_with_len_N};/64_median 12.0 ns 12.0 ns 10 -lstringa<512> copy{str_with_len_N};/64_stddev 0.503 ns 0.321 ns 10 -lstringa<512> copy{str_with_len_N};/64_cv 4.16 % 2.68 % 10 -lstringa<512> copy{str_with_len_N};/128_mean 12.3 ns 12.2 ns 10 -lstringa<512> copy{str_with_len_N};/128_median 12.3 ns 12.2 ns 10 -lstringa<512> copy{str_with_len_N};/128_stddev 0.130 ns 0.178 ns 10 -lstringa<512> copy{str_with_len_N};/128_cv 1.06 % 1.46 % 10 -lstringa<512> copy{str_with_len_N};/256_mean 13.2 ns 13.0 ns 10 -lstringa<512> copy{str_with_len_N};/256_median 12.9 ns 12.8 ns 10 -lstringa<512> copy{str_with_len_N};/256_stddev 0.876 ns 0.958 ns 10 -lstringa<512> copy{str_with_len_N};/256_cv 6.66 % 7.35 % 10 -lstringa<512> copy{str_with_len_N};/512_mean 14.6 ns 14.4 ns 10 -lstringa<512> copy{str_with_len_N};/512_median 14.6 ns 14.4 ns 10 -lstringa<512> copy{str_with_len_N};/512_stddev 0.416 ns 0.362 ns 10 -lstringa<512> copy{str_with_len_N};/512_cv 2.84 % 2.51 % 10 -lstringa<512> copy{str_with_len_N};/1024_mean 98.2 ns 97.9 ns 10 -lstringa<512> copy{str_with_len_N};/1024_median 99.0 ns 98.4 ns 10 -lstringa<512> copy{str_with_len_N};/1024_stddev 3.15 ns 3.24 ns 10 -lstringa<512> copy{str_with_len_N};/1024_cv 3.21 % 3.31 % 10 -lstringa<512> copy{str_with_len_N};/2048_mean 131 ns 130 ns 10 -lstringa<512> copy{str_with_len_N};/2048_median 131 ns 132 ns 10 -lstringa<512> copy{str_with_len_N};/2048_stddev 3.47 ns 3.03 ns 10 -lstringa<512> copy{str_with_len_N};/2048_cv 2.66 % 2.33 % 10 -lstringa<512> copy{str_with_len_N};/4096_mean 195 ns 193 ns 10 -lstringa<512> copy{str_with_len_N};/4096_median 193 ns 193 ns 10 -lstringa<512> copy{str_with_len_N};/4096_stddev 8.17 ns 8.37 ns 10 -lstringa<512> copy{str_with_len_N};/4096_cv 4.18 % 4.35 % 10 +stringa copy{str_with_len_N};/32_stddev 0.251 ns 0.313 ns 10 +stringa copy{str_with_len_N};/32_cv 1.35 % 1.70 % 10 +stringa copy{str_with_len_N};/64_mean 18.6 ns 18.5 ns 10 +stringa copy{str_with_len_N};/64_median 18.5 ns 18.4 ns 10 +stringa copy{str_with_len_N};/64_stddev 0.532 ns 0.385 ns 10 +stringa copy{str_with_len_N};/64_cv 2.85 % 2.08 % 10 +stringa copy{str_with_len_N};/128_mean 18.5 ns 18.1 ns 10 +stringa copy{str_with_len_N};/128_median 18.5 ns 18.0 ns 10 +stringa copy{str_with_len_N};/128_stddev 0.403 ns 0.316 ns 10 +stringa copy{str_with_len_N};/128_cv 2.18 % 1.74 % 10 +stringa copy{str_with_len_N};/256_mean 18.5 ns 18.4 ns 10 +stringa copy{str_with_len_N};/256_median 18.5 ns 18.4 ns 10 +stringa copy{str_with_len_N};/256_stddev 0.340 ns 0.366 ns 10 +stringa copy{str_with_len_N};/256_cv 1.84 % 1.99 % 10 +stringa copy{str_with_len_N};/512_mean 18.4 ns 18.2 ns 10 +stringa copy{str_with_len_N};/512_median 18.3 ns 18.2 ns 10 +stringa copy{str_with_len_N};/512_stddev 0.276 ns 0.293 ns 10 +stringa copy{str_with_len_N};/512_cv 1.50 % 1.60 % 10 +stringa copy{str_with_len_N};/1024_mean 18.9 ns 18.8 ns 10 +stringa copy{str_with_len_N};/1024_median 18.7 ns 18.6 ns 10 +stringa copy{str_with_len_N};/1024_stddev 0.739 ns 0.711 ns 10 +stringa copy{str_with_len_N};/1024_cv 3.91 % 3.78 % 10 +stringa copy{str_with_len_N};/2048_mean 18.4 ns 18.2 ns 10 +stringa copy{str_with_len_N};/2048_median 18.3 ns 18.0 ns 10 +stringa copy{str_with_len_N};/2048_stddev 0.265 ns 0.296 ns 10 +stringa copy{str_with_len_N};/2048_cv 1.44 % 1.63 % 10 +stringa copy{str_with_len_N};/4096_mean 18.3 ns 18.3 ns 10 +stringa copy{str_with_len_N};/4096_median 18.3 ns 18.4 ns 10 +stringa copy{str_with_len_N};/4096_stddev 0.201 ns 0.324 ns 10 +stringa copy{str_with_len_N};/4096_cv 1.10 % 1.77 % 10 +lstringa<16> copy{str_with_len_N};/15_mean 7.84 ns 7.80 ns 10 +lstringa<16> copy{str_with_len_N};/15_median 7.79 ns 7.85 ns 10 +lstringa<16> copy{str_with_len_N};/15_stddev 0.204 ns 0.118 ns 10 +lstringa<16> copy{str_with_len_N};/15_cv 2.60 % 1.51 % 10 +lstringa<16> copy{str_with_len_N};/16_mean 7.89 ns 7.78 ns 10 +lstringa<16> copy{str_with_len_N};/16_median 7.82 ns 7.74 ns 10 +lstringa<16> copy{str_with_len_N};/16_stddev 0.209 ns 0.132 ns 10 +lstringa<16> copy{str_with_len_N};/16_cv 2.65 % 1.70 % 10 +lstringa<16> copy{str_with_len_N};/23_mean 7.73 ns 7.71 ns 10 +lstringa<16> copy{str_with_len_N};/23_median 7.68 ns 7.67 ns 10 +lstringa<16> copy{str_with_len_N};/23_stddev 0.151 ns 0.138 ns 10 +lstringa<16> copy{str_with_len_N};/23_cv 1.96 % 1.78 % 10 +lstringa<16> copy{str_with_len_N};/24_mean 82.1 ns 81.6 ns 10 +lstringa<16> copy{str_with_len_N};/24_median 81.9 ns 81.6 ns 10 +lstringa<16> copy{str_with_len_N};/24_stddev 3.09 ns 2.96 ns 10 +lstringa<16> copy{str_with_len_N};/24_cv 3.76 % 3.63 % 10 +lstringa<16> copy{str_with_len_N};/32_mean 84.1 ns 83.7 ns 10 +lstringa<16> copy{str_with_len_N};/32_median 83.9 ns 83.7 ns 10 +lstringa<16> copy{str_with_len_N};/32_stddev 1.82 ns 1.42 ns 10 +lstringa<16> copy{str_with_len_N};/32_cv 2.16 % 1.70 % 10 +lstringa<16> copy{str_with_len_N};/64_mean 84.8 ns 84.2 ns 10 +lstringa<16> copy{str_with_len_N};/64_median 82.9 ns 82.0 ns 10 +lstringa<16> copy{str_with_len_N};/64_stddev 4.78 ns 4.87 ns 10 +lstringa<16> copy{str_with_len_N};/64_cv 5.63 % 5.78 % 10 +lstringa<16> copy{str_with_len_N};/128_mean 84.7 ns 83.7 ns 10 +lstringa<16> copy{str_with_len_N};/128_median 83.8 ns 83.7 ns 10 +lstringa<16> copy{str_with_len_N};/128_stddev 2.94 ns 2.61 ns 10 +lstringa<16> copy{str_with_len_N};/128_cv 3.47 % 3.12 % 10 +lstringa<16> copy{str_with_len_N};/256_mean 649 ns 646 ns 10 +lstringa<16> copy{str_with_len_N};/256_median 643 ns 642 ns 10 +lstringa<16> copy{str_with_len_N};/256_stddev 15.9 ns 11.5 ns 10 +lstringa<16> copy{str_with_len_N};/256_cv 2.45 % 1.78 % 10 +lstringa<16> copy{str_with_len_N};/512_mean 91.6 ns 89.8 ns 10 +lstringa<16> copy{str_with_len_N};/512_median 89.9 ns 87.9 ns 10 +lstringa<16> copy{str_with_len_N};/512_stddev 4.09 ns 3.62 ns 10 +lstringa<16> copy{str_with_len_N};/512_cv 4.47 % 4.03 % 10 +lstringa<16> copy{str_with_len_N};/1024_mean 96.2 ns 95.8 ns 10 +lstringa<16> copy{str_with_len_N};/1024_median 97.3 ns 96.3 ns 10 +lstringa<16> copy{str_with_len_N};/1024_stddev 2.69 ns 1.92 ns 10 +lstringa<16> copy{str_with_len_N};/1024_cv 2.80 % 2.01 % 10 +lstringa<16> copy{str_with_len_N};/2048_mean 128 ns 127 ns 10 +lstringa<16> copy{str_with_len_N};/2048_median 129 ns 126 ns 10 +lstringa<16> copy{str_with_len_N};/2048_stddev 5.41 ns 5.62 ns 10 +lstringa<16> copy{str_with_len_N};/2048_cv 4.21 % 4.43 % 10 +lstringa<16> copy{str_with_len_N};/4096_mean 185 ns 182 ns 10 +lstringa<16> copy{str_with_len_N};/4096_median 185 ns 182 ns 10 +lstringa<16> copy{str_with_len_N};/4096_stddev 4.32 ns 6.00 ns 10 +lstringa<16> copy{str_with_len_N};/4096_cv 2.34 % 3.30 % 10 +lstringa<512> copy{str_with_len_N};/15_mean 8.54 ns 8.43 ns 10 +lstringa<512> copy{str_with_len_N};/15_median 8.50 ns 8.37 ns 10 +lstringa<512> copy{str_with_len_N};/15_stddev 0.107 ns 0.141 ns 10 +lstringa<512> copy{str_with_len_N};/15_cv 1.25 % 1.67 % 10 +lstringa<512> copy{str_with_len_N};/16_mean 8.63 ns 8.62 ns 10 +lstringa<512> copy{str_with_len_N};/16_median 8.50 ns 8.51 ns 10 +lstringa<512> copy{str_with_len_N};/16_stddev 0.377 ns 0.420 ns 10 +lstringa<512> copy{str_with_len_N};/16_cv 4.37 % 4.87 % 10 +lstringa<512> copy{str_with_len_N};/23_mean 8.58 ns 8.50 ns 10 +lstringa<512> copy{str_with_len_N};/23_median 8.56 ns 8.58 ns 10 +lstringa<512> copy{str_with_len_N};/23_stddev 0.136 ns 0.108 ns 10 +lstringa<512> copy{str_with_len_N};/23_cv 1.59 % 1.27 % 10 +lstringa<512> copy{str_with_len_N};/24_mean 8.55 ns 8.52 ns 10 +lstringa<512> copy{str_with_len_N};/24_median 8.49 ns 8.48 ns 10 +lstringa<512> copy{str_with_len_N};/24_stddev 0.246 ns 0.280 ns 10 +lstringa<512> copy{str_with_len_N};/24_cv 2.87 % 3.29 % 10 +lstringa<512> copy{str_with_len_N};/32_mean 11.5 ns 11.4 ns 10 +lstringa<512> copy{str_with_len_N};/32_median 11.4 ns 11.4 ns 10 +lstringa<512> copy{str_with_len_N};/32_stddev 0.298 ns 0.244 ns 10 +lstringa<512> copy{str_with_len_N};/32_cv 2.59 % 2.14 % 10 +lstringa<512> copy{str_with_len_N};/64_mean 11.9 ns 11.7 ns 10 +lstringa<512> copy{str_with_len_N};/64_median 11.9 ns 11.7 ns 10 +lstringa<512> copy{str_with_len_N};/64_stddev 0.441 ns 0.382 ns 10 +lstringa<512> copy{str_with_len_N};/64_cv 3.71 % 3.27 % 10 +lstringa<512> copy{str_with_len_N};/128_mean 12.1 ns 11.8 ns 10 +lstringa<512> copy{str_with_len_N};/128_median 12.1 ns 11.7 ns 10 +lstringa<512> copy{str_with_len_N};/128_stddev 0.349 ns 0.328 ns 10 +lstringa<512> copy{str_with_len_N};/128_cv 2.89 % 2.77 % 10 +lstringa<512> copy{str_with_len_N};/256_mean 13.0 ns 12.8 ns 10 +lstringa<512> copy{str_with_len_N};/256_median 12.9 ns 12.9 ns 10 +lstringa<512> copy{str_with_len_N};/256_stddev 0.254 ns 0.386 ns 10 +lstringa<512> copy{str_with_len_N};/256_cv 1.96 % 3.01 % 10 +lstringa<512> copy{str_with_len_N};/512_mean 14.3 ns 14.3 ns 10 +lstringa<512> copy{str_with_len_N};/512_median 14.3 ns 14.3 ns 10 +lstringa<512> copy{str_with_len_N};/512_stddev 0.162 ns 0.219 ns 10 +lstringa<512> copy{str_with_len_N};/512_cv 1.13 % 1.54 % 10 +lstringa<512> copy{str_with_len_N};/1024_mean 97.2 ns 97.3 ns 10 +lstringa<512> copy{str_with_len_N};/1024_median 95.8 ns 96.3 ns 10 +lstringa<512> copy{str_with_len_N};/1024_stddev 3.21 ns 3.45 ns 10 +lstringa<512> copy{str_with_len_N};/1024_cv 3.30 % 3.55 % 10 +lstringa<512> copy{str_with_len_N};/2048_mean 127 ns 126 ns 10 +lstringa<512> copy{str_with_len_N};/2048_median 125 ns 123 ns 10 +lstringa<512> copy{str_with_len_N};/2048_stddev 6.82 ns 7.42 ns 10 +lstringa<512> copy{str_with_len_N};/2048_cv 5.38 % 5.88 % 10 +lstringa<512> copy{str_with_len_N};/4096_mean 186 ns 184 ns 10 +lstringa<512> copy{str_with_len_N};/4096_median 187 ns 184 ns 10 +lstringa<512> copy{str_with_len_N};/4096_stddev 6.34 ns 7.34 ns 10 +lstringa<512> copy{str_with_len_N};/4096_cv 3.41 % 3.99 % 10 ----- Convert to int '1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_mean 32.4 ns 32.2 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 32.5 ns 32.1 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 0.397 ns 0.455 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 1.23 % 1.42 % 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 15.0 ns 15.0 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 15.1 ns 15.2 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.852 ns 0.770 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 5.68 % 5.14 % 10 -stringa s = "123456789"; int res = s.to_int_mean 15.3 ns 15.1 ns 10 -stringa s = "123456789"; int res = s.to_int_median 14.9 ns 14.9 ns 10 -stringa s = "123456789"; int res = s.to_int_stddev 0.752 ns 0.501 ns 10 -stringa s = "123456789"; int res = s.to_int_cv 4.93 % 3.32 % 10 -ssa s = "123456789"; int res = s.to_int_mean 16.2 ns 15.8 ns 10 -ssa s = "123456789"; int res = s.to_int_median 16.3 ns 15.5 ns 10 -ssa s = "123456789"; int res = s.to_int_stddev 0.833 ns 0.768 ns 10 -ssa s = "123456789"; int res = s.to_int_cv 5.13 % 4.87 % 10 -lstringa<20> s = "123456789"; int res = s.to_int_mean 15.9 ns 15.5 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_median 16.0 ns 15.5 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_stddev 0.591 ns 0.499 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_cv 3.71 % 3.22 % 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_mean 32.2 ns 32.1 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 31.9 ns 32.1 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 0.839 ns 0.870 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 2.60 % 2.71 % 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 13.8 ns 13.7 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 13.7 ns 13.7 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.442 ns 0.359 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 3.21 % 2.62 % 10 +stringa s = "123456789"; int res = s.to_int_mean 15.7 ns 15.7 ns 10 +stringa s = "123456789"; int res = s.to_int_median 15.5 ns 15.5 ns 10 +stringa s = "123456789"; int res = s.to_int_stddev 0.567 ns 0.531 ns 10 +stringa s = "123456789"; int res = s.to_int_cv 3.61 % 3.39 % 10 +ssa s = "123456789"; int res = s.to_int_mean 15.1 ns 14.9 ns 10 +ssa s = "123456789"; int res = s.to_int_median 15.0 ns 14.8 ns 10 +ssa s = "123456789"; int res = s.to_int_stddev 0.325 ns 0.449 ns 10 +ssa s = "123456789"; int res = s.to_int_cv 2.16 % 3.00 % 10 +lstringa<20> s = "123456789"; int res = s.to_int_mean 16.1 ns 15.9 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_median 16.1 ns 15.9 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_stddev 0.287 ns 0.287 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_cv 1.79 % 1.80 % 10 ----- Convert to unsigned 'abcDef' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 35.7 ns 35.3 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 35.6 ns 35.7 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 0.826 ns 0.617 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 2.31 % 1.75 % 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 9.90 ns 9.75 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 9.83 ns 9.84 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 0.322 ns 0.176 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 3.25 % 1.81 % 10 -stringa s = "abcDef"; int res = s.to_int_mean 14.6 ns 14.3 ns 10 -stringa s = "abcDef"; int res = s.to_int_median 14.5 ns 14.2 ns 10 -stringa s = "abcDef"; int res = s.to_int_stddev 0.426 ns 0.353 ns 10 -stringa s = "abcDef"; int res = s.to_int_cv 2.93 % 2.46 % 10 -ssa s = "abcDef"; int res = s.to_int_mean 14.0 ns 13.6 ns 10 -ssa s = "abcDef"; int res = s.to_int_median 13.8 ns 13.7 ns 10 -ssa s = "abcDef"; int res = s.to_int_stddev 0.442 ns 0.176 ns 10 -ssa s = "abcDef"; int res = s.to_int_cv 3.16 % 1.30 % 10 -lstringa<20> s = "abcDef"; int res = s.to_int_mean 13.9 ns 13.7 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_median 13.6 ns 13.5 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_stddev 0.600 ns 0.368 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_cv 4.32 % 2.69 % 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 35.1 ns 34.8 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 34.9 ns 34.5 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 1.07 ns 1.04 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 3.04 % 2.97 % 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 9.56 ns 9.52 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 9.46 ns 9.42 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 0.246 ns 0.320 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 2.57 % 3.37 % 10 +stringa s = "abcDef"; int res = s.to_int_mean 13.5 ns 13.1 ns 10 +stringa s = "abcDef"; int res = s.to_int_median 13.3 ns 13.2 ns 10 +stringa s = "abcDef"; int res = s.to_int_stddev 0.431 ns 0.212 ns 10 +stringa s = "abcDef"; int res = s.to_int_cv 3.20 % 1.62 % 10 +ssa s = "abcDef"; int res = s.to_int_mean 13.0 ns 12.8 ns 10 +ssa s = "abcDef"; int res = s.to_int_median 12.8 ns 12.8 ns 10 +ssa s = "abcDef"; int res = s.to_int_stddev 0.294 ns 0.263 ns 10 +ssa s = "abcDef"; int res = s.to_int_cv 2.27 % 2.05 % 10 +lstringa<20> s = "abcDef"; int res = s.to_int_mean 13.3 ns 13.2 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_median 13.1 ns 13.1 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_stddev 0.427 ns 0.256 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_cv 3.22 % 1.95 % 10 ----- Convert to int ' 1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_mean 47.2 ns 46.1 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 47.6 ns 45.4 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 1.81 ns 1.51 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 3.83 % 3.28 % 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 20.0 ns 19.8 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 20.1 ns 20.1 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 1.14 ns 1.26 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 5.72 % 6.38 % 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 18.5 ns 18.2 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 18.3 ns 18.2 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.872 ns 0.630 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 4.71 % 3.47 % 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_mean 45.3 ns 44.8 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 45.3 ns 44.9 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 1.32 ns 0.971 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 2.92 % 2.17 % 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 19.7 ns 19.5 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 19.6 ns 19.3 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 0.325 ns 0.356 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 1.65 % 1.83 % 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 17.7 ns 17.5 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 17.7 ns 17.6 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.306 ns 0.282 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 1.73 % 1.62 % 10 ----- Convert to double '1234.567e10' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 106 ns 103 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_median 106 ns 101 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 3.88 ns 5.53 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 3.67 % 5.35 % 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 85.6 ns 83.4 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 85.1 ns 82.8 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 3.98 ns 2.30 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 4.65 % 2.75 % 10 -ssa s = "1234.567e10"; double res = *s.to_double()_mean 37.7 ns 37.1 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_median 37.8 ns 37.7 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_stddev 1.27 ns 1.26 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_cv 3.38 % 3.38 % 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 102 ns 101 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_median 101 ns 100 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 2.49 ns 2.76 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 2.44 % 2.73 % 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 76.5 ns 76.2 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 75.7 ns 75.9 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 2.73 ns 2.73 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 3.57 % 3.59 % 10 +ssa s = "1234.567e10"; double res = *s.to_double()_mean 36.6 ns 36.3 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_median 36.1 ns 36.1 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_stddev 1.09 ns 0.986 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_cv 2.99 % 2.72 % 10 -- Append const literal of 16 bytes 64 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << "abbaabbaabbaabba";_mean 5830 ns 5720 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_median 5859 ns 5650 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 286 ns 218 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_cv 4.90 % 3.81 % 10 -std::string str; ... str += "abbaabbaabbaabba";_mean 1313 ns 1300 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_median 1287 ns 1287 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_stddev 60.3 ns 44.9 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_cv 4.59 % 3.45 % 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 973 ns 958 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_median 958 ns 952 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 47.7 ns 38.0 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 4.90 % 3.96 % 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 541 ns 539 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_median 542 ns 539 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 10.1 ns 13.3 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 1.87 % 2.46 % 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 365 ns 363 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_median 363 ns 361 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 11.3 ns 12.0 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 3.11 % 3.30 % 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 254 ns 251 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_median 252 ns 254 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 9.08 ns 6.52 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_cv 3.57 % 2.60 % 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_mean 5705 ns 5706 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_median 5476 ns 5511 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 425 ns 443 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_cv 7.44 % 7.77 % 10 +std::string str; ... str += "abbaabbaabbaabba";_mean 1288 ns 1278 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_median 1272 ns 1270 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_stddev 52.8 ns 48.9 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_cv 4.10 % 3.82 % 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 923 ns 911 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_median 915 ns 903 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 34.1 ns 28.3 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 3.69 % 3.11 % 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 531 ns 527 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_median 525 ns 523 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 14.9 ns 16.6 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 2.81 % 3.14 % 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 349 ns 346 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_median 348 ns 345 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 5.90 ns 5.66 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 1.69 % 1.64 % 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 234 ns 232 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_median 234 ns 229 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 4.73 ns 4.75 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_cv 2.02 % 2.05 % 10 -- Append string of 16 bytes and const literal of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 5571 ns 5547 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 5587 ns 5625 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 161 ns 184 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 2.88 % 3.32 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 4182 ns 4187 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_median 4019 ns 4051 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 473 ns 453 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 11.30 % 10.83 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 827 ns 818 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 821 ns 816 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 13.5 ns 15.4 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 1.63 % 1.89 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 542 ns 534 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 537 ns 530 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 18.1 ns 6.74 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 3.34 % 1.26 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 381 ns 380 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 376 ns 372 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 15.9 ns 18.4 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 4.17 % 4.83 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 271 ns 270 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 269 ns 270 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 7.20 ns 6.62 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 2.66 % 2.45 % 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 5637 ns 5500 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 5631 ns 5469 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 259 ns 123 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 4.60 % 2.24 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 3881 ns 3845 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_median 3863 ns 3836 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 85.9 ns 49.5 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 2.21 % 1.29 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 839 ns 828 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 835 ns 828 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 18.8 ns 18.8 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 2.24 % 2.27 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 533 ns 527 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 526 ns 523 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 27.6 ns 23.4 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.18 % 4.43 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 387 ns 379 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 390 ns 377 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 13.0 ns 11.8 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 3.35 % 3.13 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 285 ns 279 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 286 ns 276 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 9.43 ns 10.1 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 3.31 % 3.62 % 10 -- Append string of 16 bytes and const literal of 16 bytes 2048 times, 65536 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 284627 ns 281865 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 284009 ns 282493 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 11243 ns 7516 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 3.95 % 2.67 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 193928 ns 192121 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 193685 ns 192540 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 4904 ns 3665 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.53 % 1.91 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 23525 ns 23333 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 23269 ns 23280 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 737 ns 505 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.13 % 2.17 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 22444 ns 22168 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 22628 ns 22217 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 812 ns 1035 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.62 % 4.67 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 22848 ns 22656 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 22732 ns 22705 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 519 ns 573 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.27 % 2.53 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 21680 ns 21484 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 21456 ns 21484 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 666 ns 515 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.07 % 2.40 % 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 274181 ns 271821 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 272079 ns 269938 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 6678 ns 7279 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 2.44 % 2.68 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 196295 ns 193795 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 196074 ns 192540 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 5109 ns 6559 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.60 % 3.38 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 23926 ns 23242 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 23566 ns 22949 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 1393 ns 573 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 5.82 % 2.47 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 22113 ns 21777 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 22164 ns 21484 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 539 ns 573 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 2.44 % 2.63 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 23784 ns 23646 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 23238 ns 23019 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 1312 ns 1369 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 5.51 % 5.79 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 22963 ns 22851 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 22728 ns 22670 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 784 ns 805 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.42 % 3.52 % 10 -- Append 2 string of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var1 << str_var2;_mean 5453 ns 5406 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_median 5451 ns 5391 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_stddev 231 ns 168 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_cv 4.24 % 3.11 % 10 -std::string str; ... str += str_var1 + str_var2;_mean 4415 ns 4371 ns 10 -std::string str; ... str += str_var1 + str_var2;_median 4393 ns 4353 ns 10 -std::string str; ... str += str_var1 + str_var2;_stddev 385 ns 377 ns 10 -std::string str; ... str += str_var1 + str_var2;_cv 8.72 % 8.63 % 10 -lstringa<16> str; ... str += str_var1 + str_var2;_mean 959 ns 942 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_median 940 ns 921 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_stddev 57.9 ns 45.2 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_cv 6.04 % 4.80 % 10 -lstringa<128> str; ... str += str_var1 + str_var2;_mean 656 ns 646 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_median 647 ns 642 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_stddev 28.2 ns 18.7 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_cv 4.30 % 2.89 % 10 -lstringa<512> str; ... str += str_var1 + str_var2;_mean 484 ns 478 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_median 483 ns 481 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_stddev 14.5 ns 9.93 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_cv 3.00 % 2.08 % 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_mean 388 ns 382 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_median 379 ns 377 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 30.0 ns 22.8 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_cv 7.74 % 5.96 % 10 +std::stringstream str; ... str << str_var1 << str_var2;_mean 5373 ns 5281 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_median 5528 ns 5234 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_stddev 262 ns 231 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_cv 4.88 % 4.37 % 10 +std::string str; ... str += str_var1 + str_var2;_mean 3964 ns 3889 ns 10 +std::string str; ... str += str_var1 + str_var2;_median 3945 ns 3861 ns 10 +std::string str; ... str += str_var1 + str_var2;_stddev 102 ns 89.3 ns 10 +std::string str; ... str += str_var1 + str_var2;_cv 2.57 % 2.30 % 10 +lstringa<16> str; ... str += str_var1 + str_var2;_mean 932 ns 914 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_median 922 ns 889 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_stddev 45.8 ns 47.4 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_cv 4.91 % 5.18 % 10 +lstringa<128> str; ... str += str_var1 + str_var2;_mean 597 ns 596 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_median 596 ns 600 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_stddev 9.11 ns 9.42 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_cv 1.53 % 1.58 % 10 +lstringa<512> str; ... str += str_var1 + str_var2;_mean 449 ns 448 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_median 446 ns 449 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_stddev 7.41 ns 9.71 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_cv 1.65 % 2.17 % 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_mean 353 ns 350 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_median 351 ns 349 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 6.61 ns 8.67 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_cv 1.87 % 2.48 % 10 -- Append text, number, text --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; str << "test = " << k << " times";_mean 12174 ns 12137 ns 10 -std::stringstream str; str << "test = " << k << " times";_median 11764 ns 11719 ns 10 -std::stringstream str; str << "test = " << k << " times";_stddev 1156 ns 1164 ns 10 -std::stringstream str; str << "test = " << k << " times";_cv 9.50 % 9.59 % 10 -std::string str = "test = " + std::to_string(k) + " times";_mean 1244 ns 1239 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_median 1242 ns 1242 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_stddev 22.1 ns 27.0 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_cv 1.78 % 2.18 % 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 2886 ns 2856 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 2866 ns 2825 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 70.1 ns 79.7 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 2.43 % 2.79 % 10 -std::string str = std::format("test = {} times", k);_mean 2480 ns 2455 ns 10 -std::string str = std::format("test = {} times", k);_median 2463 ns 2426 ns 10 -std::string str = std::format("test = {} times", k);_stddev 103 ns 102 ns 10 -std::string str = std::format("test = {} times", k);_cv 4.16 % 4.13 % 10 -lstringa<8> str; str.format("test = {} times", k);_mean 2641 ns 2621 ns 10 -lstringa<8> str; str.format("test = {} times", k);_median 2628 ns 2609 ns 10 -lstringa<8> str; str.format("test = {} times", k);_stddev 73.3 ns 67.3 ns 10 -lstringa<8> str; str.format("test = {} times", k);_cv 2.77 % 2.57 % 10 -lstringa<32> str; str.format("test = {} times", k);_mean 1551 ns 1538 ns 10 -lstringa<32> str; str.format("test = {} times", k);_median 1550 ns 1535 ns 10 -lstringa<32> str; str.format("test = {} times", k);_stddev 30.9 ns 25.7 ns 10 -lstringa<32> str; str.format("test = {} times", k);_cv 1.99 % 1.67 % 10 -lstringa<8> str = "test = " + k + " times";_mean 911 ns 906 ns 10 -lstringa<8> str = "test = " + k + " times";_median 912 ns 903 ns 10 -lstringa<8> str = "test = " + k + " times";_stddev 19.4 ns 18.0 ns 10 -lstringa<8> str = "test = " + k + " times";_cv 2.13 % 1.99 % 10 -lstringa<32> str = "test = " + k + " times";_mean 195 ns 192 ns 10 -lstringa<32> str = "test = " + k + " times";_median 192 ns 190 ns 10 -lstringa<32> str = "test = " + k + " times";_stddev 5.69 ns 5.32 ns 10 -lstringa<32> str = "test = " + k + " times";_cv 2.92 % 2.77 % 10 -stringa str = "test = " + k + " times";_mean 247 ns 244 ns 10 -stringa str = "test = " + k + " times";_median 243 ns 244 ns 10 -stringa str = "test = " + k + " times";_stddev 11.5 ns 6.58 ns 10 -stringa str = "test = " + k + " times";_cv 4.68 % 2.69 % 10 +std::stringstream str; str << "test = " << k << " times";_mean 11252 ns 11143 ns 10 +std::stringstream str; str << "test = " << k << " times";_median 11193 ns 10986 ns 10 +std::stringstream str; str << "test = " << k << " times";_stddev 294 ns 398 ns 10 +std::stringstream str; str << "test = " << k << " times";_cv 2.61 % 3.58 % 10 +std::string str = "test = " + std::to_string(k) + " times";_mean 1222 ns 1216 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_median 1221 ns 1221 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_stddev 22.2 ns 22.4 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_cv 1.82 % 1.85 % 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 2807 ns 2800 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 2814 ns 2825 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 48.0 ns 43.9 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 1.71 % 1.57 % 10 +std::string str = std::format("test = {} times", k);_mean 2421 ns 2412 ns 10 +std::string str = std::format("test = {} times", k);_median 2380 ns 2407 ns 10 +std::string str = std::format("test = {} times", k);_stddev 88.1 ns 71.7 ns 10 +std::string str = std::format("test = {} times", k);_cv 3.64 % 2.97 % 10 +lstringa<8> str; str.format("test = {} times", k);_mean 2671 ns 2633 ns 10 +lstringa<8> str; str.format("test = {} times", k);_median 2648 ns 2609 ns 10 +lstringa<8> str; str.format("test = {} times", k);_stddev 70.0 ns 50.0 ns 10 +lstringa<8> str; str.format("test = {} times", k);_cv 2.62 % 1.90 % 10 +lstringa<32> str; str.format("test = {} times", k);_mean 1531 ns 1523 ns 10 +lstringa<32> str; str.format("test = {} times", k);_median 1522 ns 1515 ns 10 +lstringa<32> str; str.format("test = {} times", k);_stddev 32.6 ns 44.5 ns 10 +lstringa<32> str; str.format("test = {} times", k);_cv 2.13 % 2.92 % 10 +lstringa<8> str = "test = " + k + " times";_mean 880 ns 872 ns 10 +lstringa<8> str = "test = " + k + " times";_median 880 ns 872 ns 10 +lstringa<8> str = "test = " + k + " times";_stddev 19.1 ns 16.4 ns 10 +lstringa<8> str = "test = " + k + " times";_cv 2.17 % 1.89 % 10 +lstringa<32> str = "test = " + k + " times";_mean 187 ns 182 ns 10 +lstringa<32> str = "test = " + k + " times";_median 188 ns 181 ns 10 +lstringa<32> str = "test = " + k + " times";_stddev 5.30 ns 4.63 ns 10 +lstringa<32> str = "test = " + k + " times";_cv 2.84 % 2.54 % 10 +stringa str = "test = " + k + " times";_mean 236 ns 234 ns 10 +stringa str = "test = " + k + " times";_median 231 ns 232 ns 10 +stringa str = "test = " + k + " times";_stddev 10.9 ns 9.21 ns 10 +stringa str = "test = " + k + " times";_cv 4.62 % 3.93 % 10 -- Split text and convert to int --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string::find + substr + std::strtol_mean 571 ns 564 ns 10 -std::string::find + substr + std::strtol_median 562 ns 562 ns 10 -std::string::find + substr + std::strtol_stddev 24.3 ns 23.8 ns 10 -std::string::find + substr + std::strtol_cv 4.26 % 4.22 % 10 -ssa::splitter + ssa::as_int_mean 311 ns 304 ns 10 -ssa::splitter + ssa::as_int_median 308 ns 301 ns 10 -ssa::splitter + ssa::as_int_stddev 16.7 ns 10.4 ns 10 -ssa::splitter + ssa::as_int_cv 5.38 % 3.40 % 10 -ssa::splitf + functor_mean 220 ns 216 ns 10 -ssa::splitf + functor_median 217 ns 215 ns 10 -ssa::splitf + functor_stddev 7.86 ns 6.11 ns 10 -ssa::splitf + functor_cv 3.58 % 2.83 % 10 +std::string::find + substr + std::strtol_mean 550 ns 539 ns 10 +std::string::find + substr + std::strtol_median 544 ns 530 ns 10 +std::string::find + substr + std::strtol_stddev 21.9 ns 13.5 ns 10 +std::string::find + substr + std::strtol_cv 3.99 % 2.50 % 10 +ssa::splitter + ssa::as_int_mean 303 ns 300 ns 10 +ssa::splitter + ssa::as_int_median 303 ns 295 ns 10 +ssa::splitter + ssa::as_int_stddev 15.1 ns 17.4 ns 10 +ssa::splitter + ssa::as_int_cv 4.98 % 5.80 % 10 +ssa::splitf + functor_mean 217 ns 214 ns 10 +ssa::splitf + functor_median 217 ns 212 ns 10 +ssa::splitf + functor_stddev 5.38 ns 6.73 ns 10 +ssa::splitf + functor_cv 2.49 % 3.15 % 10 -- Replace symbols in text ~400 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Naive (and wrong) replace symbols with std::string find + replace_mean 1258 ns 1247 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_median 1241 ns 1228 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_stddev 44.5 ns 37.3 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_cv 3.54 % 2.99 % 10 -replace symbols with std::string find_first_of + replace_mean 2344 ns 2317 ns 10 -replace symbols with std::string find_first_of + replace_median 2350 ns 2312 ns 10 -replace symbols with std::string find_first_of + replace_stddev 183 ns 179 ns 10 -replace symbols with std::string find_first_of + replace_cv 7.80 % 7.74 % 10 -replace symbols with std::string_view find_first_of + copy_mean 2606 ns 2600 ns 10 -replace symbols with std::string_view find_first_of + copy_median 2547 ns 2511 ns 10 -replace symbols with std::string_view find_first_of + copy_stddev 175 ns 188 ns 10 -replace symbols with std::string_view find_first_of + copy_cv 6.70 % 7.23 % 10 -replace runtime symbols with string expressions and without remembering all search results_mean 1524 ns 1521 ns 10 -replace runtime symbols with string expressions and without remembering all search results_median 1515 ns 1517 ns 10 -replace runtime symbols with string expressions and without remembering all search results_stddev 48.0 ns 44.1 ns 10 -replace runtime symbols with string expressions and without remembering all search results_cv 3.15 % 2.90 % 10 -replace runtime symbols with simstr and memorization of all search results_mean 1405 ns 1390 ns 10 -replace runtime symbols with simstr and memorization of all search results_median 1399 ns 1381 ns 10 -replace runtime symbols with simstr and memorization of all search results_stddev 53.5 ns 45.2 ns 10 -replace runtime symbols with simstr and memorization of all search results_cv 3.81 % 3.25 % 10 -replace const symbols with string expressions and without remembering all search results_mean 1288 ns 1270 ns 10 -replace const symbols with string expressions and without remembering all search results_median 1278 ns 1256 ns 10 -replace const symbols with string expressions and without remembering all search results_stddev 56.7 ns 40.0 ns 10 -replace const symbols with string expressions and without remembering all search results_cv 4.40 % 3.15 % 10 -replace const symbols with string expressions and memorization of all search results_mean 1198 ns 1194 ns 10 -replace const symbols with string expressions and memorization of all search results_median 1197 ns 1200 ns 10 -replace const symbols with string expressions and memorization of all search results_stddev 26.6 ns 28.8 ns 10 -replace const symbols with string expressions and memorization of all search results_cv 2.22 % 2.41 % 10 +Naive (and wrong) replace symbols with std::string find + replace_mean 1298 ns 1292 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_median 1287 ns 1270 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_stddev 82.0 ns 86.3 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_cv 6.32 % 6.68 % 10 +replace symbols with std::string find_first_of + replace_mean 2231 ns 2212 ns 10 +replace symbols with std::string find_first_of + replace_median 2235 ns 2197 ns 10 +replace symbols with std::string find_first_of + replace_stddev 86.8 ns 97.8 ns 10 +replace symbols with std::string find_first_of + replace_cv 3.89 % 4.42 % 10 +replace symbols with std::string_view find_first_of + copy_mean 2520 ns 2517 ns 10 +replace symbols with std::string_view find_first_of + copy_median 2524 ns 2511 ns 10 +replace symbols with std::string_view find_first_of + copy_stddev 31.7 ns 31.7 ns 10 +replace symbols with std::string_view find_first_of + copy_cv 1.26 % 1.26 % 10 +replace runtime symbols with string expressions and without remembering all search results_mean 1580 ns 1573 ns 10 +replace runtime symbols with string expressions and without remembering all search results_median 1559 ns 1554 ns 10 +replace runtime symbols with string expressions and without remembering all search results_stddev 51.1 ns 56.2 ns 10 +replace runtime symbols with string expressions and without remembering all search results_cv 3.23 % 3.58 % 10 +replace runtime symbols with simstr and memorization of all search results_mean 1389 ns 1384 ns 10 +replace runtime symbols with simstr and memorization of all search results_median 1377 ns 1381 ns 10 +replace runtime symbols with simstr and memorization of all search results_stddev 36.5 ns 31.2 ns 10 +replace runtime symbols with simstr and memorization of all search results_cv 2.63 % 2.25 % 10 +replace const symbols with string expressions and without remembering all search results_mean 1283 ns 1271 ns 10 +replace const symbols with string expressions and without remembering all search results_median 1270 ns 1256 ns 10 +replace const symbols with string expressions and without remembering all search results_stddev 31.2 ns 22.2 ns 10 +replace const symbols with string expressions and without remembering all search results_cv 2.43 % 1.75 % 10 +replace const symbols with string expressions and memorization of all search results_mean 1242 ns 1233 ns 10 +replace const symbols with string expressions and memorization of all search results_median 1240 ns 1228 ns 10 +replace const symbols with string expressions and memorization of all search results_stddev 39.7 ns 31.7 ns 10 +replace const symbols with string expressions and memorization of all search results_cv 3.20 % 2.57 % 10 -- Replace symbols in text ~40 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Short Naive (and wrong) replace symbols with std::string find + replace_mean 346 ns 342 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_median 343 ns 342 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_stddev 8.86 ns 5.15 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_cv 2.56 % 1.50 % 10 -Short replace symbols with std::string find_first_of + replace_mean 435 ns 435 ns 10 -Short replace symbols with std::string find_first_of + replace_median 435 ns 435 ns 10 -Short replace symbols with std::string find_first_of + replace_stddev 15.1 ns 14.7 ns 10 -Short replace symbols with std::string find_first_of + replace_cv 3.48 % 3.39 % 10 -Short replace symbols with std::string_view find_first_of + copy_mean 381 ns 377 ns 10 -Short replace symbols with std::string_view find_first_of + copy_median 382 ns 377 ns 10 -Short replace symbols with std::string_view find_first_of + copy_stddev 19.3 ns 20.0 ns 10 -Short replace symbols with std::string_view find_first_of + copy_cv 5.07 % 5.31 % 10 -Short replace runtime symbols with string expressions and without remembering all search results_mean 277 ns 276 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_median 276 ns 276 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_stddev 6.52 ns 6.91 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_cv 2.35 % 2.51 % 10 -Short replace runtime symbols with simstr and memorization of all search results_mean 374 ns 374 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_median 374 ns 371 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_stddev 7.40 ns 9.60 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_cv 1.98 % 2.57 % 10 -Short replace const symbols with string expressions and without remembering all search results_mean 252 ns 251 ns 10 -Short replace const symbols with string expressions and without remembering all search results_median 250 ns 251 ns 10 -Short replace const symbols with string expressions and without remembering all search results_stddev 3.37 ns 4.72 ns 10 -Short replace const symbols with string expressions and without remembering all search results_cv 1.34 % 1.88 % 10 -Short replace const symbols with string expressions and memorization of all search results_mean 342 ns 341 ns 10 -Short replace const symbols with string expressions and memorization of all search results_median 331 ns 330 ns 10 -Short replace const symbols with string expressions and memorization of all search results_stddev 29.9 ns 31.1 ns 10 -Short replace const symbols with string expressions and memorization of all search results_cv 8.73 % 9.14 % 10 +Short Naive (and wrong) replace symbols with std::string find + replace_mean 339 ns 338 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_median 335 ns 338 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_stddev 9.07 ns 6.26 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_cv 2.67 % 1.86 % 10 +Short replace symbols with std::string find_first_of + replace_mean 431 ns 429 ns 10 +Short replace symbols with std::string find_first_of + replace_median 429 ns 425 ns 10 +Short replace symbols with std::string find_first_of + replace_stddev 15.6 ns 15.2 ns 10 +Short replace symbols with std::string find_first_of + replace_cv 3.63 % 3.55 % 10 +Short replace symbols with std::string_view find_first_of + copy_mean 357 ns 356 ns 10 +Short replace symbols with std::string_view find_first_of + copy_median 356 ns 356 ns 10 +Short replace symbols with std::string_view find_first_of + copy_stddev 8.94 ns 9.86 ns 10 +Short replace symbols with std::string_view find_first_of + copy_cv 2.50 % 2.77 % 10 +Short replace runtime symbols with string expressions and without remembering all search results_mean 315 ns 313 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_median 313 ns 311 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_stddev 8.27 ns 7.56 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_cv 2.62 % 2.41 % 10 +Short replace runtime symbols with simstr and memorization of all search results_mean 393 ns 390 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_median 386 ns 388 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_stddev 14.7 ns 8.27 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_cv 3.74 % 2.12 % 10 +Short replace const symbols with string expressions and without remembering all search results_mean 253 ns 250 ns 10 +Short replace const symbols with string expressions and without remembering all search results_median 254 ns 249 ns 10 +Short replace const symbols with string expressions and without remembering all search results_stddev 8.12 ns 7.82 ns 10 +Short replace const symbols with string expressions and without remembering all search results_cv 3.21 % 3.13 % 10 +Short replace const symbols with string expressions and memorization of all search results_mean 359 ns 352 ns 10 +Short replace const symbols with string expressions and memorization of all search results_median 359 ns 352 ns 10 +Short replace const symbols with string expressions and memorization of all search results_stddev 12.2 ns 9.21 ns 10 +Short replace const symbols with string expressions and memorization of all search results_cv 3.41 % 2.61 % 10 ----- Replace All Str To Longer Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to ---- in std::string|64_mean 248 ns 248 ns 10 -replace bb to ---- in std::string|64_median 245 ns 246 ns 10 -replace bb to ---- in std::string|64_stddev 8.91 ns 8.80 ns 10 -replace bb to ---- in std::string|64_cv 3.59 % 3.55 % 10 -replace bb to ---- in std::string|256_mean 807 ns 799 ns 10 -replace bb to ---- in std::string|256_median 803 ns 802 ns 10 -replace bb to ---- in std::string|256_stddev 23.6 ns 24.4 ns 10 -replace bb to ---- in std::string|256_cv 2.93 % 3.05 % 10 -replace bb to ---- in std::string|512_mean 1551 ns 1535 ns 10 -replace bb to ---- in std::string|512_median 1532 ns 1517 ns 10 -replace bb to ---- in std::string|512_stddev 79.4 ns 71.7 ns 10 -replace bb to ---- in std::string|512_cv 5.12 % 4.67 % 10 -replace bb to ---- in std::string|1024_mean 3622 ns 3610 ns 10 -replace bb to ---- in std::string|1024_median 3713 ns 3706 ns 10 -replace bb to ---- in std::string|1024_stddev 355 ns 361 ns 10 -replace bb to ---- in std::string|1024_cv 9.79 % 10.00 % 10 -replace bb to ---- in std::string|2048_mean 8251 ns 8126 ns 10 -replace bb to ---- in std::string|2048_median 8212 ns 8109 ns 10 -replace bb to ---- in std::string|2048_stddev 224 ns 187 ns 10 -replace bb to ---- in std::string|2048_cv 2.72 % 2.31 % 10 -replace bb to ---- in lstringa<8>|64_mean 331 ns 328 ns 10 -replace bb to ---- in lstringa<8>|64_median 329 ns 329 ns 10 -replace bb to ---- in lstringa<8>|64_stddev 13.1 ns 9.60 ns 10 -replace bb to ---- in lstringa<8>|64_cv 3.95 % 2.93 % 10 -replace bb to ---- in lstringa<8>|256_mean 685 ns 677 ns 10 -replace bb to ---- in lstringa<8>|256_median 689 ns 680 ns 10 -replace bb to ---- in lstringa<8>|256_stddev 11.8 ns 16.0 ns 10 -replace bb to ---- in lstringa<8>|256_cv 1.72 % 2.37 % 10 -replace bb to ---- in lstringa<8>|512_mean 1198 ns 1189 ns 10 -replace bb to ---- in lstringa<8>|512_median 1186 ns 1172 ns 10 -replace bb to ---- in lstringa<8>|512_stddev 44.1 ns 40.0 ns 10 -replace bb to ---- in lstringa<8>|512_cv 3.68 % 3.36 % 10 -replace bb to ---- in lstringa<8>|1024_mean 2107 ns 2090 ns 10 -replace bb to ---- in lstringa<8>|1024_median 2091 ns 2100 ns 10 -replace bb to ---- in lstringa<8>|1024_stddev 46.7 ns 30.9 ns 10 -replace bb to ---- in lstringa<8>|1024_cv 2.22 % 1.48 % 10 -replace bb to ---- in lstringa<8>|2048_mean 4065 ns 3972 ns 10 -replace bb to ---- in lstringa<8>|2048_median 4024 ns 3990 ns 10 -replace bb to ---- in lstringa<8>|2048_stddev 156 ns 147 ns 10 -replace bb to ---- in lstringa<8>|2048_cv 3.84 % 3.70 % 10 -replace bb to ---- by init stringa|64_mean 230 ns 227 ns 10 -replace bb to ---- by init stringa|64_median 230 ns 228 ns 10 -replace bb to ---- by init stringa|64_stddev 9.24 ns 7.88 ns 10 -replace bb to ---- by init stringa|64_cv 4.01 % 3.47 % 10 -replace bb to ---- by init stringa|256_mean 582 ns 582 ns 10 -replace bb to ---- by init stringa|256_median 584 ns 586 ns 10 -replace bb to ---- by init stringa|256_stddev 11.2 ns 13.2 ns 10 -replace bb to ---- by init stringa|256_cv 1.93 % 2.28 % 10 -replace bb to ---- by init stringa|512_mean 1007 ns 999 ns 10 -replace bb to ---- by init stringa|512_median 1000 ns 989 ns 10 -replace bb to ---- by init stringa|512_stddev 32.1 ns 40.6 ns 10 -replace bb to ---- by init stringa|512_cv 3.19 % 4.07 % 10 -replace bb to ---- by init stringa|1024_mean 1913 ns 1875 ns 10 -replace bb to ---- by init stringa|1024_median 1878 ns 1842 ns 10 -replace bb to ---- by init stringa|1024_stddev 90.7 ns 70.6 ns 10 -replace bb to ---- by init stringa|1024_cv 4.74 % 3.76 % 10 -replace bb to ---- by init stringa|2048_mean 3605 ns 3557 ns 10 -replace bb to ---- by init stringa|2048_median 3575 ns 3557 ns 10 -replace bb to ---- by init stringa|2048_stddev 96.4 ns 44.1 ns 10 -replace bb to ---- by init stringa|2048_cv 2.67 % 1.24 % 10 +replace bb to ---- in std::string|64_mean 251 ns 247 ns 10 +replace bb to ---- in std::string|64_median 250 ns 248 ns 10 +replace bb to ---- in std::string|64_stddev 10.6 ns 8.74 ns 10 +replace bb to ---- in std::string|64_cv 4.24 % 3.54 % 10 +replace bb to ---- in std::string|256_mean 825 ns 814 ns 10 +replace bb to ---- in std::string|256_median 835 ns 802 ns 10 +replace bb to ---- in std::string|256_stddev 29.2 ns 26.1 ns 10 +replace bb to ---- in std::string|256_cv 3.54 % 3.20 % 10 +replace bb to ---- in std::string|512_mean 1501 ns 1482 ns 10 +replace bb to ---- in std::string|512_median 1483 ns 1475 ns 10 +replace bb to ---- in std::string|512_stddev 55.0 ns 32.4 ns 10 +replace bb to ---- in std::string|512_cv 3.67 % 2.19 % 10 +replace bb to ---- in std::string|1024_mean 3319 ns 3289 ns 10 +replace bb to ---- in std::string|1024_median 3344 ns 3333 ns 10 +replace bb to ---- in std::string|1024_stddev 93.5 ns 94.2 ns 10 +replace bb to ---- in std::string|1024_cv 2.82 % 2.87 % 10 +replace bb to ---- in std::string|2048_mean 8393 ns 8119 ns 10 +replace bb to ---- in std::string|2048_median 8442 ns 8161 ns 10 +replace bb to ---- in std::string|2048_stddev 245 ns 276 ns 10 +replace bb to ---- in std::string|2048_cv 2.92 % 3.39 % 10 +replace bb to ---- in lstringa<8>|64_mean 330 ns 325 ns 10 +replace bb to ---- in lstringa<8>|64_median 329 ns 326 ns 10 +replace bb to ---- in lstringa<8>|64_stddev 7.25 ns 5.12 ns 10 +replace bb to ---- in lstringa<8>|64_cv 2.20 % 1.57 % 10 +replace bb to ---- in lstringa<8>|256_mean 692 ns 681 ns 10 +replace bb to ---- in lstringa<8>|256_median 694 ns 677 ns 10 +replace bb to ---- in lstringa<8>|256_stddev 33.0 ns 31.4 ns 10 +replace bb to ---- in lstringa<8>|256_cv 4.78 % 4.61 % 10 +replace bb to ---- in lstringa<8>|512_mean 1154 ns 1133 ns 10 +replace bb to ---- in lstringa<8>|512_median 1142 ns 1123 ns 10 +replace bb to ---- in lstringa<8>|512_stddev 32.8 ns 12.6 ns 10 +replace bb to ---- in lstringa<8>|512_cv 2.84 % 1.11 % 10 +replace bb to ---- in lstringa<8>|1024_mean 2102 ns 2049 ns 10 +replace bb to ---- in lstringa<8>|1024_median 2110 ns 2018 ns 10 +replace bb to ---- in lstringa<8>|1024_stddev 83.2 ns 66.9 ns 10 +replace bb to ---- in lstringa<8>|1024_cv 3.96 % 3.26 % 10 +replace bb to ---- in lstringa<8>|2048_mean 3939 ns 3884 ns 10 +replace bb to ---- in lstringa<8>|2048_median 3968 ns 3934 ns 10 +replace bb to ---- in lstringa<8>|2048_stddev 92.9 ns 90.0 ns 10 +replace bb to ---- in lstringa<8>|2048_cv 2.36 % 2.32 % 10 +replace bb to ---- by init stringa|64_mean 209 ns 206 ns 10 +replace bb to ---- by init stringa|64_median 208 ns 205 ns 10 +replace bb to ---- by init stringa|64_stddev 9.63 ns 7.56 ns 10 +replace bb to ---- by init stringa|64_cv 4.60 % 3.67 % 10 +replace bb to ---- by init stringa|256_mean 485 ns 477 ns 10 +replace bb to ---- by init stringa|256_median 485 ns 470 ns 10 +replace bb to ---- by init stringa|256_stddev 14.8 ns 18.7 ns 10 +replace bb to ---- by init stringa|256_cv 3.05 % 3.92 % 10 +replace bb to ---- by init stringa|512_mean 1086 ns 1078 ns 10 +replace bb to ---- by init stringa|512_median 1076 ns 1078 ns 10 +replace bb to ---- by init stringa|512_stddev 17.4 ns 28.3 ns 10 +replace bb to ---- by init stringa|512_cv 1.60 % 2.63 % 10 +replace bb to ---- by init stringa|1024_mean 2232 ns 2226 ns 10 +replace bb to ---- by init stringa|1024_median 2210 ns 2222 ns 10 +replace bb to ---- by init stringa|1024_stddev 51.5 ns 49.9 ns 10 +replace bb to ---- by init stringa|1024_cv 2.31 % 2.24 % 10 +replace bb to ---- by init stringa|2048_mean 4615 ns 4541 ns 10 +replace bb to ---- by init stringa|2048_median 4603 ns 4551 ns 10 +replace bb to ---- by init stringa|2048_stddev 99.7 ns 121 ns 10 +replace bb to ---- by init stringa|2048_cv 2.16 % 2.67 % 10 ----- Replace All Str To Same Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to -- in std::string|64_mean 206 ns 206 ns 10 -replace bb to -- in std::string|64_median 208 ns 208 ns 10 -replace bb to -- in std::string|64_stddev 4.04 ns 5.04 ns 10 -replace bb to -- in std::string|64_cv 1.96 % 2.45 % 10 -replace bb to -- in std::string|256_mean 533 ns 529 ns 10 +replace bb to -- in std::string|64_mean 209 ns 207 ns 10 +replace bb to -- in std::string|64_median 206 ns 207 ns 10 +replace bb to -- in std::string|64_stddev 6.33 ns 4.45 ns 10 +replace bb to -- in std::string|64_cv 3.04 % 2.15 % 10 +replace bb to -- in std::string|256_mean 553 ns 548 ns 10 replace bb to -- in std::string|256_median 530 ns 530 ns 10 -replace bb to -- in std::string|256_stddev 13.4 ns 12.2 ns 10 -replace bb to -- in std::string|256_cv 2.51 % 2.31 % 10 -replace bb to -- in std::string|512_mean 968 ns 963 ns 10 -replace bb to -- in std::string|512_median 958 ns 963 ns 10 -replace bb to -- in std::string|512_stddev 22.6 ns 29.6 ns 10 -replace bb to -- in std::string|512_cv 2.34 % 3.07 % 10 -replace bb to -- in std::string|1024_mean 1840 ns 1837 ns 10 -replace bb to -- in std::string|1024_median 1821 ns 1800 ns 10 -replace bb to -- in std::string|1024_stddev 47.0 ns 53.9 ns 10 -replace bb to -- in std::string|1024_cv 2.55 % 2.93 % 10 -replace bb to -- in std::string|2048_mean 3641 ns 3618 ns 10 -replace bb to -- in std::string|2048_median 3590 ns 3610 ns 10 -replace bb to -- in std::string|2048_stddev 149 ns 116 ns 10 -replace bb to -- in std::string|2048_cv 4.08 % 3.21 % 10 -replace bb to -- in lstringa<8>|64_mean 200 ns 198 ns 10 -replace bb to -- in lstringa<8>|64_median 198 ns 195 ns 10 -replace bb to -- in lstringa<8>|64_stddev 8.44 ns 7.53 ns 10 -replace bb to -- in lstringa<8>|64_cv 4.22 % 3.81 % 10 -replace bb to -- in lstringa<8>|256_mean 475 ns 472 ns 10 -replace bb to -- in lstringa<8>|256_median 464 ns 469 ns 10 -replace bb to -- in lstringa<8>|256_stddev 25.0 ns 17.7 ns 10 -replace bb to -- in lstringa<8>|256_cv 5.27 % 3.76 % 10 -replace bb to -- in lstringa<8>|512_mean 816 ns 809 ns 10 -replace bb to -- in lstringa<8>|512_median 818 ns 811 ns 10 -replace bb to -- in lstringa<8>|512_stddev 6.07 ns 16.8 ns 10 -replace bb to -- in lstringa<8>|512_cv 0.74 % 2.08 % 10 -replace bb to -- in lstringa<8>|1024_mean 1508 ns 1507 ns 10 -replace bb to -- in lstringa<8>|1024_median 1498 ns 1500 ns 10 -replace bb to -- in lstringa<8>|1024_stddev 27.1 ns 27.5 ns 10 -replace bb to -- in lstringa<8>|1024_cv 1.80 % 1.83 % 10 -replace bb to -- in lstringa<8>|2048_mean 2969 ns 2930 ns 10 -replace bb to -- in lstringa<8>|2048_median 2940 ns 2930 ns 10 -replace bb to -- in lstringa<8>|2048_stddev 84.7 ns 48.8 ns 10 -replace bb to -- in lstringa<8>|2048_cv 2.85 % 1.67 % 10 -replace bb to -- by init stringa|64_mean 192 ns 191 ns 10 -replace bb to -- by init stringa|64_median 185 ns 184 ns 10 -replace bb to -- by init stringa|64_stddev 20.4 ns 20.8 ns 10 -replace bb to -- by init stringa|64_cv 10.64 % 10.87 % 10 -replace bb to -- by init stringa|256_mean 392 ns 389 ns 10 -replace bb to -- by init stringa|256_median 388 ns 390 ns 10 -replace bb to -- by init stringa|256_stddev 19.1 ns 17.9 ns 10 -replace bb to -- by init stringa|256_cv 4.86 % 4.59 % 10 -replace bb to -- by init stringa|512_mean 660 ns 658 ns 10 -replace bb to -- by init stringa|512_median 655 ns 656 ns 10 -replace bb to -- by init stringa|512_stddev 21.3 ns 22.6 ns 10 -replace bb to -- by init stringa|512_cv 3.22 % 3.43 % 10 -replace bb to -- by init stringa|1024_mean 1196 ns 1186 ns 10 -replace bb to -- by init stringa|1024_median 1192 ns 1186 ns 10 -replace bb to -- by init stringa|1024_stddev 31.1 ns 30.1 ns 10 -replace bb to -- by init stringa|1024_cv 2.60 % 2.54 % 10 -replace bb to -- by init stringa|2048_mean 2432 ns 2433 ns 10 -replace bb to -- by init stringa|2048_median 2355 ns 2354 ns 10 -replace bb to -- by init stringa|2048_stddev 223 ns 207 ns 10 -replace bb to -- by init stringa|2048_cv 9.18 % 8.50 % 10 +replace bb to -- in std::string|256_stddev 61.0 ns 55.0 ns 10 +replace bb to -- in std::string|256_cv 11.03 % 10.04 % 10 +replace bb to -- in std::string|512_mean 975 ns 971 ns 10 +replace bb to -- in std::string|512_median 971 ns 963 ns 10 +replace bb to -- in std::string|512_stddev 24.3 ns 26.5 ns 10 +replace bb to -- in std::string|512_cv 2.50 % 2.73 % 10 +replace bb to -- in std::string|1024_mean 1826 ns 1807 ns 10 +replace bb to -- in std::string|1024_median 1812 ns 1803 ns 10 +replace bb to -- in std::string|1024_stddev 36.9 ns 38.2 ns 10 +replace bb to -- in std::string|1024_cv 2.02 % 2.11 % 10 +replace bb to -- in std::string|2048_mean 3547 ns 3489 ns 10 +replace bb to -- in std::string|2048_median 3532 ns 3449 ns 10 +replace bb to -- in std::string|2048_stddev 60.2 ns 86.6 ns 10 +replace bb to -- in std::string|2048_cv 1.70 % 2.48 % 10 +replace bb to -- in lstringa<8>|64_mean 189 ns 189 ns 10 +replace bb to -- in lstringa<8>|64_median 189 ns 188 ns 10 +replace bb to -- in lstringa<8>|64_stddev 1.39 ns 3.09 ns 10 +replace bb to -- in lstringa<8>|64_cv 0.73 % 1.64 % 10 +replace bb to -- in lstringa<8>|256_mean 470 ns 464 ns 10 +replace bb to -- in lstringa<8>|256_median 461 ns 460 ns 10 +replace bb to -- in lstringa<8>|256_stddev 18.8 ns 18.1 ns 10 +replace bb to -- in lstringa<8>|256_cv 4.00 % 3.90 % 10 +replace bb to -- in lstringa<8>|512_mean 807 ns 802 ns 10 +replace bb to -- in lstringa<8>|512_median 807 ns 802 ns 10 +replace bb to -- in lstringa<8>|512_stddev 11.3 ns 16.4 ns 10 +replace bb to -- in lstringa<8>|512_cv 1.40 % 2.05 % 10 +replace bb to -- in lstringa<8>|1024_mean 1515 ns 1489 ns 10 +replace bb to -- in lstringa<8>|1024_median 1490 ns 1500 ns 10 +replace bb to -- in lstringa<8>|1024_stddev 62.7 ns 43.7 ns 10 +replace bb to -- in lstringa<8>|1024_cv 4.14 % 2.93 % 10 +replace bb to -- in lstringa<8>|2048_mean 2967 ns 2929 ns 10 +replace bb to -- in lstringa<8>|2048_median 2937 ns 2883 ns 10 +replace bb to -- in lstringa<8>|2048_stddev 134 ns 128 ns 10 +replace bb to -- in lstringa<8>|2048_cv 4.53 % 4.37 % 10 +replace bb to -- by init stringa|64_mean 179 ns 176 ns 10 +replace bb to -- by init stringa|64_median 178 ns 176 ns 10 +replace bb to -- by init stringa|64_stddev 3.89 ns 3.36 ns 10 +replace bb to -- by init stringa|64_cv 2.18 % 1.91 % 10 +replace bb to -- by init stringa|256_mean 392 ns 385 ns 10 +replace bb to -- by init stringa|256_median 391 ns 385 ns 10 +replace bb to -- by init stringa|256_stddev 13.1 ns 8.82 ns 10 +replace bb to -- by init stringa|256_cv 3.34 % 2.29 % 10 +replace bb to -- by init stringa|512_mean 642 ns 633 ns 10 +replace bb to -- by init stringa|512_median 643 ns 635 ns 10 +replace bb to -- by init stringa|512_stddev 21.2 ns 13.5 ns 10 +replace bb to -- by init stringa|512_cv 3.30 % 2.13 % 10 +replace bb to -- by init stringa|1024_mean 1151 ns 1138 ns 10 +replace bb to -- by init stringa|1024_median 1144 ns 1144 ns 10 +replace bb to -- by init stringa|1024_stddev 26.9 ns 34.3 ns 10 +replace bb to -- by init stringa|1024_cv 2.34 % 3.01 % 10 +replace bb to -- by init stringa|2048_mean 2264 ns 2223 ns 10 +replace bb to -- by init stringa|2048_median 2276 ns 2197 ns 10 +replace bb to -- by init stringa|2048_stddev 52.5 ns 37.0 ns 10 +replace bb to -- by init stringa|2048_cv 2.32 % 1.66 % 10 ----- Hash Map insert and find ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -hashStrMapA emplace & find stringa;_mean 4270225 ns 4248047 ns 10 -hashStrMapA emplace & find stringa;_median 4314802 ns 4248047 ns 10 -hashStrMapA emplace & find stringa;_stddev 184022 ns 179775 ns 10 -hashStrMapA emplace & find stringa;_cv 4.31 % 4.23 % 10 -std::unordered_map emplace & find std::string;_mean 5385050 ns 5312500 ns 10 -std::unordered_map emplace & find std::string;_median 5346964 ns 5312500 ns 10 -std::unordered_map emplace & find std::string;_stddev 133251 ns 0.000 ns 10 -std::unordered_map emplace & find std::string;_cv 2.47 % 0.00 % 10 -hashStrMapA emplace & find ssa;_mean 3953790 ns 3952206 ns 10 -hashStrMapA emplace & find ssa;_median 3948084 ns 3927139 ns 10 -hashStrMapA emplace & find ssa;_stddev 61645 ns 56396 ns 10 -hashStrMapA emplace & find ssa;_cv 1.56 % 1.43 % 10 -std::unordered_map emplace & find std::string_view;_mean 6874509 ns 6808036 ns 10 -std::unordered_map emplace & find std::string_view;_median 6862246 ns 6835938 ns 10 -std::unordered_map emplace & find std::string_view;_stddev 115202 ns 128200 ns 10 -std::unordered_map emplace & find std::string_view;_cv 1.68 % 1.88 % 10 +hashStrMapA emplace & find stringa;_mean 4203983 ns 4208984 ns 10 +hashStrMapA emplace & find stringa;_median 4228262 ns 4199219 ns 10 +hashStrMapA emplace & find stringa;_stddev 226508 ns 222928 ns 10 +hashStrMapA emplace & find stringa;_cv 5.39 % 5.30 % 10 +std::unordered_map emplace & find std::string;_mean 5344121 ns 5281250 ns 10 +std::unordered_map emplace & find std::string;_median 5268283 ns 5312500 ns 10 +std::unordered_map emplace & find std::string;_stddev 149555 ns 123252 ns 10 +std::unordered_map emplace & find std::string;_cv 2.80 % 2.33 % 10 +hashStrMapA emplace & find ssa;_mean 4011248 ns 3928073 ns 10 +hashStrMapA emplace & find ssa;_median 4025866 ns 3928073 ns 10 +hashStrMapA emplace & find ssa;_stddev 92509 ns 130125 ns 10 +hashStrMapA emplace & find ssa;_cv 2.31 % 3.31 % 10 +std::unordered_map emplace & find std::string_view;_mean 6304499 ns 6236049 ns 10 +std::unordered_map emplace & find std::string_view;_median 6292092 ns 6208147 ns 10 +std::unordered_map emplace & find std::string_view;_stddev 163281 ns 114854 ns 10 +std::unordered_map emplace & find std::string_view;_cv 2.59 % 1.84 % 10 ----- Build Full Func Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -Build func full name std::string;_mean 1651 ns 1632 ns 10 -Build func full name std::string;_median 1639 ns 1604 ns 10 -Build func full name std::string;_stddev 64.8 ns 63.3 ns 10 -Build func full name std::string;_cv 3.93 % 3.88 % 10 -Build func full name std::string 1;_mean 1706 ns 1669 ns 10 -Build func full name std::string 1;_median 1696 ns 1669 ns 10 -Build func full name std::string 1;_stddev 39.5 ns 41.4 ns 10 -Build func full name std::string 1;_cv 2.32 % 2.48 % 10 -Build func full name std::stream;_mean 9950 ns 9898 ns 10 -Build func full name std::stream;_median 9704 ns 9626 ns 10 -Build func full name std::stream;_stddev 674 ns 647 ns 10 -Build func full name std::stream;_cv 6.78 % 6.54 % 10 -Build func full name stringa;_mean 948 ns 947 ns 10 -Build func full name stringa;_median 920 ns 928 ns 10 -Build func full name stringa;_stddev 96.7 ns 96.8 ns 10 -Build func full name stringa;_cv 10.20 % 10.22 % 10 -Build func full name stringa 1;_mean 1108 ns 1108 ns 10 -Build func full name stringa 1;_median 1046 ns 1050 ns 10 -Build func full name stringa 1;_stddev 121 ns 125 ns 10 -Build func full name stringa 1;_cv 10.96 % 11.29 % 10 +Build func full name std::string;_mean 1645 ns 1627 ns 10 +Build func full name std::string;_median 1625 ns 1611 ns 10 +Build func full name std::string;_stddev 59.7 ns 41.2 ns 10 +Build func full name std::string;_cv 3.63 % 2.54 % 10 +Build func full name std::string 1;_mean 1711 ns 1692 ns 10 +Build func full name std::string 1;_median 1687 ns 1669 ns 10 +Build func full name std::string 1;_stddev 73.4 ns 73.4 ns 10 +Build func full name std::string 1;_cv 4.29 % 4.34 % 10 +Build func full name std::stream;_mean 10110 ns 10128 ns 10 +Build func full name std::stream;_median 9848 ns 9835 ns 10 +Build func full name std::stream;_stddev 970 ns 932 ns 10 +Build func full name std::stream;_cv 9.59 % 9.20 % 10 +Build func full name stringa;_mean 924 ns 910 ns 10 +Build func full name stringa;_median 906 ns 902 ns 10 +Build func full name stringa;_stddev 43.8 ns 24.8 ns 10 +Build func full name stringa;_cv 4.74 % 2.73 % 10 +Build func full name stringa 1;_mean 1020 ns 1002 ns 10 +Build func full name stringa 1;_median 1020 ns 1004 ns 10 +Build func full name stringa 1;_stddev 29.0 ns 23.0 ns 10 +Build func full name stringa 1;_cv 2.85 % 2.30 % 10 diff --git a/bench/results/004-Xeon E5-2682 v4, WASM Chrome, Clang-21.txt b/bench/results/004-Xeon E5-2682 v4, WASM Chrome, Clang-21.txt deleted file mode 100644 index bbb75f6..0000000 --- a/bench/results/004-Xeon E5-2682 v4, WASM Chrome, Clang-21.txt +++ /dev/null @@ -1,784 +0,0 @@ -Run on (32 X 2513.96 MHz CPU s) -Chromium: 142.0.7444.60 webasm --------------------------------------------------------------------------------------------------------------------------------------------------------- -Benchmark Time CPU Iterations --------------------------------------------------------------------------------------------------------------------------------------------------------- ------ Create Empty Str ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e;_mean 5.87 ns 5.87 ns 10 -std::string e;_median 5.83 ns 5.83 ns 10 -std::string e;_stddev 0.100 ns 0.100 ns 10 -std::string e;_cv 1.71 % 1.71 % 10 -std::string_view e;_mean 5.26 ns 5.26 ns 10 -std::string_view e;_median 5.26 ns 5.26 ns 10 -std::string_view e;_stddev 0.022 ns 0.022 ns 10 -std::string_view e;_cv 0.43 % 0.43 % 10 -ssa e;_mean 4.67 ns 4.67 ns 10 -ssa e;_median 4.67 ns 4.67 ns 10 -ssa e;_stddev 0.023 ns 0.023 ns 10 -ssa e;_cv 0.50 % 0.49 % 10 -stringa e;_mean 4.82 ns 4.82 ns 10 -stringa e;_median 4.81 ns 4.81 ns 10 -stringa e;_stddev 0.040 ns 0.040 ns 10 -stringa e;_cv 0.83 % 0.83 % 10 -lstringa<20> e;_mean 4.64 ns 4.64 ns 10 -lstringa<20> e;_median 4.62 ns 4.62 ns 10 -lstringa<20> e;_stddev 0.076 ns 0.076 ns 10 -lstringa<20> e;_cv 1.63 % 1.63 % 10 -lstringa<40> e;_mean 4.76 ns 4.76 ns 10 -lstringa<40> e;_median 4.72 ns 4.72 ns 10 -lstringa<40> e;_stddev 0.128 ns 0.128 ns 10 -lstringa<40> e;_cv 2.68 % 2.68 % 10 ------ Create Str from short literal (9 symbols) --------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text";_mean 5.17 ns 5.17 ns 10 -std::string e = "Test text";_median 5.16 ns 5.16 ns 10 -std::string e = "Test text";_stddev 0.060 ns 0.060 ns 10 -std::string e = "Test text";_cv 1.16 % 1.16 % 10 -std::string_view e = "Test text";_mean 5.57 ns 5.57 ns 10 -std::string_view e = "Test text";_median 5.56 ns 5.56 ns 10 -std::string_view e = "Test text";_stddev 0.026 ns 0.026 ns 10 -std::string_view e = "Test text";_cv 0.47 % 0.47 % 10 -ssa e = "Test text";_mean 3.41 ns 3.41 ns 10 -ssa e = "Test text";_median 3.41 ns 3.41 ns 10 -ssa e = "Test text";_stddev 0.029 ns 0.029 ns 10 -ssa e = "Test text";_cv 0.84 % 0.84 % 10 -stringa e = "Test text";_mean 5.07 ns 5.07 ns 10 -stringa e = "Test text";_median 5.01 ns 5.01 ns 10 -stringa e = "Test text";_stddev 0.168 ns 0.168 ns 10 -stringa e = "Test text";_cv 3.32 % 3.32 % 10 -lstringa<20> e = "Test text";_mean 5.37 ns 5.37 ns 10 -lstringa<20> e = "Test text";_median 5.37 ns 5.37 ns 10 -lstringa<20> e = "Test text";_stddev 0.102 ns 0.102 ns 10 -lstringa<20> e = "Test text";_cv 1.90 % 1.90 % 10 -lstringa<40> e = "Test text";_mean 5.37 ns 5.37 ns 10 -lstringa<40> e = "Test text";_median 5.36 ns 5.36 ns 10 -lstringa<40> e = "Test text";_stddev 0.061 ns 0.061 ns 10 -lstringa<40> e = "Test text";_cv 1.13 % 1.13 % 10 ------ Create Str from long literal (30 symbols) ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "123456789012345678901234567890";_mean 63.4 ns 63.4 ns 10 -std::string e = "123456789012345678901234567890";_median 63.5 ns 63.5 ns 10 -std::string e = "123456789012345678901234567890";_stddev 2.12 ns 2.12 ns 10 -std::string e = "123456789012345678901234567890";_cv 3.35 % 3.35 % 10 -std::string_view e = "123456789012345678901234567890";_mean 5.58 ns 5.58 ns 10 -std::string_view e = "123456789012345678901234567890";_median 5.57 ns 5.57 ns 10 -std::string_view e = "123456789012345678901234567890";_stddev 0.045 ns 0.045 ns 10 -std::string_view e = "123456789012345678901234567890";_cv 0.81 % 0.81 % 10 -ssa e = "123456789012345678901234567890";_mean 3.33 ns 3.33 ns 10 -ssa e = "123456789012345678901234567890";_median 3.33 ns 3.33 ns 10 -ssa e = "123456789012345678901234567890";_stddev 0.026 ns 0.026 ns 10 -ssa e = "123456789012345678901234567890";_cv 0.78 % 0.78 % 10 -stringa e = "123456789012345678901234567890";_mean 4.95 ns 4.95 ns 10 -stringa e = "123456789012345678901234567890";_median 4.90 ns 4.90 ns 10 -stringa e = "123456789012345678901234567890";_stddev 0.103 ns 0.103 ns 10 -stringa e = "123456789012345678901234567890";_cv 2.08 % 2.08 % 10 -lstringa<20> e = "123456789012345678901234567890";_mean 63.1 ns 63.1 ns 10 -lstringa<20> e = "123456789012345678901234567890";_median 63.0 ns 63.0 ns 10 -lstringa<20> e = "123456789012345678901234567890";_stddev 2.03 ns 2.03 ns 10 -lstringa<20> e = "123456789012345678901234567890";_cv 3.22 % 3.22 % 10 -lstringa<40> e = "123456789012345678901234567890";_mean 5.86 ns 5.86 ns 10 -lstringa<40> e = "123456789012345678901234567890";_median 5.90 ns 5.90 ns 10 -lstringa<40> e = "123456789012345678901234567890";_stddev 0.090 ns 0.090 ns 10 -lstringa<40> e = "123456789012345678901234567890";_cv 1.53 % 1.53 % 10 ------ Create copy of Str with 9 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "Test text"; auto c{e};_mean 11.0 ns 11.0 ns 10 -std::string e = "Test text"; auto c{e};_median 11.0 ns 11.0 ns 10 -std::string e = "Test text"; auto c{e};_stddev 0.061 ns 0.061 ns 10 -std::string e = "Test text"; auto c{e};_cv 0.55 % 0.55 % 10 -std::string_view e = "Test text"; auto c{e};_mean 5.91 ns 5.91 ns 10 -std::string_view e = "Test text"; auto c{e};_median 5.91 ns 5.91 ns 10 -std::string_view e = "Test text"; auto c{e};_stddev 0.014 ns 0.014 ns 10 -std::string_view e = "Test text"; auto c{e};_cv 0.24 % 0.24 % 10 -ssa e = "Test text"; auto c{e};_mean 6.84 ns 6.84 ns 10 -ssa e = "Test text"; auto c{e};_median 6.85 ns 6.85 ns 10 -ssa e = "Test text"; auto c{e};_stddev 0.043 ns 0.043 ns 10 -ssa e = "Test text"; auto c{e};_cv 0.62 % 0.62 % 10 -stringa e = "Test text"; auto c{e};_mean 5.18 ns 5.18 ns 10 -stringa e = "Test text"; auto c{e};_median 5.15 ns 5.15 ns 10 -stringa e = "Test text"; auto c{e};_stddev 0.150 ns 0.150 ns 10 -stringa e = "Test text"; auto c{e};_cv 2.90 % 2.90 % 10 -lstringa<20> e = "Test text"; auto c{e};_mean 17.5 ns 17.5 ns 10 -lstringa<20> e = "Test text"; auto c{e};_median 17.5 ns 17.5 ns 10 -lstringa<20> e = "Test text"; auto c{e};_stddev 0.608 ns 0.608 ns 10 -lstringa<20> e = "Test text"; auto c{e};_cv 3.48 % 3.48 % 10 -lstringa<40> e = "Test text"; auto c{e};_mean 17.4 ns 17.4 ns 10 -lstringa<40> e = "Test text"; auto c{e};_median 17.5 ns 17.5 ns 10 -lstringa<40> e = "Test text"; auto c{e};_stddev 0.419 ns 0.419 ns 10 -lstringa<40> e = "Test text"; auto c{e};_cv 2.40 % 2.40 % 10 ------ Create copy of Str with 30 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string e = "123456789012345678901234567890"; auto c{e};_mean 93.3 ns 93.3 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_median 92.5 ns 92.5 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_stddev 3.13 ns 3.13 ns 10 -std::string e = "123456789012345678901234567890"; auto c{e};_cv 3.35 % 3.35 % 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 5.57 ns 5.57 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_median 5.57 ns 5.57 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.019 ns 0.019 ns 10 -std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 0.35 % 0.35 % 10 -ssa e = "123456789012345678901234567890"; auto c{e};_mean 3.32 ns 3.32 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_median 3.32 ns 3.32 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.021 ns 0.021 ns 10 -ssa e = "123456789012345678901234567890"; auto c{e};_cv 0.63 % 0.63 % 10 -stringa e = "123456789012345678901234567890"; auto c{e};_mean 4.89 ns 4.89 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_median 4.87 ns 4.87 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.063 ns 0.063 ns 10 -stringa e = "123456789012345678901234567890"; auto c{e};_cv 1.30 % 1.30 % 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 66.3 ns 66.3 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 66.0 ns 66.1 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 2.64 ns 2.64 ns 10 -lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 3.98 % 3.98 % 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 17.0 ns 17.0 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 16.7 ns 16.7 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 0.960 ns 0.960 ns 10 -lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 5.66 % 5.66 % 10 ------ Find 9 symbols text in end of 99 symbols text ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string::find;_mean 101 ns 101 ns 10 -std::string::find;_median 101 ns 101 ns 10 -std::string::find;_stddev 1.61 ns 1.61 ns 10 -std::string::find;_cv 1.59 % 1.59 % 10 -std::string_view::find;_mean 103 ns 103 ns 10 -std::string_view::find;_median 102 ns 102 ns 10 -std::string_view::find;_stddev 4.97 ns 4.97 ns 10 -std::string_view::find;_cv 4.83 % 4.83 % 10 -ssa::find;_mean 102 ns 102 ns 10 -ssa::find;_median 102 ns 102 ns 10 -ssa::find;_stddev 2.15 ns 2.15 ns 10 -ssa::find;_cv 2.11 % 2.11 % 10 -stringa::find;_mean 105 ns 105 ns 10 -stringa::find;_median 104 ns 104 ns 10 -stringa::find;_stddev 4.34 ns 4.34 ns 10 -stringa::find;_cv 4.15 % 4.15 % 10 -lstringa<20>::find;_mean 99.9 ns 99.9 ns 10 -lstringa<20>::find;_median 99.9 ns 99.9 ns 10 -lstringa<20>::find;_stddev 1.61 ns 1.61 ns 10 -lstringa<20>::find;_cv 1.61 % 1.61 % 10 -lstringa<40>::find;_mean 100 ns 100 ns 10 -lstringa<40>::find;_median 99.2 ns 99.2 ns 10 -lstringa<40>::find;_stddev 3.67 ns 3.67 ns 10 -lstringa<40>::find;_cv 3.66 % 3.66 % 10 -------- Copy not literal Str with N symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string copy{str_with_len_N};/15_mean 97.2 ns 97.2 ns 10 -std::string copy{str_with_len_N};/15_median 98.2 ns 98.2 ns 10 -std::string copy{str_with_len_N};/15_stddev 5.39 ns 5.39 ns 10 -std::string copy{str_with_len_N};/15_cv 5.55 % 5.55 % 10 -std::string copy{str_with_len_N};/16_mean 94.6 ns 94.6 ns 10 -std::string copy{str_with_len_N};/16_median 95.7 ns 95.7 ns 10 -std::string copy{str_with_len_N};/16_stddev 3.09 ns 3.09 ns 10 -std::string copy{str_with_len_N};/16_cv 3.27 % 3.27 % 10 -std::string copy{str_with_len_N};/23_mean 91.6 ns 91.6 ns 10 -std::string copy{str_with_len_N};/23_median 91.7 ns 91.7 ns 10 -std::string copy{str_with_len_N};/23_stddev 3.83 ns 3.83 ns 10 -std::string copy{str_with_len_N};/23_cv 4.18 % 4.18 % 10 -std::string copy{str_with_len_N};/24_mean 94.5 ns 94.5 ns 10 -std::string copy{str_with_len_N};/24_median 94.9 ns 94.9 ns 10 -std::string copy{str_with_len_N};/24_stddev 3.26 ns 3.26 ns 10 -std::string copy{str_with_len_N};/24_cv 3.45 % 3.45 % 10 -std::string copy{str_with_len_N};/32_mean 97.0 ns 97.0 ns 10 -std::string copy{str_with_len_N};/32_median 97.4 ns 97.4 ns 10 -std::string copy{str_with_len_N};/32_stddev 3.12 ns 3.12 ns 10 -std::string copy{str_with_len_N};/32_cv 3.22 % 3.22 % 10 -std::string copy{str_with_len_N};/64_mean 98.1 ns 98.1 ns 10 -std::string copy{str_with_len_N};/64_median 97.6 ns 97.6 ns 10 -std::string copy{str_with_len_N};/64_stddev 4.22 ns 4.22 ns 10 -std::string copy{str_with_len_N};/64_cv 4.30 % 4.30 % 10 -std::string copy{str_with_len_N};/128_mean 103 ns 103 ns 10 -std::string copy{str_with_len_N};/128_median 100 ns 100 ns 10 -std::string copy{str_with_len_N};/128_stddev 9.59 ns 9.59 ns 10 -std::string copy{str_with_len_N};/128_cv 9.29 % 9.29 % 10 -std::string copy{str_with_len_N};/256_mean 161 ns 161 ns 10 -std::string copy{str_with_len_N};/256_median 180 ns 180 ns 10 -std::string copy{str_with_len_N};/256_stddev 40.6 ns 40.6 ns 10 -std::string copy{str_with_len_N};/256_cv 25.29 % 25.29 % 10 -std::string copy{str_with_len_N};/512_mean 151 ns 151 ns 10 -std::string copy{str_with_len_N};/512_median 150 ns 150 ns 10 -std::string copy{str_with_len_N};/512_stddev 38.1 ns 38.1 ns 10 -std::string copy{str_with_len_N};/512_cv 25.27 % 25.27 % 10 -std::string copy{str_with_len_N};/1024_mean 131 ns 131 ns 10 -std::string copy{str_with_len_N};/1024_median 126 ns 126 ns 10 -std::string copy{str_with_len_N};/1024_stddev 21.4 ns 21.4 ns 10 -std::string copy{str_with_len_N};/1024_cv 16.31 % 16.31 % 10 -std::string copy{str_with_len_N};/2048_mean 148 ns 148 ns 10 -std::string copy{str_with_len_N};/2048_median 145 ns 145 ns 10 -std::string copy{str_with_len_N};/2048_stddev 10.5 ns 10.5 ns 10 -std::string copy{str_with_len_N};/2048_cv 7.09 % 7.09 % 10 -std::string copy{str_with_len_N};/4096_mean 185 ns 185 ns 10 -std::string copy{str_with_len_N};/4096_median 183 ns 183 ns 10 -std::string copy{str_with_len_N};/4096_stddev 8.27 ns 8.27 ns 10 -std::string copy{str_with_len_N};/4096_cv 4.47 % 4.47 % 10 -stringa copy{str_with_len_N};/15_mean 5.19 ns 5.19 ns 10 -stringa copy{str_with_len_N};/15_median 5.13 ns 5.13 ns 10 -stringa copy{str_with_len_N};/15_stddev 0.223 ns 0.223 ns 10 -stringa copy{str_with_len_N};/15_cv 4.29 % 4.29 % 10 -stringa copy{str_with_len_N};/16_mean 10.0 ns 10.0 ns 10 -stringa copy{str_with_len_N};/16_median 9.95 ns 9.95 ns 10 -stringa copy{str_with_len_N};/16_stddev 0.218 ns 0.218 ns 10 -stringa copy{str_with_len_N};/16_cv 2.17 % 2.17 % 10 -stringa copy{str_with_len_N};/23_mean 9.97 ns 9.97 ns 10 -stringa copy{str_with_len_N};/23_median 9.91 ns 9.91 ns 10 -stringa copy{str_with_len_N};/23_stddev 0.223 ns 0.223 ns 10 -stringa copy{str_with_len_N};/23_cv 2.23 % 2.23 % 10 -stringa copy{str_with_len_N};/24_mean 10.1 ns 10.1 ns 10 -stringa copy{str_with_len_N};/24_median 9.98 ns 9.98 ns 10 -stringa copy{str_with_len_N};/24_stddev 0.238 ns 0.238 ns 10 -stringa copy{str_with_len_N};/24_cv 2.36 % 2.36 % 10 -stringa copy{str_with_len_N};/32_mean 10.0 ns 10.0 ns 10 -stringa copy{str_with_len_N};/32_median 10.0 ns 10.0 ns 10 -stringa copy{str_with_len_N};/32_stddev 0.122 ns 0.122 ns 10 -stringa copy{str_with_len_N};/32_cv 1.21 % 1.21 % 10 -stringa copy{str_with_len_N};/64_mean 9.95 ns 9.95 ns 10 -stringa copy{str_with_len_N};/64_median 9.90 ns 9.90 ns 10 -stringa copy{str_with_len_N};/64_stddev 0.145 ns 0.145 ns 10 -stringa copy{str_with_len_N};/64_cv 1.46 % 1.46 % 10 -stringa copy{str_with_len_N};/128_mean 9.93 ns 9.93 ns 10 -stringa copy{str_with_len_N};/128_median 9.90 ns 9.90 ns 10 -stringa copy{str_with_len_N};/128_stddev 0.178 ns 0.178 ns 10 -stringa copy{str_with_len_N};/128_cv 1.79 % 1.79 % 10 -stringa copy{str_with_len_N};/256_mean 9.95 ns 9.95 ns 10 -stringa copy{str_with_len_N};/256_median 9.92 ns 9.92 ns 10 -stringa copy{str_with_len_N};/256_stddev 0.112 ns 0.112 ns 10 -stringa copy{str_with_len_N};/256_cv 1.13 % 1.13 % 10 -stringa copy{str_with_len_N};/512_mean 10.0 ns 10.0 ns 10 -stringa copy{str_with_len_N};/512_median 9.94 ns 9.94 ns 10 -stringa copy{str_with_len_N};/512_stddev 0.214 ns 0.214 ns 10 -stringa copy{str_with_len_N};/512_cv 2.13 % 2.13 % 10 -stringa copy{str_with_len_N};/1024_mean 9.92 ns 9.92 ns 10 -stringa copy{str_with_len_N};/1024_median 9.90 ns 9.90 ns 10 -stringa copy{str_with_len_N};/1024_stddev 0.113 ns 0.113 ns 10 -stringa copy{str_with_len_N};/1024_cv 1.14 % 1.14 % 10 -stringa copy{str_with_len_N};/2048_mean 10.0 ns 10.0 ns 10 -stringa copy{str_with_len_N};/2048_median 9.97 ns 9.97 ns 10 -stringa copy{str_with_len_N};/2048_stddev 0.174 ns 0.174 ns 10 -stringa copy{str_with_len_N};/2048_cv 1.73 % 1.73 % 10 -stringa copy{str_with_len_N};/4096_mean 10.1 ns 10.1 ns 10 -stringa copy{str_with_len_N};/4096_median 9.99 ns 9.99 ns 10 -stringa copy{str_with_len_N};/4096_stddev 0.212 ns 0.212 ns 10 -stringa copy{str_with_len_N};/4096_cv 2.11 % 2.11 % 10 -lstringa<16> copy{str_with_len_N};/15_mean 17.2 ns 17.2 ns 10 -lstringa<16> copy{str_with_len_N};/15_median 17.0 ns 17.0 ns 10 -lstringa<16> copy{str_with_len_N};/15_stddev 1.43 ns 1.43 ns 10 -lstringa<16> copy{str_with_len_N};/15_cv 8.29 % 8.29 % 10 -lstringa<16> copy{str_with_len_N};/16_mean 17.0 ns 17.0 ns 10 -lstringa<16> copy{str_with_len_N};/16_median 17.0 ns 17.0 ns 10 -lstringa<16> copy{str_with_len_N};/16_stddev 0.735 ns 0.735 ns 10 -lstringa<16> copy{str_with_len_N};/16_cv 4.33 % 4.33 % 10 -lstringa<16> copy{str_with_len_N};/23_mean 77.8 ns 77.8 ns 10 -lstringa<16> copy{str_with_len_N};/23_median 77.4 ns 77.4 ns 10 -lstringa<16> copy{str_with_len_N};/23_stddev 2.84 ns 2.84 ns 10 -lstringa<16> copy{str_with_len_N};/23_cv 3.65 % 3.65 % 10 -lstringa<16> copy{str_with_len_N};/24_mean 76.5 ns 76.5 ns 10 -lstringa<16> copy{str_with_len_N};/24_median 76.1 ns 76.1 ns 10 -lstringa<16> copy{str_with_len_N};/24_stddev 1.45 ns 1.45 ns 10 -lstringa<16> copy{str_with_len_N};/24_cv 1.90 % 1.90 % 10 -lstringa<16> copy{str_with_len_N};/32_mean 79.5 ns 79.5 ns 10 -lstringa<16> copy{str_with_len_N};/32_median 80.2 ns 80.2 ns 10 -lstringa<16> copy{str_with_len_N};/32_stddev 3.63 ns 3.63 ns 10 -lstringa<16> copy{str_with_len_N};/32_cv 4.57 % 4.57 % 10 -lstringa<16> copy{str_with_len_N};/64_mean 82.9 ns 82.9 ns 10 -lstringa<16> copy{str_with_len_N};/64_median 81.8 ns 81.8 ns 10 -lstringa<16> copy{str_with_len_N};/64_stddev 7.03 ns 7.03 ns 10 -lstringa<16> copy{str_with_len_N};/64_cv 8.48 % 8.48 % 10 -lstringa<16> copy{str_with_len_N};/128_mean 83.0 ns 83.0 ns 10 -lstringa<16> copy{str_with_len_N};/128_median 82.3 ns 82.3 ns 10 -lstringa<16> copy{str_with_len_N};/128_stddev 5.89 ns 5.89 ns 10 -lstringa<16> copy{str_with_len_N};/128_cv 7.10 % 7.10 % 10 -lstringa<16> copy{str_with_len_N};/256_mean 133 ns 133 ns 10 -lstringa<16> copy{str_with_len_N};/256_median 152 ns 152 ns 10 -lstringa<16> copy{str_with_len_N};/256_stddev 34.9 ns 34.9 ns 10 -lstringa<16> copy{str_with_len_N};/256_cv 26.21 % 26.21 % 10 -lstringa<16> copy{str_with_len_N};/512_mean 130 ns 130 ns 10 -lstringa<16> copy{str_with_len_N};/512_median 131 ns 131 ns 10 -lstringa<16> copy{str_with_len_N};/512_stddev 38.4 ns 38.4 ns 10 -lstringa<16> copy{str_with_len_N};/512_cv 29.57 % 29.57 % 10 -lstringa<16> copy{str_with_len_N};/1024_mean 111 ns 111 ns 10 -lstringa<16> copy{str_with_len_N};/1024_median 102 ns 102 ns 10 -lstringa<16> copy{str_with_len_N};/1024_stddev 19.9 ns 19.9 ns 10 -lstringa<16> copy{str_with_len_N};/1024_cv 17.84 % 17.84 % 10 -lstringa<16> copy{str_with_len_N};/2048_mean 122 ns 122 ns 10 -lstringa<16> copy{str_with_len_N};/2048_median 122 ns 122 ns 10 -lstringa<16> copy{str_with_len_N};/2048_stddev 4.77 ns 4.77 ns 10 -lstringa<16> copy{str_with_len_N};/2048_cv 3.91 % 3.91 % 10 -lstringa<16> copy{str_with_len_N};/4096_mean 167 ns 167 ns 10 -lstringa<16> copy{str_with_len_N};/4096_median 167 ns 167 ns 10 -lstringa<16> copy{str_with_len_N};/4096_stddev 2.97 ns 2.97 ns 10 -lstringa<16> copy{str_with_len_N};/4096_cv 1.77 % 1.77 % 10 -lstringa<512> copy{str_with_len_N};/15_mean 17.9 ns 17.9 ns 10 -lstringa<512> copy{str_with_len_N};/15_median 17.8 ns 17.8 ns 10 -lstringa<512> copy{str_with_len_N};/15_stddev 0.742 ns 0.742 ns 10 -lstringa<512> copy{str_with_len_N};/15_cv 4.16 % 4.16 % 10 -lstringa<512> copy{str_with_len_N};/16_mean 18.5 ns 18.5 ns 10 -lstringa<512> copy{str_with_len_N};/16_median 18.3 ns 18.3 ns 10 -lstringa<512> copy{str_with_len_N};/16_stddev 1.16 ns 1.16 ns 10 -lstringa<512> copy{str_with_len_N};/16_cv 6.28 % 6.28 % 10 -lstringa<512> copy{str_with_len_N};/23_mean 18.6 ns 18.6 ns 10 -lstringa<512> copy{str_with_len_N};/23_median 18.4 ns 18.4 ns 10 -lstringa<512> copy{str_with_len_N};/23_stddev 0.848 ns 0.848 ns 10 -lstringa<512> copy{str_with_len_N};/23_cv 4.56 % 4.56 % 10 -lstringa<512> copy{str_with_len_N};/24_mean 18.8 ns 18.8 ns 10 -lstringa<512> copy{str_with_len_N};/24_median 18.6 ns 18.6 ns 10 -lstringa<512> copy{str_with_len_N};/24_stddev 0.881 ns 0.881 ns 10 -lstringa<512> copy{str_with_len_N};/24_cv 4.68 % 4.68 % 10 -lstringa<512> copy{str_with_len_N};/32_mean 25.0 ns 25.0 ns 10 -lstringa<512> copy{str_with_len_N};/32_median 24.3 ns 24.3 ns 10 -lstringa<512> copy{str_with_len_N};/32_stddev 1.68 ns 1.68 ns 10 -lstringa<512> copy{str_with_len_N};/32_cv 6.71 % 6.71 % 10 -lstringa<512> copy{str_with_len_N};/64_mean 21.2 ns 21.2 ns 10 -lstringa<512> copy{str_with_len_N};/64_median 21.0 ns 21.0 ns 10 -lstringa<512> copy{str_with_len_N};/64_stddev 0.789 ns 0.789 ns 10 -lstringa<512> copy{str_with_len_N};/64_cv 3.72 % 3.72 % 10 -lstringa<512> copy{str_with_len_N};/128_mean 22.3 ns 22.3 ns 10 -lstringa<512> copy{str_with_len_N};/128_median 22.2 ns 22.2 ns 10 -lstringa<512> copy{str_with_len_N};/128_stddev 0.675 ns 0.675 ns 10 -lstringa<512> copy{str_with_len_N};/128_cv 3.02 % 3.02 % 10 -lstringa<512> copy{str_with_len_N};/256_mean 24.0 ns 24.0 ns 10 -lstringa<512> copy{str_with_len_N};/256_median 23.9 ns 23.9 ns 10 -lstringa<512> copy{str_with_len_N};/256_stddev 0.383 ns 0.383 ns 10 -lstringa<512> copy{str_with_len_N};/256_cv 1.60 % 1.60 % 10 -lstringa<512> copy{str_with_len_N};/512_mean 26.8 ns 26.8 ns 10 -lstringa<512> copy{str_with_len_N};/512_median 26.7 ns 26.7 ns 10 -lstringa<512> copy{str_with_len_N};/512_stddev 0.830 ns 0.830 ns 10 -lstringa<512> copy{str_with_len_N};/512_cv 3.09 % 3.09 % 10 -lstringa<512> copy{str_with_len_N};/1024_mean 113 ns 113 ns 10 -lstringa<512> copy{str_with_len_N};/1024_median 106 ns 106 ns 10 -lstringa<512> copy{str_with_len_N};/1024_stddev 26.0 ns 26.0 ns 10 -lstringa<512> copy{str_with_len_N};/1024_cv 23.08 % 23.08 % 10 -lstringa<512> copy{str_with_len_N};/2048_mean 129 ns 129 ns 10 -lstringa<512> copy{str_with_len_N};/2048_median 129 ns 129 ns 10 -lstringa<512> copy{str_with_len_N};/2048_stddev 5.50 ns 5.50 ns 10 -lstringa<512> copy{str_with_len_N};/2048_cv 4.26 % 4.26 % 10 -lstringa<512> copy{str_with_len_N};/4096_mean 169 ns 169 ns 10 -lstringa<512> copy{str_with_len_N};/4096_median 167 ns 167 ns 10 -lstringa<512> copy{str_with_len_N};/4096_stddev 5.95 ns 5.95 ns 10 -lstringa<512> copy{str_with_len_N};/4096_cv 3.51 % 3.51 % 10 ------ Convert to int '1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_mean 204 ns 204 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 203 ns 203 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 10.00 ns 10.00 ns 10 -std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 4.89 % 4.89 % 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 65.9 ns 65.9 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 65.8 ns 65.8 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.675 ns 0.675 ns 10 -std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 1.02 % 1.02 % 10 -stringa s = "123456789"; int res = s.to_int_mean 58.9 ns 58.9 ns 10 -stringa s = "123456789"; int res = s.to_int_median 57.5 ns 57.5 ns 10 -stringa s = "123456789"; int res = s.to_int_stddev 3.92 ns 3.92 ns 10 -stringa s = "123456789"; int res = s.to_int_cv 6.65 % 6.65 % 10 -ssa s = "123456789"; int res = s.to_int_mean 54.2 ns 54.2 ns 10 -ssa s = "123456789"; int res = s.to_int_median 54.0 ns 54.0 ns 10 -ssa s = "123456789"; int res = s.to_int_stddev 2.00 ns 2.00 ns 10 -ssa s = "123456789"; int res = s.to_int_cv 3.69 % 3.69 % 10 -lstringa<20> s = "123456789"; int res = s.to_int_mean 54.1 ns 54.1 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_median 53.9 ns 53.9 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_stddev 1.31 ns 1.31 ns 10 -lstringa<20> s = "123456789"; int res = s.to_int_cv 2.42 % 2.42 % 10 ------ Convert to unsigned 'abcDef' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 158 ns 158 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 154 ns 154 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 7.54 ns 7.54 ns 10 -std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 4.78 % 4.78 % 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 85.4 ns 85.4 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 85.3 ns 85.3 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 1.31 ns 1.31 ns 10 -std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 1.53 % 1.53 % 10 -stringa s = "abcDef"; int res = s.to_int_mean 50.4 ns 50.4 ns 10 -stringa s = "abcDef"; int res = s.to_int_median 50.7 ns 50.7 ns 10 -stringa s = "abcDef"; int res = s.to_int_stddev 1.67 ns 1.67 ns 10 -stringa s = "abcDef"; int res = s.to_int_cv 3.32 % 3.32 % 10 -ssa s = "abcDef"; int res = s.to_int_mean 47.5 ns 47.5 ns 10 -ssa s = "abcDef"; int res = s.to_int_median 47.3 ns 47.3 ns 10 -ssa s = "abcDef"; int res = s.to_int_stddev 1.31 ns 1.31 ns 10 -ssa s = "abcDef"; int res = s.to_int_cv 2.76 % 2.76 % 10 -lstringa<20> s = "abcDef"; int res = s.to_int_mean 47.2 ns 47.2 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_median 46.5 ns 46.5 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_stddev 2.98 ns 2.98 ns 10 -lstringa<20> s = "abcDef"; int res = s.to_int_cv 6.32 % 6.32 % 10 ------ Convert to int ' 1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_mean 226 ns 226 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 225 ns 225 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 13.9 ns 13.9 ns 10 -std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 6.15 % 6.15 % 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 80.3 ns 80.3 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 79.8 ns 79.8 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 2.73 ns 2.73 ns 10 -stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 3.40 % 3.40 % 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 53.0 ns 53.0 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 52.8 ns 52.8 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.840 ns 0.840 ns 10 -ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 1.58 % 1.58 % 10 ------ Convert to double '1234.567e10' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 460 ns 460 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_median 454 ns 454 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 19.7 ns 19.7 ns 10 -std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 4.28 % 4.28 % 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 294 ns 294 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 291 ns 291 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 6.63 ns 6.63 ns 10 -std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 2.26 % 2.26 % 10 -ssa s = "1234.567e10"; double res = *s.to_double()_mean 105 ns 105 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_median 103 ns 103 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_stddev 6.39 ns 6.38 ns 10 -ssa s = "1234.567e10"; double res = *s.to_double()_cv 6.06 % 6.06 % 10 --- Append const literal of 16 bytes 64 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << "abbaabbaabbaabba";_mean 11819 ns 11819 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_median 11691 ns 11691 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 494 ns 494 ns 10 -std::stringstream str; ... str << "abbaabbaabbaabba";_cv 4.18 % 4.18 % 10 -std::string str; ... str += "abbaabbaabbaabba";_mean 1174 ns 1174 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_median 1168 ns 1168 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_stddev 76.0 ns 76.0 ns 10 -std::string str; ... str += "abbaabbaabbaabba";_cv 6.48 % 6.47 % 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 1294 ns 1294 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_median 1287 ns 1287 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 68.2 ns 68.2 ns 10 -lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 5.27 % 5.27 % 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 900 ns 900 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_median 912 ns 912 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 52.1 ns 52.1 ns 10 -lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 5.79 % 5.79 % 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 637 ns 637 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_median 631 ns 631 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 44.2 ns 44.2 ns 10 -lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 6.94 % 6.94 % 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 501 ns 501 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_median 497 ns 497 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 11.0 ns 11.0 ns 10 -lstringa<1024> str; ... str += "abbaabbaabbaabba";_cv 2.20 % 2.20 % 10 --- Append string of 16 bytes and const literal of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 11807 ns 11807 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 11726 ns 11726 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 449 ns 449 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 3.80 % 3.80 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 4085 ns 4085 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_median 4020 ns 4020 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 196 ns 196 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 4.81 % 4.81 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 1439 ns 1439 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 1449 ns 1449 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 74.9 ns 74.9 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.20 % 5.20 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 1179 ns 1179 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 1186 ns 1186 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 98.7 ns 98.7 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 8.37 % 8.37 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 934 ns 934 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 924 ns 924 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 80.9 ns 80.9 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 8.67 % 8.67 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 734 ns 734 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 727 ns 727 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 22.0 ns 22.0 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 3.00 % 3.00 % 10 --- Append string of 16 bytes and const literal of 16 bytes 2048 times, 65536 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 609176 ns 609186 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 604318 ns 604351 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 23440 ns 23440 ns 10 -std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 3.85 % 3.85 % 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 207760 ns 207762 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 210493 ns 210494 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 8896 ns 8897 ns 10 -std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 4.28 % 4.28 % 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 53812 ns 53812 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 53544 ns 53544 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 2281 ns 2281 ns 10 -lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 4.24 % 4.24 % 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 51889 ns 51889 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 51942 ns 51942 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 1660 ns 1660 ns 10 -lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 3.20 % 3.20 % 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 50113 ns 50114 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 50056 ns 50057 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 811 ns 811 ns 10 -lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 1.62 % 1.62 % 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 52780 ns 52781 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 51519 ns 51519 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 2889 ns 2889 ns 10 -lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 5.47 % 5.47 % 10 --- Append 2 string of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; ... str << str_var1 << str_var2;_mean 11836 ns 11836 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_median 11842 ns 11842 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_stddev 396 ns 396 ns 10 -std::stringstream str; ... str << str_var1 << str_var2;_cv 3.35 % 3.35 % 10 -std::string str; ... str += str_var1 + str_var2;_mean 4507 ns 4507 ns 10 -std::string str; ... str += str_var1 + str_var2;_median 4543 ns 4543 ns 10 -std::string str; ... str += str_var1 + str_var2;_stddev 123 ns 123 ns 10 -std::string str; ... str += str_var1 + str_var2;_cv 2.73 % 2.73 % 10 -lstringa<16> str; ... str += str_var1 + str_var2;_mean 1657 ns 1657 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_median 1646 ns 1646 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_stddev 80.2 ns 80.2 ns 10 -lstringa<16> str; ... str += str_var1 + str_var2;_cv 4.84 % 4.84 % 10 -lstringa<128> str; ... str += str_var1 + str_var2;_mean 1413 ns 1413 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_median 1392 ns 1392 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_stddev 97.3 ns 97.3 ns 10 -lstringa<128> str; ... str += str_var1 + str_var2;_cv 6.89 % 6.89 % 10 -lstringa<512> str; ... str += str_var1 + str_var2;_mean 1088 ns 1088 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_median 1065 ns 1065 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_stddev 58.8 ns 58.8 ns 10 -lstringa<512> str; ... str += str_var1 + str_var2;_cv 5.40 % 5.40 % 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_mean 977 ns 977 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_median 979 ns 979 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 45.7 ns 45.7 ns 10 -lstringa<1024> str; ... str += str_var1 + str_var2;_cv 4.68 % 4.68 % 10 --- Append text, number, text --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::stringstream str; str << "test = " << k << " times";_mean 19450 ns 19450 ns 10 -std::stringstream str; str << "test = " << k << " times";_median 19297 ns 19297 ns 10 -std::stringstream str; str << "test = " << k << " times";_stddev 1456 ns 1456 ns 10 -std::stringstream str; str << "test = " << k << " times";_cv 7.49 % 7.49 % 10 -std::string str = "test = " + std::to_string(k) + " times";_mean 3261 ns 3261 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_median 3216 ns 3216 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_stddev 181 ns 181 ns 10 -std::string str = "test = " + std::to_string(k) + " times";_cv 5.55 % 5.55 % 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 7677 ns 7677 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 7790 ns 7791 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 383 ns 383 ns 10 -char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 4.99 % 4.99 % 10 -std::string str = std::format("test = {} times", k);_mean 4200 ns 4200 ns 10 -std::string str = std::format("test = {} times", k);_median 4204 ns 4204 ns 10 -std::string str = std::format("test = {} times", k);_stddev 136 ns 136 ns 10 -std::string str = std::format("test = {} times", k);_cv 3.24 % 3.24 % 10 -lstringa<8> str; str.format("test = {} times", k);_mean 6598 ns 6598 ns 10 -lstringa<8> str; str.format("test = {} times", k);_median 6515 ns 6515 ns 10 -lstringa<8> str; str.format("test = {} times", k);_stddev 407 ns 407 ns 10 -lstringa<8> str; str.format("test = {} times", k);_cv 6.17 % 6.17 % 10 -lstringa<32> str; str.format("test = {} times", k);_mean 4632 ns 4632 ns 10 -lstringa<32> str; str.format("test = {} times", k);_median 4696 ns 4696 ns 10 -lstringa<32> str; str.format("test = {} times", k);_stddev 149 ns 149 ns 10 -lstringa<32> str; str.format("test = {} times", k);_cv 3.22 % 3.22 % 10 -lstringa<8> str = "test = " + k + " times";_mean 1342 ns 1342 ns 10 -lstringa<8> str = "test = " + k + " times";_median 1347 ns 1347 ns 10 -lstringa<8> str = "test = " + k + " times";_stddev 41.9 ns 41.9 ns 10 -lstringa<8> str = "test = " + k + " times";_cv 3.13 % 3.13 % 10 -lstringa<32> str = "test = " + k + " times";_mean 614 ns 614 ns 10 -lstringa<32> str = "test = " + k + " times";_median 603 ns 603 ns 10 -lstringa<32> str = "test = " + k + " times";_stddev 35.5 ns 35.5 ns 10 -lstringa<32> str = "test = " + k + " times";_cv 5.78 % 5.78 % 10 -stringa str = "test = " + k + " times";_mean 1303 ns 1303 ns 10 -stringa str = "test = " + k + " times";_median 1307 ns 1307 ns 10 -stringa str = "test = " + k + " times";_stddev 58.0 ns 58.0 ns 10 -stringa str = "test = " + k + " times";_cv 4.45 % 4.45 % 10 --- Split text and convert to int --/repeats:1 0.000 ns 0.000 ns 1000000000000 -std::string::find + substr + std::strtol_mean 1414 ns 1414 ns 10 -std::string::find + substr + std::strtol_median 1408 ns 1408 ns 10 -std::string::find + substr + std::strtol_stddev 67.5 ns 67.5 ns 10 -std::string::find + substr + std::strtol_cv 4.78 % 4.78 % 10 -ssa::splitter + ssa::as_int_mean 670 ns 670 ns 10 -ssa::splitter + ssa::as_int_median 654 ns 654 ns 10 -ssa::splitter + ssa::as_int_stddev 34.0 ns 34.0 ns 10 -ssa::splitter + ssa::as_int_cv 5.07 % 5.07 % 10 -ssa::splitf + functor_mean 939 ns 939 ns 10 -ssa::splitf + functor_median 927 ns 927 ns 10 -ssa::splitf + functor_stddev 32.8 ns 32.8 ns 10 -ssa::splitf + functor_cv 3.49 % 3.49 % 10 --- Replace symbols in text ~400 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Naive (and wrong) replace symbols with std::string find + replace_mean 6175 ns 6175 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_median 6116 ns 6116 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_stddev 236 ns 236 ns 10 -Naive (and wrong) replace symbols with std::string find + replace_cv 3.82 % 3.82 % 10 -replace symbols with std::string find_first_of + replace_mean 10124 ns 10125 ns 10 -replace symbols with std::string find_first_of + replace_median 10071 ns 10071 ns 10 -replace symbols with std::string find_first_of + replace_stddev 222 ns 222 ns 10 -replace symbols with std::string find_first_of + replace_cv 2.20 % 2.20 % 10 -replace symbols with std::string_view find_first_of + copy_mean 5505 ns 5505 ns 10 -replace symbols with std::string_view find_first_of + copy_median 5527 ns 5527 ns 10 -replace symbols with std::string_view find_first_of + copy_stddev 215 ns 215 ns 10 -replace symbols with std::string_view find_first_of + copy_cv 3.91 % 3.91 % 10 -replace runtime symbols with string expressions and without remembering all search results_mean 5599 ns 5599 ns 10 -replace runtime symbols with string expressions and without remembering all search results_median 5526 ns 5526 ns 10 -replace runtime symbols with string expressions and without remembering all search results_stddev 255 ns 255 ns 10 -replace runtime symbols with string expressions and without remembering all search results_cv 4.56 % 4.56 % 10 -replace runtime symbols with simstr and memorization of all search results_mean 5123 ns 5123 ns 10 -replace runtime symbols with simstr and memorization of all search results_median 5130 ns 5130 ns 10 -replace runtime symbols with simstr and memorization of all search results_stddev 196 ns 196 ns 10 -replace runtime symbols with simstr and memorization of all search results_cv 3.83 % 3.83 % 10 -replace const symbols with string expressions and without remembering all search results_mean 4773 ns 4773 ns 10 -replace const symbols with string expressions and without remembering all search results_median 4789 ns 4789 ns 10 -replace const symbols with string expressions and without remembering all search results_stddev 152 ns 152 ns 10 -replace const symbols with string expressions and without remembering all search results_cv 3.18 % 3.18 % 10 -replace const symbols with string expressions and memorization of all search results_mean 4477 ns 4477 ns 10 -replace const symbols with string expressions and memorization of all search results_median 4417 ns 4417 ns 10 -replace const symbols with string expressions and memorization of all search results_stddev 232 ns 232 ns 10 -replace const symbols with string expressions and memorization of all search results_cv 5.18 % 5.18 % 10 --- Replace symbols in text ~40 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 -Short Naive (and wrong) replace symbols with std::string find + replace_mean 827 ns 827 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_median 805 ns 805 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_stddev 55.5 ns 55.5 ns 10 -Short Naive (and wrong) replace symbols with std::string find + replace_cv 6.71 % 6.71 % 10 -Short replace symbols with std::string find_first_of + replace_mean 1187 ns 1187 ns 10 -Short replace symbols with std::string find_first_of + replace_median 1191 ns 1192 ns 10 -Short replace symbols with std::string find_first_of + replace_stddev 22.7 ns 22.7 ns 10 -Short replace symbols with std::string find_first_of + replace_cv 1.92 % 1.92 % 10 -Short replace symbols with std::string_view find_first_of + copy_mean 694 ns 694 ns 10 -Short replace symbols with std::string_view find_first_of + copy_median 695 ns 695 ns 10 -Short replace symbols with std::string_view find_first_of + copy_stddev 35.3 ns 35.3 ns 10 -Short replace symbols with std::string_view find_first_of + copy_cv 5.09 % 5.09 % 10 -Short replace runtime symbols with string expressions and without remembering all search results_mean 583 ns 583 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_median 580 ns 580 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_stddev 14.7 ns 14.7 ns 10 -Short replace runtime symbols with string expressions and without remembering all search results_cv 2.52 % 2.52 % 10 -Short replace runtime symbols with simstr and memorization of all search results_mean 669 ns 669 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_median 653 ns 653 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_stddev 41.6 ns 41.6 ns 10 -Short replace runtime symbols with simstr and memorization of all search results_cv 6.22 % 6.22 % 10 -Short replace const symbols with string expressions and without remembering all search results_mean 440 ns 440 ns 10 -Short replace const symbols with string expressions and without remembering all search results_median 434 ns 434 ns 10 -Short replace const symbols with string expressions and without remembering all search results_stddev 21.5 ns 21.5 ns 10 -Short replace const symbols with string expressions and without remembering all search results_cv 4.89 % 4.89 % 10 -Short replace const symbols with string expressions and memorization of all search results_mean 512 ns 512 ns 10 -Short replace const symbols with string expressions and memorization of all search results_median 497 ns 497 ns 10 -Short replace const symbols with string expressions and memorization of all search results_stddev 42.4 ns 42.4 ns 10 -Short replace const symbols with string expressions and memorization of all search results_cv 8.29 % 8.29 % 10 ------ Replace All Str To Longer Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to ---- in std::string|64_mean 759 ns 759 ns 10 -replace bb to ---- in std::string|64_median 756 ns 756 ns 10 -replace bb to ---- in std::string|64_stddev 35.6 ns 35.6 ns 10 -replace bb to ---- in std::string|64_cv 4.69 % 4.69 % 10 -replace bb to ---- in std::string|256_mean 2371 ns 2371 ns 10 -replace bb to ---- in std::string|256_median 2356 ns 2356 ns 10 -replace bb to ---- in std::string|256_stddev 141 ns 141 ns 10 -replace bb to ---- in std::string|256_cv 5.97 % 5.97 % 10 -replace bb to ---- in std::string|512_mean 4397 ns 4397 ns 10 -replace bb to ---- in std::string|512_median 4347 ns 4347 ns 10 -replace bb to ---- in std::string|512_stddev 209 ns 209 ns 10 -replace bb to ---- in std::string|512_cv 4.75 % 4.75 % 10 -replace bb to ---- in std::string|1024_mean 8983 ns 8983 ns 10 -replace bb to ---- in std::string|1024_median 8903 ns 8903 ns 10 -replace bb to ---- in std::string|1024_stddev 716 ns 716 ns 10 -replace bb to ---- in std::string|1024_cv 7.97 % 7.97 % 10 -replace bb to ---- in std::string|2048_mean 20059 ns 20059 ns 10 -replace bb to ---- in std::string|2048_median 20184 ns 20184 ns 10 -replace bb to ---- in std::string|2048_stddev 599 ns 599 ns 10 -replace bb to ---- in std::string|2048_cv 2.99 % 2.99 % 10 -replace bb to ---- in lstringa<8>|64_mean 734 ns 734 ns 10 -replace bb to ---- in lstringa<8>|64_median 729 ns 729 ns 10 -replace bb to ---- in lstringa<8>|64_stddev 12.3 ns 12.3 ns 10 -replace bb to ---- in lstringa<8>|64_cv 1.67 % 1.67 % 10 -replace bb to ---- in lstringa<8>|256_mean 2096 ns 2096 ns 10 -replace bb to ---- in lstringa<8>|256_median 2094 ns 2094 ns 10 -replace bb to ---- in lstringa<8>|256_stddev 98.1 ns 98.1 ns 10 -replace bb to ---- in lstringa<8>|256_cv 4.68 % 4.68 % 10 -replace bb to ---- in lstringa<8>|512_mean 3770 ns 3770 ns 10 -replace bb to ---- in lstringa<8>|512_median 3744 ns 3744 ns 10 -replace bb to ---- in lstringa<8>|512_stddev 171 ns 171 ns 10 -replace bb to ---- in lstringa<8>|512_cv 4.53 % 4.53 % 10 -replace bb to ---- in lstringa<8>|1024_mean 7288 ns 7288 ns 10 -replace bb to ---- in lstringa<8>|1024_median 7121 ns 7121 ns 10 -replace bb to ---- in lstringa<8>|1024_stddev 470 ns 470 ns 10 -replace bb to ---- in lstringa<8>|1024_cv 6.45 % 6.45 % 10 -replace bb to ---- in lstringa<8>|2048_mean 13342 ns 13342 ns 10 -replace bb to ---- in lstringa<8>|2048_median 13306 ns 13306 ns 10 -replace bb to ---- in lstringa<8>|2048_stddev 401 ns 401 ns 10 -replace bb to ---- in lstringa<8>|2048_cv 3.01 % 3.01 % 10 -replace bb to ---- by init stringa|64_mean 498 ns 498 ns 10 -replace bb to ---- by init stringa|64_median 490 ns 490 ns 10 -replace bb to ---- by init stringa|64_stddev 42.1 ns 42.1 ns 10 -replace bb to ---- by init stringa|64_cv 8.46 % 8.46 % 10 -replace bb to ---- by init stringa|256_mean 1896 ns 1896 ns 10 -replace bb to ---- by init stringa|256_median 1905 ns 1905 ns 10 -replace bb to ---- by init stringa|256_stddev 42.1 ns 42.1 ns 10 -replace bb to ---- by init stringa|256_cv 2.22 % 2.22 % 10 -replace bb to ---- by init stringa|512_mean 3611 ns 3611 ns 10 -replace bb to ---- by init stringa|512_median 3605 ns 3605 ns 10 -replace bb to ---- by init stringa|512_stddev 99.0 ns 99.0 ns 10 -replace bb to ---- by init stringa|512_cv 2.74 % 2.74 % 10 -replace bb to ---- by init stringa|1024_mean 6933 ns 6933 ns 10 -replace bb to ---- by init stringa|1024_median 6974 ns 6974 ns 10 -replace bb to ---- by init stringa|1024_stddev 208 ns 208 ns 10 -replace bb to ---- by init stringa|1024_cv 3.00 % 3.00 % 10 -replace bb to ---- by init stringa|2048_mean 13812 ns 13812 ns 10 -replace bb to ---- by init stringa|2048_median 13831 ns 13831 ns 10 -replace bb to ---- by init stringa|2048_stddev 412 ns 412 ns 10 -replace bb to ---- by init stringa|2048_cv 2.98 % 2.98 % 10 ------ Replace All Str To Same Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -replace bb to -- in std::string|64_mean 545 ns 545 ns 10 -replace bb to -- in std::string|64_median 546 ns 546 ns 10 -replace bb to -- in std::string|64_stddev 13.4 ns 13.4 ns 10 -replace bb to -- in std::string|64_cv 2.45 % 2.45 % 10 -replace bb to -- in std::string|256_mean 1885 ns 1885 ns 10 -replace bb to -- in std::string|256_median 1853 ns 1853 ns 10 -replace bb to -- in std::string|256_stddev 113 ns 113 ns 10 -replace bb to -- in std::string|256_cv 6.00 % 6.00 % 10 -replace bb to -- in std::string|512_mean 3368 ns 3368 ns 10 -replace bb to -- in std::string|512_median 3358 ns 3358 ns 10 -replace bb to -- in std::string|512_stddev 107 ns 107 ns 10 -replace bb to -- in std::string|512_cv 3.17 % 3.17 % 10 -replace bb to -- in std::string|1024_mean 6925 ns 6925 ns 10 -replace bb to -- in std::string|1024_median 6910 ns 6910 ns 10 -replace bb to -- in std::string|1024_stddev 344 ns 344 ns 10 -replace bb to -- in std::string|1024_cv 4.97 % 4.97 % 10 -replace bb to -- in std::string|2048_mean 13051 ns 13051 ns 10 -replace bb to -- in std::string|2048_median 12940 ns 12940 ns 10 -replace bb to -- in std::string|2048_stddev 417 ns 417 ns 10 -replace bb to -- in std::string|2048_cv 3.19 % 3.19 % 10 -replace bb to -- in lstringa<8>|64_mean 483 ns 483 ns 10 -replace bb to -- in lstringa<8>|64_median 477 ns 477 ns 10 -replace bb to -- in lstringa<8>|64_stddev 28.3 ns 28.3 ns 10 -replace bb to -- in lstringa<8>|64_cv 5.85 % 5.85 % 10 -replace bb to -- in lstringa<8>|256_mean 1542 ns 1542 ns 10 -replace bb to -- in lstringa<8>|256_median 1531 ns 1531 ns 10 -replace bb to -- in lstringa<8>|256_stddev 78.0 ns 78.0 ns 10 -replace bb to -- in lstringa<8>|256_cv 5.06 % 5.06 % 10 -replace bb to -- in lstringa<8>|512_mean 2827 ns 2827 ns 10 -replace bb to -- in lstringa<8>|512_median 2815 ns 2815 ns 10 -replace bb to -- in lstringa<8>|512_stddev 123 ns 123 ns 10 -replace bb to -- in lstringa<8>|512_cv 4.34 % 4.34 % 10 -replace bb to -- in lstringa<8>|1024_mean 5568 ns 5568 ns 10 -replace bb to -- in lstringa<8>|1024_median 5501 ns 5501 ns 10 -replace bb to -- in lstringa<8>|1024_stddev 387 ns 387 ns 10 -replace bb to -- in lstringa<8>|1024_cv 6.95 % 6.95 % 10 -replace bb to -- in lstringa<8>|2048_mean 10863 ns 10863 ns 10 -replace bb to -- in lstringa<8>|2048_median 10863 ns 10863 ns 10 -replace bb to -- in lstringa<8>|2048_stddev 541 ns 541 ns 10 -replace bb to -- in lstringa<8>|2048_cv 4.98 % 4.98 % 10 -replace bb to -- by init stringa|64_mean 363 ns 363 ns 10 -replace bb to -- by init stringa|64_median 356 ns 356 ns 10 -replace bb to -- by init stringa|64_stddev 23.8 ns 23.8 ns 10 -replace bb to -- by init stringa|64_cv 6.57 % 6.56 % 10 -replace bb to -- by init stringa|256_mean 1249 ns 1249 ns 10 -replace bb to -- by init stringa|256_median 1176 ns 1176 ns 10 -replace bb to -- by init stringa|256_stddev 145 ns 145 ns 10 -replace bb to -- by init stringa|256_cv 11.61 % 11.61 % 10 -replace bb to -- by init stringa|512_mean 2243 ns 2243 ns 10 -replace bb to -- by init stringa|512_median 2206 ns 2206 ns 10 -replace bb to -- by init stringa|512_stddev 131 ns 131 ns 10 -replace bb to -- by init stringa|512_cv 5.85 % 5.85 % 10 -replace bb to -- by init stringa|1024_mean 4204 ns 4204 ns 10 -replace bb to -- by init stringa|1024_median 4185 ns 4185 ns 10 -replace bb to -- by init stringa|1024_stddev 123 ns 123 ns 10 -replace bb to -- by init stringa|1024_cv 2.92 % 2.92 % 10 -replace bb to -- by init stringa|2048_mean 8206 ns 8207 ns 10 -replace bb to -- by init stringa|2048_median 8270 ns 8270 ns 10 -replace bb to -- by init stringa|2048_stddev 171 ns 171 ns 10 -replace bb to -- by init stringa|2048_cv 2.09 % 2.09 % 10 ------ Hash Map insert and find ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -hashStrMapA emplace & find stringa;_mean 5371717 ns 5371764 ns 10 -hashStrMapA emplace & find stringa;_median 5351902 ns 5351957 ns 10 -hashStrMapA emplace & find stringa;_stddev 95139 ns 95136 ns 10 -hashStrMapA emplace & find stringa;_cv 1.77 % 1.77 % 10 -std::unordered_map emplace & find std::string;_mean 5883527 ns 5883602 ns 10 -std::unordered_map emplace & find std::string;_median 5863441 ns 5863495 ns 10 -std::unordered_map emplace & find std::string;_stddev 121360 ns 121344 ns 10 -std::unordered_map emplace & find std::string;_cv 2.06 % 2.06 % 10 -hashStrMapA emplace & find ssa;_mean 5376097 ns 5376160 ns 10 -hashStrMapA emplace & find ssa;_median 5396723 ns 5396748 ns 10 -hashStrMapA emplace & find ssa;_stddev 55934 ns 55933 ns 10 -hashStrMapA emplace & find ssa;_cv 1.04 % 1.04 % 10 -std::unordered_map emplace & find std::string_view;_mean 6884220 ns 6884269 ns 10 -std::unordered_map emplace & find std::string_view;_median 6758571 ns 6758571 ns 10 -std::unordered_map emplace & find std::string_view;_stddev 494224 ns 494235 ns 10 -std::unordered_map emplace & find std::string_view;_cv 7.18 % 7.18 % 10 ------ Build Full Func Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 -Build func full name std::string;_mean 4861 ns 4861 ns 10 -Build func full name std::string;_median 4830 ns 4830 ns 10 -Build func full name std::string;_stddev 214 ns 214 ns 10 -Build func full name std::string;_cv 4.41 % 4.41 % 10 -Build func full name std::string 1;_mean 5220 ns 5220 ns 10 -Build func full name std::string 1;_median 5168 ns 5168 ns 10 -Build func full name std::string 1;_stddev 379 ns 379 ns 10 -Build func full name std::string 1;_cv 7.27 % 7.27 % 10 -Build func full name std::stream;_mean 16474 ns 16474 ns 10 -Build func full name std::stream;_median 16253 ns 16253 ns 10 -Build func full name std::stream;_stddev 1049 ns 1049 ns 10 -Build func full name std::stream;_cv 6.37 % 6.37 % 10 -Build func full name stringa;_mean 2853 ns 2853 ns 10 -Build func full name stringa;_median 2857 ns 2857 ns 10 -Build func full name stringa;_stddev 63.2 ns 63.2 ns 10 -Build func full name stringa;_cv 2.22 % 2.22 % 10 -Build func full name stringa 1;_mean 3292 ns 3292 ns 10 -Build func full name stringa 1;_median 3292 ns 3292 ns 10 -Build func full name stringa 1;_stddev 91.3 ns 91.3 ns 10 -Build func full name stringa 1;_cv 2.77 % 2.77 % 10 diff --git a/bench/results/004-Xeon E5-2682 v4, WASM Firefox, Clang-21.txt b/bench/results/004-Xeon E5-2682 v4, WASM Firefox, Clang-21.txt new file mode 100644 index 0000000..9c135e2 --- /dev/null +++ b/bench/results/004-Xeon E5-2682 v4, WASM Firefox, Clang-21.txt @@ -0,0 +1,870 @@ +Run on (32 X 2513.96 MHz CPU s) +Firefox: 146.0.1.60 webasm +-------------------------------------------------------------------------------------------------------------------------------------------------------- +Benchmark Time CPU Iterations +-------------------------------------------------------------------------------------------------------------------------------------------------------- +----- Concatenate string + Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and number by std to std::string_mean 925 ns 925 ns 10 +Concat std::string and number by std to std::string_median 933 ns 933 ns 10 +Concat std::string and number by std to std::string_stddev 46.4 ns 46.4 ns 10 +Concat std::string and number by std to std::string_cv 5.01 % 5.01 % 10 +Concat std::string and number by StrExpr to std::string_mean 415 ns 415 ns 10 +Concat std::string and number by StrExpr to std::string_median 418 ns 418 ns 10 +Concat std::string and number by StrExpr to std::string_stddev 14.1 ns 14.1 ns 10 +Concat std::string and number by StrExpr to std::string_cv 3.39 % 3.39 % 10 +Concat stringa and number by StrExpr to simstr::stringa_mean 211 ns 211 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_median 213 ns 213 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_stddev 11.8 ns 11.8 ns 10 +Concat stringa and number by StrExpr to simstr::stringa_cv 5.56 % 5.56 % 10 +----- Concatenate string + Hex Number + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string and hex number by std to std::string_mean 1446 ns 1446 ns 10 +Concat std::string and hex number by std to std::string_median 1429 ns 1429 ns 10 +Concat std::string and hex number by std to std::string_stddev 81.6 ns 81.6 ns 10 +Concat std::string and hex number by std to std::string_cv 5.64 % 5.64 % 10 +Concat std::string and hex number by StrExpr to std::string_mean 365 ns 365 ns 10 +Concat std::string and hex number by StrExpr to std::string_median 367 ns 367 ns 10 +Concat std::string and hex number by StrExpr to std::string_stddev 17.7 ns 17.7 ns 10 +Concat std::string and hex number by StrExpr to std::string_cv 4.87 % 4.87 % 10 +Concat stringa and hex number by StrExpr to simstr::stringa_mean 196 ns 196 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_median 188 ns 188 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_stddev 17.3 ns 17.3 ns 10 +Concat stringa and hex number by StrExpr to simstr::stringa_cv 8.84 % 8.84 % 10 +----- Concatenate string + "Literal" ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat std::string by std to std::string_mean 111 ns 111 ns 10 +Concat std::string by std to std::string_median 109 ns 109 ns 10 +Concat std::string by std to std::string_stddev 4.84 ns 4.84 ns 10 +Concat std::string by std to std::string_cv 4.37 % 4.37 % 10 +Concat std::string by StrExpr to std::string_mean 113 ns 113 ns 10 +Concat std::string by StrExpr to std::string_median 113 ns 113 ns 10 +Concat std::string by StrExpr to std::string_stddev 5.81 ns 5.80 ns 10 +Concat std::string by StrExpr to std::string_cv 5.13 % 5.13 % 10 +Concat stringa by StrExpr to stringa_mean 95.9 ns 95.9 ns 10 +Concat stringa by StrExpr to stringa_median 95.0 ns 95.0 ns 10 +Concat stringa by StrExpr to stringa_stddev 6.99 ns 6.99 ns 10 +Concat stringa by StrExpr to stringa_cv 7.29 % 7.29 % 10 +----- Find three concatenated string in string_view -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Find concat three std::string_mean 178 ns 178 ns 10 +Find concat three std::string_median 174 ns 174 ns 10 +Find concat three std::string_stddev 11.0 ns 11.0 ns 10 +Find concat three std::string_cv 6.19 % 6.19 % 10 +Find concat three strexpr_mean 106 ns 106 ns 10 +Find concat three strexpr_median 105 ns 105 ns 10 +Find concat three strexpr_stddev 3.62 ns 3.62 ns 10 +Find concat three strexpr_cv 3.42 % 3.43 % 10 +Find concat three simstr_mean 73.7 ns 73.7 ns 10 +Find concat three simstr_median 73.7 ns 73.7 ns 10 +Find concat three simstr_stddev 2.09 ns 2.08 ns 10 +Find concat three simstr_cv 2.83 % 2.83 % 10 +----- Build Type Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +BuildTypeNameStr 0/0_mean 18.2 ns 18.2 ns 10 +BuildTypeNameStr 0/0_median 18.5 ns 18.5 ns 10 +BuildTypeNameStr 0/0_stddev 1.29 ns 1.29 ns 10 +BuildTypeNameStr 0/0_cv 7.06 % 7.06 % 10 +BuildTypeNameExp 0/0_mean 17.0 ns 17.0 ns 10 +BuildTypeNameExp 0/0_median 17.1 ns 17.1 ns 10 +BuildTypeNameExp 0/0_stddev 0.847 ns 0.847 ns 10 +BuildTypeNameExp 0/0_cv 4.98 % 4.98 % 10 +BuildTypeNameSim 0/0_mean 17.0 ns 17.0 ns 10 +BuildTypeNameSim 0/0_median 16.7 ns 16.7 ns 10 +BuildTypeNameSim 0/0_stddev 1.17 ns 1.17 ns 10 +BuildTypeNameSim 0/0_cv 6.90 % 6.90 % 10 +BuildTypeNameStr 10/10_mean 275 ns 275 ns 10 +BuildTypeNameStr 10/10_median 276 ns 276 ns 10 +BuildTypeNameStr 10/10_stddev 13.0 ns 13.0 ns 10 +BuildTypeNameStr 10/10_cv 4.72 % 4.72 % 10 +BuildTypeNameExp 10/10_mean 99.6 ns 99.6 ns 10 +BuildTypeNameExp 10/10_median 101 ns 101 ns 10 +BuildTypeNameExp 10/10_stddev 6.85 ns 6.85 ns 10 +BuildTypeNameExp 10/10_cv 6.88 % 6.88 % 10 +BuildTypeNameSim 10/10_mean 71.2 ns 71.2 ns 10 +BuildTypeNameSim 10/10_median 69.2 ns 69.2 ns 10 +BuildTypeNameSim 10/10_stddev 6.72 ns 6.72 ns 10 +BuildTypeNameSim 10/10_cv 9.44 % 9.44 % 10 +----- Replace string by copy -----/repeats:1 0.000 ns 0.000 ns 1000000000000 +Concat with replace str_mean 451 ns 451 ns 10 +Concat with replace str_median 450 ns 450 ns 10 +Concat with replace str_stddev 36.0 ns 36.0 ns 10 +Concat with replace str_cv 7.98 % 7.98 % 10 +Concat with replace exp_mean 248 ns 248 ns 10 +Concat with replace exp_median 246 ns 246 ns 10 +Concat with replace exp_stddev 15.1 ns 15.1 ns 10 +Concat with replace exp_cv 6.07 % 6.07 % 10 +----- Create Empty Str ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string e;_mean 2.18 ns 2.18 ns 10 +std::string e;_median 2.18 ns 2.18 ns 10 +std::string e;_stddev 0.025 ns 0.025 ns 10 +std::string e;_cv 1.16 % 1.16 % 10 +std::string_view e;_mean 0.993 ns 0.993 ns 10 +std::string_view e;_median 0.994 ns 0.994 ns 10 +std::string_view e;_stddev 0.012 ns 0.012 ns 10 +std::string_view e;_cv 1.18 % 1.18 % 10 +ssa e;_mean 0.952 ns 0.952 ns 10 +ssa e;_median 0.952 ns 0.952 ns 10 +ssa e;_stddev 0.008 ns 0.008 ns 10 +ssa e;_cv 0.85 % 0.85 % 10 +stringa e;_mean 2.19 ns 2.19 ns 10 +stringa e;_median 2.18 ns 2.18 ns 10 +stringa e;_stddev 0.048 ns 0.048 ns 10 +stringa e;_cv 2.19 % 2.19 % 10 +lstringa<20> e;_mean 2.26 ns 2.26 ns 10 +lstringa<20> e;_median 2.27 ns 2.27 ns 10 +lstringa<20> e;_stddev 0.039 ns 0.039 ns 10 +lstringa<20> e;_cv 1.74 % 1.74 % 10 +lstringa<40> e;_mean 2.60 ns 2.60 ns 10 +lstringa<40> e;_median 2.60 ns 2.60 ns 10 +lstringa<40> e;_stddev 0.032 ns 0.032 ns 10 +lstringa<40> e;_cv 1.22 % 1.22 % 10 +----- Create Str from short literal (9 symbols) --------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string e = "Test text";_mean 2.37 ns 2.37 ns 10 +std::string e = "Test text";_median 2.37 ns 2.37 ns 10 +std::string e = "Test text";_stddev 0.060 ns 0.060 ns 10 +std::string e = "Test text";_cv 2.54 % 2.54 % 10 +std::string_view e = "Test text";_mean 1.29 ns 1.29 ns 10 +std::string_view e = "Test text";_median 1.27 ns 1.27 ns 10 +std::string_view e = "Test text";_stddev 0.057 ns 0.057 ns 10 +std::string_view e = "Test text";_cv 4.41 % 4.41 % 10 +ssa e = "Test text";_mean 1.01 ns 1.01 ns 10 +ssa e = "Test text";_median 1.00 ns 1.00 ns 10 +ssa e = "Test text";_stddev 0.034 ns 0.034 ns 10 +ssa e = "Test text";_cv 3.32 % 3.32 % 10 +stringa e = "Test text";_mean 2.63 ns 2.63 ns 10 +stringa e = "Test text";_median 2.63 ns 2.63 ns 10 +stringa e = "Test text";_stddev 0.059 ns 0.059 ns 10 +stringa e = "Test text";_cv 2.24 % 2.24 % 10 +lstringa<20> e = "Test text";_mean 2.77 ns 2.77 ns 10 +lstringa<20> e = "Test text";_median 2.77 ns 2.77 ns 10 +lstringa<20> e = "Test text";_stddev 0.092 ns 0.092 ns 10 +lstringa<20> e = "Test text";_cv 3.31 % 3.31 % 10 +lstringa<40> e = "Test text";_mean 2.78 ns 2.78 ns 10 +lstringa<40> e = "Test text";_median 2.78 ns 2.78 ns 10 +lstringa<40> e = "Test text";_stddev 0.038 ns 0.038 ns 10 +lstringa<40> e = "Test text";_cv 1.37 % 1.37 % 10 +----- Create Str from long literal (30 symbols) ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string e = "123456789012345678901234567890";_mean 16.5 ns 16.5 ns 10 +std::string e = "123456789012345678901234567890";_median 16.6 ns 16.6 ns 10 +std::string e = "123456789012345678901234567890";_stddev 0.412 ns 0.412 ns 10 +std::string e = "123456789012345678901234567890";_cv 2.50 % 2.50 % 10 +std::string_view e = "123456789012345678901234567890";_mean 1.26 ns 1.26 ns 10 +std::string_view e = "123456789012345678901234567890";_median 1.27 ns 1.27 ns 10 +std::string_view e = "123456789012345678901234567890";_stddev 0.034 ns 0.034 ns 10 +std::string_view e = "123456789012345678901234567890";_cv 2.66 % 2.66 % 10 +ssa e = "123456789012345678901234567890";_mean 1.01 ns 1.01 ns 10 +ssa e = "123456789012345678901234567890";_median 1.01 ns 1.01 ns 10 +ssa e = "123456789012345678901234567890";_stddev 0.030 ns 0.030 ns 10 +ssa e = "123456789012345678901234567890";_cv 3.03 % 3.03 % 10 +stringa e = "123456789012345678901234567890";_mean 2.67 ns 2.67 ns 10 +stringa e = "123456789012345678901234567890";_median 2.66 ns 2.66 ns 10 +stringa e = "123456789012345678901234567890";_stddev 0.058 ns 0.058 ns 10 +stringa e = "123456789012345678901234567890";_cv 2.15 % 2.15 % 10 +lstringa<20> e = "123456789012345678901234567890";_mean 16.9 ns 16.9 ns 10 +lstringa<20> e = "123456789012345678901234567890";_median 17.0 ns 17.0 ns 10 +lstringa<20> e = "123456789012345678901234567890";_stddev 0.396 ns 0.395 ns 10 +lstringa<20> e = "123456789012345678901234567890";_cv 2.34 % 2.33 % 10 +lstringa<40> e = "123456789012345678901234567890";_mean 3.01 ns 3.01 ns 10 +lstringa<40> e = "123456789012345678901234567890";_median 3.02 ns 3.02 ns 10 +lstringa<40> e = "123456789012345678901234567890";_stddev 0.056 ns 0.056 ns 10 +lstringa<40> e = "123456789012345678901234567890";_cv 1.85 % 1.85 % 10 +----- Create copy of Str with 9 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string e = "Test text"; auto c{e};_mean 2.27 ns 2.27 ns 10 +std::string e = "Test text"; auto c{e};_median 2.25 ns 2.25 ns 10 +std::string e = "Test text"; auto c{e};_stddev 0.050 ns 0.050 ns 10 +std::string e = "Test text"; auto c{e};_cv 2.19 % 2.19 % 10 +std::string_view e = "Test text"; auto c{e};_mean 1.26 ns 1.26 ns 10 +std::string_view e = "Test text"; auto c{e};_median 1.25 ns 1.25 ns 10 +std::string_view e = "Test text"; auto c{e};_stddev 0.035 ns 0.035 ns 10 +std::string_view e = "Test text"; auto c{e};_cv 2.77 % 2.77 % 10 +ssa e = "Test text"; auto c{e};_mean 1.27 ns 1.27 ns 10 +ssa e = "Test text"; auto c{e};_median 1.26 ns 1.26 ns 10 +ssa e = "Test text"; auto c{e};_stddev 0.042 ns 0.042 ns 10 +ssa e = "Test text"; auto c{e};_cv 3.31 % 3.31 % 10 +stringa e = "Test text"; auto c{e};_mean 2.64 ns 2.64 ns 10 +stringa e = "Test text"; auto c{e};_median 2.64 ns 2.64 ns 10 +stringa e = "Test text"; auto c{e};_stddev 0.056 ns 0.056 ns 10 +stringa e = "Test text"; auto c{e};_cv 2.12 % 2.12 % 10 +lstringa<20> e = "Test text"; auto c{e};_mean 14.1 ns 14.1 ns 10 +lstringa<20> e = "Test text"; auto c{e};_median 14.0 ns 14.0 ns 10 +lstringa<20> e = "Test text"; auto c{e};_stddev 0.634 ns 0.634 ns 10 +lstringa<20> e = "Test text"; auto c{e};_cv 4.49 % 4.49 % 10 +lstringa<40> e = "Test text"; auto c{e};_mean 14.2 ns 14.2 ns 10 +lstringa<40> e = "Test text"; auto c{e};_median 14.3 ns 14.3 ns 10 +lstringa<40> e = "Test text"; auto c{e};_stddev 0.671 ns 0.671 ns 10 +lstringa<40> e = "Test text"; auto c{e};_cv 4.73 % 4.73 % 10 +----- Create copy of Str with 30 symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string e = "123456789012345678901234567890"; auto c{e};_mean 34.3 ns 34.3 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_median 34.4 ns 34.4 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_stddev 2.04 ns 2.04 ns 10 +std::string e = "123456789012345678901234567890"; auto c{e};_cv 5.95 % 5.95 % 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_mean 1.25 ns 1.25 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_median 1.24 ns 1.24 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_stddev 0.021 ns 0.021 ns 10 +std::string_view e = "123456789012345678901234567890"; auto c{e};_cv 1.68 % 1.68 % 10 +ssa e = "123456789012345678901234567890"; auto c{e};_mean 1.01 ns 1.01 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_median 1.01 ns 1.01 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_stddev 0.018 ns 0.018 ns 10 +ssa e = "123456789012345678901234567890"; auto c{e};_cv 1.78 % 1.78 % 10 +stringa e = "123456789012345678901234567890"; auto c{e};_mean 2.66 ns 2.66 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_median 2.66 ns 2.66 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_stddev 0.041 ns 0.041 ns 10 +stringa e = "123456789012345678901234567890"; auto c{e};_cv 1.53 % 1.53 % 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_mean 17.2 ns 17.2 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_median 17.3 ns 17.3 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_stddev 0.371 ns 0.371 ns 10 +lstringa<20> e = "123456789012345678901234567890"; auto c{e};_cv 2.15 % 2.15 % 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_mean 13.9 ns 13.9 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_median 13.7 ns 13.7 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_stddev 1.21 ns 1.21 ns 10 +lstringa<40> e = "123456789012345678901234567890"; auto c{e};_cv 8.68 % 8.68 % 10 +----- Find 9 symbols text in end of 99 symbols text ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string::find;_mean 54.3 ns 54.3 ns 10 +std::string::find;_median 54.4 ns 54.4 ns 10 +std::string::find;_stddev 1.00 ns 1.00 ns 10 +std::string::find;_cv 1.85 % 1.85 % 10 +std::string_view::find;_mean 53.4 ns 53.4 ns 10 +std::string_view::find;_median 53.3 ns 53.3 ns 10 +std::string_view::find;_stddev 0.764 ns 0.764 ns 10 +std::string_view::find;_cv 1.43 % 1.43 % 10 +ssa::find;_mean 52.7 ns 52.7 ns 10 +ssa::find;_median 52.9 ns 52.9 ns 10 +ssa::find;_stddev 0.944 ns 0.944 ns 10 +ssa::find;_cv 1.79 % 1.79 % 10 +stringa::find;_mean 53.8 ns 53.8 ns 10 +stringa::find;_median 53.7 ns 53.7 ns 10 +stringa::find;_stddev 1.24 ns 1.24 ns 10 +stringa::find;_cv 2.30 % 2.30 % 10 +lstringa<20>::find;_mean 52.5 ns 52.5 ns 10 +lstringa<20>::find;_median 52.3 ns 52.3 ns 10 +lstringa<20>::find;_stddev 1.02 ns 1.02 ns 10 +lstringa<20>::find;_cv 1.94 % 1.94 % 10 +lstringa<40>::find;_mean 52.6 ns 52.6 ns 10 +lstringa<40>::find;_median 52.8 ns 52.8 ns 10 +lstringa<40>::find;_stddev 0.944 ns 0.944 ns 10 +lstringa<40>::find;_cv 1.79 % 1.79 % 10 +------- Copy not literal Str with N symbols ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string copy{str_with_len_N};/15_mean 35.9 ns 35.9 ns 10 +std::string copy{str_with_len_N};/15_median 35.7 ns 35.7 ns 10 +std::string copy{str_with_len_N};/15_stddev 2.19 ns 2.19 ns 10 +std::string copy{str_with_len_N};/15_cv 6.10 % 6.10 % 10 +std::string copy{str_with_len_N};/16_mean 35.4 ns 35.4 ns 10 +std::string copy{str_with_len_N};/16_median 35.0 ns 35.0 ns 10 +std::string copy{str_with_len_N};/16_stddev 2.38 ns 2.38 ns 10 +std::string copy{str_with_len_N};/16_cv 6.72 % 6.72 % 10 +std::string copy{str_with_len_N};/23_mean 36.3 ns 36.3 ns 10 +std::string copy{str_with_len_N};/23_median 36.1 ns 36.1 ns 10 +std::string copy{str_with_len_N};/23_stddev 2.00 ns 2.00 ns 10 +std::string copy{str_with_len_N};/23_cv 5.51 % 5.51 % 10 +std::string copy{str_with_len_N};/24_mean 35.6 ns 35.6 ns 10 +std::string copy{str_with_len_N};/24_median 36.2 ns 36.2 ns 10 +std::string copy{str_with_len_N};/24_stddev 2.33 ns 2.33 ns 10 +std::string copy{str_with_len_N};/24_cv 6.53 % 6.53 % 10 +std::string copy{str_with_len_N};/32_mean 39.4 ns 39.4 ns 10 +std::string copy{str_with_len_N};/32_median 38.5 ns 38.5 ns 10 +std::string copy{str_with_len_N};/32_stddev 3.37 ns 3.37 ns 10 +std::string copy{str_with_len_N};/32_cv 8.55 % 8.55 % 10 +std::string copy{str_with_len_N};/64_mean 39.6 ns 39.6 ns 10 +std::string copy{str_with_len_N};/64_median 38.5 ns 38.5 ns 10 +std::string copy{str_with_len_N};/64_stddev 3.59 ns 3.59 ns 10 +std::string copy{str_with_len_N};/64_cv 9.06 % 9.06 % 10 +std::string copy{str_with_len_N};/128_mean 41.3 ns 41.3 ns 10 +std::string copy{str_with_len_N};/128_median 41.4 ns 41.4 ns 10 +std::string copy{str_with_len_N};/128_stddev 2.50 ns 2.50 ns 10 +std::string copy{str_with_len_N};/128_cv 6.05 % 6.05 % 10 +std::string copy{str_with_len_N};/256_mean 58.6 ns 58.6 ns 10 +std::string copy{str_with_len_N};/256_median 64.1 ns 64.1 ns 10 +std::string copy{str_with_len_N};/256_stddev 13.0 ns 13.0 ns 10 +std::string copy{str_with_len_N};/256_cv 22.24 % 22.24 % 10 +std::string copy{str_with_len_N};/512_mean 53.9 ns 53.9 ns 10 +std::string copy{str_with_len_N};/512_median 53.5 ns 53.5 ns 10 +std::string copy{str_with_len_N};/512_stddev 11.7 ns 11.7 ns 10 +std::string copy{str_with_len_N};/512_cv 21.69 % 21.69 % 10 +std::string copy{str_with_len_N};/1024_mean 53.1 ns 53.1 ns 10 +std::string copy{str_with_len_N};/1024_median 51.3 ns 51.3 ns 10 +std::string copy{str_with_len_N};/1024_stddev 7.15 ns 7.15 ns 10 +std::string copy{str_with_len_N};/1024_cv 13.46 % 13.46 % 10 +std::string copy{str_with_len_N};/2048_mean 77.9 ns 77.9 ns 10 +std::string copy{str_with_len_N};/2048_median 77.8 ns 77.8 ns 10 +std::string copy{str_with_len_N};/2048_stddev 3.38 ns 3.38 ns 10 +std::string copy{str_with_len_N};/2048_cv 4.34 % 4.34 % 10 +std::string copy{str_with_len_N};/4096_mean 130 ns 130 ns 10 +std::string copy{str_with_len_N};/4096_median 132 ns 132 ns 10 +std::string copy{str_with_len_N};/4096_stddev 7.79 ns 7.79 ns 10 +std::string copy{str_with_len_N};/4096_cv 5.99 % 5.99 % 10 +stringa copy{str_with_len_N};/15_mean 2.64 ns 2.64 ns 10 +stringa copy{str_with_len_N};/15_median 2.63 ns 2.63 ns 10 +stringa copy{str_with_len_N};/15_stddev 0.060 ns 0.060 ns 10 +stringa copy{str_with_len_N};/15_cv 2.26 % 2.27 % 10 +stringa copy{str_with_len_N};/16_mean 4.98 ns 4.98 ns 10 +stringa copy{str_with_len_N};/16_median 5.00 ns 5.00 ns 10 +stringa copy{str_with_len_N};/16_stddev 0.113 ns 0.113 ns 10 +stringa copy{str_with_len_N};/16_cv 2.27 % 2.27 % 10 +stringa copy{str_with_len_N};/23_mean 5.00 ns 5.00 ns 10 +stringa copy{str_with_len_N};/23_median 4.95 ns 4.95 ns 10 +stringa copy{str_with_len_N};/23_stddev 0.234 ns 0.234 ns 10 +stringa copy{str_with_len_N};/23_cv 4.68 % 4.68 % 10 +stringa copy{str_with_len_N};/24_mean 5.02 ns 5.02 ns 10 +stringa copy{str_with_len_N};/24_median 4.98 ns 4.98 ns 10 +stringa copy{str_with_len_N};/24_stddev 0.122 ns 0.122 ns 10 +stringa copy{str_with_len_N};/24_cv 2.43 % 2.43 % 10 +stringa copy{str_with_len_N};/32_mean 4.98 ns 4.98 ns 10 +stringa copy{str_with_len_N};/32_median 4.92 ns 4.92 ns 10 +stringa copy{str_with_len_N};/32_stddev 0.146 ns 0.146 ns 10 +stringa copy{str_with_len_N};/32_cv 2.93 % 2.93 % 10 +stringa copy{str_with_len_N};/64_mean 4.94 ns 4.94 ns 10 +stringa copy{str_with_len_N};/64_median 4.97 ns 4.97 ns 10 +stringa copy{str_with_len_N};/64_stddev 0.094 ns 0.092 ns 10 +stringa copy{str_with_len_N};/64_cv 1.90 % 1.87 % 10 +stringa copy{str_with_len_N};/128_mean 4.99 ns 4.99 ns 10 +stringa copy{str_with_len_N};/128_median 4.98 ns 4.98 ns 10 +stringa copy{str_with_len_N};/128_stddev 0.139 ns 0.139 ns 10 +stringa copy{str_with_len_N};/128_cv 2.79 % 2.79 % 10 +stringa copy{str_with_len_N};/256_mean 4.90 ns 4.90 ns 10 +stringa copy{str_with_len_N};/256_median 4.90 ns 4.90 ns 10 +stringa copy{str_with_len_N};/256_stddev 0.092 ns 0.092 ns 10 +stringa copy{str_with_len_N};/256_cv 1.89 % 1.89 % 10 +stringa copy{str_with_len_N};/512_mean 5.01 ns 5.01 ns 10 +stringa copy{str_with_len_N};/512_median 5.00 ns 5.00 ns 10 +stringa copy{str_with_len_N};/512_stddev 0.119 ns 0.119 ns 10 +stringa copy{str_with_len_N};/512_cv 2.37 % 2.37 % 10 +stringa copy{str_with_len_N};/1024_mean 5.07 ns 5.07 ns 10 +stringa copy{str_with_len_N};/1024_median 5.06 ns 5.06 ns 10 +stringa copy{str_with_len_N};/1024_stddev 0.146 ns 0.146 ns 10 +stringa copy{str_with_len_N};/1024_cv 2.87 % 2.87 % 10 +stringa copy{str_with_len_N};/2048_mean 5.01 ns 5.01 ns 10 +stringa copy{str_with_len_N};/2048_median 5.00 ns 5.00 ns 10 +stringa copy{str_with_len_N};/2048_stddev 0.095 ns 0.095 ns 10 +stringa copy{str_with_len_N};/2048_cv 1.91 % 1.91 % 10 +stringa copy{str_with_len_N};/4096_mean 4.92 ns 4.92 ns 10 +stringa copy{str_with_len_N};/4096_median 4.89 ns 4.89 ns 10 +stringa copy{str_with_len_N};/4096_stddev 0.137 ns 0.137 ns 10 +stringa copy{str_with_len_N};/4096_cv 2.80 % 2.80 % 10 +lstringa<16> copy{str_with_len_N};/15_mean 14.1 ns 14.1 ns 10 +lstringa<16> copy{str_with_len_N};/15_median 14.2 ns 14.2 ns 10 +lstringa<16> copy{str_with_len_N};/15_stddev 0.738 ns 0.738 ns 10 +lstringa<16> copy{str_with_len_N};/15_cv 5.24 % 5.24 % 10 +lstringa<16> copy{str_with_len_N};/16_mean 14.6 ns 14.6 ns 10 +lstringa<16> copy{str_with_len_N};/16_median 14.7 ns 14.7 ns 10 +lstringa<16> copy{str_with_len_N};/16_stddev 0.858 ns 0.858 ns 10 +lstringa<16> copy{str_with_len_N};/16_cv 5.88 % 5.88 % 10 +lstringa<16> copy{str_with_len_N};/23_mean 31.6 ns 31.6 ns 10 +lstringa<16> copy{str_with_len_N};/23_median 31.4 ns 31.4 ns 10 +lstringa<16> copy{str_with_len_N};/23_stddev 1.59 ns 1.59 ns 10 +lstringa<16> copy{str_with_len_N};/23_cv 5.04 % 5.04 % 10 +lstringa<16> copy{str_with_len_N};/24_mean 30.9 ns 30.9 ns 10 +lstringa<16> copy{str_with_len_N};/24_median 31.3 ns 31.3 ns 10 +lstringa<16> copy{str_with_len_N};/24_stddev 0.895 ns 0.895 ns 10 +lstringa<16> copy{str_with_len_N};/24_cv 2.89 % 2.89 % 10 +lstringa<16> copy{str_with_len_N};/32_mean 35.1 ns 35.1 ns 10 +lstringa<16> copy{str_with_len_N};/32_median 35.5 ns 35.5 ns 10 +lstringa<16> copy{str_with_len_N};/32_stddev 1.74 ns 1.74 ns 10 +lstringa<16> copy{str_with_len_N};/32_cv 4.96 % 4.96 % 10 +lstringa<16> copy{str_with_len_N};/64_mean 34.9 ns 34.9 ns 10 +lstringa<16> copy{str_with_len_N};/64_median 34.9 ns 34.9 ns 10 +lstringa<16> copy{str_with_len_N};/64_stddev 1.80 ns 1.80 ns 10 +lstringa<16> copy{str_with_len_N};/64_cv 5.16 % 5.16 % 10 +lstringa<16> copy{str_with_len_N};/128_mean 35.5 ns 35.5 ns 10 +lstringa<16> copy{str_with_len_N};/128_median 34.9 ns 34.9 ns 10 +lstringa<16> copy{str_with_len_N};/128_stddev 2.20 ns 2.20 ns 10 +lstringa<16> copy{str_with_len_N};/128_cv 6.19 % 6.19 % 10 +lstringa<16> copy{str_with_len_N};/256_mean 54.3 ns 54.3 ns 10 +lstringa<16> copy{str_with_len_N};/256_median 60.1 ns 60.1 ns 10 +lstringa<16> copy{str_with_len_N};/256_stddev 13.2 ns 13.2 ns 10 +lstringa<16> copy{str_with_len_N};/256_cv 24.32 % 24.32 % 10 +lstringa<16> copy{str_with_len_N};/512_mean 48.8 ns 48.8 ns 10 +lstringa<16> copy{str_with_len_N};/512_median 48.2 ns 48.2 ns 10 +lstringa<16> copy{str_with_len_N};/512_stddev 12.5 ns 12.5 ns 10 +lstringa<16> copy{str_with_len_N};/512_cv 25.63 % 25.63 % 10 +lstringa<16> copy{str_with_len_N};/1024_mean 48.6 ns 48.6 ns 10 +lstringa<16> copy{str_with_len_N};/1024_median 44.8 ns 44.8 ns 10 +lstringa<16> copy{str_with_len_N};/1024_stddev 9.55 ns 9.55 ns 10 +lstringa<16> copy{str_with_len_N};/1024_cv 19.65 % 19.65 % 10 +lstringa<16> copy{str_with_len_N};/2048_mean 71.5 ns 71.5 ns 10 +lstringa<16> copy{str_with_len_N};/2048_median 72.0 ns 72.0 ns 10 +lstringa<16> copy{str_with_len_N};/2048_stddev 2.92 ns 2.92 ns 10 +lstringa<16> copy{str_with_len_N};/2048_cv 4.09 % 4.09 % 10 +lstringa<16> copy{str_with_len_N};/4096_mean 118 ns 118 ns 10 +lstringa<16> copy{str_with_len_N};/4096_median 119 ns 119 ns 10 +lstringa<16> copy{str_with_len_N};/4096_stddev 4.85 ns 4.85 ns 10 +lstringa<16> copy{str_with_len_N};/4096_cv 4.12 % 4.12 % 10 +lstringa<512> copy{str_with_len_N};/15_mean 15.2 ns 15.2 ns 10 +lstringa<512> copy{str_with_len_N};/15_median 15.5 ns 15.5 ns 10 +lstringa<512> copy{str_with_len_N};/15_stddev 0.706 ns 0.706 ns 10 +lstringa<512> copy{str_with_len_N};/15_cv 4.63 % 4.63 % 10 +lstringa<512> copy{str_with_len_N};/16_mean 15.3 ns 15.3 ns 10 +lstringa<512> copy{str_with_len_N};/16_median 15.2 ns 15.2 ns 10 +lstringa<512> copy{str_with_len_N};/16_stddev 1.27 ns 1.27 ns 10 +lstringa<512> copy{str_with_len_N};/16_cv 8.27 % 8.27 % 10 +lstringa<512> copy{str_with_len_N};/23_mean 14.6 ns 14.6 ns 10 +lstringa<512> copy{str_with_len_N};/23_median 14.5 ns 14.5 ns 10 +lstringa<512> copy{str_with_len_N};/23_stddev 1.07 ns 1.07 ns 10 +lstringa<512> copy{str_with_len_N};/23_cv 7.30 % 7.30 % 10 +lstringa<512> copy{str_with_len_N};/24_mean 15.2 ns 15.2 ns 10 +lstringa<512> copy{str_with_len_N};/24_median 15.0 ns 15.0 ns 10 +lstringa<512> copy{str_with_len_N};/24_stddev 0.835 ns 0.835 ns 10 +lstringa<512> copy{str_with_len_N};/24_cv 5.50 % 5.50 % 10 +lstringa<512> copy{str_with_len_N};/32_mean 17.8 ns 17.8 ns 10 +lstringa<512> copy{str_with_len_N};/32_median 18.1 ns 18.1 ns 10 +lstringa<512> copy{str_with_len_N};/32_stddev 0.989 ns 0.989 ns 10 +lstringa<512> copy{str_with_len_N};/32_cv 5.55 % 5.55 % 10 +lstringa<512> copy{str_with_len_N};/64_mean 18.3 ns 18.3 ns 10 +lstringa<512> copy{str_with_len_N};/64_median 18.5 ns 18.5 ns 10 +lstringa<512> copy{str_with_len_N};/64_stddev 0.865 ns 0.864 ns 10 +lstringa<512> copy{str_with_len_N};/64_cv 4.72 % 4.72 % 10 +lstringa<512> copy{str_with_len_N};/128_mean 18.8 ns 18.8 ns 10 +lstringa<512> copy{str_with_len_N};/128_median 18.3 ns 18.3 ns 10 +lstringa<512> copy{str_with_len_N};/128_stddev 1.22 ns 1.22 ns 10 +lstringa<512> copy{str_with_len_N};/128_cv 6.45 % 6.45 % 10 +lstringa<512> copy{str_with_len_N};/256_mean 20.1 ns 20.1 ns 10 +lstringa<512> copy{str_with_len_N};/256_median 19.9 ns 19.9 ns 10 +lstringa<512> copy{str_with_len_N};/256_stddev 1.24 ns 1.24 ns 10 +lstringa<512> copy{str_with_len_N};/256_cv 6.16 % 6.16 % 10 +lstringa<512> copy{str_with_len_N};/512_mean 26.9 ns 26.9 ns 10 +lstringa<512> copy{str_with_len_N};/512_median 26.8 ns 26.8 ns 10 +lstringa<512> copy{str_with_len_N};/512_stddev 0.929 ns 0.929 ns 10 +lstringa<512> copy{str_with_len_N};/512_cv 3.45 % 3.45 % 10 +lstringa<512> copy{str_with_len_N};/1024_mean 48.0 ns 48.0 ns 10 +lstringa<512> copy{str_with_len_N};/1024_median 44.6 ns 44.6 ns 10 +lstringa<512> copy{str_with_len_N};/1024_stddev 7.96 ns 7.96 ns 10 +lstringa<512> copy{str_with_len_N};/1024_cv 16.59 % 16.59 % 10 +lstringa<512> copy{str_with_len_N};/2048_mean 71.3 ns 71.3 ns 10 +lstringa<512> copy{str_with_len_N};/2048_median 71.0 ns 71.0 ns 10 +lstringa<512> copy{str_with_len_N};/2048_stddev 3.84 ns 3.84 ns 10 +lstringa<512> copy{str_with_len_N};/2048_cv 5.38 % 5.38 % 10 +lstringa<512> copy{str_with_len_N};/4096_mean 120 ns 120 ns 10 +lstringa<512> copy{str_with_len_N};/4096_median 122 ns 122 ns 10 +lstringa<512> copy{str_with_len_N};/4096_stddev 5.12 ns 5.12 ns 10 +lstringa<512> copy{str_with_len_N};/4096_cv 4.27 % 4.27 % 10 +----- Convert to int '1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_mean 69.5 ns 69.5 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_median 69.6 ns 69.6 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_stddev 2.36 ns 2.36 ns 10 +std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);_cv 3.39 % 3.39 % 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_mean 28.4 ns 28.4 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_median 28.0 ns 28.0 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_stddev 0.994 ns 0.994 ns 10 +std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);_cv 3.51 % 3.51 % 10 +stringa s = "123456789"; int res = s.to_int_mean 19.0 ns 19.0 ns 10 +stringa s = "123456789"; int res = s.to_int_median 19.0 ns 19.0 ns 10 +stringa s = "123456789"; int res = s.to_int_stddev 0.550 ns 0.550 ns 10 +stringa s = "123456789"; int res = s.to_int_cv 2.89 % 2.89 % 10 +ssa s = "123456789"; int res = s.to_int_mean 17.3 ns 17.3 ns 10 +ssa s = "123456789"; int res = s.to_int_median 17.2 ns 17.2 ns 10 +ssa s = "123456789"; int res = s.to_int_stddev 0.520 ns 0.520 ns 10 +ssa s = "123456789"; int res = s.to_int_cv 3.00 % 3.00 % 10 +lstringa<20> s = "123456789"; int res = s.to_int_mean 17.4 ns 17.4 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_median 17.4 ns 17.4 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_stddev 0.349 ns 0.349 ns 10 +lstringa<20> s = "123456789"; int res = s.to_int_cv 2.00 % 2.00 % 10 +----- Convert to unsigned 'abcDef' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_mean 54.6 ns 54.6 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_median 54.5 ns 54.5 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_stddev 1.46 ns 1.46 ns 10 +std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);_cv 2.67 % 2.67 % 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_mean 30.6 ns 30.6 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_median 30.6 ns 30.6 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_stddev 0.742 ns 0.742 ns 10 +std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);_cv 2.43 % 2.43 % 10 +stringa s = "abcDef"; int res = s.to_int_mean 17.9 ns 17.9 ns 10 +stringa s = "abcDef"; int res = s.to_int_median 18.0 ns 18.0 ns 10 +stringa s = "abcDef"; int res = s.to_int_stddev 0.451 ns 0.451 ns 10 +stringa s = "abcDef"; int res = s.to_int_cv 2.51 % 2.51 % 10 +ssa s = "abcDef"; int res = s.to_int_mean 16.8 ns 16.8 ns 10 +ssa s = "abcDef"; int res = s.to_int_median 16.8 ns 16.8 ns 10 +ssa s = "abcDef"; int res = s.to_int_stddev 0.368 ns 0.368 ns 10 +ssa s = "abcDef"; int res = s.to_int_cv 2.19 % 2.19 % 10 +lstringa<20> s = "abcDef"; int res = s.to_int_mean 16.8 ns 16.8 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_median 16.8 ns 16.8 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_stddev 0.494 ns 0.494 ns 10 +lstringa<20> s = "abcDef"; int res = s.to_int_cv 2.94 % 2.94 % 10 +----- Convert to int ' 1234567' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_mean 74.6 ns 74.6 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_median 74.7 ns 74.7 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_stddev 1.85 ns 1.85 ns 10 +std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);_cv 2.48 % 2.48 % 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_mean 25.4 ns 25.4 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_median 25.3 ns 25.3 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_stddev 0.670 ns 0.670 ns 10 +stringa s = " 123456789"; int res = s.to_int; // Check overflow_cv 2.64 % 2.64 % 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_mean 23.4 ns 23.4 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_median 23.3 ns 23.3 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_stddev 0.974 ns 0.974 ns 10 +ssa s = " 123456789"; int res = s.to_int; // No check overflow_cv 4.15 % 4.15 % 10 +----- Convert to double '1234.567e10' ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_mean 200 ns 200 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_median 200 ns 200 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_stddev 3.85 ns 3.85 ns 10 +std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);_cv 1.93 % 1.93 % 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_mean 111 ns 111 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_median 112 ns 112 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_stddev 2.42 ns 2.42 ns 10 +std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);_cv 2.17 % 2.17 % 10 +ssa s = "1234.567e10"; double res = *s.to_double()_mean 43.1 ns 43.1 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_median 43.3 ns 43.3 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_stddev 0.975 ns 0.975 ns 10 +ssa s = "1234.567e10"; double res = *s.to_double()_cv 2.26 % 2.26 % 10 +-- Append const literal of 16 bytes 64 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::stringstream str; ... str << "abbaabbaabbaabba";_mean 4383 ns 4383 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_median 4377 ns 4377 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_stddev 152 ns 152 ns 10 +std::stringstream str; ... str << "abbaabbaabbaabba";_cv 3.46 % 3.46 % 10 +std::string str; ... str += "abbaabbaabbaabba";_mean 587 ns 587 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_median 587 ns 587 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_stddev 25.0 ns 25.0 ns 10 +std::string str; ... str += "abbaabbaabbaabba";_cv 4.25 % 4.25 % 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_mean 704 ns 704 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_median 696 ns 696 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_stddev 32.7 ns 32.7 ns 10 +lstringa<8> str; ... str += "abbaabbaabbaabba";_cv 4.65 % 4.65 % 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_mean 569 ns 569 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_median 564 ns 564 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_stddev 27.9 ns 27.9 ns 10 +lstringa<128> str; ... str += "abbaabbaabbaabba";_cv 4.90 % 4.90 % 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_mean 516 ns 516 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_median 521 ns 521 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_stddev 20.9 ns 20.9 ns 10 +lstringa<512> str; ... str += "abbaabbaabbaabba";_cv 4.05 % 4.05 % 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_mean 403 ns 403 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_median 400 ns 400 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_stddev 11.2 ns 11.2 ns 10 +lstringa<1024> str; ... str += "abbaabbaabbaabba";_cv 2.77 % 2.77 % 10 +-- Append string of 16 bytes and const literal of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_mean 4402 ns 4402 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_median 4457 ns 4457 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_stddev 133 ns 133 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba";_cv 3.02 % 3.02 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_mean 1940 ns 1940 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_median 1930 ns 1930 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_stddev 97.4 ns 97.4 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba";_cv 5.02 % 5.02 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_mean 834 ns 834 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_median 817 ns 817 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_stddev 59.4 ns 59.4 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";_cv 7.12 % 7.12 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_mean 698 ns 698 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_median 718 ns 718 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_stddev 46.3 ns 46.3 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";_cv 6.62 % 6.62 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_mean 592 ns 592 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_median 594 ns 594 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_stddev 26.6 ns 26.6 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";_cv 4.49 % 4.49 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_mean 546 ns 546 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_median 541 ns 541 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_stddev 30.4 ns 30.4 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";_cv 5.56 % 5.56 % 10 +-- Append string of 16 bytes and const literal of 16 bytes 2048 times, 65536 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_mean 227747 ns 227748 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_median 227780 ns 227780 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_stddev 7201 ns 7203 ns 10 +std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 times_cv 3.16 % 3.16 % 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 107590 ns 107591 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 109011 ns 109011 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 4697 ns 4696 ns 10 +std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 4.37 % 4.37 % 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 39528 ns 39528 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 38718 ns 38718 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 2165 ns 2165 ns 10 +lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 5.48 % 5.48 % 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 38289 ns 38289 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 38168 ns 38168 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 3141 ns 3141 ns 10 +lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 8.20 % 8.20 % 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 39586 ns 39586 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 39363 ns 39363 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 2349 ns 2349 ns 10 +lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 5.93 % 5.93 % 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_mean 38827 ns 38828 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_median 38977 ns 38977 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_stddev 2031 ns 2031 ns 10 +lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 times_cv 5.23 % 5.23 % 10 +-- Append 2 string of 16 bytes 32 times, 1024 total length --/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::stringstream str; ... str << str_var1 << str_var2;_mean 4714 ns 4714 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_median 4708 ns 4708 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_stddev 244 ns 244 ns 10 +std::stringstream str; ... str << str_var1 << str_var2;_cv 5.18 % 5.18 % 10 +std::string str; ... str += str_var1 + str_var2;_mean 2421 ns 2421 ns 10 +std::string str; ... str += str_var1 + str_var2;_median 2435 ns 2435 ns 10 +std::string str; ... str += str_var1 + str_var2;_stddev 152 ns 152 ns 10 +std::string str; ... str += str_var1 + str_var2;_cv 6.28 % 6.28 % 10 +lstringa<16> str; ... str += str_var1 + str_var2;_mean 1187 ns 1187 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_median 1189 ns 1189 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_stddev 55.5 ns 55.5 ns 10 +lstringa<16> str; ... str += str_var1 + str_var2;_cv 4.68 % 4.68 % 10 +lstringa<128> str; ... str += str_var1 + str_var2;_mean 1062 ns 1062 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_median 1057 ns 1057 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_stddev 70.9 ns 70.9 ns 10 +lstringa<128> str; ... str += str_var1 + str_var2;_cv 6.68 % 6.68 % 10 +lstringa<512> str; ... str += str_var1 + str_var2;_mean 907 ns 907 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_median 916 ns 916 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_stddev 60.9 ns 60.9 ns 10 +lstringa<512> str; ... str += str_var1 + str_var2;_cv 6.72 % 6.72 % 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_mean 856 ns 856 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_median 833 ns 833 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_stddev 61.9 ns 61.9 ns 10 +lstringa<1024> str; ... str += str_var1 + str_var2;_cv 7.23 % 7.23 % 10 +-- Append text, number, text --/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::stringstream str; str << "test = " << k << " times";_mean 6369 ns 6369 ns 10 +std::stringstream str; str << "test = " << k << " times";_median 6276 ns 6276 ns 10 +std::stringstream str; str << "test = " << k << " times";_stddev 289 ns 289 ns 10 +std::stringstream str; str << "test = " << k << " times";_cv 4.54 % 4.54 % 10 +std::string str = "test = " + std::to_string(k) + " times";_mean 1655 ns 1655 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_median 1661 ns 1661 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_stddev 74.1 ns 74.2 ns 10 +std::string str = "test = " + std::to_string(k) + " times";_cv 4.48 % 4.48 % 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_mean 2916 ns 2916 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_median 2922 ns 2922 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_stddev 76.1 ns 76.1 ns 10 +char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;_cv 2.61 % 2.61 % 10 +std::string str = std::format("test = {} times", k);_mean 2078 ns 2078 ns 10 +std::string str = std::format("test = {} times", k);_median 2061 ns 2061 ns 10 +std::string str = std::format("test = {} times", k);_stddev 65.7 ns 65.7 ns 10 +std::string str = std::format("test = {} times", k);_cv 3.16 % 3.16 % 10 +lstringa<8> str; str.format("test = {} times", k);_mean 3396 ns 3396 ns 10 +lstringa<8> str; str.format("test = {} times", k);_median 3379 ns 3379 ns 10 +lstringa<8> str; str.format("test = {} times", k);_stddev 168 ns 168 ns 10 +lstringa<8> str; str.format("test = {} times", k);_cv 4.93 % 4.93 % 10 +lstringa<32> str; str.format("test = {} times", k);_mean 2581 ns 2581 ns 10 +lstringa<32> str; str.format("test = {} times", k);_median 2579 ns 2579 ns 10 +lstringa<32> str; str.format("test = {} times", k);_stddev 62.8 ns 62.8 ns 10 +lstringa<32> str; str.format("test = {} times", k);_cv 2.43 % 2.43 % 10 +lstringa<8> str = "test = " + k + " times";_mean 610 ns 610 ns 10 +lstringa<8> str = "test = " + k + " times";_median 613 ns 613 ns 10 +lstringa<8> str = "test = " + k + " times";_stddev 30.4 ns 30.4 ns 10 +lstringa<8> str = "test = " + k + " times";_cv 4.99 % 4.99 % 10 +lstringa<32> str = "test = " + k + " times";_mean 342 ns 342 ns 10 +lstringa<32> str = "test = " + k + " times";_median 345 ns 345 ns 10 +lstringa<32> str = "test = " + k + " times";_stddev 26.2 ns 26.2 ns 10 +lstringa<32> str = "test = " + k + " times";_cv 7.68 % 7.68 % 10 +stringa str = "test = " + k + " times";_mean 562 ns 562 ns 10 +stringa str = "test = " + k + " times";_median 563 ns 563 ns 10 +stringa str = "test = " + k + " times";_stddev 23.1 ns 23.1 ns 10 +stringa str = "test = " + k + " times";_cv 4.11 % 4.11 % 10 +-- Split text and convert to int --/repeats:1 0.000 ns 0.000 ns 1000000000000 +std::string::find + substr + std::strtol_mean 651 ns 651 ns 10 +std::string::find + substr + std::strtol_median 654 ns 654 ns 10 +std::string::find + substr + std::strtol_stddev 41.4 ns 41.4 ns 10 +std::string::find + substr + std::strtol_cv 6.36 % 6.36 % 10 +ssa::splitter + ssa::as_int_mean 279 ns 279 ns 10 +ssa::splitter + ssa::as_int_median 275 ns 275 ns 10 +ssa::splitter + ssa::as_int_stddev 11.4 ns 11.4 ns 10 +ssa::splitter + ssa::as_int_cv 4.09 % 4.09 % 10 +ssa::splitf + functor_mean 346 ns 346 ns 10 +ssa::splitf + functor_median 346 ns 346 ns 10 +ssa::splitf + functor_stddev 5.25 ns 5.25 ns 10 +ssa::splitf + functor_cv 1.52 % 1.51 % 10 +-- Replace symbols in text ~400 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 +Naive (and wrong) replace symbols with std::string find + replace_mean 3588 ns 3588 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_median 3598 ns 3598 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_stddev 118 ns 118 ns 10 +Naive (and wrong) replace symbols with std::string find + replace_cv 3.28 % 3.28 % 10 +replace symbols with std::string find_first_of + replace_mean 4762 ns 4762 ns 10 +replace symbols with std::string find_first_of + replace_median 4760 ns 4760 ns 10 +replace symbols with std::string find_first_of + replace_stddev 186 ns 186 ns 10 +replace symbols with std::string find_first_of + replace_cv 3.90 % 3.90 % 10 +replace symbols with std::string_view find_first_of + copy_mean 3410 ns 3410 ns 10 +replace symbols with std::string_view find_first_of + copy_median 3378 ns 3378 ns 10 +replace symbols with std::string_view find_first_of + copy_stddev 157 ns 157 ns 10 +replace symbols with std::string_view find_first_of + copy_cv 4.62 % 4.62 % 10 +replace runtime symbols with string expressions and without remembering all search results_mean 3466 ns 3466 ns 10 +replace runtime symbols with string expressions and without remembering all search results_median 3401 ns 3401 ns 10 +replace runtime symbols with string expressions and without remembering all search results_stddev 160 ns 160 ns 10 +replace runtime symbols with string expressions and without remembering all search results_cv 4.62 % 4.62 % 10 +replace runtime symbols with simstr and memorization of all search results_mean 3059 ns 3059 ns 10 +replace runtime symbols with simstr and memorization of all search results_median 3055 ns 3055 ns 10 +replace runtime symbols with simstr and memorization of all search results_stddev 133 ns 133 ns 10 +replace runtime symbols with simstr and memorization of all search results_cv 4.35 % 4.35 % 10 +replace const symbols with string expressions and without remembering all search results_mean 2820 ns 2820 ns 10 +replace const symbols with string expressions and without remembering all search results_median 2814 ns 2814 ns 10 +replace const symbols with string expressions and without remembering all search results_stddev 135 ns 135 ns 10 +replace const symbols with string expressions and without remembering all search results_cv 4.77 % 4.78 % 10 +replace const symbols with string expressions and memorization of all search results_mean 2715 ns 2715 ns 10 +replace const symbols with string expressions and memorization of all search results_median 2703 ns 2703 ns 10 +replace const symbols with string expressions and memorization of all search results_stddev 105 ns 105 ns 10 +replace const symbols with string expressions and memorization of all search results_cv 3.89 % 3.89 % 10 +-- Replace symbols in text ~40 symbols --/repeats:1 0.000 ns 0.000 ns 1000000000000 +Short Naive (and wrong) replace symbols with std::string find + replace_mean 475 ns 475 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_median 469 ns 469 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_stddev 21.6 ns 21.6 ns 10 +Short Naive (and wrong) replace symbols with std::string find + replace_cv 4.55 % 4.55 % 10 +Short replace symbols with std::string find_first_of + replace_mean 518 ns 518 ns 10 +Short replace symbols with std::string find_first_of + replace_median 511 ns 511 ns 10 +Short replace symbols with std::string find_first_of + replace_stddev 19.0 ns 19.0 ns 10 +Short replace symbols with std::string find_first_of + replace_cv 3.68 % 3.68 % 10 +Short replace symbols with std::string_view find_first_of + copy_mean 391 ns 391 ns 10 +Short replace symbols with std::string_view find_first_of + copy_median 389 ns 389 ns 10 +Short replace symbols with std::string_view find_first_of + copy_stddev 12.7 ns 12.7 ns 10 +Short replace symbols with std::string_view find_first_of + copy_cv 3.26 % 3.26 % 10 +Short replace runtime symbols with string expressions and without remembering all search results_mean 397 ns 397 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_median 393 ns 393 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_stddev 19.6 ns 19.6 ns 10 +Short replace runtime symbols with string expressions and without remembering all search results_cv 4.93 % 4.93 % 10 +Short replace runtime symbols with simstr and memorization of all search results_mean 405 ns 405 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_median 405 ns 405 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_stddev 18.7 ns 18.7 ns 10 +Short replace runtime symbols with simstr and memorization of all search results_cv 4.61 % 4.61 % 10 +Short replace const symbols with string expressions and without remembering all search results_mean 250 ns 250 ns 10 +Short replace const symbols with string expressions and without remembering all search results_median 249 ns 249 ns 10 +Short replace const symbols with string expressions and without remembering all search results_stddev 13.6 ns 13.6 ns 10 +Short replace const symbols with string expressions and without remembering all search results_cv 5.44 % 5.44 % 10 +Short replace const symbols with string expressions and memorization of all search results_mean 297 ns 297 ns 10 +Short replace const symbols with string expressions and memorization of all search results_median 295 ns 295 ns 10 +Short replace const symbols with string expressions and memorization of all search results_stddev 11.4 ns 11.4 ns 10 +Short replace const symbols with string expressions and memorization of all search results_cv 3.84 % 3.84 % 10 +----- Replace All Str To Longer Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +replace bb to ---- in std::string|64_mean 382 ns 382 ns 10 +replace bb to ---- in std::string|64_median 383 ns 383 ns 10 +replace bb to ---- in std::string|64_stddev 15.2 ns 15.2 ns 10 +replace bb to ---- in std::string|64_cv 3.99 % 3.99 % 10 +replace bb to ---- in std::string|256_mean 1410 ns 1410 ns 10 +replace bb to ---- in std::string|256_median 1390 ns 1390 ns 10 +replace bb to ---- in std::string|256_stddev 82.5 ns 82.5 ns 10 +replace bb to ---- in std::string|256_cv 5.85 % 5.85 % 10 +replace bb to ---- in std::string|512_mean 2725 ns 2725 ns 10 +replace bb to ---- in std::string|512_median 2729 ns 2729 ns 10 +replace bb to ---- in std::string|512_stddev 113 ns 113 ns 10 +replace bb to ---- in std::string|512_cv 4.16 % 4.16 % 10 +replace bb to ---- in std::string|1024_mean 5829 ns 5829 ns 10 +replace bb to ---- in std::string|1024_median 5693 ns 5693 ns 10 +replace bb to ---- in std::string|1024_stddev 352 ns 352 ns 10 +replace bb to ---- in std::string|1024_cv 6.04 % 6.04 % 10 +replace bb to ---- in std::string|2048_mean 12920 ns 12920 ns 10 +replace bb to ---- in std::string|2048_median 12631 ns 12631 ns 10 +replace bb to ---- in std::string|2048_stddev 610 ns 610 ns 10 +replace bb to ---- in std::string|2048_cv 4.72 % 4.72 % 10 +replace bb to ---- in lstringa<8>|64_mean 339 ns 339 ns 10 +replace bb to ---- in lstringa<8>|64_median 337 ns 337 ns 10 +replace bb to ---- in lstringa<8>|64_stddev 19.7 ns 19.7 ns 10 +replace bb to ---- in lstringa<8>|64_cv 5.82 % 5.82 % 10 +replace bb to ---- in lstringa<8>|256_mean 1065 ns 1065 ns 10 +replace bb to ---- in lstringa<8>|256_median 1068 ns 1068 ns 10 +replace bb to ---- in lstringa<8>|256_stddev 44.3 ns 44.3 ns 10 +replace bb to ---- in lstringa<8>|256_cv 4.16 % 4.16 % 10 +replace bb to ---- in lstringa<8>|512_mean 1968 ns 1968 ns 10 +replace bb to ---- in lstringa<8>|512_median 1941 ns 1941 ns 10 +replace bb to ---- in lstringa<8>|512_stddev 116 ns 116 ns 10 +replace bb to ---- in lstringa<8>|512_cv 5.89 % 5.89 % 10 +replace bb to ---- in lstringa<8>|1024_mean 3761 ns 3761 ns 10 +replace bb to ---- in lstringa<8>|1024_median 3764 ns 3764 ns 10 +replace bb to ---- in lstringa<8>|1024_stddev 154 ns 154 ns 10 +replace bb to ---- in lstringa<8>|1024_cv 4.09 % 4.09 % 10 +replace bb to ---- in lstringa<8>|2048_mean 7335 ns 7335 ns 10 +replace bb to ---- in lstringa<8>|2048_median 7333 ns 7333 ns 10 +replace bb to ---- in lstringa<8>|2048_stddev 313 ns 313 ns 10 +replace bb to ---- in lstringa<8>|2048_cv 4.27 % 4.27 % 10 +replace bb to ---- by init stringa|64_mean 220 ns 220 ns 10 +replace bb to ---- by init stringa|64_median 217 ns 217 ns 10 +replace bb to ---- by init stringa|64_stddev 10.4 ns 10.4 ns 10 +replace bb to ---- by init stringa|64_cv 4.75 % 4.75 % 10 +replace bb to ---- by init stringa|256_mean 738 ns 738 ns 10 +replace bb to ---- by init stringa|256_median 734 ns 734 ns 10 +replace bb to ---- by init stringa|256_stddev 43.6 ns 43.6 ns 10 +replace bb to ---- by init stringa|256_cv 5.90 % 5.90 % 10 +replace bb to ---- by init stringa|512_mean 1733 ns 1733 ns 10 +replace bb to ---- by init stringa|512_median 1728 ns 1728 ns 10 +replace bb to ---- by init stringa|512_stddev 54.1 ns 54.1 ns 10 +replace bb to ---- by init stringa|512_cv 3.12 % 3.12 % 10 +replace bb to ---- by init stringa|1024_mean 3695 ns 3695 ns 10 +replace bb to ---- by init stringa|1024_median 3717 ns 3717 ns 10 +replace bb to ---- by init stringa|1024_stddev 156 ns 156 ns 10 +replace bb to ---- by init stringa|1024_cv 4.22 % 4.22 % 10 +replace bb to ---- by init stringa|2048_mean 7436 ns 7436 ns 10 +replace bb to ---- by init stringa|2048_median 7389 ns 7389 ns 10 +replace bb to ---- by init stringa|2048_stddev 246 ns 246 ns 10 +replace bb to ---- by init stringa|2048_cv 3.31 % 3.31 % 10 +----- Replace All Str To Same Size ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +replace bb to -- in std::string|64_mean 270 ns 270 ns 10 +replace bb to -- in std::string|64_median 272 ns 272 ns 10 +replace bb to -- in std::string|64_stddev 14.2 ns 14.2 ns 10 +replace bb to -- in std::string|64_cv 5.28 % 5.28 % 10 +replace bb to -- in std::string|256_mean 1011 ns 1011 ns 10 +replace bb to -- in std::string|256_median 1008 ns 1008 ns 10 +replace bb to -- in std::string|256_stddev 41.5 ns 41.4 ns 10 +replace bb to -- in std::string|256_cv 4.10 % 4.10 % 10 +replace bb to -- in std::string|512_mean 1878 ns 1878 ns 10 +replace bb to -- in std::string|512_median 1887 ns 1887 ns 10 +replace bb to -- in std::string|512_stddev 27.8 ns 27.8 ns 10 +replace bb to -- in std::string|512_cv 1.48 % 1.48 % 10 +replace bb to -- in std::string|1024_mean 3626 ns 3626 ns 10 +replace bb to -- in std::string|1024_median 3596 ns 3596 ns 10 +replace bb to -- in std::string|1024_stddev 115 ns 115 ns 10 +replace bb to -- in std::string|1024_cv 3.18 % 3.18 % 10 +replace bb to -- in std::string|2048_mean 7194 ns 7194 ns 10 +replace bb to -- in std::string|2048_median 7224 ns 7224 ns 10 +replace bb to -- in std::string|2048_stddev 254 ns 254 ns 10 +replace bb to -- in std::string|2048_cv 3.54 % 3.54 % 10 +replace bb to -- in lstringa<8>|64_mean 222 ns 222 ns 10 +replace bb to -- in lstringa<8>|64_median 223 ns 223 ns 10 +replace bb to -- in lstringa<8>|64_stddev 7.12 ns 7.12 ns 10 +replace bb to -- in lstringa<8>|64_cv 3.21 % 3.21 % 10 +replace bb to -- in lstringa<8>|256_mean 775 ns 775 ns 10 +replace bb to -- in lstringa<8>|256_median 778 ns 778 ns 10 +replace bb to -- in lstringa<8>|256_stddev 33.2 ns 33.2 ns 10 +replace bb to -- in lstringa<8>|256_cv 4.28 % 4.28 % 10 +replace bb to -- in lstringa<8>|512_mean 1461 ns 1461 ns 10 +replace bb to -- in lstringa<8>|512_median 1458 ns 1458 ns 10 +replace bb to -- in lstringa<8>|512_stddev 65.3 ns 65.3 ns 10 +replace bb to -- in lstringa<8>|512_cv 4.47 % 4.47 % 10 +replace bb to -- in lstringa<8>|1024_mean 2776 ns 2776 ns 10 +replace bb to -- in lstringa<8>|1024_median 2772 ns 2772 ns 10 +replace bb to -- in lstringa<8>|1024_stddev 95.9 ns 95.9 ns 10 +replace bb to -- in lstringa<8>|1024_cv 3.46 % 3.46 % 10 +replace bb to -- in lstringa<8>|2048_mean 5522 ns 5522 ns 10 +replace bb to -- in lstringa<8>|2048_median 5632 ns 5632 ns 10 +replace bb to -- in lstringa<8>|2048_stddev 267 ns 267 ns 10 +replace bb to -- in lstringa<8>|2048_cv 4.84 % 4.84 % 10 +replace bb to -- by init stringa|64_mean 180 ns 180 ns 10 +replace bb to -- by init stringa|64_median 180 ns 180 ns 10 +replace bb to -- by init stringa|64_stddev 7.12 ns 7.12 ns 10 +replace bb to -- by init stringa|64_cv 3.97 % 3.97 % 10 +replace bb to -- by init stringa|256_mean 646 ns 646 ns 10 +replace bb to -- by init stringa|256_median 639 ns 639 ns 10 +replace bb to -- by init stringa|256_stddev 40.9 ns 40.9 ns 10 +replace bb to -- by init stringa|256_cv 6.33 % 6.33 % 10 +replace bb to -- by init stringa|512_mean 1220 ns 1220 ns 10 +replace bb to -- by init stringa|512_median 1197 ns 1197 ns 10 +replace bb to -- by init stringa|512_stddev 51.8 ns 51.8 ns 10 +replace bb to -- by init stringa|512_cv 4.25 % 4.25 % 10 +replace bb to -- by init stringa|1024_mean 2371 ns 2371 ns 10 +replace bb to -- by init stringa|1024_median 2376 ns 2376 ns 10 +replace bb to -- by init stringa|1024_stddev 86.3 ns 86.3 ns 10 +replace bb to -- by init stringa|1024_cv 3.64 % 3.64 % 10 +replace bb to -- by init stringa|2048_mean 4604 ns 4604 ns 10 +replace bb to -- by init stringa|2048_median 4626 ns 4626 ns 10 +replace bb to -- by init stringa|2048_stddev 139 ns 139 ns 10 +replace bb to -- by init stringa|2048_cv 3.03 % 3.03 % 10 +----- Hash Map insert and find ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +hashStrMapA emplace & find stringa;_mean 3162304 ns 3162341 ns 10 +hashStrMapA emplace & find stringa;_median 3150599 ns 3150645 ns 10 +hashStrMapA emplace & find stringa;_stddev 88906 ns 88929 ns 10 +hashStrMapA emplace & find stringa;_cv 2.81 % 2.81 % 10 +std::unordered_map emplace & find std::string;_mean 3370915 ns 3370945 ns 10 +std::unordered_map emplace & find std::string;_median 3347562 ns 3347612 ns 10 +std::unordered_map emplace & find std::string;_stddev 63254 ns 63239 ns 10 +std::unordered_map emplace & find std::string;_cv 1.88 % 1.88 % 10 +hashStrMapA emplace & find ssa;_mean 3151333 ns 3151360 ns 10 +hashStrMapA emplace & find ssa;_median 3141930 ns 3141974 ns 10 +hashStrMapA emplace & find ssa;_stddev 51278 ns 51255 ns 10 +hashStrMapA emplace & find ssa;_cv 1.63 % 1.63 % 10 +std::unordered_map emplace & find std::string_view;_mean 3797453 ns 3797464 ns 10 +std::unordered_map emplace & find std::string_view;_median 3810615 ns 3810615 ns 10 +std::unordered_map emplace & find std::string_view;_stddev 66726 ns 66718 ns 10 +std::unordered_map emplace & find std::string_view;_cv 1.76 % 1.76 % 10 +----- Build Full Func Name ---------/repeats:1 0.000 ns 0.000 ns 1000000000000 +Build func full name std::string;_mean 2652 ns 2652 ns 10 +Build func full name std::string;_median 2680 ns 2680 ns 10 +Build func full name std::string;_stddev 80.1 ns 80.1 ns 10 +Build func full name std::string;_cv 3.02 % 3.02 % 10 +Build func full name std::string 1;_mean 2955 ns 2955 ns 10 +Build func full name std::string 1;_median 2931 ns 2931 ns 10 +Build func full name std::string 1;_stddev 128 ns 128 ns 10 +Build func full name std::string 1;_cv 4.33 % 4.33 % 10 +Build func full name std::stream;_mean 6584 ns 6584 ns 10 +Build func full name std::stream;_median 6562 ns 6562 ns 10 +Build func full name std::stream;_stddev 143 ns 143 ns 10 +Build func full name std::stream;_cv 2.17 % 2.17 % 10 +Build func full name stringa;_mean 1274 ns 1274 ns 10 +Build func full name stringa;_median 1274 ns 1274 ns 10 +Build func full name stringa;_stddev 82.4 ns 82.4 ns 10 +Build func full name stringa;_cv 6.47 % 6.47 % 10 +Build func full name stringa 1;_mean 1576 ns 1576 ns 10 +Build func full name stringa 1;_median 1547 ns 1547 ns 10 +Build func full name stringa 1;_stddev 85.2 ns 85.2 ns 10 +Build func full name stringa 1;_cv 5.40 % 5.40 % 10 diff --git a/docs/Doxyfile b/docs/Doxyfile index b768b29..b5923db 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = "simstr" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.3.1 +PROJECT_NUMBER = 1.4.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewers a diff --git a/docs/Doxyfile_ru b/docs/Doxyfile_ru index 8b6aa3d..82a05c3 100644 --- a/docs/Doxyfile_ru +++ b/docs/Doxyfile_ru @@ -48,7 +48,7 @@ PROJECT_NAME = "simstr" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.3.1 +PROJECT_NUMBER = 1.4.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewers a diff --git a/docs/overview.md b/docs/overview.md index 2668b60..ee19121 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -188,12 +188,15 @@ there was std::string_view. However, now the minimum standard version for the li First, I will talk about the library classes for the strings themselves, and then about how the string concatenation problem is optimally solved in it. Several general points: -- All classes for working with strings are templated by the type of characters, but it is assumed that the characters can be char, char16_t, - char32_t, wchar_t. +- All classes for working with strings are templated by the type of characters, but it is assumed that the characters can be `char`, `char8_t`, `char16_t`, + `char32_t`, `wchar_t`. - All strings have an explicit length. - The string owner classes store them with a trailing zero at the end, which is not included in the length of the string. - The string itself can contain zero characters, all algorithms work only through the length of the string, without paying attention to them. +- The library considers different string types to be "compatible" if they have the same character size. + That is, `char` and `char8_t` are always identical, and also in Linux `wchar_t` and `char32_t` are identical, and in Windows `wchar_t` and `char16_t`. - The string owner classes can be initialized with strings of another character type, performing conversion between UTF-8, UTF-16, UTF-32. + Moreover, if the strings are of different but compatible types, they are simply copied without conversion. - Built-in tables for the first plane of Unicode are used to change the case of characters and compare strings case-insensitively (up to 0xFFFF). Strings are considered to be represented in UTF-8, UTF-16, UTF-32 encoding, respectively. However, string normalization is not done and situations where changing the case of a character leads to a change in their number are not handled. @@ -214,6 +217,7 @@ Implements all string methods that do not modify the string. Aliases: - `ssa` for simple_str\ +- `ssb` for simple_str\ - `ssu` for simple_str\ - `ssw` for simple_str\ - `ssuu` for simple_str\ @@ -232,6 +236,7 @@ This allows you to write functions with a single parameter type that accepts any Aliases: - `stra` for simple_str_nt\ +- `strb` for simple_str_nt\ - `stru` for simple_str_nt\ - `strw` for simple_str_nt\ - `struu` for simple_str_nt\ @@ -258,6 +263,7 @@ Like `simple_str`, it implements all methods that do not modify the string. Aliases: - `stringa` for sstring\ +- `stringb` for sstring\ - `stringu` for sstring\ - `stringw` for sstring\ - `stringuu` for sstring\ @@ -309,15 +315,16 @@ Usually we assume the approximate size of the strings we will be working with, a and work with it. At the same time, without fear of buffer overflow, since in this case the string will switch to a dynamic buffer. Aliases: -- `lstringa` for lsrting\ -- `lstringu` for lsrting\ -- `lstringw` for lsrting\ -- `lstringuu` for lsrting\ -- `lstringsa` for lsrting\ -- `lstringsu` for lsrting\ -- `lstringsw` for lsrting\ -- `lstringsuu` for lsrting\ - +- `lstringa` for lsrting\ +- `lstringb` for lsrting\ +- `lstringu` for lsrting\ +- `lstringw` for lsrting\ +- `lstringuu` for lsrting\ +- `lstringsa` for lsrting\ +- `lstringsb` for lsrting\ +- `lstringsu` for lsrting\ +- `lstringsw` for lsrting\ +- `lstringsuu` for lsrting\ A small example of use with explanations: ```cpp @@ -419,6 +426,12 @@ The `length` function returns the length of the string, and the `place` function Any owning string (simstr::sstring, simstr::lstring) can be initialized with a string expression — it requests its length, allocates space for storing characters, and passes this space to the string expression, calling its place function. +In addition, all string expressions included in `simstr` can be converted to standard strings (`std::basic_string`) +compatible character types, which allows you to use fast concatenation where replacing `std::string` is not yet possible. +Compatible character types are those that match in size. +To get a standard string before C++23, using `resize`, and then fill it using `data()`, starting with C++23 +the more optimal `resize_and_overwrite` is used. + A template addition function is defined for string expressions: ```cpp template B> @@ -449,6 +462,10 @@ string expression, you can reapply `operator +`, forming a chain of several stri and eventually "materialize" the last resulting object, which first calculates the size of the entire total memory for the final result, and then places the nested subexpressions into one buffer. +The addition operation of string expressions allows you to concatenate string expressions of different but compatible types. +That is, in one expression you can mix `""` and `u8""`, in Linux `L""` and `U""`, in Windows `L""` and `u""` +character types. There are examples in `tests\test_str.cpp TEST(SimStr, StrPrintfU8)`. + All string types in the library are themselves string expressions, that is, they can serve as terms in concatenations of string expressions. @@ -460,6 +477,27 @@ Example: stringa text = header + " count=" + count + ", done"; ``` +For standard strings (`std::basic_string` and `std::basic_string_view`) addition operators with strings have also been made +expressions, so variables of these types also directly participate in concatenation operations. +However, standard strings can only participate directly in string expressions when +the other operand is also a string expression. If the other operand is not a string expression, +use a unary `operator+` before standard strings to turn `std::basic_string` or `std::basic_string_view` +to a string expression. + +Example: +```cpp +std::string make_text(const std::string& text, std::string_view what, int count) { + // + turns text into a string expression, and then they are added together + return +text + " " + count + " " + what + e_if(count > 1, "s"); + // what participates directly as an operand with a string expression +} +std::string make_answer(const std::string& text, std::string_view what, int count) { + return "Answer is: " + +text + " " + count + " " + what + e_if(count > 1, "s"); + // + turns text into a string expression, and it can be added to the previous string literal +} +``` +That is, the unary `+` is only needed somewhere at the beginning of the expression if the other operand is not a string expression. + There are several types of string expressions "out of the box" for performing various operations on strings: #### expr_spaces{} diff --git a/docs/overview_ru.md b/docs/overview_ru.md index 1dc4e98..cf04864 100644 --- a/docs/overview_ru.md +++ b/docs/overview_ru.md @@ -189,12 +189,15 @@ Сначала я расскажу о классах библиотеки для самих строк, а потом о том, как в ней оптимально решается задача конкатенации строк. Несколько общих моментов: -- Все классы для работы со строками шаблонизированы типом символов, но подразумевается, что символы могут быть char, char16_t, - char32_t, wchar_t. +- Все классы для работы со строками шаблонизированы типом символов, но подразумевается, что символы могут быть `char`, `char8_t`, `char16_t`, + `char32_t`, `wchar_t`. - Все строки имеют явную длину. - Классы владельцы строк хранят их с завершающим нулем в конце, который не входит в длину строки. - В самой строке могут содержаться нулевые символы, все алгоритмы работают только через длину строки, не обращая на них внимания. +- Библиотека считает разные строковые типы "совместимыми", если они имеют одинаковый размер символов. + То есть `char` и `char8_t` всегда тождественны, а также в Linux тождественны `wchar_t` и `char32_t`, а в Windows `wchar_t` и `char16_t`. - Классы владельцы строк могут инициализироваться строками другого типа символов, выполняя конвертацию между UTF-8, UTF-16, UTF-32. + При этом если строки разных, но совместимых типов, они просто копируются без конвертации. - Для смены регистра символов и сравнения строк без учёта регистра используются встроенные таблицы для первой плоскости юникода (до 0xFFFF). Строки считаются представленными в кодировке UTF-8, UTF-16, UTF-32 соответственно. Однако не делается нормализация строк и не обрабатываются ситуации, когда смена регистра символа приводит к изменению их количества. @@ -215,6 +218,7 @@ Алиасы: - `ssa` для simple_str\ +- `ssb` для simple_str\ - `ssu` для simple_str\ - `ssw` для simple_str\ - `ssuu` для simple_str\ @@ -233,6 +237,7 @@ Алиасы: - `stra` для simple_str_nt\ +- `strb` для simple_str_nt\ - `stru` для simple_str_nt\ - `strw` для simple_str_nt\ - `struu` для simple_str_nt\ @@ -259,6 +264,7 @@ Алиасы: - `stringa` для sstring\ +- `stringb` для sstring\ - `stringu` для sstring\ - `stringw` для sstring\ - `stringuu` для sstring\ @@ -310,14 +316,16 @@ и работать с ней. При этом не опасаясь переполнения буфера, так как в этом случае строка переключится на динамический буфер. Алиасы: -- `lstringa` для lsrting\ -- `lstringu` для lsrting\ -- `lstringw` для lsrting\ -- `lstringuu` для lsrting\ -- `lstringsa` для lsrting\ -- `lstringsu` для lsrting\ -- `lstringsw` для lsrting\ -- `lstringsuu` для lsrting\ +- `lstringa` для lsrting\ +- `lstringb` для lsrting\ +- `lstringu` для lsrting\ +- `lstringw` для lsrting\ +- `lstringuu` для lsrting\ +- `lstringsa` для lsrting\ +- `lstringsb` для lsrting\ +- `lstringsu` для lsrting\ +- `lstringsw` для lsrting\ +- `lstringsuu` для lsrting\ Небольшой пример использования с пояснениями: @@ -420,6 +428,12 @@ Любая владеющая строка (simstr::sstring, simstr::lstring) может инициализироваться строковым выражением — она запрашивает у него длину, выделяет место для хранения символов, и передает это место строковому выражению, вызывая его функцию place. +Кроме того, все входящие в `simstr` строковые выражения могут преобразовываться в стандартные строки (`std::basic_string`) +совместимых типов символов, что позволяет применять быструю конкатенацию там, где заменить `std::string` пока невозможно. +Совместимые типы символов - такие, которые совпадают по размеру. +Для получения стандартной строки до C++23 используется `resize`, а потом заполнение через `data()`, начиная с C++23 +используется более оптимальный `resize_and_overwrite`. + Для строковых выражений определена шаблонная функция сложения: ```cpp template B> @@ -450,6 +464,10 @@ и в итоге "материализовать" последний получившийся объект, который сначала посчитает размер всей общей памяти для конечного результата, а затем разместит вложенные подвыражения в один буфер. +Операция сложения строковых выражений позволяет конкатенировать строковые выражения разных, но совместимых типов. +То есть в одном выражении вы можете смешивать `""` и `u8""`, в Linux `L""` и `U""`, в Windows `L""` и `u""` +типы символов. Примеры есть в `tests\test_str.cpp TEST(SimStr, StrPrintfU8)`. + Все строковые типы библиотеки сами являются строковыми выражениями, то есть могут служить слагаемыми в конкатенациях строковых выражений. @@ -461,6 +479,27 @@ stringa text = header + " count=" + count + ", done"; ``` +Для стандартных строк (`std::basic_string` и `std::basic_string_view`) также сделаны операторы сложения со строковыми +выражениями, поэтому переменные этих типов также напрямую участвовать в операциях конкатенирования. +Однако cтандартные строки могут напрямую участвовать в строковых выражениях только когда +другой операнд тоже является строковым выражением. Если другой операнд - не строковое выражение, +используйте перед стандартными строками унарный `operator+`, чтобы превратить `std::basic_string` или `std::basic_string_view` +в строковое выражение. + +Пример: +```cpp +std::string make_text(const std::string& text, std::string_view what, int count) { + // + превращает text в строковое выражение, а дальше они уже складываются между собой + return +text + " " + count + " " + what + e_if(count > 1, "s"); + // what участвует уже напрямую как операнд со стороковым выражением +} +std::string make_answer(const std::string& text, std::string_view what, int count) { + return "Answer is: " + +text + " " + count + " " + what + e_if(count > 1, "s"); + // + превращает text в строковое выражени, и оно может быть сложено с предыдущим строковым литералом +} +``` +То есть унарный `+` нужен только где-то в начале выражения, если другой операнд не строковое выражение. + Существует несколько типов строковых выражений "из коробки", для выполнения различных операций со строками: #### expr_spaces<ТипСимвола, КоличествоСимволов, Символ = ' '>{} diff --git a/include/simstr/sstring.h b/include/simstr/sstring.h index 880fd92..69f8eae 100644 --- a/include/simstr/sstring.h +++ b/include/simstr/sstring.h @@ -1,9 +1,9 @@ /* * (c) Проект "SimStr", Александр Орефков orefkov@gmail.com - * ver. 1.3.1 + * ver. 1.4.0 * Классы для работы со строками * (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com -* ver. 1.3.1 +* ver. 1.4.0 * Classes for working with strings */ @@ -18,10 +18,17 @@ * @includedoc{doc} "overview.md" */ #pragma once -#include + #ifndef __has_declspec_attribute #define __has_declspec_attribute(x) 0 #endif +const bool isWindowsOs = // NOLINT +#ifdef _WIN32 + true +#else + false +#endif + ; #ifdef SIMSTR_IN_SHARED #if defined(_MSC_VER) || (defined(__clang__) && __has_declspec_attribute(dllexport)) @@ -38,46 +45,18 @@ #else #define SIMSTR_API #endif -const bool isWindowsOs = // NOLINT -#ifdef _WIN32 - true -#else - false -#endif - ; -const bool isx64 = sizeof(void*) == 8; // NOLINT - -#ifdef _MSC_VER -#define _no_unique_address msvc::no_unique_address -#define decl_empty_bases __declspec(empty_bases) -#else -#define _no_unique_address no_unique_address -#define decl_empty_bases -#endif - -#if defined __has_builtin -# if __has_builtin (__builtin_mul_overflow) && __has_builtin (__builtin_add_overflow) -# define HAS_BUILTIN_OVERFLOW -# endif -#endif +#define IN_FULL_SIMSTR #include "strexpr.h" +#undef simple_str -#include -#include -#include -#include #include #include -#include -#include -#include #include #include #include #include #include -#include #ifdef _WIN32 #include @@ -158,66 +137,6 @@ struct unicode_traits { } }; -namespace str { -constexpr const size_t npos = static_cast(-1); //NOLINT -} // namespace str - -template -struct ch_traits : std::char_traits{}; - -template -concept is_const_pattern = N > 1 && N <= 17; - -template -struct _ascii_mask { // NOLINT - constexpr static const size_t value = size_t(K(~0x7F)) << ((I - 1) * sizeof(K) * 8) | _ascii_mask::value; -}; - -template -struct _ascii_mask { - constexpr static const size_t value = 0; -}; - -template -struct ascii_mask { // NOLINT - using uns = std::make_unsigned_t; - constexpr static const size_t WIDTH = sizeof(size_t) / sizeof(uns); - constexpr static const size_t VALUE = _ascii_mask::value; -}; - -template -constexpr inline bool isAsciiUpper(K k) { - return k >= 'A' && k <= 'Z'; -} - -template -constexpr inline bool isAsciiLower(K k) { - return k >= 'a' && k <= 'z'; -} - -template -constexpr inline K makeAsciiLower(K k) { - return isAsciiUpper(k) ? k | 0x20 : k; -} - -template -constexpr inline K makeAsciiUpper(K k) { - return isAsciiLower(k) ? k & ~0x20 : k; -} - -enum TrimSides { TrimLeft = 1, TrimRight = 2, TrimAll = 3 }; -template -struct trim_operator; - -template -struct expr_replaces; - -template -concept FromIntNumber = - is_one_of_type, unsigned char, int, short, long, long long, unsigned, unsigned short, unsigned long, unsigned long long>::value; - -template -concept ToIntNumber = FromIntNumber || is_one_of_type::value; #if defined(_MSC_VER) && _MSC_VER <= 1933 template @@ -230,418 +149,23 @@ template using FmtString = std::basic_string_view; #endif -template -struct need_sign { // NOLINT - bool sign; - need_sign(T& t) : sign(t < 0) { - if (sign && t != std::numeric_limits::min()) - t = -t; - } - void after(K*& ptr) { - if (sign) - *--ptr = '-'; - } -}; - -template -struct need_sign { - need_sign(T&) {} - void after(K*&) {} -}; - -/*! - * @ru @brief Перечисление с возможными результатами преобразования строки в целое число - * @en @brief Enumeration with possible results of converting a string to an integer - */ -enum class IntConvertResult : char { - Success, //!< Успешно - BadSymbolAtTail, //!< Число закончилось не числовым символом - Overflow, //!< Переполнение, число не помещается в заданный тип - NotNumber //!< Вообще не число -}; - -template -struct result_type_selector { // NOLINT - using type = T; -}; - -template -struct result_type_selector { - using type = std::make_unsigned_t; -}; - -template -constexpr unsigned digit_width() { - if (Base <=2) { - return 1; - } - if (Base <= 4) { - return 2; - } - if (Base <= 8) { - return 3; - } - if (Base <= 16) { - return 4; - } - if (Base <= 32) { - return 5; - } - return 6; -} - -template -constexpr unsigned max_overflow_digits = (sizeof(T) * CHAR_BIT) / digit_width(); - -template -struct convert_result { - T value; - IntConvertResult ec; - size_t read; -}; - -struct int_convert { // NOLINT - inline static const uint8_t NUMBERS[] = { - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; - - template - static constexpr std::make_unsigned_t toDigit(K s) { - auto us = static_cast>(s); - if constexpr (Base <= 10) { - return us - '0'; - } else { - if constexpr (sizeof(K) == 1) { - return NUMBERS[us]; - } else { - return us < 256 ? NUMBERS[us] : us; - } - } - } - - template - requires(Base != 0) - static constexpr convert_result parse(const K* start, const K* current, const K* end, bool negate) { - using u_type = std::make_unsigned_t; - #ifndef HAS_BUILTIN_OVERFLOW - u_type maxMult = 0, maxAdd = 0; - if constexpr (CheckOverflow) { - maxMult = std::numeric_limits::max() / Base; - maxAdd = std::numeric_limits::max() % Base; - } - #endif - u_type number = 0; - unsigned maxDigits = max_overflow_digits; - IntConvertResult error = IntConvertResult::NotNumber; - const K* from = current; - - bool no_need_check_o_f = !CheckOverflow || end - current <= maxDigits; - - if (no_need_check_o_f) { - for (;;) { - const u_type digit = toDigit(*current); - if (digit >= Base) { - break; - } - number = number * Base + digit; - if (++current == end) { - error = IntConvertResult::Success; - break; - } - } - } else { - for (;maxDigits; maxDigits--) { - const u_type digit = toDigit(*current); - if (digit >= Base) { - break; - } - number = number * Base + digit; - ++current; - } - if (!maxDigits) { - // Прошли все цифры, дальше надо с проверкой на overflow - // All numbers have passed, then we need to check for overflow - for (;;) { - const u_type digit = toDigit(*current); - if (digit >= Base) { - break; - } - #ifdef HAS_BUILTIN_OVERFLOW - if (__builtin_mul_overflow(number, Base, &number) || - __builtin_add_overflow(number, digit, &number)) { - #else - if (number < maxMult || (number == maxMult && number < maxAdd)) { - number = number * Base + digit; - } else { - #endif - error = IntConvertResult::Overflow; - while(++current < end) { - if (toDigit(*current) >= Base) { - break; - } - } - break; - } - if (++current == end) { - error = IntConvertResult::Success; - break; - } - } - } - } - T result; - if constexpr (std::is_signed_v) { - result = negate ? 0 - number : number; - if constexpr (CheckOverflow) { - if (error != IntConvertResult::Overflow) { - if (number > std::numeric_limits::max() + (negate ? 1 : 0)) { - error = IntConvertResult::Overflow; - } - } - } - } else { - result = number; - } - if (error == IntConvertResult::NotNumber && current > from) { - error = IntConvertResult::BadSymbolAtTail; - } - return {result, error, size_t(current - start)}; - } -public: - // Если Base = 0 - то пытается определить основание по префиксу 0[xX] как 16, 0 как 8, иначе 10 - // Если Base = -1 - то пытается определить основание по префиксу 0[xX] как 16, 0[bB] как 2, 0[oO] или 0 как 8, иначе 10 - // If Base = 0, then it tries to determine the base by the prefix 0[xX] as 16, 0 as 8, otherwise 10 - // If Base = -1 - then tries to determine the base by the prefix 0[xX] as 16, 0[bB] as 2, 0[oO] or 0 as 8, otherwise 10 - template - requires(Base == -1 || (Base < 37 && Base != 1)) - static constexpr convert_result to_integer(const K* start, size_t len) noexcept { - const K *ptr = start, *end = ptr + len; - bool negate = false; - if constexpr (SkipWs) { - while (ptr < end && std::make_unsigned_t(*ptr) <= ' ') - ptr++; - } - if (ptr != end) { - if constexpr (std::is_signed_v) { - if constexpr (AllowSign) { - // Может быть число, +число или -число - // Can be a number, +number or -number - if (*ptr == '+') { - ptr++; - } else if (*ptr == '-') { - negate = true; - ptr++; - } - } else { - // Может быть число или -число - // Can be a number or -number - if (*ptr == '-') { - negate = true; - ptr++; - } - } - } else if constexpr (AllowSign) { - // Может быть число или +число - // Can be a number or +number - if (*ptr == '+') { - ptr++; - } - } - } - if (ptr != end) { - if constexpr (Base == 0 || Base == -1) { - if (*ptr == '0') { - ptr++; - if (ptr != end) { - if (*ptr == 'x' || *ptr == 'X') { - return parse(start, ++ptr, end, negate); - } - if constexpr (Base == -1) { - if (*ptr == 'b' || *ptr == 'B') { - return parse(start, ++ptr, end, negate); - } - if (*ptr == 'o' || *ptr == 'O') { - return parse(start, ++ptr, end, negate); - } - } - return parse(start, --ptr, end, negate); - } - return {0, IntConvertResult::Success, size_t(ptr - start)}; - } - return parse(start, ptr, end, negate); - } else - return parse(start, ptr, end, negate); - } - return {0, IntConvertResult::NotNumber, size_t(ptr - start)}; - } -}; - template SIMSTR_API std::optional impl_to_double(const K* start, const K* end); -template -class Splitter; - -template -class null_terminated { -public: - /*! - * @ru @brief Получить указатель на константный буфер символов строки - * @return const K* - указатель на константный буфер символов строки - * @en @brief Get a pointer to a constant character buffer of a string - * @return const K* - pointer to a constant string character buffer - */ - constexpr const K* c_str() const { return static_cast(this)->symbols(); } -}; - -template class buffer_pointers; - /*! - * @ru @brief Базовый класс для строкового буфера. - * @tparam K - тип символов. - * @tparam Impl - класс реализации. - * @en @brief Base class for a string buffer. - * @tparam K - character type. - * @tparam Impl - implementation class. - */ -template -class buffer_pointers { - constexpr const Impl& d() const { return *static_cast(this); } -public: - /*! - * @ru @brief Получить указатель на константный буфер символов строки. - * @return const K* - указатель на константный буфер символов строки. - * @en @brief Get a pointer to a constant character buffer of a string. - * @return const K* - pointer to a constant buffer of string characters. - */ - constexpr const K* data() const { return d().symbols(); } - /*! - * @ru @brief Получить указатель на константный буфер символов строки. - * @return const K* - указатель на константный буфер символов строки. - * @en @brief Get a pointer to a constant character buffer of a string. - * @return const K* - pointer to a constant buffer of string characters. - */ - constexpr const K* begin() const { return d().symbols(); } - /*! - * @ru @brief Указатель на константный символ после после последнего символа строки. - * @return const K* - конец строки. - * @en @brief Pointer to a constant character after the last character of the string. - * @return const K* - end of line. - */ - constexpr const K* end() const { return d().symbols() + d().length(); } - /*! - * @ru @brief Получить указатель на константный буфер символов строки. - * @return const K* - указатель на константный буфер символов строки. - * @en @brief Get a pointer to a constant character buffer of a string. - * @return const K* - pointer to a constant buffer of string characters. - */ - constexpr const K* cbegin() const { return d().symbols(); } - /*! - * @ru @brief Указатель на константный символ после после последнего символа строки. - * @return const K* - конец строки. - * @en @brief Pointer to a constant character after the last character of the string. - * @return const K* - end of line. - */ - constexpr const K* cend() const { return d().symbols() + d().length(); } -}; - -template -class buffer_pointers : public buffer_pointers { - constexpr Impl& d() { return *static_cast(this); } - using base = buffer_pointers; -public: - /*! - * @ru @brief Получить указатель на константный буфер символов строки. - * @return const K* - указатель на константный буфер символов строки. - * @en @brief Get a pointer to a constant character buffer of a string. - * @return const K* - pointer to a constant buffer of string characters. - */ - constexpr const K* data() const { return base::data(); } - /*! - * @ru @brief Получить указатель на константный буфер символов строки. - * @return const K* - указатель на константный буфер символов строки. - * @en @brief Get a pointer to a constant character buffer of a string. - * @return const K* - pointer to a constant buffer of string characters. - */ - constexpr const K* begin() const { return base::begin(); } - /*! - * @ru @brief Указатель на константный символ после после последнего символа строки. - * @return const K* - конец строки. - * @en @brief Pointer to a constant character after the last character of the string. - * @return const K* - end of line. - */ - constexpr const K* end() const { return base::end(); } - /*! - * @ru @brief Получить указатель на константный буфер символов строки. - * @return const K* - указатель на константный буфер символов строки. - * @en @brief Get a pointer to a constant character buffer of a string. - * @return const K* - pointer to a constant buffer of string characters. - */ - constexpr const K* cbegin() const { return base::cbegin(); } - /*! - * @ru @brief Указатель на константный символ после после последнего символа строки. - * @return const K* - конец строки. - * @en @brief Pointer to a constant character after the last character of the string. - * @return const K* - end of line. - */ - constexpr const K* cend() const { return base::cend(); } - /*! - * @ru @brief Получить указатель на буфер символов строки. - * @return K* - указатель на буфер символов строки. - * @en @brief Get a pointer to the string's character buffer. - * @return K* - pointer to a string character buffer. - */ - constexpr K* data() { return d().str(); } - /*! - * @ru @brief Получить указатель на буфер символов строки. - * @return K* - указатель на буфер символов строки. - * @en @brief Get a pointer to the string's character buffer. - * @return K* - pointer to a string character buffer. - */ - constexpr K* begin() { return d().str(); } - /*! - * @ru @brief Указатель на символ после после последнего символа строки. - * @return K* - конец строки. - * @en @brief Pointer to the character after the last character of the string. - * @return K* - end of line. - */ - constexpr K* end() { return d().str() + d().length(); } -}; - -/*! - * @ru @brief Класс с базовыми константными строковыми алгоритмами. - * @details Является базой для классов, могущих выполнять константные операции со строками. - * Ничего не знает о хранении строк, ни сам, ни у класса наследника, то есть работает - * только с указателем на строку и её длиной. - * Для работы класс-наследник должен реализовать методы: - * - size_t length() const noexcept - возвращает длину строки. - * - const K* symbols() const noexcept - возвращает указатель на начало строки. - * - bool is_empty() const noexcept - проверка, не пустая ли строка. + * @ru @brief Класс с дополнительными константными строковыми алгоритмами. + * @details Дополняет алгоритмы из str_src_algs теми, которые связаны с упрощённым юникодом и парсингом double. * @tparam K - тип символов. * @tparam StrRef - тип хранилища куска строки. * @tparam Impl - конечный класс наследник. - * @en @brief A class with basic constant string algorithms. - * @details Is the base for classes that can perform constant operations on strings. - * Doesn’t know anything about storing strings, neither itself nor the descendant class, that is, it works - * only with a pointer to a string and its length. - * To work, the descendant class must implement the following methods: - * - size_t length() const noexcept - returns the length of the string. - * - const K* symbols() const noexcept - returns a pointer to the beginning of the line. - * - bool is_empty() const noexcept - checks whether the string is empty. + * @en @brief A class with additional constant string algorithms. + * @details Supplements the algorithms from str_src_algs with those related to simplified Unicode and double parsing. * @tparam K - character type. * @tparam StrRef - storage type for the string chunk. * @tparam Impl - the final class is the successor. */ template -class str_algs : public buffer_pointers { +class str_algs : public str_src_algs { constexpr const Impl& d() const noexcept { return *static_cast(this); } @@ -662,337 +186,9 @@ public: using uni = unicode_traits; using uns_type = std::make_unsigned_t; using my_type = Impl; - using base = str_algs; + using base = str_src_algs; str_algs() = default; - /*! - * @ru @brief Копировать строку в указанный буфер. - * @details Метод предполагает, что размер выделенного буфера достаточен для всей строки, т.е. - * предварительно была запрошена `length()`. Не добавляет `\0`. - * @param ptr - указатель на буфер. - * @return указатель на символ после конца размещённой в буфере строки. - * @en @brief Copy the string to the specified buffer. - * @details The method assumes that the size of the allocated buffer is sufficient for the entire line, i.e. - * `length()` was previously requested. Does not add `\0`. - * @param ptr - pointer to the buffer. - * @return pointer to the character after the end of the symbols placed in the buffer. - */ - constexpr K* place(K* ptr) const noexcept { - size_t myLen = _len(); - if (myLen) { - traits::copy(ptr, _str(), myLen); - return ptr + myLen; - } - return ptr; - } - /*! - * @ru @brief Копировать строку в указанный буфер. - * @details Метод добавляет `\0` после скопированных символов. Не выходит за границы буфера. - * @param buffer - указатель на буфер - * @param bufSize - размер буфера в символах. - * @en @brief Copy the string to the specified buffer. - * @details The method adds `\0` after the copied characters. Does not exceed buffer boundaries. - * @param buffer - pointer to buffer - * @param bufSize - buffer size in characters. - */ - void copy_to(K* buffer, size_t bufSize) { - size_t tlen = std::min(_len(), bufSize - 1); - if (tlen) - traits::copy(buffer, _str(), tlen); - buffer[tlen] = 0; - } - /*! - * @ru @brief Размер строки в символах. - * @return size_t - * @en @brief The size of the string in characters. - * @return size_t - */ - constexpr size_t size() const { - return _len(); - } - - /*! - * @ru @brief Преобразовать себя в "кусок строки", включающий всю строку. - * @return str_piece. - * @en @brief Convert itself to a "string chunk" that includes the entire string. - * @return str_piece. - */ - constexpr operator str_piece() const noexcept { - return str_piece{_str(), _len()}; - } - /*! - * @ru @brief Преобразовать себя в "кусок строки", включающий всю строку. - * @return str_piece. - * @en @brief Convert itself to a "string chunk" that includes the entire string. - * @return str_piece. - */ - constexpr str_piece to_str() const noexcept { - return {_str(), _len()}; - } - /*! - * @ru @brief Конвертировать в std::string_view. - * @return std::basic_string_view. - * @en @brief Convert to std::string_view. - * @return std::basic_string_view. - */ - template requires is_one_of_std_char_v - constexpr std::basic_string_view to_sv() const noexcept { - return {_str(), _len()}; - } - /*! - * @ru @brief Конвертировать в std::string. - * @return std::basic_string. - * @en @brief Convert to std::string. - * @return std::basic_string. - */ - template requires is_one_of_std_char_v - constexpr std::basic_string to_string() const noexcept { - return {_str(), _len()}; - } - /*! - * @ru @brief Получить часть строки как "simple_str". - * @param from - количество символов от начала строки. - * @param len - количество символов в получаемом "куске". - * @return Подстроку, simple_str. - * @details Если `from` меньше нуля, то отсчитывается `-from` символов от конца строки в сторону начала. - * Если `len` меньше или равно нулю, то отсчитать `-len` символов от конца строки - * @en @brief Get part of a string as "simple_str". - * @param from - number of characters from the beginning of the line. - * @param len - the number of characters in the resulting "chunk". - * @return Substring, simple_str. - * @details If `from` is less than zero, then `-from` characters are counted from the end of the line towards the beginning. - * If `len` is less than or equal to zero, then count `-len` characters from the end of the line - * @~ - * ```cpp - * "0123456789"_ss(5, 2) == "56"; - * "0123456789"_ss(5) == "56789"; - * "0123456789"_ss(5, -1) == "5678"; - * "0123456789"_ss(-3) == "789"; - * "0123456789"_ss(-3, 2) == "78"; - * "0123456789"_ss(-4, -1) == "678"; - * ``` - */ - constexpr str_piece operator()(ptrdiff_t from, ptrdiff_t len = 0) const noexcept { - size_t myLen = _len(), idxStart = from >= 0 ? from : myLen > -from ? myLen + from : 0, - idxEnd = len > 0 ? idxStart + len : myLen > -len ? myLen + len : 0; - if (idxEnd > myLen) - idxEnd = myLen; - if (idxStart > idxEnd) - idxStart = idxEnd; - return str_piece{_str() + idxStart, idxEnd - idxStart}; - } - /*! - * @ru @brief Получить часть строки как "кусок строки". - * @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку. - * @param len - количество символов в получаемом "куске". При выходе за пределы строки вернёт всё до конца строки. - * @return Подстроку, simple_str. - * @en @brief Get part of a string as "string chunk". - * @param from - number of characters from the beginning of the line. If the string size is exceeded, it will return an empty string. - * @param len - the number of characters in the resulting "chunk". When going beyond the line, it will return everything up to the end of the line. - * @return Substring, simple_str. - */ - constexpr str_piece mid(size_t from, size_t len = -1) const noexcept { - size_t myLen = _len(), idxStart = from, idxEnd = from > std::numeric_limits::max() - len ? myLen : from + len; - if (idxEnd > myLen) - idxEnd = myLen; - if (idxStart > idxEnd) - idxStart = idxEnd; - return str_piece{_str() + idxStart, idxEnd - idxStart}; - } - /*! - * @ru @brief Получить подстроку simple_str с позиции от from до позиции to (не включая её). - * @details Для производительности метод никак не проверяет выходы за границы строки, используйте - * в сценариях, когда точно знаете, что это позиции внутри строки и to >= from. - * @param from - начальная позиция. - * @param to - конечная позиция (не входит в результат). - * @return Подстроку, simple_str. - * @en @brief Get the substring simple_str from position from to position to (not including it). - * @details For performance reasons, the method does not check for line boundaries in any way, use - * in scenarios when you know for sure that these are positions inside the line and to >= from. - * @param from - starting position. - * @param to - final position (not included in the result). - * @return Substring, simple_str. - */ - constexpr str_piece from_to(size_t from, size_t to) const noexcept { - return str_piece{_str() + from, to - from}; - } - /*! - * @ru @brief Проверка на пустоту. - * @en @brief Check for emptiness. - */ - constexpr bool operator!() const noexcept { - return _is_empty(); - } - /*! - * @ru @brief Получить символ на заданной позиции . - * @param idx - индекс символа. Для отрицательных значений отсчитывается от конца строки. - * @return K - символ. - * @details Не производит проверку на выход за границы строки. - * @en @brief Get the character at the given position. - * @param idx - symbol index. For negative values, it is counted from the end of the line. - * @return K - character. - * @details Does not check for line boundaries. - */ - constexpr K at(ptrdiff_t idx) const { - return _str()[idx >= 0 ? idx : _len() + idx]; - } - // Сравнение строк - // String comparison - constexpr int compare(const K* text, size_t len) const { - size_t myLen = _len(); - int cmp = traits::compare(_str(), text, std::min(myLen, len)); - return cmp == 0 ? (myLen > len ? 1 : myLen == len ? 0 : -1) : cmp; - } - /*! - * @ru @brief Сравнение строк посимвольно. - * @param o - другая строка. - * @return <0 эта строка меньше, ==0 - строки равны, >0 - эта строка больше. - * @en @brief Compare strings character by character. - * @param o - another line. - * @return <0 this string is less, ==0 - strings are equal, >0 - this string is greater. - */ - constexpr int compare(str_piece o) const { - return compare(o.symbols(), o.length()); - } - /*! - * @ru @brief Сравнение с C-строкой посимвольно. - * @param text - другая строка. - * @return <0 эта строка меньше, ==0 - строки равны, >0 - эта строка больше. - * @en @brief Compare with C-string character by character. - * @param text - another line. - * @return <0 this string is less, ==0 - strings are equal, >0 - this string is greater. - */ - constexpr int strcmp(const K* text) const { - size_t myLen = _len(), idx = 0; - const K* ptr = _str(); - for (; idx < myLen; idx++) { - uns_type s1 = (uns_type)text[idx]; - if (!s1) { - return 1; - } - uns_type s2 = (uns_type)ptr[idx]; - if (s1 < s2) { - return 1; - } else if (s1 > s2) { - return -1; - } - } - return text[idx] == 0 ? 0 : -1; - } - - constexpr bool equal(const K* text, size_t len) const noexcept { - return len == _len() && traits::compare(_str(), text, len) == 0; - } - /*! - * @ru @brief Сравнение строк на равенство. - * @param other - другая строка. - * @return равны ли строки. - * @en @brief String comparison for equality. - * @param other - another line. - * @return whether the strings are equal. - */ - constexpr bool equal(str_piece other) const noexcept { - return equal(other.symbols(), other.length()); - } - /*! - * @ru @brief Оператор сравнение строк на равенство. - * @param other - другая строка. - * @return равны ли строки. - * @en @brief Operator comparing strings for equality. - * @param other - another line. - * @return whether the strings are equal. - */ - constexpr bool operator==(const base& other) const noexcept { - return equal(other._str(), other._len()); - } - /*! - * @ru @brief Оператор сравнения строк. - * @param other - другая строка. - * @en @brief String comparison operator. - * @param other - another line. - */ - constexpr auto operator<=>(const base& other) const noexcept { - return compare(other._str(), other._len()) <=> 0; - } - /*! - * @ru @brief Оператор сравнения строки и строкового литерала на равенство. - * @param other - строковый литерал. - * @en @brief Operator for comparing a string and a string literal for equality. - * @param other - string literal. - */ - template::Count> - constexpr bool operator==(T&& other) const noexcept { - return N - 1 == _len() && traits::compare(_str(), other, N - 1) == 0; - } - /*! - * @ru @brief Оператор сравнения строки и строкового литерала. - * @param other - строковый литерал. - * @en @brief Comparison operator between a string and a string literal. - * @param other is a string literal. - */ - template::Count> - constexpr auto operator<=>(T&& other) const noexcept { - size_t myLen = _len(); - int cmp = traits::compare(_str(), other, std::min(myLen, N - 1)); - int res = cmp == 0 ? (myLen > N - 1 ? 1 : myLen == N - 1 ? 0 : -1) : cmp; - return res <=> 0; - } - - // Сравнение ascii строк без учёта регистра - // Compare ascii strings without taking into account case - constexpr int compare_ia(const K* text, size_t len) const noexcept { // NOLINT - if (!len) - return _is_empty() ? 0 : 1; - size_t myLen = _len(), checkLen = std::min(myLen, len); - const uns_type *ptr1 = reinterpret_cast(_str()), *ptr2 = reinterpret_cast(text); - while (checkLen--) { - uns_type s1 = *ptr1++, s2 = *ptr2++; - if (s1 == s2) - continue; - s1 = makeAsciiLower(s1); - s2 = makeAsciiLower(s2); - if (s1 > s2) - return 1; - else if (s1 < s2) - return -1; - } - return myLen == len ? 0 : myLen > len ? 1 : -1; - } - /*! - * @ru @brief Сравнение строк посимвольно без учёта регистра ASCII символов. - * @param text - другая строка. - * @return <0 эта строка меньше, ==0 - строки равны, >0 - эта строка больше. - * @en @brief Compare strings character by character and not case sensitive ASCII characters. - * @param text - another line. - * @return <0 this string is less, ==0 - strings are equal, >0 - this string is greater. - */ - constexpr int compare_ia(str_piece text) const noexcept { // NOLINT - return compare_ia(text.symbols(), text.length()); - } - - /*! - * @ru @brief Равна ли строка другой строке посимвольно без учёта регистра ASCII символов. - * @param text - другая строка. - * @return равны ли строки. - * @en @brief Whether a string is equal to another string, character-by-character-insensitive, of ASCII characters. - * @param text - another line. - * @return whether the strings are equal. - */ - constexpr bool equal_ia(str_piece text) const noexcept { // NOLINT - return text.length() == _len() && compare_ia(text.symbols(), text.length()) == 0; - } - /*! - * @ru @brief Меньше ли строка другой строки посимвольно без учёта регистра ASCII символов. - * @param text - другая строка. - * @return меньше ли строка. - * @en @brief Whether a string is smaller than another string, character-by-character-insensitive, ASCII characters. - * @param text - another line. - * @return whether the string is smaller. - */ - constexpr bool less_ia(str_piece text) const noexcept { // NOLINT - return compare_ia(text.symbols(), text.length()) < 0; - } - int compare_iu(const K* text, size_t len) const noexcept { // NOLINT if (!len) return _is_empty() ? 0 : 1; @@ -1009,7 +205,6 @@ public: int compare_iu(str_piece text) const noexcept { // NOLINT return compare_iu(text.symbols(), text.length()); } - /*! * @ru @brief Равна ли строка другой строке посимвольно без учёта регистра Unicode символов первой плоскости (<0xFFFF). * @param text - другая строка. @@ -1032,471 +227,58 @@ public: bool less_iu(str_piece text) const noexcept { // NOLINT return compare_iu(text.symbols(), text.length()) < 0; } - - constexpr size_t find(const K* pattern, size_t lenPattern, size_t offset) const noexcept { - size_t lenText = _len(); - // Образец, не вмещающийся в строку и пустой образец не находим - // We don't look for an empty line or a line longer than the text. - if (!lenPattern || offset >= lenText || offset + lenPattern > lenText) - return str::npos; - lenPattern--; - const K *text = _str(), *last = text + lenText - lenPattern, first = pattern[0]; - pattern++; - for (const K* fnd = text + offset;; ++fnd) { - fnd = traits::find(fnd, last - fnd, first); - if (!fnd) - return str::npos; - if (traits::compare(fnd + 1, pattern, lenPattern) == 0) - return static_cast(fnd - text); - } + // Начинается ли эта строка с указанной подстроки без учета unicode регистра + // Does this string begin with the specified substring, insensitive to unicode case + bool starts_with_iu(const K* prefix, size_t len) const noexcept { + return _len() >= len && 0 == uni::compareiu(_str(), len, prefix, len); } /*! - * @ru @brief Найти начало первого вхождения подстроки в этой строке. - * @param pattern - искомая строка. - * @param offset - с какой позиции начинать поиск. - * @return size_t - позицию начала вхождения подстроки, или -1, если не найдена. - * @en @brief Find the beginning of the first occurrence of a substring in this string. - * @param pattern - the search string. - * @param offset - from which position to start the search. - * @return size_t - the position of the beginning of the occurrence of the substring, or -1 if not found. + * @ru @brief Начинается ли строка с заданной подстроки без учёта регистра Unicode символов первой плоскости (<0xFFFF). + * @param prefix - подстрока. + * @en @brief Whether the string starts with the given substring, case-insensitive Unicode characters of the first plane (<0xFFFF). + * @param prefix - substring. */ - constexpr size_t find(str_piece pattern, size_t offset = 0) const noexcept { - return find(pattern.symbols(), pattern.length(), offset); + bool starts_with_iu(str_piece prefix) const noexcept { + return starts_with_iu(prefix.symbols(), prefix.length()); + } + // Заканчивается ли строка указанной подстрокой без учета регистра UNICODE + // Whether the string ends with the specified substring, case insensitive UNICODE + constexpr bool ends_with_iu(const K* suffix, size_t len) const noexcept { + size_t myLen = _len(); + return myLen >= len && 0 == uni::compareiu(_str() + myLen - len, len, suffix, len); } /*! - * @ru @brief Найти начало первого вхождения подстроки в этой строке или выкинуть исключение. - * @tparam Exc - тип исключения. - * @tparam Args... - типы параметров для конструирования исключения, выводятся из аргументов. - * @param pattern - искомая строка. - * @param offset - с какой позиции начинать поиск. - * @param args - аргументы для конструктора исключения. - * @return size_t - позицию начала вхождения подстроки, или выбрасывает исключение Exc, если не найдена. - * @en @brief Find the beginning of the first occurrence of a substring in this string or throw an exception. - * @tparam Exc - exception type. - * @tparam Args... - types of parameters for constructing an exception, inferred from the arguments. - * @param pattern - the search string. - * @param offset - from which position to start the search. - * @param args - arguments for the exception constructor. - * @return size_t - the position of the beginning of the substring occurrence, or throws an Exc exception if not found. + * @ru @brief Заканчивается ли строка указанной подстрокой без учёта регистра Unicode символов первой плоскости (<0xFFFF). + * @param suffix - подстрока. + * @en @brief Whether the string ends with the specified substring, case-insensitive Unicode characters of the first plane (<0xFFFF). + * @param suffix - substring. */ - template requires std::is_constructible_v - constexpr size_t find_or_throw(str_piece pattern, size_t offset = 0, Args&& ... args) const noexcept { - if (auto fnd = find(pattern.symbols(), pattern.length(), offset); fnd != str::npos) { - return fnd; - } - throw Exc(std::forward(args)...); + constexpr bool ends_with_iu(str_piece suffix) const noexcept { + return ends_with_iu(suffix.symbols(), suffix.length()); } /*! - * @ru @brief Найти конец вхождения подстроки в этой строке. - * @param pattern - искомая строка. - * @param offset - с какой позиции начинать поиск. - * @return size_t - позицию сразу за вхождением подстроки, или -1, если не найдена. - * @en @brief Find the end of the occurrence of a substring in this string. - * @param pattern - the search string. - * @param offset - from which position to start the search. - * @return size_t - the position immediately after the occurrence of the substring, or -1 if not found. + * @ru @brief Получить копию строки в верхнем регистре Unicode символов первой плоскости (<0xFFFF). + * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. + * @return R - копию строки в верхнем регистре. + * @en @brief Get a copy of the string in upper case Unicode characters of the first plane (<0xFFFF). + * @tparam R - the desired string type, by default the same whose method was called. + * @return R - uppercase copy of the string. */ - constexpr size_t find_end(str_piece pattern, size_t offset = 0) const noexcept { - size_t fnd = find(pattern.symbols(), pattern.length(), offset); - return fnd == str::npos ? fnd : fnd + pattern.length(); + template + R upperred() const { + return R::upperred_from(d()); } /*! - * @ru @brief Найти начало первого вхождения подстроки в этой строке или конец строки. - * @param pattern - искомая строка. - * @param offset - с какой позиции начинать поиск. - * @return size_t - позицию начала вхождения подстроки, или длину строки, если не найдена. - * @en @brief Find the beginning of the first occurrence of a substring in this string or the end of the string. - * @param pattern - the search string. - * @param offset - from which position to start the search. - * @return size_t - the position at which the substring begins, or the length of the string if not found. + * @ru @brief Получить копию строки в нижнем регистре Unicode символов первой плоскости (<0xFFFF). + * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. + * @return R - копию строки в нижнем регистре. + * @en @brief Get a copy of the string in lowercase Unicode characters of the first plane (<0xFFFF). + * @tparam R - the desired string type, by default the same whose method was called. + * @return R - lowercase copy of the string. */ - constexpr size_t find_or_all(str_piece pattern, size_t offset = 0) const noexcept { - auto fnd = find(pattern.symbols(), pattern.length(), offset); - return fnd == str::npos ? _len() : fnd; - } - /*! - * @ru @brief Найти конец первого вхождения подстроки в этой строке или конец строки. - * @param pattern - искомая строка. - * @param offset - с какой позиции начинать поиск. - * @return size_t - позицию сразу за вхождением подстроки, или длину строки, если не найдена. - * @en @brief Find the end of the first occurrence of a substring in this string, or the end of a string. - * @param pattern - the search string. - * @param offset - from which position to start the search. - * @return size_t - the position immediately after the occurrence of the substring, or the length of the string if not found. - */ - constexpr size_t find_end_or_all(str_piece pattern, size_t offset = 0) const noexcept { - auto fnd = find(pattern.symbols(), pattern.length(), offset); - return fnd == str::npos ? _len() : fnd + pattern.length(); - } - - constexpr size_t find_last(const K* pattern, size_t lenPattern, size_t offset) const noexcept { - if (lenPattern == 1) - return find_last(pattern[0], offset); - size_t lenText = std::min(_len(), offset); - // Образец, не вмещающийся в строку и пустой образец не находим - // We don't look for an empty line or a line longer than the text. - if (!lenPattern || lenPattern > lenText) - return str::npos; - - lenPattern--; - const K *text = _str() + lenPattern, last = pattern[lenPattern]; - lenText -= lenPattern; - while(lenText) { - if (text[--lenText] == last) { - if (traits::compare(text + lenText - lenPattern, pattern, lenPattern) == 0) { - return lenText; - } - } - } - return str::npos; - } - /*! - * @ru @brief Найти начало последнего вхождения подстроки в этой строке. - * @param pattern - искомая строка. - * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. - * @return size_t - позицию начала вхождения подстроки, или -1, если не найдена. - * @en @brief Find the beginning of the last occurrence of a substring in this string. - * @param pattern - the search string. - * @param offset - from which position to search in the opposite direction, -1 - from the very end. - * @return size_t - the position of the beginning of the occurrence of the substring, or -1 if not found. - */ - constexpr size_t find_last(str_piece pattern, size_t offset = -1) const noexcept { - return find_last(pattern.symbols(), pattern.length(), offset); - } - /*! - * @ru @brief Найти конец последнего вхождения подстроки в этой строке. - * @param pattern - искомая строка. - * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. - * @return size_t - позицию сразу за последним вхождением подстроки, или -1, если не найдена. - * @en @brief Find the end of the last occurrence of a substring in this string. - * @param pattern - the search string. - * @param offset - from which position to search in the opposite direction, -1 - from the very end. - * @return size_t - the position immediately after the last occurrence of the substring, or -1 if not found. - */ - constexpr size_t find_end_of_last(str_piece pattern, size_t offset = -1) const noexcept { - size_t fnd = find_last(pattern.symbols(), pattern.length(), offset); - return fnd == str::npos ? fnd : fnd + pattern.length(); - } - /*! - * @ru @brief Найти начало последнего вхождения подстроки в этой строке или конец строки. - * @param pattern - искомая строка. - * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. - * @return size_t - позицию начала вхождения подстроки, или длину строки, если не найдена. - * @en @brief Find the beginning of the last occurrence of a substring in this string or the end of the string. - * @param pattern - the search string. - * @param offset - from which position to search in the opposite direction, -1 - from the very end. - * @return size_t - the position at which the substring begins, or the length of the string if not found. - */ - constexpr size_t find_last_or_all(str_piece pattern, size_t offset = -1) const noexcept { - auto fnd = find_last(pattern.symbols(), pattern.length(), offset); - return fnd == str::npos ? _len() : fnd; - } - /*! - * @ru @brief Найти конец последнего вхождения подстроки в этой строке или конец строки. - * @param pattern - искомая строка. - * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. - * @return size_t - позицию сразу за последним вхождением подстроки, или длину строки, если не найдена. - * @en @brief Find the end of the last occurrence of a substring in this string, or the end of a string. - * @param pattern - the search string. - * @param offset - from which position to search in the opposite direction, -1 - from the very end. - * @return size_t - the position immediately after the last occurrence of the substring, or the length of the string if not found. - */ - constexpr size_t find_end_of_last_or_all(str_piece pattern, size_t offset = -1) const noexcept { - size_t fnd = find_last(pattern.symbols(), pattern.length(), offset); - return fnd == str::npos ? _len() : fnd + pattern.length(); - } - /*! - * @ru @brief Содержит ли строка указанную подстроку. - * @param pattern - искомая строка. - * @param offset - с какой позиции начинать поиск. - * @return bool. - * @en @brief Whether the string contains the specified substring. - * @param pattern - the search string. - * @param offset - from which position to start the search. - * @return bool. - */ - constexpr bool contains(str_piece pattern, size_t offset = 0) const noexcept { - return find(pattern, offset) != str::npos; - } - /*! - * @ru @brief Найти символ в этой строке. - * @param s - искомый символ. - * @param offset - с какой позиции начинать поиск. - * @return size_t - позицию найденного символа, или -1, если не найден. - * @en @brief Find a character in this string. - * @param s is an optional character. - * @param offset - from which position to start the search. - * @return size_t - position of the found character, or -1 if not found. - */ - constexpr size_t find(K s, size_t offset = 0) const noexcept { - size_t len = _len(); - if (offset < len) { - const K *str = _str(), *fnd = traits::find(str + offset, len - offset, s); - if (fnd) - return static_cast(fnd - str); - } - return str::npos; - } - /*! - * @ru @brief Найти символ в этой строке или конец строки. - * @param s - искомый символ. - * @param offset - с какой позиции начинать поиск. - * @return size_t - позицию найденного символа, или длину строки, если не найден. - * @en @brief Find a character in this string or the end of a string. - * @param s is an optional character. - * @param offset - from which position to start the search. - * @return size_t - position of the found character, or string length if not found. - */ - constexpr size_t find_or_all(K s, size_t offset = 0) const noexcept { - size_t len = _len(); - if (offset < len) { - const K *str = _str(), *fnd = traits::find(str + offset, len - offset, s); - if (fnd) - return static_cast(fnd - str); - } - return len; - } - - template - constexpr void for_all_finded(const Op& op, const K* pattern, size_t patternLen, size_t offset, size_t maxCount) const { - if (!maxCount) - maxCount--; - while (maxCount-- > 0) { - size_t fnd = find(pattern, patternLen, offset); - if (fnd == str::npos) - break; - op(fnd); - offset = fnd + patternLen; - } - } - /*! - * @ru @brief Вызвать функтор для всех найденных вхождений подстроки в этой строке. - * @param op - функтор, принимающий строку. - * @param pattern - искомая подстрока. - * @param offset - позиция начала поиска. - * @param maxCount - максимальное количество обрабатываемых вхождений, 0 - без ограничений. - * @en @brief Call a functor on all found occurrences of a substring in this string. - * @param op is a functor that takes a string. - * @param pattern - the substring to search for. - * @param offset - search start position. - * @param maxCount - the maximum number of occurrences to be processed, 0 - no restrictions. - */ - template - constexpr void for_all_finded(const Op& op, str_piece pattern, size_t offset = 0, size_t maxCount = 0) const { - for_all_finded(op, pattern.symbols(), pattern.length(), offset, maxCount); - } - - std::vector find_all(const K* pattern, size_t patternLen, size_t offset, size_t maxCount) const { - std::vector result; - for_all_finded([&](auto f) { result.push_back(f); }, pattern, patternLen, offset, maxCount); - return result; - } - /*! - * @ru @brief Найти все вхождения подстроки в этой строке. - * @param pattern - искомая подстрока. - * @param offset - позиция начала поиска. - * @param maxCount - максимальное количество обрабатываемых вхождений, 0 - без ограничений. - * @return std::vector - вектор с позициями начал найденных вхождений. - * @en @brief Find all occurrences of a substring in this string. - * @param pattern - the substring to search for. - * @param offset - search start position. - * @param maxCount - the maximum number of occurrences to be processed, 0 - no restrictions. - * @return std::vector - a vector with the positions of the beginnings of the found occurrences. - */ - constexpr std::vector find_all(str_piece pattern, size_t offset = 0, size_t maxCount = 0) const { - return find_all(pattern.symbols(), pattern.length(), offset, maxCount); - } - /*! - * @ru @brief Найти последнее вхождения символа в этой строке. - * @param s - искомый символ. - * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. - * @return size_t - позицию найденного символа, или -1, если не найден. - * @en @brief Find the last occurrence of a character in this string. - * @param s is an optional character. - * @param offset - from which position to search in the opposite direction, -1 - from the very end. - * @return size_t - position of the found character, or -1 if not found. - */ - constexpr size_t find_last(K s, size_t offset = -1) const noexcept { - size_t len = std::min(_len(), offset); - const K *text = _str(); - while (len > 0) { - if (text[--len] == s) - return len; - } - return str::npos; - } - /*! - * @ru @brief Найти первое вхождение символа из заданного набора символов. - * @param pattern - строка, задающая набор искомых символов. - * @param offset - позиция начала поиска. - * @return size_t - позицию найденного вхождения, или -1, если не найден. - * @en @brief Find the first occurrence of a character from a given character set. - * @param pattern - a string specifying the set of characters to search for. - * @param offset - search start position. - * @return size_t - position of the found occurrence, or -1 if not found. - */ - constexpr size_t find_first_of(str_piece pattern, size_t offset = 0) const noexcept { - return std::string_view{_str(), _len()}.find_first_of(std::string_view{pattern.str, pattern.len}, offset); - } - /*! - * @ru @brief Найти первое вхождение символа из заданного набора символов. - * @param pattern - строка, задающая набор искомых символов. - * @param offset - позиция начала поиска. - * @return std::pair - пару из позиции найденного вхождения и номера найденного символа в наборе, или -1, если не найден. - * @en @brief Find the first occurrence of a character from a given character set. - * @param pattern - a string specifying the set of characters to search for. - * @param offset - search start position. - * @return std::pair - a pair from the position of the found occurrence and the number of the found character in the set, or -1 if not found. - */ - constexpr std::pair find_first_of_idx(str_piece pattern, size_t offset = 0) const noexcept { - const K* text = _str(); - size_t fnd = std::string_view{text, _len()}.find_first_of(std::string_view{pattern.str, pattern.len}, offset); - return {fnd, fnd == std::string::npos ? fnd : pattern.find(text[fnd]) }; - } - /*! - * @ru @brief Найти первое вхождение символа не из заданного набора символов. - * @param pattern - строка, задающая набор символов. - * @param offset - позиция начала поиска. - * @return size_t - позицию найденного вхождения, или -1, если не найден. - * @en @brief Find the first occurrence of a character not from the given character set. - * @param pattern - a string specifying the character set. - * @param offset - search start position. - * @return size_t - position of the found occurrence, or -1 if not found. - */ - constexpr size_t find_first_not_of(str_piece pattern, size_t offset = 0) const noexcept { - return std::string_view{_str(), _len()}.find_first_not_of(std::string_view{pattern.str, pattern.len}, offset); - } - /*! - * @ru @brief Найти последнее вхождение символа из заданного набора символов. - * @param pattern - строка, задающая набор искомых символов. - * @param offset - позиция начала поиска. - * @return size_t - позицию найденного вхождения, или -1, если не найден. - * @en @brief Find the last occurrence of a character from a given character set. - * @param pattern - a string specifying the set of characters to search for. - * @param offset - search start position. - * @return size_t - position of the found occurrence, or -1 if not found. - */ - constexpr size_t find_last_of(str_piece pattern, size_t offset = str::npos) const noexcept { - return std::string_view{_str(), _len()}.find_last_of(std::string_view{pattern.str, pattern.len}, offset); - } - /*! - * @ru @brief Найти последнее вхождение символа из заданного набора символов. - * @param pattern - строка, задающая набор искомых символов. - * @param offset - позиция начала поиска. - * @return std::pair - пару из позиции найденного вхождения и номера найденного символа в наборе, или -1, если не найден. - * @en @brief Find the last occurrence of a character from a given character set. - * @param pattern - a string specifying the set of characters to search for. - * @param offset - search start position. - * @return std::pair - a pair from the position of the found occurrence and the number of the found character in the set, or -1 if not found. - */ - constexpr std::pair find_last_of_idx(str_piece pattern, size_t offset = str::npos) const noexcept { - const K* text = _str(); - size_t fnd = std::string_view{text, _len()}.find_last_of(std::string_view{pattern.str, pattern.len}, offset); - return {fnd, fnd == std::string::npos ? fnd : pattern.find(text[fnd]) }; - } - /*! - * @ru @brief Найти последнее вхождение символа не из заданного набора символов. - * @param pattern - строка, задающая набор символов. - * @param offset - позиция начала поиска. - * @return size_t - позицию найденного вхождения, или -1, если не найден. - * @en @brief Find the last occurrence of a character not from the given character set. - * @param pattern - a string specifying the character set. - * @param offset - search start position. - * @return size_t - position of the found occurrence, or -1 if not found. - */ - constexpr size_t find_last_not_of(str_piece pattern, size_t offset = str::npos) const noexcept { - return std::string_view{_str(), _len()}.find_last_not_of(std::string_view{pattern.str, pattern.len}, offset); - } - /*! - * @ru @brief Получить подстроку. Работает аналогично operator(), только результат выдает того же типа, к которому применён метод. - * @param from - количество символов от начала строки. Если меньше нуля, отсчитывается от конца строки в сторону начала. - * @param len - количество символов в получаемом "куске". Если меньше или равно нулю, то отсчитать len символов от конца строки. - * @return my_type - подстроку, объект того же типа, к которому применён метод. - * @en @brief Get a substring. Works similarly to operator(), only the result is the same type as the method applied to. - * @param from - number of characters from the beginning of the line. If less than zero, it is counted from the end of the line towards the beginning. - * @param len - the number of characters in the resulting "chunk". If less than or equal to zero, then count len ​​characters from the end of the line. - * @return my_type - a substring, an object of the same type to which the method is applied. - */ - constexpr my_type substr(ptrdiff_t from, ptrdiff_t len = 0) const { // индексация в code units | indexing in code units - return my_type{d()(from, len)}; - } - /*! - * @ru @brief Получить часть строки объектом того же типа, к которому применён метод, аналогично mid. - * @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку. - * @param len - количество символов в получаемом "куске". При выходе за пределы строки вернёт всё до конца строки. - * @return Строку того же типа, к которому применён метод. - * @en @brief Get part of a string with an object of the same type to which the method is applied, similar to mid. - * @param from - number of characters from the beginning of the line. If the string size is exceeded, it will return an empty string. - * @param len - the number of characters in the resulting "chunk". When going beyond the line, it will return everything up to the end of the line. - * @return A string of the same type to which the method is applied. - */ - constexpr my_type str_mid(size_t from, size_t len = -1) const { // индексация в code units | indexing in code units - return my_type{d().mid(from, len)}; - } - /*! - * @ru @brief Преобразовать строку в число заданного типа. - * @tparam T - желаемый тип числа. - * @tparam CheckOverflow - проверять на переполнение. - * @tparam Base - основание счисления числа, от -1 до 36, кроме 1. - * - Если 0: то пытается определить основание по префиксу 0[xX] как 16, 0 как 8, иначе 10. - * - Если -1: то пытается определить основание по префиксам: - * - 0 или 0[oO]: 8 - * - 0[bB]: 2 - * - 0[xX]: 16 - * - в остальных случаях 10. - * @tparam SkipWs - пропускать пробельные символы в начале строки. - * @tparam AllowSign - допустим ли знак '+' перед числом. - * @return T - число, результат преобразования, насколько оно получилось, или 0 при переполнении. - * @en @brief Convert a string to a number of the given type. - * @tparam T - the desired number type. - * @tparam CheckOverflow - check for overflow. - * @tparam Base - the base of the number, from -1 to 36, except 1. - * - If 0: then tries to determine the base by the prefix 0[xX] as 16, 0 as 8, otherwise 10. - * - If -1: then tries to determine the base by prefixes: - * - 0 or 0[oO]: 8 - * - 0[bB]: 2 - * - 0[xX]: 16 - * - in other cases 10. - * @tparam SkipWs - skip whitespace characters at the beginning of the line. - * @tparam AllowSign - whether the '+' sign is allowed before a number. - * @return T - a number, the result of the transformation, how much it turned out, or 0 if it overflows. - */ - template - constexpr T as_int() const noexcept { - auto [res, err, _] = int_convert::to_integer(_str(), _len()); - return err == IntConvertResult::Overflow ? 0 : res; - } - /*! - * @ru @brief Преобразовать строку в число заданного типа. - * @tparam T - желаемый тип числа. - * @tparam CheckOverflow - проверять на переполнение. - * @tparam Base - основание счисления числа, от -1 до 36, кроме 1. - * - Если 0: то пытается определить основание по префиксу 0[xX] как 16, 0 как 8, иначе 10 - * - Если -1: то пытается определить основание по префиксам: - * - 0 или 0[oO]: 8 - * - 0[bB]: 2 - * - 0[xX]: 16 - * - в остальных случаях 10. - * @tparam SkipWs - пропускать пробельные символы в начале строки. Пропускаются все символы с ASCII кодами <= 32. - * @tparam AllowSign - допустим ли знак '+' перед числом. - * @return convert_result - кортеж из полученного числа, успешности преобразования и количестве обработанных символов. - * @en @brief Convert a string to a number of the given type. - * @tparam T - the desired number type. - * @tparam CheckOverflow - check for overflow. - * @tparam Base - the base of the number, from -1 to 36, except 1. - * - If 0: then tries to determine the base by the prefix 0[xX] as 16, 0 as 8, otherwise 10 - * - If -1: then tries to determine the base by prefixes: - * - 0 or 0[oO]: 8 - * - 0[bB]: 2 - * - 0[xX]: 16 - * - in other cases 10. - * @tparam SkipWs - skip whitespace characters at the beginning of the line. All characters with ASCII codes <= 32 are skipped. - * @tparam AllowSign - whether the '+' sign is allowed before a number. - * @return convert_result - a tuple of the received number, the success of the conversion and the number of characters processed. - */ - template - constexpr convert_result to_int() const noexcept { - return int_convert::to_integer(_str(), _len()); + template + R lowered() const { + return R::lowered_from(d()); } /*! * @ru @brief Преобразовать строку в double. @@ -1534,42 +316,6 @@ public: #endif return impl_to_double(ptr, ptr + len); } - /*! - * @ru @brief Преобразовать строку в 16ричной записи в double. Пока работает только для char. - * @return std::optional. - * @en @brief Convert string in hex form to double. - * @return std::optional. - */ - template requires (sizeof(K) == 1) - std::optional to_double_hex() const noexcept { - size_t len = _len(); - const K* ptr = _str(); - if constexpr (SkipWS) { - while (len && uns_type(*ptr) <= ' ') { - len--; - ptr++; - } - } - if (len) { - double d{}; - if (std::from_chars(ptr, ptr + len, d, std::chars_format::hex).ec == std::errc{}) { - return d; - } - } - return {}; - } - /*! - * @ru @brief Преобразовать строку в целое число. - * @tparam T - тип числа, выводится из аргумента. - * @param t - переменная, в которую записывается результат. - * @en @brief Convert a string to an integer. - * @tparam T - number type, inferred from the argument. - * @param t - the variable into which the result is written. - */ - template - constexpr void as_number(T& t) const { - t = as_int(); - } /*! * @ru @brief Преобразовать строку в double. * @param t - переменная, в которую записывается результат. @@ -1580,632 +326,21 @@ public: auto res = to_double(); t = res ? *res : std::nan("0"); } - - template - constexpr T splitf(const K* delimeter, size_t lenDelimeter, const Op& beforeFunc, size_t offset) const { - size_t mylen = _len(); - std::conditional_t, char, T> results; - str_piece me{_str(), mylen}; - for (int i = 0;; i++) { - size_t beginOfDelim = find(delimeter, lenDelimeter, offset); - if (beginOfDelim == str::npos) { - str_piece last{me.symbols() + offset, me.length() - offset}; - if constexpr (std::is_invocable_v) { - beforeFunc(last); - } - if constexpr (requires { results.emplace_back(last); }) { - if (last.is_same(me)) { - // Пробуем положить весь объект. - // Try to put the entire object. - results.emplace_back(d()); - } else { - results.emplace_back(last); - } - } else if constexpr (requires { results.push_back(last); }) { - if (last.is_same(me)) { - // Пробуем положить весь объект. - // Try to put the entire object. - results.push_back(d()); - } else { - results.push_back(last); - } - } else if constexpr (requires {results[i] = last;} && requires{std::size(results);}) { - if (i < std::size(results)) { - if (last.is_same(me)) { - // Пробуем положить весь объект. - // Try to put the entire object. - results[i] = d(); - } else - results[i] = last; - } - } - break; - } - str_piece piece{me.symbols() + offset, beginOfDelim - offset}; - if constexpr (std::is_invocable_v) { - beforeFunc(piece); - } - if constexpr (requires { results.emplace_back(piece); }) { - results.emplace_back(piece); - } else if constexpr (requires { results.push_back(piece); }) { - results.push_back(piece); - } else if constexpr (requires { results[i] = piece; } && requires{std::size(results);}) { - if (i < std::size(results)) { - results[i] = piece; - if (i == results.size() - 1) { - break; - } - } - } - offset = beginOfDelim + lenDelimeter; - } - if constexpr (!std::is_same_v) { - return results; - } - } /*! - * @ru @brief Разделить строку на части по заданному разделителю, с возможным применением функтора к каждой подстроке. - * @tparam T - тип контейнера для складывания подстрок. - * @param delimeter - подстрока разделитель. - * @param beforeFunc - функтор для применения к найденным подстрокам, перед помещением их в результат. - * @param offset - позиция начала поиска разделителя. - * @return T - результат. - * @details Для каждой найденной подстроки, если функтор может принять её, вызывается функтор, и подстрока - * присваивается результату функтора. Далее подстрока пытается добавиться в результат, - * вызывая один из его методов - `emplace_back`, `push_back`, `operator[]`. Если ни одного этого метода - * нет, ничего не делается, только вызов функтора. - * `operator[]` пытается применится, если у результата можно получить размер через `std::size` и - * мы не выходим за этот размер. - * При этом, если найденная подстрока получается совпадающей со всей строкой - в результат пытается - * поместить не подстроку, а весь объект строки, что позволяет, например, эффективно копировать sstring. - * @en @brief Split a string into parts at a given delimiter, possibly applying a functor to each substring. - * @tparam T - type of container for folding substrings. - * @param delimeter - substring delimiter. - * @param beforeFunc - a functor to apply to the found substrings, before placing them in the result. - * @param offset - the position to start searching for the separator. - * @return T - result. - * @details For each substring found, if the functor can accept it, the functor is called, and the substring - * is assigned to the result of the functor. Next, the substring tries to be added to the result, - * calling one of its methods - `emplace_back`, `push_back`, `operator[]`. If none of this method - * no, nothing is done, just calling the functor. - * `operator[]` tries to apply if the result can have a size via `std::size` and - * we do not exceed this size. - * At the same time, if the found substring turns out to match the entire string, the result is attempted - * place not a substring, but the entire string object, which allows, for example, to effectively copy sstring. + * @ru @brief Преобразовать строку в целое число. + * @details Так как `as_number(double& t)` перекрывает видимость `as_number` из базового класса, + * придётся добавить его ещё раз. + * @tparam T - тип числа, выводится из аргумента. + * @param t - переменная, в которую записывается результат. + * @en @brief Convert a string to an integer. + * @details Since `as_number(double& t)` overrides the visibility of `as_number` from the base class, + * will have to add it again. + * @tparam T - number type, inferred from the argument. + * @param t - the variable into which the result is written. */ - template - constexpr T splitf(str_piece delimeter, const Op& beforeFunc, size_t offset = 0) const { - return splitf(delimeter.symbols(), delimeter.length(), beforeFunc, offset); - } - /*! - * @ru @brief Разделить строку на подстроки по заданному разделителю. - * @tparam T - тип контейнера для результата. - * @param delimeter - разделитель. - * @param offset - позиция начала поиска разделителя. - * @return T - контейнер с результатом. - * @en @brief Split a string into substrings using a given delimiter. - * @tparam T - container type for the result. - * @param delimeter - delimiter. - * @param offset - the position to start searching for the separator. - * @return T - container with the result. - */ - template - constexpr T split(str_piece delimeter, size_t offset = 0) const { - return splitf(delimeter.symbols(), delimeter.length(), 0, offset); - } - /*! - * @ru @brief Получить объект `Splitter` по заданному разделителю, который позволяет последовательно - * получать подстроки методом `next()`, пока `is_done()` false. - * @param delimeter - разделитель. - * @return Splitter. - * @en @brief Retrieve a `Splitter` object by the given splitter, which allows sequential - * get substrings using the `next()` method while `is_done()` is false. - * @param delimeter - delimiter. - * @return Splitter. - */ - constexpr Splitter splitter(str_piece delimeter) const; - - // Начинается ли эта строка с указанной подстроки - // Does this string start with the specified substring - constexpr bool starts_with(const K* prefix, size_t l) const noexcept { - return _len() >= l && 0 == traits::compare(_str(), prefix, l); - } - /*! - * @ru @brief Начинается ли строка с заданной подстроки. - * @param prefix - подстрока. - * @en @brief Whether the string begins with the given substring. - * @param prefix - substring. - */ - constexpr bool starts_with(str_piece prefix) const noexcept { - return starts_with(prefix.symbols(), prefix.length()); - } - - constexpr bool starts_with_ia(const K* prefix, size_t len) const noexcept { - size_t myLen = _len(); - if (myLen < len) { - return false; - } - const K* ptr1 = _str(); - while (len--) { - K s1 = *ptr1++, s2 = *prefix++; - if (s1 == s2) - continue; - if (makeAsciiLower(s1) != makeAsciiLower(s2)) - return false; - } - return true; - } - /*! - * @ru @brief Начинается ли строка с заданной подстроки без учёта регистра ASCII символов. - * @param prefix - подстрока. - * @en @brief Whether the string begins with the given substring in a case-insensitive ASCII character. - * @param prefix - substring. - */ - constexpr bool starts_with_ia(str_piece prefix) const noexcept { - return starts_with_ia(prefix.symbols(), prefix.length()); - } - // Начинается ли эта строка с указанной подстроки без учета unicode регистра - // Does this string begin with the specified substring, insensitive to unicode case - bool starts_with_iu(const K* prefix, size_t len) const noexcept { - return _len() >= len && 0 == uni::compareiu(_str(), len, prefix, len); - } - /*! - * @ru @brief Начинается ли строка с заданной подстроки без учёта регистра Unicode символов первой плоскости (<0xFFFF). - * @param prefix - подстрока. - * @en @brief Whether the string starts with the given substring, case-insensitive Unicode characters of the first plane (<0xFFFF). - * @param prefix - substring. - */ - bool starts_with_iu(str_piece prefix) const noexcept { - return starts_with_iu(prefix.symbols(), prefix.length()); - } - - // Является ли эта строка началом указанной строки - // Is this string the beginning of the specified string - constexpr bool prefix_in(const K* text, size_t len) const noexcept { - size_t myLen = _len(); - if (myLen > len) - return false; - return !myLen || 0 == traits::compare(text, _str(), myLen); - } - /*! - * @ru @brief Является ли эта строка началом другой строки. - * @param text - другая строка. - * @en @brief Whether this string is the beginning of another string. - * @param text - another string. - */ - constexpr bool prefix_in(str_piece text) const noexcept { - return prefix_in(text.symbols(), text.length()); - } - // Заканчивается ли строка указанной подстрокой - // Does the string end with the specified substring - constexpr bool ends_with(const K* suffix, size_t len) const noexcept { - size_t myLen = _len(); - return len <= myLen && traits::compare(_str() + myLen - len, suffix, len) == 0; - } - /*! - * @ru @brief Заканчивается ли строка указанной подстрокой. - * @param suffix - подстрока. - * @en @brief Whether the string ends with the specified substring. - * @param suffix - substring. - */ - constexpr bool ends_with(str_piece suffix) const noexcept { - return ends_with(suffix.symbols(), suffix.length()); - } - // Заканчивается ли строка указанной подстрокой без учета регистра ASCII - // Whether the string ends with the specified substring, case insensitive ASCII - constexpr bool ends_with_ia(const K* suffix, size_t len) const noexcept { - size_t myLen = _len(); - if (myLen < len) { - return false; - } - const K* ptr1 = _str() + myLen - len; - while (len--) { - K s1 = *ptr1++, s2 = *suffix++; - if (s1 == s2) - continue; - if (makeAsciiLower(s1) != makeAsciiLower(s2)) - return false; - } - return true; - } - /*! - * @ru @brief Заканчивается ли строка указанной подстрокой без учёта регистра ASCII символов. - * @param suffix - подстрока. - * @en @brief Whether the string ends with the specified substring in a case-insensitive ASCII character. - * @param suffix - substring. - */ - constexpr bool ends_with_ia(str_piece suffix) const noexcept { - return ends_with_ia(suffix.symbols(), suffix.length()); - } - // Заканчивается ли строка указанной подстрокой без учета регистра UNICODE - // Whether the string ends with the specified substring, case insensitive UNICODE - constexpr bool ends_with_iu(const K* suffix, size_t len) const noexcept { - size_t myLen = _len(); - return myLen >= len && 0 == uni::compareiu(_str() + myLen - len, len, suffix, len); - } - /*! - * @ru @brief Заканчивается ли строка указанной подстрокой без учёта регистра Unicode символов первой плоскости (<0xFFFF). - * @param suffix - подстрока. - * @en @brief Whether the string ends with the specified substring, case-insensitive Unicode characters of the first plane (<0xFFFF). - * @param suffix - substring. - */ - constexpr bool ends_with_iu(str_piece suffix) const noexcept { - return ends_with_iu(suffix.symbols(), suffix.length()); - } - /*! - * @ru @brief Содержит ли строка только ASCII символы. - * @en @brief Whether the string contains only ASCII characters. - */ - constexpr bool is_ascii() const noexcept { - if (_is_empty()) - return true; - const int sl = ascii_mask::WIDTH; - const size_t mask = ascii_mask::VALUE; - size_t len = _len(); - const uns_type* ptr = reinterpret_cast(_str()); - if constexpr (sl > 1) { - const size_t roundMask = sizeof(size_t) - 1; - while (len >= sl && (reinterpret_cast(ptr) & roundMask) != 0) { - if (*ptr++ > 127) - return false; - len--; - } - while (len >= sl) { - if (*reinterpret_cast(ptr) & mask) - return false; - ptr += sl; - len -= sl; - } - } - while (len--) { - if (*ptr++ > 127) - return false; - } - return true; - } - /*! - * @ru @brief Получить копию строки в верхнем регистре ASCII символов. - * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. - * @return R - копию строки в верхнем регистре. - * @en @brief Get a copy of the string in uppercase ASCII characters. - * @tparam R - the desired string type, by default the same whose method was called. - * @return R - uppercase copy of the string. - */ - template - R upperred_only_ascii() const { - return R::upperred_only_ascii_from(d()); - } - /*! - * @ru @brief Получить копию строки в нижнем регистре ASCII символов. - * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. - * @return R - копию строки в нижнем регистре. - * @en @brief Get a copy of the string in lowercase ASCII characters. - * @tparam R - the desired string type, by default the same whose method was called. - * @return R - lowercase copy of the string. - */ - template - R lowered_only_ascii() const { - return R::lowered_only_ascii_from(d()); - } - /*! - * @ru @brief Получить копию строки в верхнем регистре Unicode символов первой плоскости (<0xFFFF). - * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. - * @return R - копию строки в верхнем регистре. - * @en @brief Get a copy of the string in upper case Unicode characters of the first plane (<0xFFFF). - * @tparam R - the desired string type, by default the same whose method was called. - * @return R - uppercase copy of the string. - */ - template - R upperred() const { - return R::upperred_from(d()); - } - /*! - * @ru @brief Получить копию строки в нижнем регистре Unicode символов первой плоскости (<0xFFFF). - * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. - * @return R - копию строки в нижнем регистре. - * @en @brief Get a copy of the string in lowercase Unicode characters of the first plane (<0xFFFF). - * @tparam R - the desired string type, by default the same whose method was called. - * @return R - lowercase copy of the string. - */ - template - R lowered() const { - return R::lowered_from(d()); - } - /*! - * @ru @brief Получить копию строки с заменёнными вхождениями подстрок. - * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. - * @param pattern - искомая подстрока. - * @param repl - строка, на которую заменять. - * @param offset - начальная позиция поиска. - * @param maxCount - максимальное количество замен, 0 - без ограничений. - * @return R строку заданного типа, по умолчанию того же, чей метод вызывался. - * @en @brief Get a copy of the string with occurrences of substrings replaced. - * @tparam R - the desired string type, by default the same whose method was called. - * @param pattern - the substring to search for. - * @param repl - the string to replace with. - * @param offset - starting position of the search. - * @param maxCount - maximum number of replacements, 0 - no restrictions. - * @return R a string of the given type, by default the same whose method was called. - */ - template - R replaced(str_piece pattern, str_piece repl, size_t offset = 0, size_t maxCount = 0) const { - return R::replaced_from(d(), pattern, repl, offset, maxCount); - } - - /*! - * @ru @brief Получить строковое выражение, которое выдает строку с заменёнными подстроками, заданными строковыми литералами. - * @param pattern - строковый литерал, подстрока, которую меняем. - * @param repl - строковый литерал, подстрока, на которую меняем. - * @return строковое выражение, заменяющее подстроки. - * @en @brief Get a string expression that produces a string with replaced substrings given by string literals. - * @param pattern - string literal, substring to be changed. - * @param repl - string literal, substring to change to. - * @return a string expression that replaces substrings. - */ - template::Count, typename M, size_t L = const_lit_for::Count> - constexpr expr_replaces replace_init(T&& pattern, M&& repl) const { - return expr_replaces{d(), pattern, repl}; - } - - template From> - constexpr static my_type make_trim_op(const From& from, const auto& opTrim) { - str_piece sfrom = from, newPos = opTrim(sfrom); - return newPos.is_same(sfrom) ? my_type{from} : my_type{newPos}; - } - template From> - constexpr static my_type trim_static(const From& from) { - return make_trim_op(from, trim_operator(-1), true>{}); - } - - template::Count, StrType From> - requires is_const_pattern - constexpr static my_type trim_static(const From& from, T&& pattern) { - return make_trim_op(from, trim_operator{pattern}); - } - - template From> - constexpr static my_type trim_static(const From& from, str_piece pattern) { - return make_trim_op(from, trim_operator{{pattern}}); - } - /*! - * @ru @brief Получить строку с удалением пробельных символов слева и справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @return R - строка, с удалёнными в начале и в конце пробельными символами. - * @en @brief Get a string with whitespace removed on the left and right. - * @tparam R - desired string type, default simple_str. - * @return R - a string with whitespace characters removed at the beginning and end. - */ - template - constexpr R trimmed() const { - return R::template trim_static(d()); - } - /*! - * @ru @brief Получить строку с удалением пробельных символов слева. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @return R - строка, с удалёнными в начале пробельными символами. - * @en @brief Get a string with whitespace removed on the left. - * @tparam R - desired string type, default simple_str. - * @return R - a string with leading whitespace characters removed. - */ - template - R trimmed_left() const { - return R::template trim_static(d()); - } - /*! - * @ru @brief Получить строку с удалением пробельных символов справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @return R - строка, с удалёнными в конце пробельными символами. - * @en @brief Get a string with whitespace removed on the right. - * @tparam R - desired string type, default simple_str. - * @return R - a string with whitespace characters removed at the end. - */ - template - R trimmed_right() const { - return R::template trim_static(d()); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных строковым литералом, слева и справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. - * @return R - строка, с удалёнными в начале и в конце символами, содержащимися в литерале. - * @en @brief Get a string with the characters specified by the string literal removed from the left and right. - * @tparam R - desired string type, default simple_str. - * @param pattern is a string literal specifying the characters that will be trimmed. - * @return R - a string with the characters contained in the literal removed at the beginning and at the end. - */ - template::Count> - requires is_const_pattern - R trimmed(T&& pattern) const { - return R::template trim_static(d(), pattern); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных строковым литералом, слева. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. - * @return R - строка, с удалёнными в начале символами, содержащимися в литерале. - * @en @brief Get a string with the characters specified by the string literal removed from the left. - * @tparam R - desired string type, default simple_str. - * @param pattern is a string literal specifying the characters that will be trimmed. - * @return R - a string with the characters contained in the literal removed at the beginning. - */ - template::Count> - requires is_const_pattern - R trimmed_left(T&& pattern) const { - return R::template trim_static(d(), pattern); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных строковым литералом, справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. - * @return R - строка, с удалёнными в конце символами, содержащимися в литерале. - * @en @brief Get a string with the characters specified by the string literal removed from the right. - * @tparam R - desired string type, default simple_str. - * @param pattern is a string literal specifying the characters that will be trimmed. - * @return R - a string with characters contained in the literal removed at the end. - */ - template::Count> - requires is_const_pattern - R trimmed_right(T&& pattern) const { - return R::template trim_static(d(), pattern); - } - // Триминг по символам в литерале и пробелам - // Trimming by characters in literal and spaces - - /*! - * @ru @brief Получить строку с удалением символов, заданных строковым литералом, а также - * пробельных символов, слева и справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. - * @return R - строка, с удалёнными в начале и в конце символами, содержащимися в литерале - * и пробельными символами. - * @en @brief Get a string with the characters specified by the string literal removed, as well as - * whitespace characters, left and right. - * @tparam R - desired string type, default simple_str. - * @param pattern is a string literal specifying the characters that will be trimmed. - * @return R - a string with the characters contained in the literal removed at the beginning and at the end - * and whitespace characters. - */ - template::Count> - requires is_const_pattern - R trimmed_with_spaces(T&& pattern) const { - return R::template trim_static(d(), pattern); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных строковым литералом, а также - * пробельных символов, слева. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. - * @return R - строка, с удалёнными в начале символами, содержащимися в литерале - * и пробельными символами. - * @en @brief Get a string with the characters specified by the string literal removed, as well as - * whitespace characters, left. - * @tparam R - desired string type, default simple_str. - * @param pattern is a string literal specifying the characters that will be trimmed. - * @return R - a string with the characters contained in the literal removed at the beginning - * and whitespace characters. - */ - template::Count> - requires is_const_pattern - R trimmed_left_with_spaces(T&& pattern) const { - return R::template trim_static(d(), pattern); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных строковым литералом, а также - * пробельных символов, справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. - * @return R - строка, с удалёнными в конце символами, содержащимися в литерале - * и пробельными символами. - * @en @brief Get a string with the characters specified by the string literal removed, as well as - * whitespace characters, right. - * @tparam R - desired string type, default simple_str. - * @param pattern is a string literal specifying the characters that will be trimmed. - * @return R - a string with characters contained in the literal removed at the end - * and whitespace characters. - */ - template::Count> - requires is_const_pattern - R trimmed_right_with_spaces(T&& pattern) const { - return R::template trim_static(d(), pattern); - } - // Триминг по динамическому источнику - // Trimming by dynamic source - - /*! - * @ru @brief Получить строку с удалением символов, заданных другой строкой, слева и справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строка, задающая символы, которые будут обрезаться. - * @return R - строка, с удалёнными в начале и в конце символами, содержащимися в шаблоне. - * @en @brief Get a string with characters specified by another string removed, left and right. - * @tparam R - desired string type, default simple_str. - * @param pattern - a string specifying the characters that will be trimmed. - * @return R - a string with the characters contained in the pattern removed at the beginning and at the end. - */ - template - R trimmed(str_piece pattern) const { - return R::template trim_static(d(), pattern); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных другой строкой, слева. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строка, задающая символы, которые будут обрезаться. - * @return R - строка, с удалёнными в начале символами, содержащимися в шаблоне. - * @en @brief Get a string with characters specified by another string removed from the left. - * @tparam R - desired string type, default simple_str. - * @param pattern - a string specifying the characters that will be trimmed. - * @return R - a string with the characters contained in the pattern removed at the beginning. - */ - template - R trimmed_left(str_piece pattern) const { - return R::template trim_static(d(), pattern); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных другой строкой, справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строка, задающая символы, которые будут обрезаться. - * @return R - строка, с удалёнными в конце символами, содержащимися в шаблоне. - * @en @brief Get a string with characters specified by another string removed to the right. - * @tparam R - desired string type, default simple_str. - * @param pattern - a string specifying the characters that will be trimmed. - * @return R - a string with characters contained in the pattern removed at the end. - */ - template - R trimmed_right(str_piece pattern) const { - return R::template trim_static(d(), pattern); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных другой строкой, а также - * пробельных символов, слева и справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строка, задающая символы, которые будут обрезаться. - * @return R - строка, с удалёнными в начале и в конце символами, содержащимися в шаблоне - * и пробельными символами. - * @en @brief Get a string, removing characters specified by another string, as well as - * whitespace characters, left and right. - * @tparam R - desired string type, default simple_str. - * @param pattern - a string specifying the characters that will be trimmed. - * @return R - a string with the characters contained in the pattern removed at the beginning and at the end - * and whitespace characters. - */ - template - R trimmed_with_spaces(str_piece pattern) const { - return R::template trim_static(d(), pattern); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных другой строкой, а также - * пробельных символов, слева. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строка, задающая символы, которые будут обрезаться. - * @return R - строка, с удалёнными в начале символами, содержащимися в шаблоне - * и пробельными символами. - * @en @brief Get a string, removing characters specified by another string, as well as - * whitespace characters, left. - * @tparam R - desired string type, default simple_str. - * @param pattern - a string specifying the characters that will be trimmed. - * @return R - a string with the characters contained in the pattern removed at the beginning - * and whitespace characters. - */ - template - R trimmed_left_with_spaces(str_piece pattern) const { - return R::template trim_static(d(), pattern); - } - /*! - * @ru @brief Получить строку с удалением символов, заданных другой строкой, а также - * пробельных символов, справа. - * @tparam R - желаемый тип строки, по умолчанию simple_str. - * @param pattern - строка, задающая символы, которые будут обрезаться. - * @return R - строка, с удалёнными в конце символами, содержащимися в шаблоне - * и пробельными символами. - * @en @brief Get a string, removing characters specified by another string, as well as - * whitespace characters, right. - * @tparam R - desired string type, default simple_str. - * @param pattern - a string specifying the characters that will be trimmed. - * @return R - a string with characters contained in the template removed at the end - * and whitespace characters. - */ - template - R trimmed_right_with_spaces(str_piece pattern) const { - return R::template trim_static(d(), pattern); + template + constexpr void as_number(T& t) const { + base::as_number(t); } }; @@ -2238,7 +373,9 @@ struct simple_str : str_algs, simple_str, false> { const symb_type* str; size_t len; - simple_str() = default; + constexpr simple_str() = default; + + constexpr simple_str(str_src src) : str(src.str), len(src.len){} /*! * @ru @brief Конструктор из строкового литерала. @@ -2252,15 +389,16 @@ struct simple_str : str_algs, simple_str, false> { */ constexpr simple_str(const K* p, size_t l) noexcept : str(p), len(l) {} /*! - * @ru @brief Конструктор, позволяющий инициализировать объектами std::string, и std::string_view - * при условии, что они lvalue, то есть не временные. - * @en @brief Constructor that allows you to initialize std::string and std::string_view objects - * provided that they are lvalue, that is, not temporary. + *@ru @brief Конструктор из std::basic_string. + *@en @brief Constructor from std::basic_string. */ - template - requires(std::is_same_v&> || std::is_same_v&> - || std::is_same_v&> || std::is_same_v&>) - constexpr simple_str(S&& s) noexcept : str(s.data()), len(s.length()) {} + template + constexpr simple_str(const std::basic_string, A>& s) noexcept : str(s.data()), len(s.length()) {} + /*! + *@ru @brief Конструктор из std::basic_string_view. + *@en @brief Constructor from std::basic_string_view. + */ + constexpr simple_str(const std::basic_string_view>& s) noexcept : str(s.data()), len(s.length()) {} /*! * @ru @brief Получить длину строки. * @en @brief Get the length of the string. @@ -2338,6 +476,11 @@ struct simple_str : str_algs, simple_str, false> { } }; +template +struct simple_str_selector { + using type = simple_str; +}; + /*! * @ru @brief Класс, заявляющий, что ссылается на нуль-терминированную строку. * @tparam K - тип символов строки. @@ -2363,7 +506,6 @@ struct simple_str_nt : simple_str, null_terminated> { using symb_type = K; using my_type = simple_str_nt; using base = simple_str; - using base::base; constexpr static const K empty_string[1] = {0}; @@ -2384,32 +526,37 @@ struct simple_str_nt : simple_str, null_terminated> { * the length of the C-string was calculated only once and was not subsequently lost accidentally when transferred between different * types of string objects. */ - template requires std::is_same_v>>, K> + template requires is_one_of_type, const K*, K*>::value constexpr explicit simple_str_nt(T&& p) noexcept { base::len = p ? static_cast(base::traits::length(p)) : 0; base::str = base::len ? p : empty_string; } /*! - * @ru @brief Конструктор, позволяющий инициализировать объектами std::string, и std::string_view - * при условии, что они lvalue, то есть не временные. - * @en @brief Constructor that allows you to initialize std::string and std::string_view objects - * provided that they are lvalue, that is, not temporary. + * @ru @brief Конструктор из строкового литерала. + * @en @brief Constructor from a string literal. */ - template - requires(std::is_same_v || std::is_same_v - || std::is_same_v || std::is_same_v) - constexpr simple_str_nt(S&& s) noexcept : base(s) {} + template::Count> + constexpr simple_str_nt(T&& v) noexcept : base(std::forward(v)) {} + + /*! + * @ru @brief Конструктор из указателя и длины. + * @en @brief Constructor from pointer and length. + */ + constexpr simple_str_nt(const K* p, size_t l) noexcept : base(p, l) {} + + template T> + constexpr simple_str_nt(T&& t) { + base::str = t.symbols(); + base::len = t.length(); + } + /*! + *@ru @brief Конструктор из std::basic_string. + *@en @brief Constructor from std::basic_string. + */ + template + constexpr simple_str_nt(const std::basic_string, A>& s) noexcept : base(s) {} static const my_type empty_str; - /*! - * @ru @brief Оператор преобразования в нуль-терминированную C-строку. - * @return const K* - указатель на начало строки. - * @en @brief Conversion operator to a null-terminated C string. - * @return const K* - pointer to the beginning of the line. - */ - constexpr operator const K*() const noexcept { - return base::str; - } /*! * @ru @brief Получить нуль-терминированную строку, сдвинув начало на заданное количество символов. * @param from - на сколько символов сдвинуть начало строки. @@ -2429,174 +576,20 @@ struct simple_str_nt : simple_str, null_terminated> { template inline const simple_str_nt simple_str_nt::empty_str{simple_str_nt::empty_string, 0}; +template +using Splitter = SplitterBase>; + using ssa = simple_str; +using ssb = simple_str; using ssw = simple_str; using ssu = simple_str; using ssuu = simple_str; using stra = simple_str_nt; +using strb = simple_str_nt; using strw = simple_str_nt; using stru = simple_str_nt; using struu = simple_str_nt; -/*! - * @ru @brief Класс для последовательного получения подстрок по заданному разделителю. - * @tparam K - тип символов. - * @en @brief Class for sequentially obtaining substrings by a given delimiter. - * @tparam K - character type. - */ -template -class Splitter { - simple_str text_; - simple_str delim_; - -public: - constexpr Splitter(simple_str text, simple_str delim) : text_(text), delim_(delim) {} - /*! - * @ru @brief Узнать, не закончились ли подстроки. - * @en @brief Find out if substrings are running out. - */ - constexpr bool is_done() const { - return text_.length() == str::npos; - } - /*! - * @ru @brief Получить следующую подстроку. - * @return simple_str. - * @en @brief Get the next substring. - * @return simple_str. - */ - constexpr simple_str next() { - if (!text_.length()) { - auto ret = text_; - text_.str++; - text_.len--; - return ret; - } else if (text_.length() == str::npos) { - return {nullptr, 0}; - } - size_t pos = text_.find(delim_), next = 0; - if (pos == str::npos) { - pos = text_.length(); - next = pos + 1; - } else { - next = pos + delim_.length(); - } - simple_str result{text_.str, pos}; - text_.str += next; - text_.len -= next; - return result; - } -}; - -template -constexpr Splitter str_algs::splitter(StrRef delimeter) const { - return Splitter{*this, delimeter}; -} - -template -struct CheckSpaceTrim { - constexpr bool is_trim_spaces(K s) const { - return s == ' ' || (s >= 9 && s <= 13); // || isspace(s); - } -}; -template -struct CheckSpaceTrim { - constexpr bool is_trim_spaces(K) const { - return false; - } -}; - -template -struct CheckSymbolsTrim { - simple_str symbols; - constexpr bool is_trim_symbols(K s) const { - return symbols.len != 0 && simple_str::traits::find(symbols.str, symbols.len, s) != nullptr; - } -}; - -template -struct CheckConstSymbolsTrim { - const const_lit_to_array symbols; - - template::Count> requires (M == N + 1) - constexpr CheckConstSymbolsTrim(T&& s) : symbols(std::forward(s)) {} - - constexpr bool is_trim_symbols(K s) const noexcept { - return symbols.contain(s); - } -}; - -template -struct CheckConstSymbolsTrim { - constexpr bool is_trim_symbols(K) const { - return false; - } -}; - -template -struct SymbSelector { - using type = CheckConstSymbolsTrim; -}; - -template -struct SymbSelector { - using type = CheckSymbolsTrim; -}; - -template -struct SymbSelector(-1)> { - using type = CheckConstSymbolsTrim; -}; - -template -struct trim_operator : SymbSelector::type, CheckSpaceTrim { - constexpr bool isTrim(K s) const { - return CheckSpaceTrim::is_trim_spaces(s) || SymbSelector::type::is_trim_symbols(s); - } - constexpr simple_str operator()(simple_str from) const { - if constexpr ((S & TrimSides::TrimLeft) != 0) { - while (from.len) { - if (isTrim(*from.str)) { - from.str++; - from.len--; - } else - break; - } - } - if constexpr ((S & TrimSides::TrimRight) != 0) { - const K* back = from.str + from.len - 1; - while (from.len) { - if (isTrim(*back)) { - back--; - from.len--; - } else - break; - } - } - return from; - } -}; - -template -using SimpleTrim = trim_operator; - -using trim_w = SimpleTrim; -using trim_a = SimpleTrim; -using triml_w = SimpleTrim; -using triml_a = SimpleTrim; -using trimr_w = SimpleTrim; -using trimr_a = SimpleTrim; - -template::Count> - requires is_const_pattern -constexpr inline auto trimOp(T&& pattern) { - return trim_operator{pattern}; -} - -template -constexpr inline auto trimOp(simple_str pattern) { - return trim_operator{pattern}; -} - template struct utf_convert_selector; @@ -2722,6 +715,28 @@ struct utf_convert_selector { } }; +template<> +struct utf_convert_selector { + static size_t need_len(const u8s* src, size_t srcLen) { + return srcLen; + } + static size_t convert(const u8s* src, size_t srcLen, ubs* dest) { + ch_traits::copy((u8s*)dest, src, srcLen); + return srcLen; + } +}; + +template<> +struct utf_convert_selector { + static size_t need_len(const ubs* src, size_t srcLen) { + return srcLen; + } + static size_t convert(const ubs* src, size_t srcLen, u8s* dest) { + ch_traits::copy(dest, (const u8s*)src, srcLen); + return srcLen; + } +}; + /*! * @ru @brief Базовый класс для строк, могущих конвертироваться из другого типа символов. * @tparam K - тип символов. @@ -2777,12 +792,14 @@ public: * @tparam To - What type of string we convert to. */ template requires (!std::is_same_v) -struct expr_utf { +struct expr_utf : expr_to_std_string> { using symb_type = To; using worker = utf_convert_selector; simple_str source_; + constexpr expr_utf(simple_str source) : source_(source){} + size_t length() const noexcept { return worker::need_len(source_.symbols(), source_.length()); } @@ -2804,8 +821,8 @@ struct expr_utf { * @param from - the string from which to convert. */ template requires (!std::is_same_v) -auto e_utf(simple_str from) { - return expr_utf{from}; +expr_utf e_utf(simple_str from) { + return {from}; } /*! @@ -2975,10 +992,11 @@ protected: * allocates memory of the required size, and calls the `place()` method to allocate * result in buffer. */ - constexpr void init_str_expr(const StrExprForType auto& expr) { + template A> + constexpr void init_str_expr(const A& expr) { size_t len = expr.length(); if (len) - *expr.place(d().init(len)) = 0; + *expr.place((typename A::symb_type*)d().init(len)) = 0; else d().create_empty(); } @@ -3140,15 +1158,15 @@ public: /*! * @ru @brief Конкатенация строк из контейнера в одну строку. * @param strings - контейнер со строками. - * @param delimeter - разделитель, добавляемый между строками. + * @param delimiter - разделитель, добавляемый между строками. * @param tail - добавить разделитель после последней строки. * @param skip_empty - пропускать пустые строки без добавления разделителя. * @param ...args - параметры для инициализации аллокатора. * @details Функция служит для слияния контейнера строк в одну строку с разделителем. * ```cpp * std::vector strings = get_strings(); - * ssa delim = get_current_delimeter(); - * auto line = lstringa<200>::join(strings, delimeter); + * ssa delim = get_current_delimiter(); + * auto line = lstringa<200>::join(strings, delimiter); * ``` * Стоит отметить, что при заранее известном разделителе лучше пользоваться строковым выражением `e_join`. * ```cpp @@ -3158,15 +1176,15 @@ public: * В этом случае компилятор может лучше оптимизировать код слияния строк. * @en @brief Concatenate strings from the container into one string. * @param strings - container with strings. - * @param delimeter - delimiter added between lines. + * @param delimiter - delimiter added between lines. * @param tail - add a separator after the last line. * @param skip_empty - skip empty lines without adding a separator. * @param ...args - parameters for initializing the allocator. * @details The function is used to merge a container of strings into one delimited string. * ```cpp * std::vector strings = get_strings(); - * ssa delim = get_current_delimeter(); - * auto line = lstringa<200>::join(strings, delimeter); + * ssa delim = get_current_delimiter(); + * auto line = lstringa<200>::join(strings, delimiter); * ``` * It is worth noting that if the separator is known in advance, it is better to use the string expression `e_join`. * ```cpp @@ -3177,10 +1195,10 @@ public: */ template requires std::is_constructible_v - static my_type join(const T& strings, s_str delimeter, bool tail = false, bool skip_empty = false, Args&&... args) { + static my_type join(const T& strings, s_str delimiter, bool tail = false, bool skip_empty = false, Args&&... args) { my_type result(std::forward(args)...); if (strings.size()) { - if (strings.size() == 1 && (!delimeter.length() || !tail)) { + if (strings.size() == 1 && (!delimiter.length() || !tail)) { result = strings.front(); } else { size_t commonLen = 0; @@ -3188,27 +1206,27 @@ public: size_t len = t.length(); if (len > 0 || !skip_empty) { if (commonLen > 0) { - commonLen += delimeter.len; + commonLen += delimiter.len; } commonLen += len; } } - commonLen += (tail && delimeter.len > 0 && (commonLen > 0 || (!skip_empty && strings.size() > 0))? delimeter.len : 0); + commonLen += (tail && delimiter.len > 0 && (commonLen > 0 || (!skip_empty && strings.size() > 0))? delimiter.len : 0); if (commonLen) { K* ptr = result.init(commonLen); K* write = ptr; for (const auto& t: strings) { size_t copyLen = t.length(); - if (delimeter.len > 0 && write != ptr && (copyLen || !skip_empty)) { - ch_traits::copy(write, delimeter.str, delimeter.len); - write += delimeter.len; + if (delimiter.len > 0 && write != ptr && (copyLen || !skip_empty)) { + ch_traits::copy(write, delimiter.str, delimiter.len); + write += delimiter.len; } ch_traits::copy(write, t.symbols(), copyLen); write += copyLen; } - if (delimeter.len > 0 && tail && (write != ptr || (!skip_empty && strings.size() > 0))) { - ch_traits::copy(write, delimeter.str, delimeter.len); - write += delimeter.len; + if (delimiter.len > 0 && tail && (write != ptr || (!skip_empty && strings.size() > 0))) { + ch_traits::copy(write, delimiter.str, delimiter.len); + write += delimiter.len; } *write = 0; } else { @@ -3314,13 +1332,13 @@ concept Allocatorable = requires(A& a, size_t size, void* void_ptr) { struct printf_selector { template requires (is_one_of_std_char_v) static int snprintf(K* buffer, size_t count, const K* format, T&&... args) { - if constexpr (std::is_same_v) { + if constexpr (sizeof(K) == 1) { #ifndef _WIN32 - return std::snprintf(buffer, count, format, std::forward(args)...); + return std::snprintf(to_one_of_std_char(buffer), count, to_one_of_std_char(format), std::forward(args)...); #else // Поддерживает позиционные параметры // Supports positional parameters - return _sprintf_p(buffer, count, format, args...); + return _sprintf_p(to_one_of_std_char(buffer), count, to_one_of_std_char(format), args...); #endif } else { #ifndef _WIN32 @@ -3358,6 +1376,24 @@ inline size_t grow2(size_t ret, size_t currentCapacity) { return ret <= currentCapacity ? ret : ret * 2; } +template +struct to_std_char_type : std::type_identity{}; + +template<> +struct to_std_char_type{ + using type = char; +}; + +template<> +struct to_std_char_type{ + using type = std::conditional_t; +}; + +template<> +struct to_std_char_type{ + using type = std::conditional_t; +}; + /*! * @ru @brief Базовый класс работы с изменяемыми строками * @tparam K - тип символов @@ -3422,7 +1458,7 @@ private: template Impl& make_trim_op(const Op& op) { - str_piece me = static_cast(d()), pos = op(me); + str_piece me = d(), pos = op(me); if (me.length() != pos.length()) { if (me.symbols() != pos.symbols()) traits::move(const_cast(me.symbols()), pos.symbols(), pos.length()); @@ -4360,6 +2396,7 @@ public: writer& operator=(writer&&) noexcept = default; using difference_type = int; }; + using fmt_type = typename to_std_char_type::type; /*! * @ru @brief Добавляет отформатированный с помощью std::format вывод, начиная с указанной позиции. * @param from - начальная позиция добавления. @@ -4375,7 +2412,7 @@ public: * @details Automatically increases the string buffer size if necessary. */ template requires (is_one_of_std_char_v) - Impl& format_from(size_t from, const FmtString& format, T&&... args) { + Impl& format_from(size_t from, const FmtString& format, T&&... args) { size_t size = _len(); if (from > size) from = size; @@ -4439,7 +2476,7 @@ public: * @details Automatically increases the string buffer size if necessary. */ template requires (is_one_of_std_char_v) - Impl& format(const FmtString& pattern, T&&... args) { + Impl& format(const FmtString& pattern, T&&... args) { return format_from(0, pattern, std::forward(args)...); } /*! @@ -4455,7 +2492,7 @@ public: * @details Automatically increases the string buffer size if necessary. */ template requires (is_one_of_std_char_v) - Impl& append_formatted(const FmtString& format, T&&... args) { + Impl& append_formatted(const FmtString& format, T&&... args) { return format_from(_len(), format, std::forward(args)...); } /*! @@ -5190,6 +3227,8 @@ public: template using lstringa = lstring; template +using lstringb = lstring; +template using lstringw = lstring; template using lstringu = lstring; @@ -5199,6 +3238,8 @@ using lstringuu = lstring; template using lstringsa = lstring; template +using lstringsb = lstring; +template using lstringsw = lstring; template using lstringsu = lstring; @@ -5737,7 +3778,7 @@ public: * @return my_type. */ template - static my_type format(const FmtString& fmtString, T&&... args) { + static my_type format(const FmtString::type, T...>& fmtString, T&&... args) { return my_type{lstring{}.format(fmtString, std::forward(args)...)}; } /*! @@ -5759,139 +3800,6 @@ public: template inline const sstring sstring::empty_str{}; -template -struct digits_selector { - using wider_type = uint16_t; -}; - -template<> -struct digits_selector<2> { - using wider_type = uint32_t; -}; - -template<> -struct digits_selector<4> { - using wider_type = uint64_t; -}; - -template -constexpr size_t fromInt(K* bufEnd, T val) { - const char* twoDigit = - "0001020304050607080910111213141516171819" - "2021222324252627282930313233343536373839" - "4041424344454647484950515253545556575859" - "6061626364656667686970717273747576777879" - "8081828384858687888990919293949596979899"; - if (val) { - need_sign, T> sign(val); - K* itr = bufEnd; - // Когда у нас минимальное отрицательное число, оно не меняется и остается меньше нуля - // When we have a minimum negative number, it does not change and remains less than zero - if constexpr (std::is_signed_v) { - if (val < 0) { - // Возьмем две последние цифры - // Take the last two digits - const char* ptr = twoDigit - (val % 100) * 2; - *--itr = static_cast(ptr[1]); - *--itr = static_cast(ptr[0]); - val /= 100; - val = -val; - } - } - while (val >= 100) { - const char* ptr = twoDigit + (val % 100) * 2; - *--itr = static_cast(ptr[1]); - *--itr = static_cast(ptr[0]); - val /= 100; - } - if (val < 10) { - *--itr = static_cast('0' + val); - } else { - const char* ptr = twoDigit + val * 2; - *--itr = static_cast(ptr[1]); - *--itr = static_cast(ptr[0]); - } - sign.after(itr); - return size_t(bufEnd - itr); - } - bufEnd[-1] = '0'; - return 1; -} - -template -struct expr_num { - using symb_type = K; - using my_type = expr_num; - - enum { bufSize = 24 }; - mutable T value; - mutable K buf[bufSize]; - - expr_num(T t) : value(t) {} - expr_num(expr_num&& t) : value(t.value) {} - - size_t length() const noexcept { - value = (T)fromInt(buf + bufSize, value); - return (size_t)value; - } - K* place(K* ptr) const noexcept { - ch_traits::copy(ptr, buf + bufSize - (size_t)value, (size_t)value); - return ptr + (size_t)value; - } -}; - -/*! - * @ingroup StrExprs - * @ru @brief Оператор конкатенации для строкового выражения и целого числа. - * @param a - строковое выражение. - * @param s - число. - * @details Число конвертируется в десятичное строковое представление. - * @en @brief Concatenation operator for string expression and integer. - * @param a is a string expression. - * @param s - number. - * @details The number is converted to a decimal string representation. - */ -template -constexpr strexprjoin_c> operator + (const A& a, T s) { - return {a, s}; -} - -/*! - * @ingroup StrExprs - * @ru @brief Оператор конкатенации для целого числа и строкового выражения. - * @param s - число. - * @param a - строковое выражение. - * @details Число конвертируется в десятичное строковое представление. - * @en @brief Concatenation operator for integer and string expression. - * @param s - number. - * @param a is a string expression. - * @details The number is converted to a decimal string representation. - */ -template -constexpr strexprjoin_c, false> operator + (T s, const A& a) { - return {a, s}; -} - -/*! - * @ingroup StrExprs - * @ru @brief Преобразование целого числа в строковое выражение. - * @tparam K - тип символов. - * @tparam T - тип числа, выводится из аргумента. - * @param t - число. - * @details Возвращает строковое выражение, которое генерирует десятичное представление заданного числа. - * Может использоваться, когда надо конкатенировть число и строковый литерал. - * @en @brief Convert an integer to a string expression. - * @tparam K - character type. - * @tparam T - number type, inferred from the argument. - * @param t - number. - * @details Returns a string expression that generates the decimal representation of the given number. - * Can be used when you need to concatenate a number and a string literal. - */ -template -constexpr expr_num e_num(T t) { - return {t}; -} - template consteval simple_str_nt select_str(simple_str_nt s8, simple_str_nt sw, simple_str_nt s16, simple_str_nt s32) { if constexpr (std::is_same_v) @@ -5906,816 +3814,6 @@ consteval simple_str_nt select_str(simple_str_nt s8, simple_str_nt #define uni_string(K, p) select_str(p, L##p, u##p, U##p) -template -struct expr_real { - using symb_type = K; - mutable std::conditional_t, K, u8s> buf[40]; - mutable size_t l; - double v; - expr_real(double d) : v(d) {} - expr_real(float d) : v(d) {} - - size_t length() const noexcept { - if constexpr (is_one_of_std_char_v) { - printf_selector::snprintf(buf, 40, uni_string(K, "%.16g").str, v); - l = (size_t)ch_traits::length(buf); - } else { - l = std::snprintf(buf, sizeof(buf), "%.16g", v); - } - return l; - } - K* place(K* ptr) const noexcept { - if constexpr (is_one_of_std_char_v) { - ch_traits::copy(ptr, buf, l); - } else { - for (size_t i = 0; i < l; i++) { - ptr[i] = buf[i]; - } - } - return ptr + l; - } -}; - -/*! - * @ingroup StrExprs - * @ru @brief Оператор конкатенации для строкового выражения и вещественного числа (`float`, `double`). - * @param a - строковое выражение. - * @param s - число. - * @details Число конвертируется в строковое представление через sprintf("%.16g"). - * @en @brief Concatenation operator for string expression and real number (`float`, `double`). - * @param a is a string expression. - * @param s - number. - * @details The number is converted to a string representation via sprintf("%.16g"). - */ -template - requires(std::is_same_v || std::is_same_v) -inline constexpr auto operator+(const A& a, R s) { - return strexprjoin_c>{a, s}; -} - -/*! - * @ingroup StrExprs - * @ru @brief Оператор конкатенации для вещественного числа (`float`, `double`) и строкового выражения. - * @param s - число. - * @param a - строковое выражение. - * @details Число конвертируется в строковое представление через `sprintf("%.16g")`. - * @en @brief Concatenation operator for float (`float`, `double`) and string expression. - * @param s - number. - * @param a is a string expression. - * @details The number is converted to a string representation via `sprintf("%.16g")`. - */ -template - requires(is_one_of_std_char_v && (std::is_same_v || std::is_same_v)) -inline constexpr auto operator+(R s, const A& a) { - return strexprjoin_c, false>{a, s}; -} - -/*! - * @ingroup StrExprs - * @ru @brief Преобразование `double` числа в строковое выражение. - * @param t - число. - * @details Возвращает строковое выражение, которое генерирует десятичное представление заданного числа. - * с помощью `sprintf("%.16g")`. Может использоваться, когда надо конкатенировть число и строковый литерал. - * @en @brief Convert a `double` number to a string expression. - * @param t - number. - * @details Returns a string expression that generates the decimal representation of the given number. - * using `sprintf("%.16g")`. Can be used when you need to concatenate a number and a string literal. - */ -template requires(is_one_of_std_char_v) -inline constexpr auto e_real(double t) { - return expr_real{t}; -} - -/* -* Для создания строковых конкатенаций с векторами и списками, сджойненными константным разделителем -* K - тип символов строки -* T - тип контейнера строк (vector, list) -* I - длина разделителя в символах -* tail - добавлять разделитель после последнего элемента контейнера. -* Если контейнер пустой, разделитель в любом случае не добавляется -* skip_empty - пропускать пустые строки без добавления разделителя -* To create string concatenations with vectors and lists joined by a constant delimiter -* K is the symbols -* T - type of string container (vector, list) -* I - length of separator in characters -* tail - add a separator after the last element of the container. -* If the container is empty, the separator is not added anyway -* skip_empty - skip empty lines without adding a separator -*/ -template -struct expr_join { - using symb_type = K; - using my_type = expr_join; - - const T& s; - const K* delim; - - constexpr size_t length() const noexcept { - size_t l = 0; - for (const auto& t: s) { - size_t len = t.length(); - if (len > 0 || !skip_empty) { - if (I > 0 && l > 0) { - l += I; - } - l += len; - } - } - return l + (tail && I > 0 && (l > 0 || (!skip_empty && s.size() > 0))? I : 0); - } - constexpr K* place(K* ptr) const noexcept { - if (s.empty()) { - return ptr; - } - K* write = ptr; - for (const auto& t: s) { - size_t copyLen = t.length(); - if (I > 0 && write != ptr && (copyLen || !skip_empty)) { - ch_traits::copy(write, delim, I); - write += I; - } - ch_traits::copy(write, t.symbols(), copyLen); - write += copyLen; - } - if (I > 0 && tail && (write != ptr || (!skip_empty && s.size() > 0))) { - ch_traits::copy(write, delim, I); - write += I; - } - return write; - } -}; - -/*! - * @ingroup StrExprs - * @ru @brief Получить строковое выражение, конкатенирующее строки в контейнере в одну строку с заданным разделителем. - * @tparam tail - добавлять ли разделитель после последней строки. - * @tparam skip_empty - пропускать пустые строки без добавления разделителя. - * @param s - контейнер со строками, должен поддерживать `range for`. - * @param d - разделитель, строковый литерал. - * @en @brief Get a string expression concatenating the strings in the container into a single string with the given delimiter.limiter.limiter. - * @tparam tail - whether to add a separator after the last line. - * @tparam skip_empty - skip empty lines without adding a separator. - * @param s - container with strings, must support `range for`. - * @param d - delimiter, string literal. - */ -template::symb_type, size_t I = const_lit::Count, typename T> -inline constexpr auto e_join(const T& s, L&& d) { - return expr_join{s, d}; -} - -template -struct expr_replaces { - using symb_type = K; - using my_type = expr_replaces; - simple_str what; - const K* pattern; - const K* repl; - mutable size_t first_, last_; - - constexpr expr_replaces(simple_str w, const K* p, const K* r) : what(w), pattern(p), repl(r) {} - - constexpr size_t length() const { - size_t l = what.length(); - if constexpr (N == L) { - return l; - } - first_ = what.find(pattern, N, 0); - if (first_ != str::npos) { - last_ = first_ + N; - for (;;) { - l += L - N; - size_t next = what.find(pattern, N, last_); - if (next == str::npos) { - break; - } - last_ = next + N; - } - } - return l; - } - constexpr K* place(K* ptr) const noexcept { - if constexpr (N == L) { - const K* from = what.symbols(); - for (size_t start = 0; start < what.length();) { - size_t next = what.find(pattern, N, start); - if (next == str::npos) { - next = what.length(); - } - size_t delta = next - start; - ch_traits::copy(ptr, from + start, delta); - ptr += delta; - ch_traits::copy(ptr, repl, L); - ptr += L; - start = next + N; - } - return ptr; - } - if (first_ == str::npos) { - return what.place(ptr); - } - const K* from = what.symbols(); - for (size_t start = 0, offset = first_; ;) { - ch_traits::copy(ptr, from + start, offset - start); - ptr += offset - start; - ch_traits::copy(ptr, repl, L); - ptr += L; - start = offset + N; - if (start >= last_) { - size_t tail = what.length() - last_; - ch_traits::copy(ptr, from + last_, tail); - ptr += tail; - break; - } else { - offset = what.find(pattern, N, start); - } - } - return ptr; - } -}; - -/*! - * @ingroup StrExprs - * @ru @brief Получить строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки. - * @tparam K - тип символа, выводится из первого аргумента. - * @param w - начальная строка. - * @param p - строковый литерал, искомая подстрока. - * @param r - строковый литерал, на что заменять. - * @en @brief Get a string expression that generates a string with all occurrences of a given substring replaced. - * @tparam K - the type of the symbol, inferred from the first argument. - * @param w - starting line. - * @param p - string literal, searched substring. - * @param r - string literal, what to replace with. - */ -template::Count, typename X, size_t L = const_lit_for::Count> - requires(N > 1) -inline constexpr auto e_repl(simple_str w, T&& p, X&& r) { - return expr_replaces{w, p, r}; -} - -/*! - * @ingroup StrExprs - * @ru @brief Строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки. - * @tparam K - тип строки. - * @details `e_repl` позволяет заменять только с использование строковых литералов. - * В случае, когда искомая подстрока или строка замены не известны при компиляции, и задаются в runtime, - * следует использовать этот тип, например: - * @en @brief A string expression that generates a string replacing all occurrences of the given substring. - * @tparam K - string type. - * @details `e_repl` only allows replacement using string literals. - * In the case when the required substring or replacement string is not known at compilation, and is set at runtime, - * this type should be used, for example: - * @~ - * ```cpp - * stringa result = "
    " + expr_replaced{source, pattern, repl} + "
    "; - * ``` - */ -template -struct expr_replaced { - using symb_type = K; - using my_type = expr_replaced; - simple_str what; - const simple_str pattern; - const simple_str repl; - mutable size_t first_, last_; - /*! - * @ru @brief Конструктор. - * @param w - исходная строка. - * @param p - искомая подстрока. - * @param r - строка замены. - * @en @brief Constructor. - * @param w - source string. - * @param p - the searched substring. - * @param r - replacement string. - */ - constexpr expr_replaced(simple_str w, simple_str p, simple_str r) : what(w), pattern(p), repl(r) {} - - constexpr size_t length() const { - size_t l = what.length(); - if (pattern.length() == repl.length()) { - return l; - } - first_ = what.find(pattern); - if (first_ != str::npos) { - last_ = first_ + pattern.length(); - for (;;) { - l += repl.length() - pattern.length(); - size_t next = what.find(pattern, last_); - if (next == str::npos) { - break; - } - last_ = next + pattern.length(); - } - } - return l; - } - constexpr K* place(K* ptr) const noexcept { - if (repl.length() == pattern.length()) { - const K* from = what.symbols(); - for (size_t start = 0; start < what.length();) { - size_t next = what.find(pattern, start); - if (next == str::npos) { - next = what.length(); - } - size_t delta = next - start; - ch_traits::copy(ptr, from + start, delta); - ptr += delta; - ch_traits::copy(ptr, repl.symbols(), repl.length()); - ptr += repl.length(); - start = next + pattern.length(); - } - return ptr; - } - if (first_ == str::npos) { - return what.place(ptr); - } - const K* from = what.symbols(); - for (size_t start = 0, offset = first_; ;) { - ch_traits::copy(ptr, from + start, offset - start); - ptr += offset - start; - ch_traits::copy(ptr, repl.symbols(), repl.length()); - ptr += repl.length(); - start = offset + pattern.length(); - if (start >= last_) { - size_t tail = what.length() - last_; - ch_traits::copy(ptr, from + last_, tail); - ptr += tail; - break; - } else { - offset = what.find(pattern, start); - } - } - return ptr; - } -}; - -template -struct replace_search_result_store { - size_t count_{}; - std::pair replaces_[16]; -}; - -template<> -struct replace_search_result_store : std::vector> {}; - -/*! - * @ingroup StrExprs - * @ru @brief Тип для строкового выражения, генерирующее строку, в которой заданные символы заменяются на заданные строки. - * @tparam K - тип символа. - * @tparam UseVectorForReplace - использовать вектор для запоминания результатов поиска вхождений символов. - * @details Этот тип применяется, когда состав символов или соответствующих им замен не известен в compile time, - * а определяется в runtime. В конструктор передается вектор из пар `символ - строка замены`. - * Параметр `UseVectorForReplace` задаёт стратегию реализации. Дело в том, что работа любых строковых выражений - * разбита на две фазы - вызов `length()`, в котором подсчитывется количество символов в результате, - * и вызов `place()`, в котором результат помещается в предоставленный буфер. - * При `UseVectorForReplace == true` во время фазы подcчёта количества символов, позиции найденных вхождений - * сохраняются в векторе, и во время второй фазы поиск уже не выполняется, а позиции берутся из вектора. - * Это, с одной стороны, уменьшает время во второй фазе - не нужно снова выполнять поиск, но увеличивает - * время в первой фазе - добавление элементов в вектор не бесплатно, и требует времени. - * При `UseVectorForReplace == false` во время фазы подcчёта количества символов, в локальном массиве запоминается позиции - * первых 16 вхождений и их общее количество, а во время второй фазы, если вхождений больше 16, то поиск повторяется, - * но уже только с позиции 16го вхождения. Это может увеличить время во второй фазе, но сокращает время в первой - * фазе - не нужно добавлять элементы в вектор, не нужна динамическая аллокация. - * В разных сценариях использования более оптимальными могут быть та или иная стратегия, и вы можете сами решить, - * что в каждом конкретном случае больше подойдёт. - * @en @brief A type for a string expression that generates a string in which the given characters are replaced by the given strings. - * @tparam K - symbol type. - * @tparam UseVectorForReplace - use a vector to remember the results of searching for occurrences of characters. - * @details This type is used when the composition of symbols or their corresponding replacements is not known at compile time, - * and is defined at runtime. A vector of `character - replacement string` pairs is passed to the constructor. - * The `UseVectorForReplace` parameter specifies the implementation strategy. The point is that the work of any string expressions - * is divided into two phases - the `length()` call, which counts the number of characters in the result, - * and a call to `place()`, which places the result in the provided buffer. - * When `UseVectorForReplace == true` during the phase of counting the number of characters, the position of the found occurrences - * are stored in the vector, and during the second phase the search is no longer performed, and the positions are taken from the vector. - * This, on the one hand, reduces the time in the second phase - there is no need to search again, but it increases - * time in the first phase - adding elements to the vector is not free, and takes time. - * When `UseVectorForReplace == false` during the phase of counting the number of characters, positions in the local array are remembered - * the first 16 occurrences and their total number, and during the second phase, if there are more than 16 occurrences, then the search is repeated, - * but only from the position of the 16th occurrence. This may increase the time in the second phase, but reduces the time in the first - * phase - no need to add elements to the vector, no need for dynamic allocation. - *In different use cases, one or another strategy may be more optimal, and you can decide for yourself - * whichever is more suitable in each specific case. - */ -template -struct expr_replace_symbols { - using symb_type = K; - inline static const int BIT_SEARCH_TRESHHOLD = 4; - - const simple_str source_; - const std::vector>>& replaces_; - - lstring pattern_; - - mutable replace_search_result_store search_results_; - - uu8s bit_mask_[sizeof(K) == 1 ? 32 : 64]{}; - /*! - * @ru @brief Конструктор выражения. - * @param source - исходная строка. - * @param repl - вектор из пар "символ->строка замены". - * @details Пример: - * @en @brief Expression constructor. - * @param source - source string. - * @param repl - a vector of "character->replacement string" pairs. - * @details Example: - * @~ - * ```cpp - stringa result = expr_replace_symbols{source, { - {'-', ""}, - {'<', "<"}, - {'>', ">"}, - {'\'', "'"}, - {'\"', """}, - {'&', "&"}, - }}; - * ``` - * @ru Пример приведен для наглядности использования. В данном случае и заменяемые символы, и строки замены - * известны в compile time, и в этом случае лучше применять e_repl_const_symbols, а этот класс - * используется, когда символы или замены задаются в runtime. - * @en An example is provided for clarity of use. In this case, both the characters to be replaced and the replacement strings - * known at compile time, in which case it is better to use e_repl_const_symbols, and this class - * is used when characters or replacements are specified at runtime. - */ - constexpr expr_replace_symbols(simple_str source, const std::vector>>& repl ) - : source_(source), replaces_(repl) - { - size_t pattern_len = replaces_.size(); - K* pattern = pattern_.set_size(pattern_len); - - for (size_t idx = 0; idx < replaces_.size(); idx++) { - *pattern++ = replaces_[idx].first; - } - - if (pattern_len >= BIT_SEARCH_TRESHHOLD) { - for (size_t idx = 0; idx < pattern_len; idx++) { - uu8s s = static_cast(pattern_[idx]); - if constexpr (sizeof(K) == 1) { - bit_mask_[s >> 3] |= (1 << (s & 7)); - } else { - if (std::make_unsigned_t(pattern_[idx]) > 255) { - bit_mask_[32 + (s >> 3)] |= (1 << (s & 7)); - } else { - bit_mask_[s >> 3] |= (1 << (s & 7)); - } - } - } - } - } - - size_t length() const { - size_t l = source_.length(); - auto [fnd, num] = find_first_of(source_.str, source_.len); - if (fnd == str::npos) { - return l; - } - l += replaces_[num].second.len - 1; - if constexpr (UseVectorForReplace) { - search_results_.reserve((l >> 4) + 8); - search_results_.emplace_back(fnd, num); - for (size_t start = fnd + 1;;) { - auto [fnd, idx] = find_first_of(source_.str, source_.len, start); - if (fnd == str::npos) { - break; - } - search_results_.emplace_back(fnd, idx); - start = fnd + 1; - l += replaces_[idx].second.len - 1; - } - } else { - const size_t max_store = std::size(search_results_.replaces_); - search_results_.replaces_[0] = {fnd, num}; - search_results_.count_++; - for (size_t start = fnd + 1;;) { - auto [found, idx] = find_first_of(source_.str, source_.len, start); - if (found == str::npos) { - break; - } - if (search_results_.count_ < max_store) { - search_results_.replaces_[search_results_.count_] = {found, idx}; - } - l += replaces_[idx].second.len - 1; - search_results_.count_++; - start = found + 1; - } - } - return l; - } - K* place(K* ptr) const noexcept { - size_t start = 0; - const K* text = source_.str; - if constexpr (UseVectorForReplace) { - for (const auto& [pos, num] : search_results_) { - size_t delta = pos - start; - ch_traits::copy(ptr, text + start, delta); - ptr += delta; - ptr = replaces_[num].second.place(ptr); - start = pos + 1; - } - } else { - const size_t max_store = std::size(search_results_.replaces_); - size_t founded = search_results_.count_; - for (size_t idx = 0, stop = std::min(founded, max_store); idx < stop; idx++) { - const auto [pos, num] = search_results_.replaces_[idx]; - size_t delta = pos - start; - ch_traits::copy(ptr, text + start, delta); - ptr += delta; - ptr = replaces_[num].second.place(ptr); - start = pos + 1; - } - if (founded > max_store) { - founded -= max_store; - while (founded--) { - auto [fnd, idx] = find_first_of(source_.str, source_.len, start); - size_t delta = fnd - start; - ch_traits::copy(ptr, text + start, delta); - ptr += delta; - ptr = replaces_[idx].second.place(ptr); - start = fnd + 1; - } - } - } - size_t tail = source_.len - start; - ch_traits::copy(ptr, text + start, tail); - return ptr + tail; - } - -protected: - size_t index_of(K s) const { - return pattern_.find(s); - } - - bool is_in_mask(uu8s s) const { - return (bit_mask_[s >> 3] & (1 << (s & 7))) != 0; - } - bool is_in_mask2(uu8s s) const { - return (bit_mask_[32 + (s >> 3)] & (1 << (s & 7))) != 0; - } - - bool is_in_pattern(K s, size_t& idx) const { - if constexpr (sizeof(K) == 1) { - if (is_in_mask(s)) { - idx = index_of(s); - return true; - } - } else { - if (std::make_unsigned_t(s) > 255) { - if (is_in_mask2(s)) { - return (idx = index_of(s)) != -1; - } - } else { - if (is_in_mask(s)) { - idx = index_of(s); - return true; - } - } - } - return false; - } - - std::pair find_first_of(const K* text, size_t len, size_t offset = 0) const { - size_t pl = pattern_.length(); - if (pl >= BIT_SEARCH_TRESHHOLD) { - size_t idx; - while (offset < len) { - if (is_in_pattern(text[offset], idx)) { - return {offset, idx}; - } - offset++; - } - } else { - while (offset < len) { - if (size_t idx = index_of(text[offset]); idx != -1) { - return {offset, idx}; - } - offset++; - } - } - return {-1, -1}; - } -}; - -// Строковое выражение для замены символов -// String expression to replace characters -template -struct expr_replace_const_symbols { - using symb_type = K; - inline static const int BIT_SEARCH_TRESHHOLD = 4; - const K pattern_[N]; - const simple_str source_; - const simple_str replaces_[N]; - - mutable replace_search_result_store search_results_; - - [[_no_unique_address]] - uu8s bit_mask_[N >= BIT_SEARCH_TRESHHOLD ? (sizeof(K) == 1 ? 32 : 64) : 0]{}; - - template requires (sizeof...(Repl) == N * 2) - constexpr expr_replace_const_symbols(simple_str source, Repl&& ... repl) : expr_replace_const_symbols(0, source, std::forward(repl)...) {} - - size_t length() const { - size_t l = source_.length(); - auto [fnd, num] = find_first_of(source_.str, source_.len); - if (fnd == str::npos) { - return l; - } - l += replaces_[num].len - 1; - if constexpr (UseVectorForReplace) { - search_results_.reserve((l >> 4) + 8); - search_results_.emplace_back(fnd, num); - for (size_t start = fnd + 1;;) { - auto [fnd, idx] = find_first_of(source_.str, source_.len, start); - if (fnd == str::npos) { - break; - } - search_results_.emplace_back(fnd, idx); - start = fnd + 1; - l += replaces_[idx].len - 1; - } - } else { - const size_t max_store = std::size(search_results_.replaces_); - search_results_.replaces_[0] = {fnd, num}; - search_results_.count_++; - for (size_t start = fnd + 1;;) { - auto [found, idx] = find_first_of(source_.str, source_.len, start); - if (found == str::npos) { - break; - } - if (search_results_.count_ < max_store) { - search_results_.replaces_[search_results_.count_] = {found, idx}; - } - l += replaces_[idx].len - 1; - search_results_.count_++; - start = found + 1; - } - } - return l; - } - K* place(K* ptr) const noexcept { - size_t start = 0; - const K* text = source_.str; - if constexpr (UseVectorForReplace) { - for (const auto& [pos, num] : search_results_) { - size_t delta = pos - start; - ch_traits::copy(ptr, text + start, delta); - ptr += delta; - ptr = replaces_[num].place(ptr); - start = pos + 1; - } - } else { - const size_t max_store = std::size(search_results_.replaces_); - size_t founded = search_results_.count_; - for (size_t idx = 0, stop = std::min(founded, max_store); idx < stop; idx++) { - const auto [pos, num] = search_results_.replaces_[idx]; - size_t delta = pos - start; - ch_traits::copy(ptr, text + start, delta); - ptr += delta; - ptr = replaces_[num].place(ptr); - start = pos + 1; - } - if (founded > max_store) { - founded -= max_store; - while (founded--) { - auto [fnd, idx] = find_first_of(source_.str, source_.len, start); - size_t delta = fnd - start; - ch_traits::copy(ptr, text + start, delta); - ptr += delta; - ptr = replaces_[idx].place(ptr); - start = fnd + 1; - } - } - } - size_t tail = source_.len - start; - ch_traits::copy(ptr, text + start, tail); - return ptr + tail; - } - -protected: - template - constexpr expr_replace_const_symbols(int, simple_str source, K s, simple_str r, Repl&&... repl) : - expr_replace_const_symbols(0, source, std::forward(repl)..., std::make_pair(s, r)){} - - template requires (sizeof...(Repl) == N) - constexpr expr_replace_const_symbols(int, simple_str source, Repl&&... repl) : - source_(source), pattern_ {repl.first...}, replaces_{repl.second...} - { - if constexpr (N >= BIT_SEARCH_TRESHHOLD) { - for (size_t idx = 0; idx < N; idx++) { - uu8s s = static_cast(pattern_[idx]); - if constexpr (sizeof(K) == 1) { - bit_mask_[s >> 3] |= 1 << (s & 7); - } else { - if (std::make_unsigned_t(pattern_[idx]) > 255) { - bit_mask_[32 + (s >> 3)] |= 1 << (s & 7); - } else { - bit_mask_[s >> 3] |= 1 << (s & 7); - } - } - } - } - } - - template - size_t index_of(K s) const { - if constexpr (Idx < N) { - return pattern_[Idx] == s ? Idx : index_of(s); - } - return -1; - } - bool is_in_mask(uu8s s) const { - return (bit_mask_[s >> 3] & (1 <<(s & 7))) != 0; - } - bool is_in_mask2(uu8s s) const { - return (bit_mask_[32 + (s >> 3)] & (1 <<(s & 7))) != 0; - } - - bool is_in_pattern(K s, size_t& idx) const { - if constexpr (N >= BIT_SEARCH_TRESHHOLD) { - if constexpr (sizeof(K) == 1) { - if (is_in_mask(s)) { - idx = index_of<0>(s); - return true; - } - } else { - if (std::make_unsigned_t(s) > 255) { - if (is_in_mask2(s)) { - return (idx = index_of<0>(s)) != -1; - } - } else { - if (is_in_mask(s)) { - idx = index_of<0>(s); - return true; - } - } - } - } - return false; - } - std::pair find_first_of(const K* text, size_t len, size_t offset = 0) const { - if constexpr (N >= BIT_SEARCH_TRESHHOLD) { - size_t idx; - while (offset < len) { - if (is_in_pattern(text[offset], idx)) { - return {offset, idx}; - } - offset++; - } - } else { - while (offset < len) { - if (size_t idx = index_of<0>(text[offset]); idx != -1) { - return {offset, idx}; - } - offset++; - } - } - return {-1, -1}; - } -}; - -/*! - * @ingroup StrExprs - * @ru @brief Возвращает строковое выражение, генерирующее строку, в которой заданные символы - * заменены на заданные подстроки. - * @tparam UseVector - использовать вектор для сохранения результатов поиска символов. - * Более подробно описано в `expr_replace_symbols`. - * @param src - исходная строка. - * @param symbol - константный символ, который надо заменять. - * @param repl - строковый литерал, на который заменять символ. - * @param ... symbol, repl - другие символы и строки. - * @details Применяется для генерации замены символов на строки, в случае если все они известны - * в compile time. Пример: - * @en @brief Returns a string expression that generates a string containing the given characters - * replaced with given substrings. - * @tparam UseVector - use a vector to save symbol search results. - * Described in more detail in `expr_replace_symbols`. - * @param src - source string. - * @param symbol - constant symbol that needs to be replaced. - * @param repl - string literal to replace the character with. - * @param ... symbol, repl - other symbols and strings. - * @details Used to generate character replacements for strings if all of them are known - * at compile time. Example: - * @~ - * ```cpp - * out += "
    " + e_repl_const_symbols(text, '\"', """, '<', "<", '\'', "'", '&', "&") + "
    "; - * ``` - * @ru В принипе, `e_repl_const_symbols` вполне безопасно возвращать из функции, если исходная строка - * внешняя по отношению к функции. - * @en In principle, `e_repl_const_symbols` is quite safe to return from a function if the source string - * external to function. - * @~ - * ```cpp - * auto repl_html_symbols(ssa text) { - * return e_repl_const_symbols(text, '\"', """, '<', "<", '\'', "'", '&', "&"); - * } - * .... - * out += "
    " + repl_html_symbols(content) + "
    "; - * ``` - */ -template -requires (sizeof...(Repl) % 2 == 0) -auto e_repl_const_symbols(simple_str src, Repl&& ... other) { - return expr_replace_const_symbols(src, std::forward(other)...); -} - template struct StoreType { simple_str str; @@ -7144,7 +4242,7 @@ struct strhashiu { * Itself is a string expression. */ template -class chunked_string_builder { +class chunked_string_builder : expr_to_std_string> { using chunk_t = std::pair, size_t>; std::vector chunks; // блоки и длина данных в них | blocks and data length in them K* write{}; // Текущая позиция записи | Current write position @@ -7375,6 +4473,7 @@ public: }; using stringa = sstring; +using stringb = sstring; using stringw = sstring; using stringu = sstring; using stringuu = sstring; @@ -7462,20 +4561,6 @@ inline constexpr simple_str_nt utf8_bom{"\xEF\xBB\xBF", 3}; // NOLINT inline namespace literals { -#ifdef _MSC_VER -/* MSVC иногда не может сделать "text"_ss consteval, выдает ошибку C7595. -Находил подобное https://developercommunity.visualstudio.com/t/User-defined-literals-not-constant-expre/10108165 -Пишут, что баг исправлен, но видимо не до конца. -Без этого в тестах в двух местах не понимает "text"_ss, хотя в других местах - нормально работает*/ -/* MSVC sometimes fails to do "text"_ss consteval and gives error C7595. -Found something like this https://developercommunity.visualstudio.com/t/User-defined-literals-not-constant-expre/10108165 -They write that the bug has been fixed, but apparently not completely. -Without this, in tests in two places it does not understand “text”_ss, although in other places it works fine */ -#define SS_CONSTEVAL constexpr -#else -#define SS_CONSTEVAL consteval -#endif - /*! * @ru @brief Оператор литерал в simple_str_nt. * @param ptr - указатель на строку. @@ -7489,6 +4574,19 @@ Without this, in tests in two places it does not understand “text”_ss, altho SS_CONSTEVAL simple_str_nt operator""_ss(const u8s* ptr, size_t l) { return simple_str_nt{ptr, l}; } +/*! + * @ru @brief Оператор литерал в simple_str_nt. + * @param ptr - указатель на строку. + * @param l - длина строки. + * @return simple_str_nt. + * @en @brief Operator literal in simple_str_nt. + * @param ptr - pointer to a string. + * @param l - string length. + * @return simple_str_nt. + */ +SS_CONSTEVAL simple_str_nt operator""_ss(const ubs* ptr, size_t l) { + return simple_str_nt{ptr, l}; +} /*! * @ru @brief Оператор литерал в simple_str_nt. * @param ptr - указатель на строку. @@ -7885,3 +4983,107 @@ struct std::formatter, K> : std::formatter, K>::format({t.symbols(), t.length()}, fc); } }; + +/*! + * @ru @brief Форматтер для использования в std::format значений типа simple_str. + * @en @brief Formatter to use in std::format for values ​​of type simple_str. + */ +template<> +struct std::formatter, char> : std::formatter, char> { + // Define format() by calling the base class implementation with the wrapped value + template + auto format(simstr::simple_str t, FormatContext& fc) const { + return std::formatter, char>::format({(const char*)t.str, t.len}, fc); + } +}; + +/*! + * @ru @brief Форматтер для использования в std::format значений типа simple_str_nt. + * @en @brief Formatter to use in std::format for values ​​of type simple_str_nt. + */ +template<> +struct std::formatter, char> : std::formatter, char> { + // Define format() by calling the base class implementation with the wrapped value + template + auto format(simstr::simple_str_nt t, FormatContext& fc) const { + return std::formatter, char>::format({(const char*)t.str, t.len}, fc); + } +}; + +/*! + * @ru @brief Форматтер для использования в std::format значений типа sstring. + * @en @brief Formatter to use in std::format for values ​​of type string. + */ +template<> +struct std::formatter, char> : std::formatter, char> { + // Define format() by calling the base class implementation with the wrapped value + template + auto format(const simstr::sstring& t, FormatContext& fc) const { + return std::formatter, char>::format({(const char*)t.symbols(), t.length()}, fc); + } +}; + +/*! + * @ru @brief Форматтер для использования в std::format значений типа lstring. + * @en @brief Formatter to use in std::format for values ​​of type lstring. + */ +template +struct std::formatter, char> : std::formatter, char> { + // Define format() by calling the base class implementation with the wrapped value + template + auto format(const simstr::lstring& t, FormatContext& fc) const { + return std::formatter, char>::format({(const char*)t.symbols(), t.length()}, fc); + } +}; + +/*! + * @ru @brief Форматтер для использования в std::format значений типа simple_str. + * @en @brief Formatter to use in std::format for values ​​of type simple_str. + */ +template<> +struct std::formatter, wchar_t> : std::formatter, wchar_t> { + // Define format() by calling the base class implementation with the wrapped value + template + auto format(simstr::simple_str t, FormatContext& fc) const { + return std::formatter, wchar_t>::format({(const wchar_t*)t.str, t.len}, fc); + } +}; + +/*! + * @ru @brief Форматтер для использования в std::format значений типа simple_str_nt. + * @en @brief Formatter to use in std::format for values ​​of type simple_str_nt. + */ +template<> +struct std::formatter, wchar_t> : std::formatter, wchar_t> { + // Define format() by calling the base class implementation with the wrapped value + template + auto format(simstr::simple_str_nt t, FormatContext& fc) const { + return std::formatter, wchar_t>::format({(const wchar_t*)t.str, t.len}, fc); + } +}; + +/*! + * @ru @brief Форматтер для использования в std::format значений типа sstring. + * @en @brief Formatter to use in std::format for values ​​of type string. + */ +template<> +struct std::formatter, wchar_t> : std::formatter, wchar_t> { + // Define format() by calling the base class implementation with the wrapped value + template + auto format(const simstr::sstring& t, FormatContext& fc) const { + return std::formatter, wchar_t>::format({(const wchar_t*)t.symbols(), t.length()}, fc); + } +}; + +/*! + * @ru @brief Форматтер для использования в std::format значений типа lstring. + * @en @brief Formatter to use in std::format for values ​​of type lstring. + */ +template +struct std::formatter, wchar_t> : std::formatter, wchar_t> { + // Define format() by calling the base class implementation with the wrapped value + template + auto format(const simstr::lstring& t, FormatContext& fc) const { + return std::formatter, wchar_t>::format({(const wchar_t*)t.symbols(), t.length()}, fc); + } +}; diff --git a/include/simstr/strexpr.h b/include/simstr/strexpr.h index 0f624b1..6b1511a 100644 --- a/include/simstr/strexpr.h +++ b/include/simstr/strexpr.h @@ -1,17 +1,49 @@ /* - * ver. 1.3.1 + * ver. 1.4.0 * (c) Проект "SimStr", Александр Орефков orefkov@gmail.com * База для строковых конкатенаций через выражения времени компиляции * (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com * Base for string concatenations via compile-time expressions */ #pragma once -#include +#include +#include +#include +#include #include #include -#include #include -#include +#include +#include +#include + +#if defined __has_builtin +# if __has_builtin(__builtin_mul_overflow) && __has_builtin(__builtin_add_overflow) +# define HAS_BUILTIN_OVERFLOW +# endif +#endif + +#ifdef _MSC_VER +#define _no_unique_address msvc::no_unique_address +#define decl_empty_bases __declspec(empty_bases) +#else +#define _no_unique_address no_unique_address +#define decl_empty_bases +#endif + +#ifdef _MSC_VER +/* MSVC иногда не может сделать "text"_ss consteval, выдает ошибку C7595. +Находил подобное https://developercommunity.visualstudio.com/t/User-defined-literals-not-constant-expre/10108165 +Пишут, что баг исправлен, но видимо не до конца. +Без этого в тестах в двух местах не понимает "text"_ss, хотя в других местах - нормально работает*/ +/* MSVC sometimes fails to do "text"_ss consteval and gives error C7595. +Found something like this https://developercommunity.visualstudio.com/t/User-defined-literals-not-constant-expre/10108165 +They write that the bug has been fixed, but apparently not completely. +Without this, in tests in two places it does not understand “text”_ss, although in other places it works fine */ +#define SS_CONSTEVAL constexpr +#else +#define SS_CONSTEVAL consteval +#endif /*! * @ru @brief Пространство имён для объектов библиотеки @@ -42,23 +74,33 @@ inline const wchar_t* from_w(const wchar_type* p) { } using u8s = char; +using ubs = char8_t; using uws = wchar_t; using u16s = char16_t; using u32s = char32_t; using uu8s = std::make_unsigned::type; -template -constexpr bool is_one_of_char_v = std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v; +template +struct is_one_of_type { + static constexpr bool value = std::is_same_v || is_one_of_type::value; +}; +template +struct is_one_of_type : std::false_type {}; template -constexpr bool is_one_of_std_char_v = std::is_same_v || std::is_same_v || std::is_same_v; +constexpr bool is_one_of_char_v = is_one_of_type::value; + +template +constexpr bool is_one_of_std_char_v = is_one_of_type::value; template requires (is_one_of_std_char_v) auto to_one_of_std_char(From* from) { if constexpr (std::is_same_v || std::is_same_v) { return from; + } else if constexpr (std::is_same_v) { + return reinterpret_cast(from); } else { return from_w(from); } @@ -68,11 +110,31 @@ requires (is_one_of_std_char_v) auto to_one_of_std_char(const From* from) { if constexpr (std::is_same_v || std::is_same_v) { return from; + } else if constexpr (std::is_same_v) { + return reinterpret_cast(from); } else { return from_w(from); } } +/*! + * @ingroup StrExprs + * @ru @brief Проверка, являются ли два типа совместимыми строковыми типами. + * @tparam K1 - первый проверяемый тип. + * @tparam K2 - второй проверяемый тип. + * @details Оба типа должны быть строковыми типами и совпадать по размеру. + * То есть char и char8_t всегда совместимы, wchar_t тождественен в Linux char32_t, а в Windows - char16_t. + * Это для возможности смешивать строковые выражения совместимых типов. + * @en @brief Checks whether two types are compatible string types. + * @tparam K1 is the first type to check. + * @tparam K2 is the second type to check. + * @details Both types must be string types and the same size. + * That is, char and char8_t are always compatible, wchar_t is identical to char32_t on Linux, and char16_t on Windows. + * This is for the ability to mix string expressions of compatible types. + */ +template +constexpr bool is_equal_str_type_v = is_one_of_char_v && is_one_of_char_v && sizeof(K1) == sizeof(K2); + /* Вспомогательные шаблоны для определения строковых литералов. Используются для того, чтобы в параметрах функций ограничивать типы строго как `const K(&)[N]` @@ -133,9 +195,9 @@ struct const_lit { // Here we further restrict the type of the literal template struct const_lit_for; -template - requires(is_one_of_char_v) -struct const_lit_for { +template + requires(is_equal_str_type_v) +struct const_lit_for { constexpr static size_t Count = N; }; @@ -203,7 +265,7 @@ concept StrType = requires(const A& a) { /*! * @ru @defgroup StrExprs Строковые выражения * @brief Описание строковых выражений - * @details Все типы владеющих строк могут инициализироваться с помощью "строковых выражений" + * @details Все типы владеющих строк в simstr могут инициализироваться с помощью "строковых выражений". * (по сути это вариант https://en.wikipedia.org/wiki/Expression_templates для строк). * Строковое выражение - это объект произвольного типа, у которого имеются методы: * - `size_t length() const`: выдает длину строки @@ -213,6 +275,10 @@ concept StrType = requires(const A& a) { * При инициализации строковый объект запрашивает у строкового выражения его размер, выделяет необходимую память, * и передает память строковому выражению, которое помещает символы в отведённый буфер. * + * Кроме того, для совместимости с `std`, строковые выражения simstr могут конвертироваться в стандартные строки + * (std::basic_string) совместимых типов. До C++23 используется `resize` и потом заполнение через `data()`, начиная с C++23 + * используется более оптимальный `resize_and_overwrite`. Это позволяет использовать быструю конкатенацию там, где требуются стандартные строки. + * * Все строковые объекты библиотеки сами являются строковыми выражениями, которые просто копирует исходную строку. * В-основном строковые выражения используются для конкатенации или конвертации строк. * @@ -249,12 +315,14 @@ concept StrType = requires(const A& a) { * между элементами. * Если `ПропускатьПустые == true`, то пустые строки не добавляют разделитель, иначе для каждой пустой строки * тоже вставляется разделитель - * - `e_repl(ИсходнаяСтрока, "Искать", "Заменять")`: заменяет в исходной строке вхождения "Искать" на "Заменять". - * Шаблоны поиска и замены - строковые литералы времени компиляции. - * - `expr_replaced< ТипСимвола>{ИсходнаяСтрока, Искать, Заменять}`: заменяет в исходной строке вхождения Искать на Заменять. - * Шаблоны поиска и замены - могут быть любыми строковыми объектами в рантайме. + * - `e_repl(ИсходнаяСтрока, Искать, Заменять)`: заменяет в исходной строке вхождения Искать на Заменять. + * - `e_hex(Число)`: генерирует строку с 16ричным представлением числа. + * - `e_fill_left(StrExpr, width, symbol)`, `e_fill_right(StrExpr, width, symbol)`: дополняет строковое выражение до нужной длины заданным символом. * и т.д. и т.п. * + * В одно выражение могут объединятся строковые выражения для символов разных, но совместимых типов. + * То есть можно сочетать `char` и `char8_t`, под Linux `wchar_t` и `char32_t`, под Windows `wchar_t` и `char16_t`. + * * @en @defgroup StrExprs String Expressions * @brief Description of String Expressions * @details All owning string types can be initialized using "string expressions" @@ -267,6 +335,10 @@ concept StrType = requires(const A& a) { * During initialization, a string object asks the string expression for its size, allocates the necessary memory, * and passes the memory to a string expression that places the characters in the allocated buffer. * + * Additionally, for compatibility with `std`, simstr string expressions can be converted to standard strings + * (std::basic_string) compatible types. Before C++23, `resize` and `data` is used, starting with C++23 + * the more optimal `resize_and_overwrite` is used. This allows for fast concatenation where standard strings are required. + * * All library string objects are themselves string expressions that simply copy the original string. * Basically, string expressions are used to concatenate or convert strings. * @@ -303,18 +375,20 @@ concept StrType = requires(const A& a) { * between elements. * If `Skip Empty == true`, then empty lines do not add a separator, otherwise for each empty line * a separator is also inserted - * - `e_repl(SourceString, "Search", "Replace")`: replaces occurrences of "Search" with "Replace" in the source string. - * Find and replace patterns are compile-time string literals. - * - `expr_replaced< CharacterType>{SourceString, Search, Replace}`: replaces occurrences of Search with Replace in the source string. - * Search and replace patterns - can be any string objects at runtime. + * - `e_repl(SourceString, Search, Replace)`: replaces the occurrences of Search with Replace in the source string. + * - `e_hex(Number)`: generates a string with hexadecimal representation of the number. + * - `e_fill_left(StrExpr, width, symbol)`, `e_fill_right(StrExpr, width, symbol)`: fills a string expression to the required length with a given character. * etc. etc. + * + * String expressions for characters of different but compatible types can be combined into one expression. + * That is, you can combine `char` and `char8_t`, and under Linux `wchar_t` and `char32_t`, under Windows `wchar_t` and `char16_t`. */ /*! * @ingroup StrExprs - * @ru @brief Концепт "Строковых выражений" + * @ru @brief Концепт "Строковых выражений". * @details Это концепт, проверяющий, является ли тип "строковым выражением". - * @en @brief Concept of "String Expressions" + * @en @brief Concept of "String Expressions". * @details This is a concept that checks whether a type is a "string expression". */ template @@ -326,17 +400,17 @@ concept StrExpr = requires(const A& a) { /*! * @ingroup StrExprs - * @ru @brief Концепт строкового выражения заданного типа символов - * @tparam A - проверяемый тип - * @tparam K - проверяемый тип символов - * @details Служит для задания ограничения к строковому выражению по типу символов - * @en @brief The concept of a string expression of a given character type - * @tparam A - type being checked - * @tparam K - character type to be checked - * @details Used to set restrictions on a string expression by character type + * @ru @brief Концепт строкового выражения, совместимого с заданным типом символов. + * @tparam A - проверяемый тип. + * @tparam K - проверяемый тип символов. + * @details Служит для задания ограничения к строковому выражению по типу символов. + * @en @brief The concept of a string expression compatible with a given character type. + * @tparam A - type being checked. + * @tparam K - character type to be checked. + * @details Used to set restrictions on a string expression by character type. */ template -concept StrExprForType = StrExpr && std::is_same_v; +concept StrExprForType = StrExpr && is_equal_str_type_v; /* * Шаблонные классы для создания строковых выражений из нескольких источников. @@ -354,6 +428,46 @@ concept StrExprForType = StrExpr && std::is_same_v; * For concatenating two string expression objects into one. */ +template +constexpr std::basic_string, Allocator> to_std_string(const A& expr) { + std::basic_string, Allocator> res; + if (size_t l = expr.length()) { + auto fill = [&](K* ptr, size_t size) -> size_t { + expr.place((typename A::symb_type*)ptr); + return l; + }; + if constexpr (requires { res.resize_and_overwrite(l, fill); }) { + res.resize_and_overwrite(l, fill); + } else if constexpr (requires{ res._Resize_and_overwrite(l, fill); }) { + // Work in MSVC std lib before C++23 + res._Resize_and_overwrite(l, fill); + } else { + res.resize(l); // bad, fill by 0 first. + expr.place((typename A::symb_type*)res.data()); + } + } + return res; +} + +/*! + * @ru @brief Базовый класс для преобразования строковых выражений в стандартные строки + * @details Если хотите, чтобы ваш тип строкового выражения конвертировался в стандартную строку, + * наследуйтесь от этого класса. + * @tparam Impl - конечный класс-наследник, для CRTP. + * @en @brief Base class for converting string expressions to standard strings + * @details If you want your string expression type to be converted to a standard string, + * inherit from this class. + * @tparam Impl - final descendant class for CRTP. + */ +template +struct expr_to_std_string { + template + requires is_equal_str_type_v + constexpr operator std::basic_string, Allocator>() const { + return to_std_string(*static_cast(this)); + } +}; + /*! * @ingroup StrExprs * @ru @brief Шаблонный класс для конкатенации двух строковых выражений в одно с помощью `operator +` @@ -370,7 +484,7 @@ concept StrExprForType = StrExpr && std::is_same_v; * When asked to place characters in a buffer, place the first operand first, then the second. */ template B> -struct strexprjoin { +struct strexprjoin : expr_to_std_string>{ using symb_type = typename A::symb_type; const A& a; const B& b; @@ -379,12 +493,7 @@ struct strexprjoin { return a.length() + b.length(); } constexpr symb_type* place(symb_type* p) const noexcept { - return b.place(a.place(p)); - } - constexpr symb_type* len_and_place(symb_type* p) const noexcept { - a.length(); - b.length(); - return place(p); + return (symb_type*)b.place((typename B::symb_type*)a.place(p)); } }; @@ -437,7 +546,7 @@ constexpr strexprjoin operator+(const A& a, const B& b) { * You can see an example in simstr::operator+() */ template B, bool last = true> -struct strexprjoin_c { +struct strexprjoin_c : expr_to_std_string>{ using symb_type = typename A::symb_type; const A& a; B b; @@ -448,25 +557,13 @@ struct strexprjoin_c { } constexpr symb_type* place(symb_type* p) const noexcept { if constexpr (last) { - return b.place(a.place(p)); + return (symb_type*)b.place((typename B::symb_type*)a.place(p)); } else { - return a.place(b.place(p)); + return a.place((symb_type*)b.place((typename B::symb_type*)p)); } } - constexpr symb_type* len_and_place(symb_type* p) const noexcept { - a.length(); - b.length(); - return place(p); - } }; -template -struct is_one_of_type { - static constexpr bool value = std::is_same_v || is_one_of_type::value; -}; -template -struct is_one_of_type : std::false_type {}; - /*! * @ingroup StrExprs * @ru @brief "Пустое" строковое выражение. @@ -504,7 +601,7 @@ struct is_one_of_type : std::false_type {}; * ``` */ template -struct empty_expr { +struct empty_expr : expr_to_std_string>{ using symb_type = K; constexpr size_t length() const noexcept { return 0; @@ -520,6 +617,12 @@ struct empty_expr { * @en @brief Empty string expression of type char. */ inline constexpr empty_expr eea{}; +/*! + * @ingroup StrExprs + * @ru @brief Пустое строковое выражение типа char8_t. + * @en @brief Empty string expression of type char8_t. + */ +inline constexpr empty_expr eeb{}; /*! * @ingroup StrExprs * @ru @brief Пустое строковое выражение типа wchar_t. @@ -540,10 +643,10 @@ inline constexpr empty_expr eeu{}; inline constexpr empty_expr eeuu{}; template -struct expr_char { +struct expr_char : expr_to_std_string>{ using symb_type = K; K value; - expr_char(K v) : value(v){} + constexpr expr_char(K v) : value(v){} constexpr size_t length() const noexcept { return 1; } @@ -586,9 +689,11 @@ constexpr expr_char e_char(K s) { } template -struct expr_literal { +struct expr_literal : expr_to_std_string> { using symb_type = K; const K (&str)[N + 1]; + constexpr expr_literal(const K (&str_)[N + 1]) : str(str_){} + constexpr size_t length() const noexcept { return N; } @@ -657,10 +762,13 @@ constexpr expr_literal::symb_type, static_cast(N - } template -struct expr_literal_join { +struct expr_literal_join : expr_to_std_string> { using symb_type = K; + using atype = typename A::symb_type; const K (&str)[N + 1]; const A& a; + constexpr expr_literal_join(const K (&str_)[N + 1], const A& a_) : str(str_), a(a_){} + constexpr size_t length() const noexcept { return N + a.length(); } @@ -668,9 +776,9 @@ struct expr_literal_join { if constexpr (N != 0) { if constexpr (first) { std::char_traits::copy(p, str, N); - return a.place(p + N); + return (symb_type*)a.place((atype*)(p + N)); } else { - p = a.place(p); + p = (symb_type*)a.place((atype*)p); std::char_traits::copy(p, str, N); return p + N; } @@ -678,10 +786,6 @@ struct expr_literal_join { return a.place(p); } } - constexpr symb_type* len_and_place(symb_type* p) const noexcept { - a.length(); - return place(p); - } }; /*! @@ -691,8 +795,8 @@ struct expr_literal_join { * @en @brief The addition operator for a string expression and a string literal of the same character type. * @return A string expression concatenating the operands. */ -template::Count> -constexpr expr_literal_join operator+(const A& a, T&& s) { +template::symb_type, size_t N = const_lit::Count> requires is_equal_str_type_v +constexpr expr_literal_join operator+(const A& a, T&& s) { return {s, a}; } @@ -703,8 +807,8 @@ constexpr expr_literal_join operator+(const A& a, T&& s) { * @en @brief The addition operator for a string literal of the same character type and string expression. * @return A string expression concatenating the operands. */ -template::Count> -constexpr expr_literal_join operator+(T&& s, const A& a) { +template::symb_type, size_t N = const_lit::Count> requires is_equal_str_type_v +constexpr expr_literal_join operator+(T&& s, const A& a) { return {s, a}; } @@ -722,7 +826,7 @@ constexpr expr_literal_join operator+(T&& s, const A& a) { * @tparam S - character, space by default. */ template -struct expr_spaces { +struct expr_spaces : expr_to_std_string> { using symb_type = K; constexpr size_t length() const noexcept { return N; @@ -782,10 +886,11 @@ constexpr expr_spaces e_spcw() { * Usually not used directly, created via e_c(). */ template -struct expr_pad { +struct expr_pad : expr_to_std_string> { using symb_type = K; size_t len; K s; + constexpr expr_pad(size_t len_, K s_) : len(len_), s(s_){} constexpr size_t length() const noexcept { return len; } @@ -815,33 +920,51 @@ constexpr expr_pad e_c(size_t l, K s) { } template -struct expr_repeat_lit { +struct expr_repeat_lit : expr_to_std_string> { using symb_type = K; size_t repeat_; const K (&s)[N + 1]; + constexpr expr_repeat_lit(size_t repeat, const K (&s_)[N + 1]) : repeat_(repeat), s(s_){} constexpr size_t length() const noexcept { return N * repeat_; } constexpr symb_type* place(symb_type* p) const noexcept { - for (size_t i = 0; i < repeat_; i++) { - std::char_traits::copy(p, s, N); - p += N; + if constexpr (N) { + for (size_t i = 0; i < repeat_; i++) { + std::char_traits::copy(p, s, N); + p += N; + } } return p; } }; template -struct expr_repeat_expr { +struct expr_repeat_expr : expr_to_std_string> { using symb_type = typename A::symb_type; size_t repeat_; const A& expr_; + constexpr expr_repeat_expr(size_t repeat, const A& expr) : repeat_(repeat), expr_(expr){} constexpr size_t length() const noexcept { - return repeat_ * expr_.length(); + if (repeat_) { + return repeat_ * expr_.length(); + } + return 0; } constexpr symb_type* place(symb_type* p) const noexcept { - for (size_t i = 0; i < repeat_; i++) { + if (repeat_) { + if (repeat_ == 1) { + return expr_.place(p); + } + symb_type* start = p; p = expr_.place(p); + size_t len = size_t(p - start); + if (len) { + for (size_t i = 1; i < repeat_; i++) { + std::char_traits::copy(p, start, len); + p += len; + } + } } return p; } @@ -897,18 +1020,20 @@ constexpr expr_repeat_expr e_repeat(const A& s, size_t l) { * The type is usually not used directly; it is created via e_choice(). */ template B> -struct expr_choice { +struct expr_choice : expr_to_std_string> { using symb_type = typename A::symb_type; using my_type = expr_choice; const A& a; const B& b; bool choice; + constexpr expr_choice(const A& _a, const B& _b, bool _choice) : a(_a), b(_b), choice(_choice){} + constexpr size_t length() const noexcept { return choice ? a.length() : b.length(); } constexpr symb_type* place(symb_type* ptr) const noexcept { - return choice ? a.place(ptr) : b.place(ptr); + return choice ? a.place(ptr) : (symb_type*)b.place((typename B::symb_type*)ptr); } }; @@ -924,11 +1049,12 @@ struct expr_choice { * Title type usually not used, create through e_if(). */ template -struct expr_if { +struct expr_if : expr_to_std_string> { using symb_type = typename A::symb_type; using my_type = expr_if; const A& a; bool choice; + constexpr expr_if(const A& _a, bool _choice) : a(_a), choice(_choice){} constexpr size_t length() const noexcept { return choice ? a.length() : 0; @@ -984,19 +1110,20 @@ struct expr_if { * e_if(!condition, "empty"); * ``` */ -template -struct expr_choice_one_lit { - using symb_type = typename A::symb_type; +template A, size_t N, bool Compare> +struct expr_choice_one_lit : expr_to_std_string> { + using symb_type = L; const symb_type (&str)[N + 1]; const A& a; bool choice; + constexpr expr_choice_one_lit(const symb_type (&_str)[N + 1], const A& _a, bool _choice) : str(_str), a(_a), choice(_choice){} constexpr size_t length() const noexcept { return choice == Compare ? a.length() : N; } constexpr symb_type* place(symb_type* ptr) const noexcept { if (choice == Compare) { - return a.place(ptr); + return (L*)a.place((typename A::symb_type*)ptr); } if constexpr (N != 0) { std::char_traits::copy(ptr, str, N); @@ -1049,12 +1176,14 @@ struct expr_choice_one_lit { * e_if(!condition, "empty"); * ``` */ -template -struct expr_choice_two_lit { +template +struct expr_choice_two_lit : expr_to_std_string> { using symb_type = K; - const symb_type (&str_a)[N + 1]; - const symb_type (&str_b)[M + 1]; + const K (&str_a)[N + 1]; + const P (&str_b)[M + 1]; bool choice; + constexpr expr_choice_two_lit(const K(&_str_a)[N + 1], const P(&_str_b)[M + 1], bool _choice) + : str_a(_str_a), str_b(_str_b), choice(_choice){} constexpr size_t length() const noexcept { return choice ? N : M; @@ -1067,7 +1196,7 @@ struct expr_choice_two_lit { return ptr + N; } if constexpr (M != 0) { - std::char_traits::copy(ptr, str_b, M); + std::char_traits::copy(ptr, (const K(&)[M + 1])str_b, M); } return ptr + M; } @@ -1113,7 +1242,7 @@ constexpr expr_choice e_choice(bool c, const A& a, const B& b) { * @en @brief Overload e_choice when the third argument is a string literal. */ template::Count> -constexpr expr_choice_one_lit e_choice(bool c, const A& a, T&& str) { +constexpr expr_choice_one_lit::symb_type, A, N - 1, true> e_choice(bool c, const A& a, T&& str) { return {str, a, c}; } @@ -1123,7 +1252,7 @@ constexpr expr_choice_one_lit e_choice(bool c, const A& a, T&& s * @en @brief Overload e_choice when the second argument is a string literal. */ template::Count> -constexpr expr_choice_one_lit e_choice(bool c, T&& str, const A& a) { +constexpr expr_choice_one_lit::symb_type, A, N - 1, false> e_choice(bool c, T&& str, const A& a) { return {str, a, c}; } /*! @@ -1131,8 +1260,10 @@ constexpr expr_choice_one_lit e_choice(bool c, T&& str, const A * @ru @brief Перегрузка e_choice, когда второй и третий аргумент - строковые литералы. * @en @brief Overload e_choice when the second and third arguments are string literals. */ -template::Count, size_t M = const_lit_for::symb_type, L>::Count> -constexpr expr_choice_two_lit::symb_type, N -1, M - 1> e_choice(bool c, T&& str_a, L&& str_b) { +template::symb_type, typename P = typename const_lit::symb_type, + size_t N = const_lit::Count, size_t M = const_lit_for::symb_type, L>::Count> + requires is_equal_str_type_v +constexpr expr_choice_two_lit e_choice(bool c, T&& str_a, L&& str_b) { return {str_a, str_b, c}; } @@ -1189,20 +1320,35 @@ constexpr expr_if e_if(bool c, const A& a) { */ template::Count> constexpr auto e_if(bool c, T&& str) { - const typename const_lit::symb_type empty[1] = {0}; - return expr_choice_two_lit::symb_type, N - 1, 0>{str, empty, c}; + using K = typename const_lit::symb_type; + const K empty[1] = {0}; + return expr_choice_two_lit{str, empty, c}; } +template struct is_std_string_source : std::false_type{}; + +template +struct is_std_string_source, A>> : std::true_type{}; + +template +struct is_std_string_source>> : std::true_type{}; + +template +constexpr bool is_std_string_source_v = is_std_string_source::value; + +template +concept StdStrSource = is_std_string_source_v>; + /*! * @ingroup StrExprs - * @ru @brief Тип для использования std::string и std::string_view как источников в строковых выражениях. + * @ru @brief Тип для использования std::basic_string и std::basic_string_view как источников в строковых выражениях. * @tparam K - тип символа. * @tparam T - тип источника. * @en @brief A type for using std::string and std::string_view as sources in string expressions. * @tparam K is a symbol. * @tparam T - source type. */ -template +template requires is_equal_str_type_v struct expr_stdstr { using symb_type = K; const T& t_; @@ -1210,7 +1356,7 @@ struct expr_stdstr { expr_stdstr(const T& t) : t_(t){} constexpr size_t length() const noexcept { - return t_.size(); + return t_.length(); } constexpr symb_type* place(symb_type* p) const noexcept { size_t s = t_.size(); @@ -1221,130 +1367,3776 @@ struct expr_stdstr { /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для char строкового выражения и std::string. - * @en @brief Addition operator for char string expression and std::string. + * @ru @brief Оператор сложения для строкового выражения и стандартных строк совместимого типа. + * @en @brief The addition operator for string expression and standard strings of compatible type. */ -template A> -constexpr strexprjoin_c, true> operator+(const A& a, const std::string& s) { +template A> +constexpr strexprjoin_c, true> operator+(const A& a, const T& s) { return {a, s}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для std::string и char строкового выражения. - * @en @brief Addition operator for std::string and char string expression. + * @ru @brief Оператор сложения для стандартных строк и строкового выражения совместимого типа. + * @en @brief The addition operator for standard strings and string expressions of compatible type. */ -template A> -constexpr strexprjoin_c, false> operator+(const std::string& s, const A& a) { +template A> +constexpr strexprjoin_c, false> operator+(const T& s, const A& a) { + return {a, s}; +} + +namespace str { +constexpr const size_t npos = static_cast(-1); //NOLINT +} // namespace str + +template +struct ch_traits : std::char_traits{}; + +template +concept FromIntNumber = + is_one_of_type, unsigned char, int, short, long, long long, unsigned, unsigned short, unsigned long, unsigned long long>::value; + +template +concept ToIntNumber = FromIntNumber || is_one_of_type::value; + +template +struct need_sign { // NOLINT + bool negate; + need_sign(T& t) : negate(t < 0) { + if (negate && t != std::numeric_limits::min()) + t = -t; + } + void after(K*& ptr) { + if (negate) + *--ptr = '-'; + } +}; + +template +struct need_sign { + need_sign(T&) {} + void after(K*&) {} +}; + +template +constexpr size_t fromInt(K* bufEnd, T val) { + const char* twoDigit = + "0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"; + if (val) { + need_sign, T> sign(val); + K* itr = bufEnd; + // Когда у нас минимальное отрицательное число, оно не меняется и остается меньше нуля + // When we have a minimum negative number, it does not change and remains less than zero + if constexpr (std::is_signed_v) { + if (val < 0) { + // Возьмем две последние цифры + // Take the last two digits + const char* ptr = twoDigit - (val % 100) * 2; + *--itr = static_cast(ptr[1]); + *--itr = static_cast(ptr[0]); + val /= 100; + val = -val; + } + } + while (val >= 100) { + const char* ptr = twoDigit + (val % 100) * 2; + *--itr = static_cast(ptr[1]); + *--itr = static_cast(ptr[0]); + val /= 100; + } + if (val < 10) { + *--itr = static_cast('0' + val); + } else { + const char* ptr = twoDigit + val * 2; + *--itr = static_cast(ptr[1]); + *--itr = static_cast(ptr[0]); + } + sign.after(itr); + return size_t(bufEnd - itr); + } + bufEnd[-1] = '0'; + return 1; +} + +template +struct expr_num : expr_to_std_string> { + using symb_type = K; + using my_type = expr_num; + + enum { bufSize = 24 }; + mutable T value; + mutable K buf[bufSize]; + + constexpr expr_num(T t) : value(t) {} + constexpr expr_num(expr_num&& t) : value(t.value) {} + + size_t length() const noexcept { + value = (T)fromInt(buf + bufSize, value); + return (size_t)value; + } + K* place(K* ptr) const noexcept { + size_t len = (size_t)value; + ch_traits::copy(ptr, buf + bufSize - len, len); + return ptr + len; + } +}; + +/*! + * @ingroup StrExprs + * @ru @brief Оператор конкатенации для строкового выражения и целого числа. + * @param a - строковое выражение. + * @param s - число. + * @details Число конвертируется в десятичное строковое представление. + * @en @brief Concatenation operator for string expression and integer. + * @param a is a string expression. + * @param s - number. + * @details The number is converted to a decimal string representation. + */ +template +constexpr strexprjoin_c> operator + (const A& a, T s) { return {a, s}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для char строкового выражения и std::string_view. - * @en @brief Addition operator for char string expression and std::string_view. + * @ru @brief Оператор конкатенации для целого числа и строкового выражения. + * @param s - число. + * @param a - строковое выражение. + * @details Число конвертируется в десятичное строковое представление. + * @en @brief Concatenation operator for integer and string expression. + * @param s - number. + * @param a is a string expression. + * @details The number is converted to a decimal string representation. */ -template A> -constexpr strexprjoin_c, true> operator+(const A& a, const std::string_view& s) { +template +constexpr strexprjoin_c, false> operator + (T s, const A& a) { return {a, s}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для std::string_view и char строкового выражения. - * @en @brief Addition operator for std::string_view and char string expression. + * @ru @brief Преобразование целого числа в строковое выражение. + * @tparam K - тип символов. + * @tparam T - тип числа, выводится из аргумента. + * @param t - число. + * @details Возвращает строковое выражение, которое генерирует десятичное представление заданного числа. + * Может использоваться, когда надо конкатенировать число и строковый литерал. + * @en @brief Convert an integer to a string expression. + * @tparam K - character type. + * @tparam T - number type, inferred from the argument. + * @param t - number. + * @details Returns a string expression that generates the decimal representation of the given number. + * Can be used when you need to concatenate a number and a string literal. */ -template A> -constexpr strexprjoin_c, false> operator+(const std::string_view& s, const A& a) { - return {a, s}; +template +constexpr expr_num e_num(T t) { + return {t}; +} + +template +struct expr_real : expr_to_std_string> { + using symb_type = K; + mutable std::conditional_t, K, u8s> buf[40]; + mutable size_t l; + double v; + constexpr expr_real(double d) : v(d) {} + constexpr expr_real(float d) : v(d) {} + + size_t length() const noexcept { + if constexpr (sizeof(buf[0]) == 1) { + l = std::snprintf(to_one_of_std_char(buf), std::size(buf), "%.16g", v); + } else { + l = std::swprintf(to_one_of_std_char(buf), std::size(buf), L"%.16g", v); + } + return l; + } + K* place(K* ptr) const noexcept { + if constexpr (sizeof(K) == sizeof(buf[0])) { + ch_traits::copy(ptr, buf, l); + } else { + for (size_t i = 0; i < l; i++) { + ptr[i] = buf[i]; + } + } + return ptr + l; + } +}; + +/*! + * @ingroup StrExprs + * @ru @brief Оператор конкатенации для строкового выражения и вещественного числа (`float`, `double`). + * @param a - строковое выражение. + * @param s - число. + * @details Число конвертируется в строковое представление через sprintf("%.16g"). + * @en @brief Concatenation operator for string expression and real number (`float`, `double`). + * @param a is a string expression. + * @param s - number. + * @details The number is converted to a string representation via sprintf("%.16g"). + */ +template + requires(std::is_same_v || std::is_same_v) +inline constexpr auto operator+(const A& a, R s) { + return strexprjoin_c>{a, s}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для wchar_t строкового выражения и std::wstring. - * @en @brief Addition operator for wchar_t string expression and std::wstring. + * @ru @brief Оператор конкатенации для вещественного числа (`float`, `double`) и строкового выражения. + * @param s - число. + * @param a - строковое выражение. + * @details Число конвертируется в строковое представление через `sprintf("%.16g")`. + * @en @brief Concatenation operator for float (`float`, `double`) and string expression. + * @param s - number. + * @param a is a string expression. + * @details The number is converted to a string representation via `sprintf("%.16g")`. */ -template A> -constexpr strexprjoin_c, true> operator+(const A& a, const std::wstring& s) { - return {a, s}; +template + requires(std::is_same_v || std::is_same_v) +inline constexpr auto operator+(R s, const A& a) { + return strexprjoin_c, false>{a, s}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для std::wstring и wchar_t строкового выражения. - * @en @brief Addition operator for std::wstring and wchar_t string expression. + * @ru @brief Преобразование `double` числа в строковое выражение. + * @param t - число. + * @details Возвращает строковое выражение, которое генерирует десятичное представление заданного числа. + * с помощью `sprintf("%.16g")`. Может использоваться, когда надо конкатенировть число и строковый литерал. + * @en @brief Convert a `double` number to a string expression. + * @param t - number. + * @details Returns a string expression that generates the decimal representation of the given number. + * using `sprintf("%.16g")`. Can be used when you need to concatenate a number and a string literal. */ -template A> -constexpr strexprjoin_c, false> operator+(const std::wstring& s, const A& a) { - return {a, s}; +template requires is_one_of_char_v +inline constexpr auto e_num(double t) { + return expr_real{t}; +} + +template +constexpr K hex_symbols[16] = {K('0'), K('1'), K('2'), K('3'), K('4'), K('5'), K('6'), + K('7'), K('8'), K('9'), K(Ucase ? 'A' : 'a'), K(Ucase ? 'B' : 'b'), K(Ucase ? 'C' : 'c'), + K(Ucase ? 'D' : 'd'), K(Ucase ? 'E' : 'e'), K(Ucase ? 'F' : 'f')}; + +template +requires std::is_unsigned_v +struct expr_hex : expr_to_std_string> { + using symb_type = K; + mutable Val v_; + mutable K buf_[sizeof(Val) * 2]; + + explicit constexpr expr_hex(Val v) : v_(v){} + + constexpr size_t length() const noexcept { + K* ptr = buf_ + sizeof(Val) * 2; + Val value = v_; + size_t l = 0; + for (;;) { + *--ptr = hex_symbols[value & 0xF]; + value >>= 4; + l++; + if (value) { + *--ptr = hex_symbols[value & 0xF]; + value >>= 4; + l++; + } + if (!value) { + if constexpr (All) { + if (size_t need = sizeof(Val) * 2 - l) { + ch_traits::assign(buf_, need, K('0')); + l = sizeof(Val) * 2; + } + } + break; + } + } + v_ = (Val)l; + return l + (Ox ? 2 : 0); + } + constexpr K* place(K* ptr) const noexcept { + if constexpr (Ox) { + *ptr++ = K('0'); + *ptr++ = K('x'); + } + ch_traits::copy(ptr, buf_ + sizeof(Val) * 2 - v_, v_); + return ptr + v_; + } +}; + +template +requires std::is_unsigned_v +struct expr_hex_src { + explicit constexpr expr_hex_src(Val v) : v_(v){} + Val v_; +}; + +/*! + * @ingroup StrExprs + * @ru @brief Флаги для функции e_hex. + * @en @brief Flags for the e_hex function. + */ +enum HexFlags : unsigned { + Short = 1, ///< without leading zeroes + No0x = 2, //< without 0x prefix + Lcase = 4, //< Use lower case +}; + +/*! + * @ingroup StrExprs + * @ru @brief Позволяет конкатенировать текст и беззнаковое число в 16-ричном виде. + * @tparam Flags - флаги форматирования, побитовое ИЛИ из HexFlags. + * @tparam T - тип числа, выводится автоматически. + * @en @brief Allows you to concatenate text and a unsigned number in hexadecimal. + * @tparam Flags - format flags, bitwise OR of HexFlags. + * @tparam T - number type, deducted automatically. + * @details @ru Пример @en Example @~ + * ```cpp + * stringa text = +"val = "sv + e_hex(10u); + * EXPECT_EQ(text, "val = 0x0000000A"); + * + * stringu textu = +u"val = 0X"sv + e_hex(0x12Au); + * EXPECT_EQ(textu, u"val = 0X12a"); + * ``` + */ +template requires std::is_unsigned_v +constexpr auto e_hex(T v) { + return expr_hex_src{v}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для wchar_t строкового выражения и std::wstring_view. - * @en @brief Addition operator for wchar_t string expression and std::wstring_view. + * @ru @brief Оператор конкатенации для строкового выражения и 16ричного представления числа из e_hex(). + * @param a - строковое выражение. + * @param b - e_hex(число). + * @en @brief Concatenation operator for a string expression and a hexadecimal representation of a number from e_hex(). + * @param a is a string expression. + * @param b is e_hex(number). */ -template A> -constexpr strexprjoin_c, true> operator+(const A& a, const std::wstring_view& s) { - return {a, s}; +template +constexpr strexprjoin_c, true> operator+(const A& a, const expr_hex_src& b) { + return {a, expr_hex{b.v_}}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для std::wstring_view и wchar_t строкового выражения. - * @en @brief Addition operator for std::wstring_view and wchar_t string expression. + * @ru @brief Оператор конкатенации для 16ричного представления числа из e_hex() и строкового выражения. + * @param a - e_hex(число). + * @param b - строковое выражение. + * @en @brief Concatenation operator for the hexadecimal representation of a number from e_hex() and a string expression. + * @param a - e_hex(number). + * @param b is a string expression. */ -template A> -constexpr strexprjoin_c, false> operator+(const std::wstring_view& s, const A& a) { - return {a, s}; +template +constexpr strexprjoin_c, false> operator+(const expr_hex_src& b, const A& a) { + return {a, expr_hex{b.v_}}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для совместимого с wchar_t строкового выражения (char16_t или - * char32_t, в зависимости от компилятора) и std::wstring. - * @en @brief Addition operator for wchar_t compatible string expression (char16_t or - * char32_t, depending on the compiler) and std::wstring. + * @ru @brief Оператор конкатенации для строкового выражения и указателя, представляет его как 0xDEADBEEF. + * @param a - строковое выражение. + * @param b - указатель. + * @en @brief Concatenation operator for a string expression and a pointer, representing it as 0xDEADBEEF. + * @param a is a string expression. + * @param b is a pointer. */ -template A> -constexpr strexprjoin_c, true> operator+(const A& a, const std::wstring& s) { - return {a, s}; +template +constexpr strexprjoin_c, true> operator+(const A& a, const void* b) { + return {a, (uintptr_t)b}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для std::wstring и совместимого с wchar_t строкового выражения - * (char16_t или char32_t, в зависимости от компилятора). - * @en @brief Addition operator for std::wstring and wchar_t-compatible string expression - * (char16_t or char32_t, depending on the compiler). + * @ru @brief Оператор конкатенации для указателя и строкового выражения, представляет его как 0xDEADBEEF. + * @param a - указатель. + * @param b - строковое выражение. + * @en @brief Concatenation operator for a pointer and a string expression, representing it as 0xDEADBEEF. + * @param a - pointer. + * @param b is a string expression. */ -template A> -constexpr strexprjoin_c, false> operator+(const std::wstring& s, const A& a) { - return {a, s}; +template +constexpr strexprjoin_c, false> operator+(const void* b, const A& a) { + return {a, (uintptr_t)b}; +} + +template A, bool Left> +struct expr_fill : expr_to_std_string>{ + using symb_type = K; + K symbol_; + size_t width_; + const A& a_; + mutable size_t alen_{}; + constexpr expr_fill(K symbol, size_t width, const A& a) : symbol_(symbol), width_(width), a_(a){} + + constexpr size_t length() const noexcept { + alen_ = a_.length(); + return std::max(alen_, width_); + } + constexpr K* place(K* ptr) const noexcept { + if (alen_ >= width_) { + return (K*)a_.place((typename A::symb_type*)ptr); + } + size_t w = width_ - alen_; + if constexpr (Left) { + ch_traits::assign(ptr, w, symbol_); + ptr += w; + return (K*)a_.place((typename A::symb_type*)ptr); + } else { + ptr = (K*)a_.place((typename A::symb_type*)ptr); + ch_traits::assign(ptr, w, symbol_); + return ptr + w; + } + } +}; + +/*! + * @ingroup StrExprs + * @ru @brief Создает выражение, которое дополняет указанное строковое выражение до заданной длины + * заданным символом слева. + * @param width - дополнять до этой ширины + * @param symbol - символ для заполнения + * @details Если строковое выражение выдаёт строку короче заданной длины, добавляет перед ней + * указанный символ, дополняя до нужной длины. Не обрезает строку до указанной длины. + * Будьте внимательны, длина берётся в code units, не в code points, а символ заполнения + * не может быть суррогатным, то есть занимать более одного code unit. Если надо быть точным + * с Unicode-символами - используйте конвертацию в char32_t и обратно. + * @en @brief Creates an expression that expands the specified string expression to the specified length + * given character to the left. + * @param width - pad to this width + * @param symbol - symbol to fill + * @details If a string expression produces a string shorter than the given length, prepend it with + * the specified character, padding to the desired length. Does not truncate the string to the specified length. + * Be careful, the length is taken in code units, not in code points, and the padding character + * cannot be a surrogate, that is, occupy more than one code unit. If you have to be precise + * with Unicode characters - use conversion to char32_t and vice versa. + */ +template +expr_fill e_fill_left(const A& a, size_t width, K symbol = K(' ')) { + return {symbol, width, a}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для совместимого с wchar_t строкового выражения (char16_t или - * char32_t, в зависимости от компилятора) и std::wstring_view. - * @en @brief Addition operator for wchar_t compatible string expression (char16_t or - * char32_t, depending on the compiler) and std::wstring_view. + * @ru @brief Создает выражение, которое дополняет указанное строковое выражение до заданной длины + * заданным символом справа. + * @param width - дополнять до этой ширины + * @param symbol - символ для заполнения + * @details Если строковое выражение выдаёт строку короче заданной длины, добавляет к ней + * указанный символ, дополняя до нужной длины. Не обрезает строку до указанной длины. + * Будьте внимательны, длина берётся в code units, не в code points, а символ заполнения + * не может быть суррогатным, то есть занимать более одного code unit. Если надо быть точным + * с Unicode-символами - используйте конвертацию в char32_t и обратно. + * @en @brief Creates an expression that expands the specified string expression to the specified length + * given character to the right. + * @param width - pad to this width + * @param symbol - symbol to fill + * @details If a string expression produces a string shorter than the given length, appends it + * the specified character, padding to the desired length. Does not truncate the string to the specified length. + * Be careful, the length is taken in code units, not in code points, and the padding character + * cannot be a surrogate, that is, occupy more than one code unit. If you have to be precise + * with Unicode characters - use conversion to char32_t and vice versa. */ -template A> -constexpr strexprjoin_c, true> operator+(const A& a, const std::wstring_view& s) { - return {a, s}; +template +expr_fill e_fill_right(const A& a, size_t width, K symbol = K(' ')) { + return {symbol, width, a}; +} + +/* +* Для создания строковых конкатенаций с векторами и списками, сджойненными константным разделителем +* K - тип символов строки +* T - тип контейнера строк (vector, list) +* I - длина разделителя в символах +* tail - добавлять разделитель после последнего элемента контейнера. +* Если контейнер пустой, разделитель в любом случае не добавляется +* skip_empty - пропускать пустые строки без добавления разделителя +* To create string concatenations with vectors and lists joined by a constant delimiter +* K is the symbols +* T - type of string container (vector, list) +* I - length of separator in characters +* tail - add a separator after the last element of the container. +* If the container is empty, the separator is not added anyway +* skip_empty - skip empty lines without adding a separator +*/ +template +struct expr_join : expr_to_std_string> { + using symb_type = K; + using my_type = expr_join; + + const T& s; + const K* delim; + constexpr expr_join(const T& _s, const K* _delim) : s(_s), delim(_delim){} + + constexpr size_t length() const noexcept { + size_t l = 0; + for (const auto& t: s) { + size_t len = t.length(); + if (len > 0 || !skip_empty) { + if (I > 0 && l > 0) { + l += I; + } + l += len; + } + } + return l + (tail && I > 0 && (l > 0 || (!skip_empty && s.size() > 0))? I : 0); + } + constexpr K* place(K* ptr) const noexcept { + if (s.empty()) { + return ptr; + } + K* write = ptr; + for (const auto& t: s) { + size_t copyLen = t.length(); + if (I > 0 && write != ptr && (copyLen || !skip_empty)) { + ch_traits::copy(write, delim, I); + write += I; + } + ch_traits::copy(write, t.data(), copyLen); + write += copyLen; + } + if (I > 0 && tail && (write != ptr || (!skip_empty && s.size() > 0))) { + ch_traits::copy(write, delim, I); + write += I; + } + return write; + } +}; + +/*! + * @ingroup StrExprs + * @ru @brief Получить строковое выражение, конкатенирующее строки в контейнере в одну строку с заданным разделителем. + * @tparam tail - добавлять ли разделитель после последней строки. + * @tparam skip_empty - пропускать пустые строки без добавления разделителя. + * @param s - контейнер со строками, должен поддерживать `range for`. + * @param d - разделитель, строковый литерал. + * @en @brief Get a string expression concatenating the strings in the container into a single string with the given delimiter.limiter.limiter. + * @tparam tail - whether to add a separator after the last line. + * @tparam skip_empty - skip empty lines without adding a separator. + * @param s - container with strings, must support `range for`. + * @param d - delimiter, string literal. + */ +template::symb_type, size_t I = const_lit::Count, typename T> +inline constexpr auto e_join(const T& s, L&& d) { + return expr_join{s, d}; +} + +template +concept is_const_pattern = N > 1 && N <= 17; + +template +struct _ascii_mask { // NOLINT + constexpr static const size_t value = size_t(K(~0x7F)) << ((I - 1) * sizeof(K) * 8) | _ascii_mask::value; +}; + +template +struct _ascii_mask { + constexpr static const size_t value = 0; +}; + +template +struct ascii_mask { // NOLINT + using uns = std::make_unsigned_t; + constexpr static const size_t WIDTH = sizeof(size_t) / sizeof(uns); + constexpr static const size_t VALUE = _ascii_mask::value; +}; + +template +constexpr inline bool isAsciiUpper(K k) { + return k >= 'A' && k <= 'Z'; +} + +template +constexpr inline bool isAsciiLower(K k) { + return k >= 'a' && k <= 'z'; +} + +template +constexpr inline K makeAsciiLower(K k) { + return isAsciiUpper(k) ? k | 0x20 : k; +} + +template +constexpr inline K makeAsciiUpper(K k) { + return isAsciiLower(k) ? k & ~0x20 : k; +} + +enum TrimSides { TrimLeft = 1, TrimRight = 2, TrimAll = 3 }; +template +struct trim_operator; + +template +struct digits_selector { + using wider_type = uint16_t; +}; + +template<> +struct digits_selector<2> { + using wider_type = uint32_t; +}; + +template<> +struct digits_selector<4> { + using wider_type = uint64_t; +}; + +/*! + * @ru @brief Перечисление с возможными результатами преобразования строки в целое число + * @en @brief Enumeration with possible results of converting a string to an integer + */ +enum class IntConvertResult : char { + Success, //!< Успешно + BadSymbolAtTail, //!< Число закончилось не числовым символом + Overflow, //!< Переполнение, число не помещается в заданный тип + NotNumber //!< Вообще не число +}; + +template +struct result_type_selector { // NOLINT + using type = T; +}; + +template +struct result_type_selector { + using type = std::make_unsigned_t; +}; + +template +constexpr unsigned digit_width() { + if (Base <=2) { + return 1; + } + if (Base <= 4) { + return 2; + } + if (Base <= 8) { + return 3; + } + if (Base <= 16) { + return 4; + } + if (Base <= 32) { + return 5; + } + return 6; +} + +template +constexpr unsigned max_overflow_digits = (sizeof(T) * CHAR_BIT) / digit_width(); + +template +struct convert_result { + T value; + IntConvertResult ec; + size_t read; +}; + +struct int_convert { // NOLINT + inline static const uint8_t NUMBERS[] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; + + template + static constexpr std::make_unsigned_t toDigit(K s) { + auto us = static_cast>(s); + if constexpr (Base <= 10) { + return us - '0'; + } else { + if constexpr (sizeof(K) == 1) { + return NUMBERS[us]; + } else { + return us < 256 ? NUMBERS[us] : us; + } + } + } + + template + requires(Base != 0) + static constexpr convert_result parse(const K* start, const K* current, const K* end, bool negate) { + using u_type = std::make_unsigned_t; + #ifndef HAS_BUILTIN_OVERFLOW + u_type maxMult = 0, maxAdd = 0; + if constexpr (CheckOverflow) { + maxMult = std::numeric_limits::max() / Base; + maxAdd = std::numeric_limits::max() % Base; + } + #endif + u_type number = 0; + unsigned maxDigits = max_overflow_digits; + IntConvertResult error = IntConvertResult::NotNumber; + const K* from = current; + + bool no_need_check_o_f = !CheckOverflow || end - current <= maxDigits; + + if (no_need_check_o_f) { + for (;;) { + const u_type digit = toDigit(*current); + if (digit >= Base) { + break; + } + number = number * Base + digit; + if (++current == end) { + error = IntConvertResult::Success; + break; + } + } + } else { + for (;maxDigits; maxDigits--) { + const u_type digit = toDigit(*current); + if (digit >= Base) { + break; + } + number = number * Base + digit; + ++current; + } + if (!maxDigits) { + // Прошли все цифры, дальше надо с проверкой на overflow + // All numbers have passed, then we need to check for overflow + for (;;) { + const u_type digit = toDigit(*current); + if (digit >= Base) { + break; + } + #ifdef HAS_BUILTIN_OVERFLOW + if (__builtin_mul_overflow(number, Base, &number) || + __builtin_add_overflow(number, digit, &number)) { + #else + if (number < maxMult || (number == maxMult && number < maxAdd)) { + number = number * Base + digit; + } else { + #endif + error = IntConvertResult::Overflow; + while(++current < end) { + if (toDigit(*current) >= Base) { + break; + } + } + break; + } + if (++current == end) { + error = IntConvertResult::Success; + break; + } + } + } + } + T result; + if constexpr (std::is_signed_v) { + result = negate ? 0 - number : number; + if constexpr (CheckOverflow) { + if (error != IntConvertResult::Overflow) { + if (number > std::numeric_limits::max() + (negate ? 1 : 0)) { + error = IntConvertResult::Overflow; + } + } + } + } else { + result = number; + } + if (error == IntConvertResult::NotNumber && current > from) { + error = IntConvertResult::BadSymbolAtTail; + } + return {result, error, size_t(current - start)}; + } +public: + // Если Base = 0 - то пытается определить основание по префиксу 0[xX] как 16, 0 как 8, иначе 10 + // Если Base = -1 - то пытается определить основание по префиксу 0[xX] как 16, 0[bB] как 2, 0[oO] или 0 как 8, иначе 10 + // If Base = 0, then it tries to determine the base by the prefix 0[xX] as 16, 0 as 8, otherwise 10 + // If Base = -1 - then tries to determine the base by the prefix 0[xX] as 16, 0[bB] as 2, 0[oO] or 0 as 8, otherwise 10 + template + requires(Base == -1 || (Base < 37 && Base != 1)) + static constexpr convert_result to_integer(const K* start, size_t len) noexcept { + const K *ptr = start, *end = ptr + len; + bool negate = false; + if constexpr (SkipWs) { + while (ptr < end && std::make_unsigned_t(*ptr) <= ' ') + ptr++; + } + if (ptr != end) { + if constexpr (std::is_signed_v) { + if constexpr (AllowSign) { + // Может быть число, +число или -число + // Can be a number, +number or -number + if (*ptr == '+') { + ptr++; + } else if (*ptr == '-') { + negate = true; + ptr++; + } + } else { + // Может быть число или -число + // Can be a number or -number + if (*ptr == '-') { + negate = true; + ptr++; + } + } + } else if constexpr (AllowSign) { + // Может быть число или +число + // Can be a number or +number + if (*ptr == '+') { + ptr++; + } + } + } + if (ptr != end) { + if constexpr (Base == 0 || Base == -1) { + if (*ptr == '0') { + ptr++; + if (ptr != end) { + if (*ptr == 'x' || *ptr == 'X') { + return parse(start, ++ptr, end, negate); + } + if constexpr (Base == -1) { + if (*ptr == 'b' || *ptr == 'B') { + return parse(start, ++ptr, end, negate); + } + if (*ptr == 'o' || *ptr == 'O') { + return parse(start, ++ptr, end, negate); + } + } + return parse(start, --ptr, end, negate); + } + return {0, IntConvertResult::Success, size_t(ptr - start)}; + } + return parse(start, ptr, end, negate); + } else + return parse(start, ptr, end, negate); + } + return {0, IntConvertResult::NotNumber, size_t(ptr - start)}; + } +}; + +template +class null_terminated { +public: + /*! + * @ru @brief Получить указатель на константный буфер символов строки + * @return const K* - указатель на константный буфер символов строки + * @en @brief Get a pointer to a constant character buffer of a string + * @return const K* - pointer to a constant string character buffer + */ + constexpr const K* c_str() const { return static_cast(this)->symbols(); } +}; + +template class buffer_pointers; + +/*! + * @ru @brief Базовый класс для строкового буфера. + * @tparam K - тип символов. + * @tparam Impl - класс реализации. + * @en @brief Base class for a string buffer. + * @tparam K - character type. + * @tparam Impl - implementation class. + */ +template +class buffer_pointers { + constexpr const Impl& d() const { return *static_cast(this); } +public: + /*! + * @ru @brief Получить указатель на константный буфер символов строки. + * @return const K* - указатель на константный буфер символов строки. + * @en @brief Get a pointer to a constant character buffer of a string. + * @return const K* - pointer to a constant buffer of string characters. + */ + constexpr const K* data() const { return d().symbols(); } + /*! + * @ru @brief Получить указатель на константный буфер символов строки. + * @return const K* - указатель на константный буфер символов строки. + * @en @brief Get a pointer to a constant character buffer of a string. + * @return const K* - pointer to a constant buffer of string characters. + */ + constexpr const K* begin() const { return d().symbols(); } + /*! + * @ru @brief Указатель на константный символ после после последнего символа строки. + * @return const K* - конец строки. + * @en @brief Pointer to a constant character after the last character of the string. + * @return const K* - end of line. + */ + constexpr const K* end() const { return d().symbols() + d().length(); } + /*! + * @ru @brief Получить указатель на константный буфер символов строки. + * @return const K* - указатель на константный буфер символов строки. + * @en @brief Get a pointer to a constant character buffer of a string. + * @return const K* - pointer to a constant buffer of string characters. + */ + constexpr const K* cbegin() const { return d().symbols(); } + /*! + * @ru @brief Указатель на константный символ после после последнего символа строки. + * @return const K* - конец строки. + * @en @brief Pointer to a constant character after the last character of the string. + * @return const K* - end of line. + */ + constexpr const K* cend() const { return d().symbols() + d().length(); } +}; + +template +class buffer_pointers : public buffer_pointers { + constexpr Impl& d() { return *static_cast(this); } + using base = buffer_pointers; +public: + /*! + * @ru @brief Получить указатель на константный буфер символов строки. + * @return const K* - указатель на константный буфер символов строки. + * @en @brief Get a pointer to a constant character buffer of a string. + * @return const K* - pointer to a constant buffer of string characters. + */ + constexpr const K* data() const { return base::data(); } + /*! + * @ru @brief Получить указатель на константный буфер символов строки. + * @return const K* - указатель на константный буфер символов строки. + * @en @brief Get a pointer to a constant character buffer of a string. + * @return const K* - pointer to a constant buffer of string characters. + */ + constexpr const K* begin() const { return base::begin(); } + /*! + * @ru @brief Указатель на константный символ после после последнего символа строки. + * @return const K* - конец строки. + * @en @brief Pointer to a constant character after the last character of the string. + * @return const K* - end of line. + */ + constexpr const K* end() const { return base::end(); } + /*! + * @ru @brief Получить указатель на константный буфер символов строки. + * @return const K* - указатель на константный буфер символов строки. + * @en @brief Get a pointer to a constant character buffer of a string. + * @return const K* - pointer to a constant buffer of string characters. + */ + constexpr const K* cbegin() const { return base::cbegin(); } + /*! + * @ru @brief Указатель на константный символ после после последнего символа строки. + * @return const K* - конец строки. + * @en @brief Pointer to a constant character after the last character of the string. + * @return const K* - end of line. + */ + constexpr const K* cend() const { return base::cend(); } + /*! + * @ru @brief Получить указатель на буфер символов строки. + * @return K* - указатель на буфер символов строки. + * @en @brief Get a pointer to the string's character buffer. + * @return K* - pointer to a string character buffer. + */ + constexpr K* data() { return d().str(); } + /*! + * @ru @brief Получить указатель на буфер символов строки. + * @return K* - указатель на буфер символов строки. + * @en @brief Get a pointer to the string's character buffer. + * @return K* - pointer to a string character buffer. + */ + constexpr K* begin() { return d().str(); } + /*! + * @ru @brief Указатель на символ после после последнего символа строки. + * @return K* - конец строки. + * @en @brief Pointer to the character after the last character of the string. + * @return K* - end of line. + */ + constexpr K* end() { return d().str() + d().length(); } +}; + +/*! + * @ru @brief Класс для последовательного получения подстрок по заданному разделителю. + * @tparam K - тип символов. + * @en @brief Class for sequentially obtaining substrings by a given delimiter. + * @tparam K - character type. + */ +template +class SplitterBase { + using str_t = StrSrc; + str_t text_; + str_t delim_; + +public: + constexpr SplitterBase(str_t text, str_t delim) : text_(text), delim_(delim) {} + /*! + * @ru @brief Узнать, не закончились ли подстроки. + * @en @brief Find out if substrings are running out. + */ + constexpr bool is_done() const { + return text_.length() == str::npos; + } + /*! + * @ru @brief Получить следующую подстроку. + * @return simple_str. + * @en @brief Get the next substring. + * @return simple_str. + */ + constexpr str_t next() { + if (!text_.length()) { + auto ret = text_; + text_.str++; + text_.len--; + return ret; + } else if (text_.length() == str::npos) { + return {nullptr, 0}; + } + size_t pos = text_.find(delim_), next = 0; + if (pos == str::npos) { + pos = text_.length(); + next = pos + 1; + } else { + next = pos + delim_.length(); + } + str_t result{text_.str, pos}; + text_.str += next; + text_.len -= next; + return result; + } +}; + +/*! + * @ru @brief Класс с базовыми константными строковыми алгоритмами. + * @details Является базой для классов, могущих выполнять константные операции со строками. + * Ничего не знает о хранении строк, ни сам, ни у класса наследника, то есть работает + * только с указателем на строку и её длиной. + * Для работы класс-наследник должен реализовать методы: + * - size_t length() const noexcept - возвращает длину строки. + * - const K* symbols() const noexcept - возвращает указатель на начало строки. + * - bool is_empty() const noexcept - проверка, не пустая ли строка. + * @tparam K - тип символов. + * @tparam StrRef - тип хранилища куска строки. + * @tparam Impl - конечный класс наследник. + * @en @brief A class with basic constant string algorithms. + * @details Is the base for classes that can perform constant operations on strings. + * Doesn’t know anything about storing strings, neither itself nor the descendant class, that is, it works + * only with a pointer to a string and its length. + * To work, the descendant class must implement the following methods: + * - size_t length() const noexcept - returns the length of the string. + * - const K* symbols() const noexcept - returns a pointer to the beginning of the line. + * - bool is_empty() const noexcept - checks whether the string is empty. + * @tparam K - character type. + * @tparam StrRef - storage type for the string chunk. + * @tparam Impl - the final class is the successor. + */ +template +class str_src_algs : public buffer_pointers { + constexpr const Impl& d() const noexcept { + return *static_cast(this); + } + constexpr size_t _len() const noexcept { + return d().length(); + } + constexpr const K* _str() const noexcept { + return d().symbols(); + } + constexpr bool _is_empty() const noexcept { + return d().is_empty(); + } + +public: + using symb_type = K; + using str_piece = StrRef; + using traits = ch_traits; + using uns_type = std::make_unsigned_t; + using my_type = Impl; + using base = str_src_algs; + str_src_algs() = default; + + /*! + * @ru @brief Копировать строку в указанный буфер. + * @details Метод предполагает, что размер выделенного буфера достаточен для всей строки, т.е. + * предварительно была запрошена `length()`. Не добавляет `\0`. + * @param ptr - указатель на буфер. + * @return указатель на символ после конца размещённой в буфере строки. + * @en @brief Copy the string to the specified buffer. + * @details The method assumes that the size of the allocated buffer is sufficient for the entire line, i.e. + * `length()` was previously requested. Does not add `\0`. + * @param ptr - pointer to the buffer. + * @return pointer to the character after the end of the symbols placed in the buffer. + */ + constexpr K* place(K* ptr) const noexcept { + size_t myLen = _len(); + traits::copy(ptr, _str(), myLen); + return ptr + myLen; + } + /*! + * @ru @brief Копировать строку в указанный буфер. + * @details Метод добавляет `\0` после скопированных символов. Не выходит за границы буфера. + * @param buffer - указатель на буфер + * @param bufSize - размер буфера в символах. + * @en @brief Copy the string to the specified buffer. + * @details The method adds `\0` after the copied characters. Does not exceed buffer boundaries. + * @param buffer - pointer to buffer + * @param bufSize - buffer size in characters. + */ + void copy_to(K* buffer, size_t bufSize) { + size_t tlen = std::min(_len(), bufSize - 1); + traits::copy(buffer, _str(), tlen); + buffer[tlen] = 0; + } + /*! + * @ru @brief Размер строки в символах. + * @return size_t + * @en @brief The size of the string in characters. + * @return size_t + */ + constexpr size_t size() const { + return _len(); + } + + /*! + * @ru @brief Конвертировать в std::basic_string_view. + * @return std::basic_string_view. + * @en @brief Convert to std::basic_string_view. + * @return std::basic_string_view. + */ + template requires is_equal_str_type_v + constexpr std::basic_string_view to_sv() const noexcept { + return {(const D*)_str(), _len()}; + } + /*! + * @ru @brief Конвертировать в std::basic_string_view. + * @return std::basic_string_view. + * @en @brief Convert to std::basic_string_view. + * @return std::basic_string_view. + */ + template requires is_equal_str_type_v + constexpr operator std::basic_string_view() const { + return {(const D*)_str(), _len()}; + } + /*! + * @ru @brief Конвертировать в std::basic_string. + * @return std::basic_string. + * @en @brief Convert to std::basic_string. + * @return std::basic_string. + */ + template, typename Allocator = std::allocator> requires is_equal_str_type_v + constexpr std::basic_string to_string() const { + return {(const D*)_str(), _len()}; + } + /*! + * @ru @brief Конвертировать в std::basic_string. + * @return std::basic_string. + * @en @brief Convert to std::basic_string. + * @return std::basic_string. + */ + template requires is_equal_str_type_v + constexpr operator std::basic_string() const { + return {(const D*)_str(), _len()}; + } + /*! + * @ru @brief Преобразовать себя в "кусок строки", включающий всю строку. + * @return str_piece. + * @en @brief Convert itself to a "string chunk" that includes the entire string. + * @return str_piece. + */ + constexpr operator str_piece() const noexcept { + return str_piece{_str(), _len()}; + } + /*! + * @ru @brief Преобразовать себя в "кусок строки", включающий всю строку. + * @return str_piece. + * @en @brief Convert itself to a "string chunk" that includes the entire string. + * @return str_piece. + */ + constexpr str_piece to_str() const noexcept { + return {_str(), _len()}; + } + /*! + * @ru @brief Получить часть строки как "str_src". + * @param from - количество символов от начала строки. + * @param len - количество символов в получаемом "куске". + * @return Подстроку, str_src. + * @details Если `from` меньше нуля, то отсчитывается `-from` символов от конца строки в сторону начала. + * Если `len` меньше или равно нулю, то отсчитать `-len` символов от конца строки + * @en @brief Get part of a string as "str_src". + * @param from - number of characters from the beginning of the line. + * @param len - the number of characters in the resulting "chunk". + * @return Substring, str_src. + * @details If `from` is less than zero, then `-from` characters are counted from the end of the line towards the beginning. + * If `len` is less than or equal to zero, then count `-len` characters from the end of the line + * @~ + * ```cpp + * "0123456789"_ss(5, 2) == "56"; + * "0123456789"_ss(5) == "56789"; + * "0123456789"_ss(5, -1) == "5678"; + * "0123456789"_ss(-3) == "789"; + * "0123456789"_ss(-3, 2) == "78"; + * "0123456789"_ss(-4, -1) == "678"; + * ``` + */ + constexpr str_piece operator()(ptrdiff_t from, ptrdiff_t len = 0) const noexcept { + size_t myLen = _len(), idxStart = from >= 0 ? from : myLen > -from ? myLen + from : 0, + idxEnd = len > 0 ? idxStart + len : myLen > -len ? myLen + len : 0; + if (idxEnd > myLen) + idxEnd = myLen; + if (idxStart > idxEnd) + idxStart = idxEnd; + return str_piece{_str() + idxStart, idxEnd - idxStart}; + } + /*! + * @ru @brief Получить часть строки как "кусок строки". + * @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку. + * @param len - количество символов в получаемом "куске". При выходе за пределы строки вернёт всё до конца строки. + * @return Подстроку, str_src. + * @en @brief Get part of a string as "string chunk". + * @param from - number of characters from the beginning of the line. If the string size is exceeded, it will return an empty string. + * @param len - the number of characters in the resulting "chunk". When going beyond the line, it will return everything up to the end of the line. + * @return Substring, str_src. + */ + constexpr str_piece mid(size_t from, size_t len = -1) const noexcept { + size_t myLen = _len(), idxStart = from, idxEnd = from > std::numeric_limits::max() - len ? myLen : from + len; + if (idxEnd > myLen) + idxEnd = myLen; + if (idxStart > idxEnd) + idxStart = idxEnd; + return str_piece{_str() + idxStart, idxEnd - idxStart}; + } + /*! + * @ru @brief Получить подстроку str_src с позиции от from до позиции to (не включая её). + * @details Для производительности метод никак не проверяет выходы за границы строки, используйте + * в сценариях, когда точно знаете, что это позиции внутри строки и to >= from. + * @param from - начальная позиция. + * @param to - конечная позиция (не входит в результат). + * @return Подстроку, str_src. + * @en @brief Get the substring str_src from position from to position to (not including it). + * @details For performance reasons, the method does not check for line boundaries in any way, use + * in scenarios when you know for sure that these are positions inside the line and to >= from. + * @param from - starting position. + * @param to - final position (not included in the result). + * @return Substring, str_src. + */ + constexpr str_piece from_to(size_t from, size_t to) const noexcept { + return str_piece{_str() + from, to - from}; + } + /*! + * @ru @brief Проверка на пустоту. + * @en @brief Check for emptiness. + */ + constexpr bool operator!() const noexcept { + return _is_empty(); + } + /*! + * @ru @brief Получить символ на заданной позиции . + * @param idx - индекс символа. Для отрицательных значений отсчитывается от конца строки. + * @return K - символ. + * @details Не производит проверку на выход за границы строки. + * @en @brief Get the character at the given position. + * @param idx - symbol index. For negative values, it is counted from the end of the line. + * @return K - character. + * @details Does not check for line boundaries. + */ + constexpr K at(ptrdiff_t idx) const { + return _str()[idx >= 0 ? idx : _len() + idx]; + } + // Сравнение строк + // String comparison + constexpr int compare(const K* text, size_t len) const { + size_t myLen = _len(); + int cmp = traits::compare(_str(), text, std::min(myLen, len)); + return cmp == 0 ? (myLen > len ? 1 : myLen == len ? 0 : -1) : cmp; + } + /*! + * @ru @brief Сравнение строк посимвольно. + * @param o - другая строка. + * @return <0 эта строка меньше, ==0 - строки равны, >0 - эта строка больше. + * @en @brief Compare strings character by character. + * @param o - another line. + * @return <0 this string is less, ==0 - strings are equal, >0 - this string is greater. + */ + constexpr int compare(str_piece o) const { + return compare(o.symbols(), o.length()); + } + /*! + * @ru @brief Сравнение с C-строкой посимвольно. + * @param text - другая строка. + * @return <0 эта строка меньше, ==0 - строки равны, >0 - эта строка больше. + * @en @brief Compare with C-string character by character. + * @param text - another line. + * @return <0 this string is less, ==0 - strings are equal, >0 - this string is greater. + */ + constexpr int strcmp(const K* text) const { + size_t myLen = _len(), idx = 0; + const K* ptr = _str(); + for (; idx < myLen; idx++) { + uns_type s1 = (uns_type)text[idx]; + if (!s1) { + return 1; + } + uns_type s2 = (uns_type)ptr[idx]; + if (s1 < s2) { + return 1; + } else if (s1 > s2) { + return -1; + } + } + return text[idx] == 0 ? 0 : -1; + } + + constexpr bool equal(const K* text, size_t len) const noexcept { + return len == _len() && traits::compare(_str(), text, len) == 0; + } + /*! + * @ru @brief Сравнение строк на равенство. + * @param other - другая строка. + * @return равны ли строки. + * @en @brief String comparison for equality. + * @param other - another line. + * @return whether the strings are equal. + */ + constexpr bool equal(str_piece other) const noexcept { + return equal(other.symbols(), other.length()); + } + /*! + * @ru @brief Оператор сравнение строк на равенство. + * @param other - другая строка. + * @return равны ли строки. + * @en @brief Operator comparing strings for equality. + * @param other - another line. + * @return whether the strings are equal. + */ + constexpr bool operator==(const base& other) const noexcept { + return equal(other._str(), other._len()); + } + /*! + * @ru @brief Оператор сравнения строк. + * @param other - другая строка. + * @en @brief String comparison operator. + * @param other - another line. + */ + constexpr auto operator<=>(const base& other) const noexcept { + return compare(other._str(), other._len()) <=> 0; + } + /*! + * @ru @brief Оператор сравнения строки и строкового литерала на равенство. + * @param other - строковый литерал. + * @en @brief Operator for comparing a string and a string literal for equality. + * @param other - string literal. + */ + template::Count> + constexpr bool operator==(T&& other) const noexcept { + return N - 1 == _len() && traits::compare(_str(), other, N - 1) == 0; + } + /*! + * @ru @brief Оператор сравнения строки и строкового литерала. + * @param other - строковый литерал. + * @en @brief Comparison operator between a string and a string literal. + * @param other is a string literal. + */ + template::Count> + constexpr auto operator<=>(T&& other) const noexcept { + size_t myLen = _len(); + int cmp = traits::compare(_str(), other, std::min(myLen, N - 1)); + int res = cmp == 0 ? (myLen > N - 1 ? 1 : myLen == N - 1 ? 0 : -1) : cmp; + return res <=> 0; + } + + // Сравнение ascii строк без учёта регистра + // Compare ascii strings without taking into account case + constexpr int compare_ia(const K* text, size_t len) const noexcept { // NOLINT + if (!len) + return _is_empty() ? 0 : 1; + size_t myLen = _len(), checkLen = std::min(myLen, len); + const uns_type *ptr1 = reinterpret_cast(_str()), *ptr2 = reinterpret_cast(text); + while (checkLen--) { + uns_type s1 = *ptr1++, s2 = *ptr2++; + if (s1 == s2) + continue; + s1 = makeAsciiLower(s1); + s2 = makeAsciiLower(s2); + if (s1 > s2) + return 1; + else if (s1 < s2) + return -1; + } + return myLen == len ? 0 : myLen > len ? 1 : -1; + } + /*! + * @ru @brief Сравнение строк посимвольно без учёта регистра ASCII символов. + * @param text - другая строка. + * @return <0 эта строка меньше, ==0 - строки равны, >0 - эта строка больше. + * @en @brief Compare strings character by character and not case sensitive ASCII characters. + * @param text - another line. + * @return <0 this string is less, ==0 - strings are equal, >0 - this string is greater. + */ + constexpr int compare_ia(str_piece text) const noexcept { // NOLINT + return compare_ia(text.symbols(), text.length()); + } + + /*! + * @ru @brief Равна ли строка другой строке посимвольно без учёта регистра ASCII символов. + * @param text - другая строка. + * @return равны ли строки. + * @en @brief Whether a string is equal to another string, character-by-character-insensitive, of ASCII characters. + * @param text - another line. + * @return whether the strings are equal. + */ + constexpr bool equal_ia(str_piece text) const noexcept { // NOLINT + return text.length() == _len() && compare_ia(text.symbols(), text.length()) == 0; + } + /*! + * @ru @brief Меньше ли строка другой строки посимвольно без учёта регистра ASCII символов. + * @param text - другая строка. + * @return меньше ли строка. + * @en @brief Whether a string is smaller than another string, character-by-character-insensitive, ASCII characters. + * @param text - another line. + * @return whether the string is smaller. + */ + constexpr bool less_ia(str_piece text) const noexcept { // NOLINT + return compare_ia(text.symbols(), text.length()) < 0; + } + + constexpr size_t find(const K* pattern, size_t lenPattern, size_t offset) const noexcept { + size_t lenText = _len(); + // Образец, не вмещающийся в строку и пустой образец не находим + // We don't look for an empty line or a line longer than the text. + if (!lenPattern || offset >= lenText || offset + lenPattern > lenText) + return str::npos; + lenPattern--; + const K *text = _str(), *last = text + lenText - lenPattern, first = pattern[0]; + pattern++; + for (const K* fnd = text + offset;; ++fnd) { + fnd = traits::find(fnd, last - fnd, first); + if (!fnd) + return str::npos; + if (traits::compare(fnd + 1, pattern, lenPattern) == 0) + return static_cast(fnd - text); + } + } + /*! + * @ru @brief Найти начало первого вхождения подстроки в этой строке. + * @param pattern - искомая строка. + * @param offset - с какой позиции начинать поиск. + * @return size_t - позицию начала вхождения подстроки, или -1, если не найдена. + * @en @brief Find the beginning of the first occurrence of a substring in this string. + * @param pattern - the search string. + * @param offset - from which position to start the search. + * @return size_t - the position of the beginning of the occurrence of the substring, or -1 if not found. + */ + constexpr size_t find(str_piece pattern, size_t offset = 0) const noexcept { + return find(pattern.symbols(), pattern.length(), offset); + } + /*! + * @ru @brief Найти начало первого вхождения подстроки в этой строке или выкинуть исключение. + * @tparam Exc - тип исключения. + * @tparam Args... - типы параметров для конструирования исключения, выводятся из аргументов. + * @param pattern - искомая строка. + * @param offset - с какой позиции начинать поиск. + * @param args - аргументы для конструктора исключения. + * @return size_t - позицию начала вхождения подстроки, или выбрасывает исключение Exc, если не найдена. + * @en @brief Find the beginning of the first occurrence of a substring in this string or throw an exception. + * @tparam Exc - exception type. + * @tparam Args... - types of parameters for constructing an exception, inferred from the arguments. + * @param pattern - the search string. + * @param offset - from which position to start the search. + * @param args - arguments for the exception constructor. + * @return size_t - the position of the beginning of the substring occurrence, or throws an Exc exception if not found. + */ + template requires std::is_constructible_v + constexpr size_t find_or_throw(str_piece pattern, size_t offset = 0, Args&& ... args) const noexcept { + if (auto fnd = find(pattern.symbols(), pattern.length(), offset); fnd != str::npos) { + return fnd; + } + throw Exc(std::forward(args)...); + } + /*! + * @ru @brief Найти конец вхождения подстроки в этой строке. + * @param pattern - искомая строка. + * @param offset - с какой позиции начинать поиск. + * @return size_t - позицию сразу за вхождением подстроки, или -1, если не найдена. + * @en @brief Find the end of the occurrence of a substring in this string. + * @param pattern - the search string. + * @param offset - from which position to start the search. + * @return size_t - the position immediately after the occurrence of the substring, or -1 if not found. + */ + constexpr size_t find_end(str_piece pattern, size_t offset = 0) const noexcept { + size_t fnd = find(pattern.symbols(), pattern.length(), offset); + return fnd == str::npos ? fnd : fnd + pattern.length(); + } + /*! + * @ru @brief Найти начало первого вхождения подстроки в этой строке или конец строки. + * @param pattern - искомая строка. + * @param offset - с какой позиции начинать поиск. + * @return size_t - позицию начала вхождения подстроки, или длину строки, если не найдена. + * @en @brief Find the beginning of the first occurrence of a substring in this string or the end of the string. + * @param pattern - the search string. + * @param offset - from which position to start the search. + * @return size_t - the position at which the substring begins, or the length of the string if not found. + */ + constexpr size_t find_or_all(str_piece pattern, size_t offset = 0) const noexcept { + auto fnd = find(pattern.symbols(), pattern.length(), offset); + return fnd == str::npos ? _len() : fnd; + } + /*! + * @ru @brief Найти конец первого вхождения подстроки в этой строке или конец строки. + * @param pattern - искомая строка. + * @param offset - с какой позиции начинать поиск. + * @return size_t - позицию сразу за вхождением подстроки, или длину строки, если не найдена. + * @en @brief Find the end of the first occurrence of a substring in this string, or the end of a string. + * @param pattern - the search string. + * @param offset - from which position to start the search. + * @return size_t - the position immediately after the occurrence of the substring, or the length of the string if not found. + */ + constexpr size_t find_end_or_all(str_piece pattern, size_t offset = 0) const noexcept { + auto fnd = find(pattern.symbols(), pattern.length(), offset); + return fnd == str::npos ? _len() : fnd + pattern.length(); + } + + constexpr size_t find_last(const K* pattern, size_t lenPattern, size_t offset) const noexcept { + if (lenPattern == 1) + return find_last(pattern[0], offset); + size_t lenText = std::min(_len(), offset); + // Образец, не вмещающийся в строку и пустой образец не находим + // We don't look for an empty line or a line longer than the text. + if (!lenPattern || lenPattern > lenText) + return str::npos; + + lenPattern--; + const K *text = _str() + lenPattern, last = pattern[lenPattern]; + lenText -= lenPattern; + while(lenText) { + if (text[--lenText] == last) { + if (traits::compare(text + lenText - lenPattern, pattern, lenPattern) == 0) { + return lenText; + } + } + } + return str::npos; + } + /*! + * @ru @brief Найти начало последнего вхождения подстроки в этой строке. + * @param pattern - искомая строка. + * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. + * @return size_t - позицию начала вхождения подстроки, или -1, если не найдена. + * @en @brief Find the beginning of the last occurrence of a substring in this string. + * @param pattern - the search string. + * @param offset - from which position to search in the opposite direction, -1 - from the very end. + * @return size_t - the position of the beginning of the occurrence of the substring, or -1 if not found. + */ + constexpr size_t find_last(str_piece pattern, size_t offset = -1) const noexcept { + return find_last(pattern.symbols(), pattern.length(), offset); + } + /*! + * @ru @brief Найти конец последнего вхождения подстроки в этой строке. + * @param pattern - искомая строка. + * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. + * @return size_t - позицию сразу за последним вхождением подстроки, или -1, если не найдена. + * @en @brief Find the end of the last occurrence of a substring in this string. + * @param pattern - the search string. + * @param offset - from which position to search in the opposite direction, -1 - from the very end. + * @return size_t - the position immediately after the last occurrence of the substring, or -1 if not found. + */ + constexpr size_t find_end_of_last(str_piece pattern, size_t offset = -1) const noexcept { + size_t fnd = find_last(pattern.symbols(), pattern.length(), offset); + return fnd == str::npos ? fnd : fnd + pattern.length(); + } + /*! + * @ru @brief Найти начало последнего вхождения подстроки в этой строке или конец строки. + * @param pattern - искомая строка. + * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. + * @return size_t - позицию начала вхождения подстроки, или длину строки, если не найдена. + * @en @brief Find the beginning of the last occurrence of a substring in this string or the end of the string. + * @param pattern - the search string. + * @param offset - from which position to search in the opposite direction, -1 - from the very end. + * @return size_t - the position at which the substring begins, or the length of the string if not found. + */ + constexpr size_t find_last_or_all(str_piece pattern, size_t offset = -1) const noexcept { + auto fnd = find_last(pattern.symbols(), pattern.length(), offset); + return fnd == str::npos ? _len() : fnd; + } + /*! + * @ru @brief Найти конец последнего вхождения подстроки в этой строке или конец строки. + * @param pattern - искомая строка. + * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. + * @return size_t - позицию сразу за последним вхождением подстроки, или длину строки, если не найдена. + * @en @brief Find the end of the last occurrence of a substring in this string, or the end of a string. + * @param pattern - the search string. + * @param offset - from which position to search in the opposite direction, -1 - from the very end. + * @return size_t - the position immediately after the last occurrence of the substring, or the length of the string if not found. + */ + constexpr size_t find_end_of_last_or_all(str_piece pattern, size_t offset = -1) const noexcept { + size_t fnd = find_last(pattern.symbols(), pattern.length(), offset); + return fnd == str::npos ? _len() : fnd + pattern.length(); + } + /*! + * @ru @brief Содержит ли строка указанную подстроку. + * @param pattern - искомая строка. + * @param offset - с какой позиции начинать поиск. + * @return bool. + * @en @brief Whether the string contains the specified substring. + * @param pattern - the search string. + * @param offset - from which position to start the search. + * @return bool. + */ + constexpr bool contains(str_piece pattern, size_t offset = 0) const noexcept { + return find(pattern, offset) != str::npos; + } + /*! + * @ru @brief Найти символ в этой строке. + * @param s - искомый символ. + * @param offset - с какой позиции начинать поиск. + * @return size_t - позицию найденного символа, или -1, если не найден. + * @en @brief Find a character in this string. + * @param s is an optional character. + * @param offset - from which position to start the search. + * @return size_t - position of the found character, or -1 if not found. + */ + constexpr size_t find(K s, size_t offset = 0) const noexcept { + size_t len = _len(); + if (offset < len) { + const K *str = _str(), *fnd = traits::find(str + offset, len - offset, s); + if (fnd) + return static_cast(fnd - str); + } + return str::npos; + } + /*! + * @ru @brief Найти символ в этой строке или конец строки. + * @param s - искомый символ. + * @param offset - с какой позиции начинать поиск. + * @return size_t - позицию найденного символа, или длину строки, если не найден. + * @en @brief Find a character in this string or the end of a string. + * @param s is an optional character. + * @param offset - from which position to start the search. + * @return size_t - position of the found character, or string length if not found. + */ + constexpr size_t find_or_all(K s, size_t offset = 0) const noexcept { + size_t len = _len(); + if (offset < len) { + const K *str = _str(), *fnd = traits::find(str + offset, len - offset, s); + if (fnd) + return static_cast(fnd - str); + } + return len; + } + + template + constexpr void for_all_finded(const Op& op, const K* pattern, size_t patternLen, size_t offset, size_t maxCount) const { + if (!maxCount) + maxCount--; + while (maxCount-- > 0) { + size_t fnd = find(pattern, patternLen, offset); + if (fnd == str::npos) + break; + op(fnd); + offset = fnd + patternLen; + } + } + /*! + * @ru @brief Вызвать функтор для всех найденных вхождений подстроки в этой строке. + * @param op - функтор, принимающий строку. + * @param pattern - искомая подстрока. + * @param offset - позиция начала поиска. + * @param maxCount - максимальное количество обрабатываемых вхождений, 0 - без ограничений. + * @en @brief Call a functor on all found occurrences of a substring in this string. + * @param op is a functor that takes a string. + * @param pattern - the substring to search for. + * @param offset - search start position. + * @param maxCount - the maximum number of occurrences to be processed, 0 - no restrictions. + */ + template + constexpr void for_all_finded(const Op& op, str_piece pattern, size_t offset = 0, size_t maxCount = 0) const { + for_all_finded(op, pattern.symbols(), pattern.length(), offset, maxCount); + } + + template> + constexpr To find_all(const K* pattern, size_t patternLen, size_t offset, size_t maxCount) const { + To result; + for_all_finded([&](auto f) { result.emplace_back(f); }, pattern, patternLen, offset, maxCount); + return result; + } + /*! + * @ru @brief Найти все вхождения подстроки в этой строке. + * @param pattern - искомая подстрока. + * @param offset - позиция начала поиска. + * @param maxCount - максимальное количество обрабатываемых вхождений, 0 - без ограничений. + * @return std::vector - вектор с позициями начал найденных вхождений. + * @en @brief Find all occurrences of a substring in this string. + * @param pattern - the substring to search for. + * @param offset - search start position. + * @param maxCount - the maximum number of occurrences to be processed, 0 - no restrictions. + * @return std::vector - a vector with the positions of the beginnings of the found occurrences. + */ + template> + constexpr To find_all(str_piece pattern, size_t offset = 0, size_t maxCount = 0) const { + return find_all(pattern.symbols(), pattern.length(), offset, maxCount); + } + template> + constexpr void find_all_to(To& to, const K* pattern, size_t len, size_t offset = 0, size_t maxCount = 0) const { + return for_all_finded([&](size_t pos) { + to.emplace_back(pos); + }, pattern, len, offset, maxCount); + } + /*! + * @ru @brief Найти последнее вхождения символа в этой строке. + * @param s - искомый символ. + * @param offset - c какой позиции вести поиск в обратную сторону, -1 - с самого конца. + * @return size_t - позицию найденного символа, или -1, если не найден. + * @en @brief Find the last occurrence of a character in this string. + * @param s is an optional character. + * @param offset - from which position to search in the opposite direction, -1 - from the very end. + * @return size_t - position of the found character, or -1 if not found. + */ + constexpr size_t find_last(K s, size_t offset = -1) const noexcept { + size_t len = std::min(_len(), offset); + const K *text = _str(); + while (len > 0) { + if (text[--len] == s) + return len; + } + return str::npos; + } + /*! + * @ru @brief Найти первое вхождение символа из заданного набора символов. + * @param pattern - строка, задающая набор искомых символов. + * @param offset - позиция начала поиска. + * @return size_t - позицию найденного вхождения, или -1, если не найден. + * @en @brief Find the first occurrence of a character from a given character set. + * @param pattern - a string specifying the set of characters to search for. + * @param offset - search start position. + * @return size_t - position of the found occurrence, or -1 if not found. + */ + constexpr size_t find_first_of(str_piece pattern, size_t offset = 0) const noexcept { + return std::string_view{_str(), _len()}.find_first_of(std::string_view{pattern.str, pattern.len}, offset); + } + /*! + * @ru @brief Найти первое вхождение символа из заданного набора символов. + * @param pattern - строка, задающая набор искомых символов. + * @param offset - позиция начала поиска. + * @return std::pair - пару из позиции найденного вхождения и номера найденного символа в наборе, или -1, если не найден. + * @en @brief Find the first occurrence of a character from a given character set. + * @param pattern - a string specifying the set of characters to search for. + * @param offset - search start position. + * @return std::pair - a pair from the position of the found occurrence and the number of the found character in the set, or -1 if not found. + */ + constexpr std::pair find_first_of_idx(str_piece pattern, size_t offset = 0) const noexcept { + const K* text = _str(); + size_t fnd = std::string_view{text, _len()}.find_first_of(std::string_view{pattern.str, pattern.len}, offset); + return {fnd, fnd == std::string::npos ? fnd : pattern.find(text[fnd]) }; + } + /*! + * @ru @brief Найти первое вхождение символа не из заданного набора символов. + * @param pattern - строка, задающая набор символов. + * @param offset - позиция начала поиска. + * @return size_t - позицию найденного вхождения, или -1, если не найден. + * @en @brief Find the first occurrence of a character not from the given character set. + * @param pattern - a string specifying the character set. + * @param offset - search start position. + * @return size_t - position of the found occurrence, or -1 if not found. + */ + constexpr size_t find_first_not_of(str_piece pattern, size_t offset = 0) const noexcept { + return std::string_view{_str(), _len()}.find_first_not_of(std::string_view{pattern.str, pattern.len}, offset); + } + /*! + * @ru @brief Найти последнее вхождение символа из заданного набора символов. + * @param pattern - строка, задающая набор искомых символов. + * @param offset - позиция начала поиска. + * @return size_t - позицию найденного вхождения, или -1, если не найден. + * @en @brief Find the last occurrence of a character from a given character set. + * @param pattern - a string specifying the set of characters to search for. + * @param offset - search start position. + * @return size_t - position of the found occurrence, or -1 if not found. + */ + constexpr size_t find_last_of(str_piece pattern, size_t offset = str::npos) const noexcept { + return std::string_view{_str(), _len()}.find_last_of(std::string_view{pattern.str, pattern.len}, offset); + } + /*! + * @ru @brief Найти последнее вхождение символа из заданного набора символов. + * @param pattern - строка, задающая набор искомых символов. + * @param offset - позиция начала поиска. + * @return std::pair - пару из позиции найденного вхождения и номера найденного символа в наборе, или -1, если не найден. + * @en @brief Find the last occurrence of a character from a given character set. + * @param pattern - a string specifying the set of characters to search for. + * @param offset - search start position. + * @return std::pair - a pair from the position of the found occurrence and the number of the found character in the set, or -1 if not found. + */ + constexpr std::pair find_last_of_idx(str_piece pattern, size_t offset = str::npos) const noexcept { + const K* text = _str(); + size_t fnd = std::string_view{text, _len()}.find_last_of(std::string_view{pattern.str, pattern.len}, offset); + return {fnd, fnd == std::string::npos ? fnd : pattern.find(text[fnd]) }; + } + /*! + * @ru @brief Найти последнее вхождение символа не из заданного набора символов. + * @param pattern - строка, задающая набор символов. + * @param offset - позиция начала поиска. + * @return size_t - позицию найденного вхождения, или -1, если не найден. + * @en @brief Find the last occurrence of a character not from the given character set. + * @param pattern - a string specifying the character set. + * @param offset - search start position. + * @return size_t - position of the found occurrence, or -1 if not found. + */ + constexpr size_t find_last_not_of(str_piece pattern, size_t offset = str::npos) const noexcept { + return std::string_view{_str(), _len()}.find_last_not_of(std::string_view{pattern.str, pattern.len}, offset); + } + /*! + * @ru @brief Получить подстроку. Работает аналогично operator(), только результат выдает того же типа, к которому применён метод. + * @param from - количество символов от начала строки. Если меньше нуля, отсчитывается от конца строки в сторону начала. + * @param len - количество символов в получаемом "куске". Если меньше или равно нулю, то отсчитать len символов от конца строки. + * @return my_type - подстроку, объект того же типа, к которому применён метод. + * @en @brief Get a substring. Works similarly to operator(), only the result is the same type as the method applied to. + * @param from - number of characters from the beginning of the line. If less than zero, it is counted from the end of the line towards the beginning. + * @param len - the number of characters in the resulting "chunk". If less than or equal to zero, then count len ​​characters from the end of the line. + * @return my_type - a substring, an object of the same type to which the method is applied. + */ + constexpr my_type substr(ptrdiff_t from, ptrdiff_t len = 0) const { // индексация в code units | indexing in code units + return my_type{d()(from, len)}; + } + /*! + * @ru @brief Получить часть строки объектом того же типа, к которому применён метод, аналогично mid. + * @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку. + * @param len - количество символов в получаемом "куске". При выходе за пределы строки вернёт всё до конца строки. + * @return Строку того же типа, к которому применён метод. + * @en @brief Get part of a string with an object of the same type to which the method is applied, similar to mid. + * @param from - number of characters from the beginning of the line. If the string size is exceeded, it will return an empty string. + * @param len - the number of characters in the resulting "chunk". When going beyond the line, it will return everything up to the end of the line. + * @return A string of the same type to which the method is applied. + */ + constexpr my_type str_mid(size_t from, size_t len = -1) const { // индексация в code units | indexing in code units + return my_type{d().mid(from, len)}; + } + /*! + * @ru @brief Преобразовать строку в число заданного типа. + * @tparam T - желаемый тип числа. + * @tparam CheckOverflow - проверять на переполнение. + * @tparam Base - основание счисления числа, от -1 до 36, кроме 1. + * - Если 0: то пытается определить основание по префиксу 0[xX] как 16, 0 как 8, иначе 10. + * - Если -1: то пытается определить основание по префиксам: + * - 0 или 0[oO]: 8 + * - 0[bB]: 2 + * - 0[xX]: 16 + * - в остальных случаях 10. + * @tparam SkipWs - пропускать пробельные символы в начале строки. + * @tparam AllowSign - допустим ли знак '+' перед числом. + * @return T - число, результат преобразования, насколько оно получилось, или 0 при переполнении. + * @en @brief Convert a string to a number of the given type. + * @tparam T - the desired number type. + * @tparam CheckOverflow - check for overflow. + * @tparam Base - the base of the number, from -1 to 36, except 1. + * - If 0: then tries to determine the base by the prefix 0[xX] as 16, 0 as 8, otherwise 10. + * - If -1: then tries to determine the base by prefixes: + * - 0 or 0[oO]: 8 + * - 0[bB]: 2 + * - 0[xX]: 16 + * - in other cases 10. + * @tparam SkipWs - skip whitespace characters at the beginning of the line. + * @tparam AllowSign - whether the '+' sign is allowed before a number. + * @return T - a number, the result of the transformation, how much it turned out, or 0 if it overflows. + */ + template + constexpr T as_int() const noexcept { + auto [res, err, _] = int_convert::to_integer(_str(), _len()); + return err == IntConvertResult::Overflow ? 0 : res; + } + /*! + * @ru @brief Преобразовать строку в число заданного типа. + * @tparam T - желаемый тип числа. + * @tparam CheckOverflow - проверять на переполнение. + * @tparam Base - основание счисления числа, от -1 до 36, кроме 1. + * - Если 0: то пытается определить основание по префиксу 0[xX] как 16, 0 как 8, иначе 10 + * - Если -1: то пытается определить основание по префиксам: + * - 0 или 0[oO]: 8 + * - 0[bB]: 2 + * - 0[xX]: 16 + * - в остальных случаях 10. + * @tparam SkipWs - пропускать пробельные символы в начале строки. Пропускаются все символы с ASCII кодами <= 32. + * @tparam AllowSign - допустим ли знак '+' перед числом. + * @return convert_result - кортеж из полученного числа, успешности преобразования и количестве обработанных символов. + * @en @brief Convert a string to a number of the given type. + * @tparam T - the desired number type. + * @tparam CheckOverflow - check for overflow. + * @tparam Base - the base of the number, from -1 to 36, except 1. + * - If 0: then tries to determine the base by the prefix 0[xX] as 16, 0 as 8, otherwise 10 + * - If -1: then tries to determine the base by prefixes: + * - 0 or 0[oO]: 8 + * - 0[bB]: 2 + * - 0[xX]: 16 + * - in other cases 10. + * @tparam SkipWs - skip whitespace characters at the beginning of the line. All characters with ASCII codes <= 32 are skipped. + * @tparam AllowSign - whether the '+' sign is allowed before a number. + * @return convert_result - a tuple of the received number, the success of the conversion and the number of characters processed. + */ + template + constexpr convert_result to_int() const noexcept { + return int_convert::to_integer(_str(), _len()); + } + /*! + * @ru @brief Преобразовать строку в double. + * @return std::optional. + * @en @brief Convert string to double. + * @return std::optional. + */ + template requires (sizeof(K) == 1) + std::optional to_double() const noexcept { + size_t len = _len(); + const K* ptr = _str(); + if constexpr (SkipWS) { + while (len && uns_type(*ptr) <= ' ') { + len--; + ptr++; + } + } + if constexpr (AllowPlus) { + if (len && *ptr == K('+')) { + ptr++; + len--; + } + } + if (!len) { + return {}; + } + double d{}; + if (std::from_chars(ptr, ptr + len, d).ec == std::errc{}) { + return d; + } + return {}; + } + /*! + * @ru @brief Преобразовать строку в 16ричной записи в double. Пока работает только для char. + * @return std::optional. + * @en @brief Convert string in hex form to double. + * @return std::optional. + */ + template requires (sizeof(K) == 1) + std::optional to_double_hex() const noexcept { + size_t len = _len(); + const K* ptr = _str(); + if constexpr (SkipWS) { + while (len && uns_type(*ptr) <= ' ') { + len--; + ptr++; + } + } + if (len) { + double d{}; + if (std::from_chars(ptr, ptr + len, d, std::chars_format::hex).ec == std::errc{}) { + return d; + } + } + return {}; + } + /*! + * @ru @brief Преобразовать строку в целое число. + * @tparam T - тип числа, выводится из аргумента. + * @param t - переменная, в которую записывается результат. + * @en @brief Convert a string to an integer. + * @tparam T - number type, inferred from the argument. + * @param t - the variable into which the result is written. + */ + template + constexpr void as_number(T& t) const { + t = as_int(); + } + + template + constexpr T splitf(const K* delimiter, size_t lendelimiter, const Op& beforeFunc, size_t offset) const { + size_t mylen = _len(); + std::conditional_t, char, T> results; + str_piece me{_str(), mylen}; + for (int i = 0;; i++) { + size_t beginOfDelim = find(delimiter, lendelimiter, offset); + if (beginOfDelim == str::npos) { + str_piece last{me.symbols() + offset, me.length() - offset}; + if constexpr (std::is_invocable_v) { + beforeFunc(last); + } + if constexpr (requires { results.emplace_back(last); }) { + if (last.is_same(me)) { + // Пробуем положить весь объект. + // Try to put the entire object. + results.emplace_back(d()); + } else { + results.emplace_back(last); + } + } else if constexpr (requires { results.push_back(last); }) { + if (last.is_same(me)) { + // Пробуем положить весь объект. + // Try to put the entire object. + results.push_back(d()); + } else { + results.push_back(last); + } + } else if constexpr (requires {results[i] = last;} && requires{std::size(results);}) { + if (i < std::size(results)) { + if (last.is_same(me)) { + // Пробуем положить весь объект. + // Try to put the entire object. + results[i] = d(); + } else + results[i] = last; + } + } + break; + } + str_piece piece{me.symbols() + offset, beginOfDelim - offset}; + if constexpr (std::is_invocable_v) { + beforeFunc(piece); + } + if constexpr (requires { results.emplace_back(piece); }) { + results.emplace_back(piece); + } else if constexpr (requires { results.push_back(piece); }) { + results.push_back(piece); + } else if constexpr (requires { results[i] = piece; } && requires{std::size(results);}) { + if (i < std::size(results)) { + results[i] = piece; + if (i == results.size() - 1) { + break; + } + } + } + offset = beginOfDelim + lendelimiter; + } + if constexpr (!std::is_same_v) { + return results; + } + } + /*! + * @ru @brief Разделить строку на части по заданному разделителю, с возможным применением функтора к каждой подстроке. + * @tparam T - тип контейнера для складывания подстрок. + * @param delimiter - подстрока разделитель. + * @param beforeFunc - функтор для применения к найденным подстрокам, перед помещением их в результат. + * @param offset - позиция начала поиска разделителя. + * @return T - результат. + * @details Для каждой найденной подстроки, если функтор может принять её, вызывается функтор, и подстрока + * присваивается результату функтора. Далее подстрока пытается добавиться в результат, + * вызывая один из его методов - `emplace_back`, `push_back`, `operator[]`. Если ни одного этого метода + * нет, ничего не делается, только вызов функтора. + * `operator[]` пытается применится, если у результата можно получить размер через `std::size` и + * мы не выходим за этот размер. + * При этом, если найденная подстрока получается совпадающей со всей строкой - в результат пытается + * поместить не подстроку, а весь объект строки, что позволяет, например, эффективно копировать sstring. + * @en @brief Split a string into parts at a given delimiter, possibly applying a functor to each substring. + * @tparam T - type of container for folding substrings. + * @param delimiter - substring delimiter. + * @param beforeFunc - a functor to apply to the found substrings, before placing them in the result. + * @param offset - the position to start searching for the separator. + * @return T - result. + * @details For each substring found, if the functor can accept it, the functor is called, and the substring + * is assigned to the result of the functor. Next, the substring tries to be added to the result, + * calling one of its methods - `emplace_back`, `push_back`, `operator[]`. If none of this method + * no, nothing is done, just calling the functor. + * `operator[]` tries to apply if the result can have a size via `std::size` and + * we do not exceed this size. + * At the same time, if the found substring turns out to match the entire string, the result is attempted + * place not a substring, but the entire string object, which allows, for example, to effectively copy sstring. + */ + template + constexpr T splitf(str_piece delimiter, const Op& beforeFunc, size_t offset = 0) const { + return splitf(delimiter.symbols(), delimiter.length(), beforeFunc, offset); + } + /*! + * @ru @brief Разделить строку на подстроки по заданному разделителю. + * @tparam T - тип контейнера для результата. + * @param delimiter - разделитель. + * @param offset - позиция начала поиска разделителя. + * @return T - контейнер с результатом. + * @en @brief Split a string into substrings using a given delimiter. + * @tparam T - container type for the result. + * @param delimiter - delimiter. + * @param offset - the position to start searching for the separator. + * @return T - container with the result. + */ + template + constexpr T split(str_piece delimiter, size_t offset = 0) const { + return splitf(delimiter.symbols(), delimiter.length(), 0, offset); + } + + // Начинается ли эта строка с указанной подстроки + // Does this string start with the specified substring + constexpr bool starts_with(const K* prefix, size_t l) const noexcept { + return _len() >= l && 0 == traits::compare(_str(), prefix, l); + } + /*! + * @ru @brief Начинается ли строка с заданной подстроки. + * @param prefix - подстрока. + * @en @brief Whether the string begins with the given substring. + * @param prefix - substring. + */ + constexpr bool starts_with(str_piece prefix) const noexcept { + return starts_with(prefix.symbols(), prefix.length()); + } + + constexpr bool starts_with_ia(const K* prefix, size_t len) const noexcept { + size_t myLen = _len(); + if (myLen < len) { + return false; + } + const K* ptr1 = _str(); + while (len--) { + K s1 = *ptr1++, s2 = *prefix++; + if (s1 == s2) + continue; + if (makeAsciiLower(s1) != makeAsciiLower(s2)) + return false; + } + return true; + } + /*! + * @ru @brief Начинается ли строка с заданной подстроки без учёта регистра ASCII символов. + * @param prefix - подстрока. + * @en @brief Whether the string begins with the given substring in a case-insensitive ASCII character. + * @param prefix - substring. + */ + constexpr bool starts_with_ia(str_piece prefix) const noexcept { + return starts_with_ia(prefix.symbols(), prefix.length()); + } + + // Является ли эта строка началом указанной строки + // Is this string the beginning of the specified string + constexpr bool prefix_in(const K* text, size_t len) const noexcept { + size_t myLen = _len(); + if (myLen > len) + return false; + return !myLen || 0 == traits::compare(text, _str(), myLen); + } + /*! + * @ru @brief Является ли эта строка началом другой строки. + * @param text - другая строка. + * @en @brief Whether this string is the beginning of another string. + * @param text - another string. + */ + constexpr bool prefix_in(str_piece text) const noexcept { + return prefix_in(text.symbols(), text.length()); + } + // Заканчивается ли строка указанной подстрокой + // Does the string end with the specified substring + constexpr bool ends_with(const K* suffix, size_t len) const noexcept { + size_t myLen = _len(); + return len <= myLen && traits::compare(_str() + myLen - len, suffix, len) == 0; + } + /*! + * @ru @brief Заканчивается ли строка указанной подстрокой. + * @param suffix - подстрока. + * @en @brief Whether the string ends with the specified substring. + * @param suffix - substring. + */ + constexpr bool ends_with(str_piece suffix) const noexcept { + return ends_with(suffix.symbols(), suffix.length()); + } + // Заканчивается ли строка указанной подстрокой без учета регистра ASCII + // Whether the string ends with the specified substring, case insensitive ASCII + constexpr bool ends_with_ia(const K* suffix, size_t len) const noexcept { + size_t myLen = _len(); + if (myLen < len) { + return false; + } + const K* ptr1 = _str() + myLen - len; + while (len--) { + K s1 = *ptr1++, s2 = *suffix++; + if (s1 == s2) + continue; + if (makeAsciiLower(s1) != makeAsciiLower(s2)) + return false; + } + return true; + } + /*! + * @ru @brief Заканчивается ли строка указанной подстрокой без учёта регистра ASCII символов. + * @param suffix - подстрока. + * @en @brief Whether the string ends with the specified substring in a case-insensitive ASCII character. + * @param suffix - substring. + */ + constexpr bool ends_with_ia(str_piece suffix) const noexcept { + return ends_with_ia(suffix.symbols(), suffix.length()); + } + /*! + * @ru @brief Содержит ли строка только ASCII символы. + * @en @brief Whether the string contains only ASCII characters. + */ + constexpr bool is_ascii() const noexcept { + if (_is_empty()) + return true; + const int sl = ascii_mask::WIDTH; + const size_t mask = ascii_mask::VALUE; + size_t len = _len(); + const uns_type* ptr = reinterpret_cast(_str()); + if constexpr (sl > 1) { + const size_t roundMask = sizeof(size_t) - 1; + while (len >= sl && (reinterpret_cast(ptr) & roundMask) != 0) { + if (*ptr++ > 127) + return false; + len--; + } + while (len >= sl) { + if (*reinterpret_cast(ptr) & mask) + return false; + ptr += sl; + len -= sl; + } + } + while (len--) { + if (*ptr++ > 127) + return false; + } + return true; + } + /*! + * @ru @brief Получить копию строки в верхнем регистре ASCII символов. + * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. + * @return R - копию строки в верхнем регистре. + * @en @brief Get a copy of the string in uppercase ASCII characters. + * @tparam R - the desired string type, by default the same whose method was called. + * @return R - uppercase copy of the string. + */ + template + R upperred_only_ascii() const { + return R::upperred_only_ascii_from(d()); + } + /*! + * @ru @brief Получить копию строки в нижнем регистре ASCII символов. + * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. + * @return R - копию строки в нижнем регистре. + * @en @brief Get a copy of the string in lowercase ASCII characters. + * @tparam R - the desired string type, by default the same whose method was called. + * @return R - lowercase copy of the string. + */ + template + R lowered_only_ascii() const { + return R::lowered_only_ascii_from(d()); + } + /*! + * @ru @brief Получить копию строки с заменёнными вхождениями подстрок. + * @tparam R - желаемый тип строки, по умолчанию тот же, чей метод вызывался. + * @param pattern - искомая подстрока. + * @param repl - строка, на которую заменять. + * @param offset - начальная позиция поиска. + * @param maxCount - максимальное количество замен, 0 - без ограничений. + * @return R строку заданного типа, по умолчанию того же, чей метод вызывался. + * @en @brief Get a copy of the string with occurrences of substrings replaced. + * @tparam R - the desired string type, by default the same whose method was called. + * @param pattern - the substring to search for. + * @param repl - the string to replace with. + * @param offset - starting position of the search. + * @param maxCount - maximum number of replacements, 0 - no restrictions. + * @return R a string of the given type, by default the same whose method was called. + */ + template + R replaced(str_piece pattern, str_piece repl, size_t offset = 0, size_t maxCount = 0) const { + return R::replaced_from(d(), pattern, repl, offset, maxCount); + } + + template From> + constexpr static my_type make_trim_op(const From& from, const auto& opTrim) { + str_piece sfrom = from, newPos = opTrim(sfrom); + if (newPos.is_same(sfrom)) { + my_type res = from; + return res; + } + return my_type{newPos}; + } + template From> + constexpr static my_type trim_static(const From& from) { + return make_trim_op(from, trim_operator(-1), true>{}); + } + + template::Count, StrType From> + requires is_const_pattern + constexpr static my_type trim_static(const From& from, T&& pattern) { + return make_trim_op(from, trim_operator{pattern}); + } + + template From> + constexpr static my_type trim_static(const From& from, str_piece pattern) { + return make_trim_op(from, trim_operator{{pattern}}); + } + /*! + * @ru @brief Получить строку с удалением пробельных символов слева и справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @return R - строка, с удалёнными в начале и в конце пробельными символами. + * @en @brief Get a string with whitespace removed on the left and right. + * @tparam R - desired string type, default str_src. + * @return R - a string with whitespace characters removed at the beginning and end. + */ + template + constexpr R trimmed() const { + return R::template trim_static(d()); + } + /*! + * @ru @brief Получить строку с удалением пробельных символов слева. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @return R - строка, с удалёнными в начале пробельными символами. + * @en @brief Get a string with whitespace removed on the left. + * @tparam R - desired string type, default str_src. + * @return R - a string with leading whitespace characters removed. + */ + template + R trimmed_left() const { + return R::template trim_static(d()); + } + /*! + * @ru @brief Получить строку с удалением пробельных символов справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @return R - строка, с удалёнными в конце пробельными символами. + * @en @brief Get a string with whitespace removed on the right. + * @tparam R - desired string type, default str_src. + * @return R - a string with whitespace characters removed at the end. + */ + template + R trimmed_right() const { + return R::template trim_static(d()); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных строковым литералом, слева и справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. + * @return R - строка, с удалёнными в начале и в конце символами, содержащимися в литерале. + * @en @brief Get a string with the characters specified by the string literal removed from the left and right. + * @tparam R - desired string type, default str_src. + * @param pattern is a string literal specifying the characters that will be trimmed. + * @return R - a string with the characters contained in the literal removed at the beginning and at the end. + */ + template::Count> + requires is_const_pattern + R trimmed(T&& pattern) const { + return R::template trim_static(d(), pattern); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных строковым литералом, слева. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. + * @return R - строка, с удалёнными в начале символами, содержащимися в литерале. + * @en @brief Get a string with the characters specified by the string literal removed from the left. + * @tparam R - desired string type, default str_src. + * @param pattern is a string literal specifying the characters that will be trimmed. + * @return R - a string with the characters contained in the literal removed at the beginning. + */ + template::Count> + requires is_const_pattern + R trimmed_left(T&& pattern) const { + return R::template trim_static(d(), pattern); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных строковым литералом, справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. + * @return R - строка, с удалёнными в конце символами, содержащимися в литерале. + * @en @brief Get a string with the characters specified by the string literal removed from the right. + * @tparam R - desired string type, default str_src. + * @param pattern is a string literal specifying the characters that will be trimmed. + * @return R - a string with characters contained in the literal removed at the end. + */ + template::Count> + requires is_const_pattern + R trimmed_right(T&& pattern) const { + return R::template trim_static(d(), pattern); + } + // Триминг по символам в литерале и пробелам + // Trimming by characters in literal and spaces + + /*! + * @ru @brief Получить строку с удалением символов, заданных строковым литералом, а также + * пробельных символов, слева и справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. + * @return R - строка, с удалёнными в начале и в конце символами, содержащимися в литерале + * и пробельными символами. + * @en @brief Get a string with the characters specified by the string literal removed, as well as + * whitespace characters, left and right. + * @tparam R - desired string type, default str_src. + * @param pattern is a string literal specifying the characters that will be trimmed. + * @return R - a string with the characters contained in the literal removed at the beginning and at the end + * and whitespace characters. + */ + template::Count> + requires is_const_pattern + R trimmed_with_spaces(T&& pattern) const { + return R::template trim_static(d(), pattern); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных строковым литералом, а также + * пробельных символов, слева. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. + * @return R - строка, с удалёнными в начале символами, содержащимися в литерале + * и пробельными символами. + * @en @brief Get a string with the characters specified by the string literal removed, as well as + * whitespace characters, left. + * @tparam R - desired string type, default str_src. + * @param pattern is a string literal specifying the characters that will be trimmed. + * @return R - a string with the characters contained in the literal removed at the beginning + * and whitespace characters. + */ + template::Count> + requires is_const_pattern + R trimmed_left_with_spaces(T&& pattern) const { + return R::template trim_static(d(), pattern); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных строковым литералом, а также + * пробельных символов, справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строковый литерал, задающий символы, которые будут обрезаться. + * @return R - строка, с удалёнными в конце символами, содержащимися в литерале + * и пробельными символами. + * @en @brief Get a string with the characters specified by the string literal removed, as well as + * whitespace characters, right. + * @tparam R - desired string type, default str_src. + * @param pattern is a string literal specifying the characters that will be trimmed. + * @return R - a string with characters contained in the literal removed at the end + * and whitespace characters. + */ + template::Count> + requires is_const_pattern + R trimmed_right_with_spaces(T&& pattern) const { + return R::template trim_static(d(), pattern); + } + // Триминг по динамическому источнику + // Trimming by dynamic source + + /*! + * @ru @brief Получить строку с удалением символов, заданных другой строкой, слева и справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строка, задающая символы, которые будут обрезаться. + * @return R - строка, с удалёнными в начале и в конце символами, содержащимися в шаблоне. + * @en @brief Get a string with characters specified by another string removed, left and right. + * @tparam R - desired string type, default str_src. + * @param pattern - a string specifying the characters that will be trimmed. + * @return R - a string with the characters contained in the pattern removed at the beginning and at the end. + */ + template + R trimmed(str_piece pattern) const { + return R::template trim_static(d(), pattern); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных другой строкой, слева. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строка, задающая символы, которые будут обрезаться. + * @return R - строка, с удалёнными в начале символами, содержащимися в шаблоне. + * @en @brief Get a string with characters specified by another string removed from the left. + * @tparam R - desired string type, default str_src. + * @param pattern - a string specifying the characters that will be trimmed. + * @return R - a string with the characters contained in the pattern removed at the beginning. + */ + template + R trimmed_left(str_piece pattern) const { + return R::template trim_static(d(), pattern); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных другой строкой, справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строка, задающая символы, которые будут обрезаться. + * @return R - строка, с удалёнными в конце символами, содержащимися в шаблоне. + * @en @brief Get a string with characters specified by another string removed to the right. + * @tparam R - desired string type, default str_src. + * @param pattern - a string specifying the characters that will be trimmed. + * @return R - a string with characters contained in the pattern removed at the end. + */ + template + R trimmed_right(str_piece pattern) const { + return R::template trim_static(d(), pattern); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных другой строкой, а также + * пробельных символов, слева и справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строка, задающая символы, которые будут обрезаться. + * @return R - строка, с удалёнными в начале и в конце символами, содержащимися в шаблоне + * и пробельными символами. + * @en @brief Get a string, removing characters specified by another string, as well as + * whitespace characters, left and right. + * @tparam R - desired string type, default str_src. + * @param pattern - a string specifying the characters that will be trimmed. + * @return R - a string with the characters contained in the pattern removed at the beginning and at the end + * and whitespace characters. + */ + template + R trimmed_with_spaces(str_piece pattern) const { + return R::template trim_static(d(), pattern); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных другой строкой, а также + * пробельных символов, слева. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строка, задающая символы, которые будут обрезаться. + * @return R - строка, с удалёнными в начале символами, содержащимися в шаблоне + * и пробельными символами. + * @en @brief Get a string, removing characters specified by another string, as well as + * whitespace characters, left. + * @tparam R - desired string type, default str_src. + * @param pattern - a string specifying the characters that will be trimmed. + * @return R - a string with the characters contained in the pattern removed at the beginning + * and whitespace characters. + */ + template + R trimmed_left_with_spaces(str_piece pattern) const { + return R::template trim_static(d(), pattern); + } + /*! + * @ru @brief Получить строку с удалением символов, заданных другой строкой, а также + * пробельных символов, справа. + * @tparam R - желаемый тип строки, по умолчанию str_src. + * @param pattern - строка, задающая символы, которые будут обрезаться. + * @return R - строка, с удалёнными в конце символами, содержащимися в шаблоне + * и пробельными символами. + * @en @brief Get a string, removing characters specified by another string, as well as + * whitespace characters, right. + * @tparam R - desired string type, default str_src. + * @param pattern - a string specifying the characters that will be trimmed. + * @return R - a string with characters contained in the template removed at the end + * and whitespace characters. + */ + template + R trimmed_right_with_spaces(str_piece pattern) const { + return R::template trim_static(d(), pattern); + } + + /*! + * @ru @brief Получить объект `Splitter` по заданному разделителю, который позволяет последовательно + * получать подстроки методом `next()`, пока `is_done()` false. + * @param delimiter - разделитель. + * @return Splitter. + * @en @brief Retrieve a `Splitter` object by the given splitter, which allows sequential + * get substrings using the `next()` method while `is_done()` is false. + * @param delimiter - delimiter. + * @return Splitter. + */ + constexpr SplitterBase splitter(str_piece delimiter) const { + return SplitterBase{*this, delimiter}; + } +}; + +template requires (N > 1) +struct find_all_container { + static constexpr size_t max_capacity = N; + size_t positions_[N]; + size_t added_{}; + + void emplace_back(size_t pos) { + positions_[added_++] = pos; + } +}; + +/*! + * @ru @brief Простейший класс иммутабельной не владеющей строки. + * @details Этот класс заменяет `simple_str`, если вы используете только "strexpr.h". + * Аналог std::string_view. Содержит только указатель и длину. + * Как наследник от str_algs поддерживает все константные строковые методы, + * за исключением парсинга double из любых типов символов - поддерживаются только + * char, wchar_t, и совместимые с ними по размеру символы. Также не содержит + * работы с упрощённым юникодом. + * @tparam K - тип символов строки. + * @en @brief The simplest class of an immutable non-owning string. + * @details This class replaces `simple_str` if you only use `strexpr.h`. + * Analogous to std::string_view. Contains only a pointer and a length. + * As a descendant of str_algs, it supports all constant string methods, + * except for parsing double from any character types - only supported + * char, wchar_t, and characters compatible with them in size. Also does not contain + * work with simplified Unicode. + * @tparam K - the character type of the string. + */ +template +struct str_src : str_src_algs, str_src, false> { + using symb_type = K; + using my_type = str_src; + + const symb_type* str; + size_t len; + + str_src() = default; + /*! + * @ru @brief Конструктор из строкового литерала. + * @en @brief Constructor from a string literal. + */ + template::Count> + constexpr str_src(T&& v) noexcept : str(v), len(N - 1) {} + + /*! + * @ru @brief Конструктор из указателя и длины. + * @en @brief Constructor from pointer and length. + */ + constexpr str_src(const K* p, size_t l) noexcept : str(p), len(l) {} + + template T> + constexpr str_src(T&& t) : str(t.symbols()), len(t.length()){} + + /*! + *@ru @brief Конструктор из std::basic_string. + *@en @brief Constructor from std::basic_string. + */ + template + constexpr str_src(const std::basic_string, A>& s) noexcept : str(s.data()), len(s.length()) {} + /*! + *@ru @brief Конструктор из std::basic_string_view. + *@en @brief Constructor from std::basic_string_view. + */ + constexpr str_src(const std::basic_string_view>& s) noexcept : str(s.data()), len(s.length()) {} + + /*! + * @ru @brief Получить длину строки. + * @en @brief Get the length of the string. + */ + constexpr size_t length() const noexcept { + return len; + } + /*! + * @ru @brief Получить указатель на константный буфер с символами строки. + * @en @brief Get a pointer to a constant buffer containing string characters. + */ + constexpr const symb_type* symbols() const noexcept { + return str; + } + /*! + * @ru @brief Проверить, не пуста ли строка. + * @en @brief Check if a string is empty. + */ + constexpr bool is_empty() const noexcept { + return len == 0; + } + /*! + * @ru @brief Проверить, не указывают ли два объекта на одну строку. + * @param other - другая строка. + * @en @brief Check if two objects point to the same string. + * @param other - another string. + */ + constexpr bool is_same(str_src other) const noexcept { + return str == other.str && len == other.len; + } + /*! + * @ru @brief Проверить, не является ли строка частью другой строки. + * @param other - другая строка. + * @en @brief Check if a string is part of another string. + * @param other - another string. + */ + constexpr bool is_part_of(str_src other) const noexcept { + return str >= other.str && str + len <= other.str + other.len; + } + /*! + * @ru @brief Получить символ из указанной позиции. Проверка границ не выполняется. + * @param idx - позиция символа. + * @return K - символ. + * @en @brief Get the character from the specified position. Bounds checking is not performed. + * @param idx - position of the symbol. + * @return K is a symbol. + */ + constexpr K operator[](size_t idx) const { + return str[idx]; + } + /*! + * @ru @brief Сдвигает начало строки на заданное количество символов. + * @param delta - количество символов. + * @return my_type&. + * @en @brief Shifts the start of a line by the specified number of characters. + * @param delta - number of characters. + * @return my_type&. + */ + constexpr my_type& remove_prefix(size_t delta) { + str += delta; + len -= delta; + return *this; + } + /*! + * @ru @brief Укорачивает строку на заданное количество символов. + * @param delta - количество символов. + * @return my_type&. + * @en @brief Shortens the string by the specified number of characters. + * @param delta - number of characters. + * @return my_type&. + */ + constexpr my_type& remove_suffix(size_t delta) { + len -= delta; + return *this; + } +}; + +/*! + * @ru @brief Класс, заявляющий, что ссылается на нуль-терминированную строку. + * @tparam K - тип символов строки. + * @details Упрощённая реализация simple_str_nt, когда вы используете только strexpr.h. + * Служит для показа того, что функция параметром хочет получить + * строку с нулем в конце, например, ей надо дальше передавать его в + * стороннее API. Без этого ей надо было бы либо указывать параметром + * конкретный класс строки, что лишает универсальности, либо приводило бы + * к постоянным накладным расходам на излишнее копирование строк во временный + * буфер. Источником нуль-терминированных строк могут быть строковые литералы + * при компиляции, либо классы, хранящие строки. + * @en @brief A class that claims to refer to a null-terminated string. + * @tparam K - the character type of the string. + * @details Simplified implementation of simple_str_nt when you only use strexpr.h. + * Shows what the function wants to receive as a parameter + * a string with a zero at the end, for example, she needs to further transfer it to + * third party API. Without this, she would have to either specify the parameter + * specific string class, which deprives universality, or would lead + * to the constant overhead of unnecessary copying of string into the temporary + * buffer. Null-terminated strings can be sourced from string literals + * during compilation, or classes that store strings. + */ +template +struct str_src_nt : str_src, null_terminated> { + using symb_type = K; + using my_type = str_src_nt; + using base = str_src; + + constexpr static const K empty_string[1] = {0}; + + str_src_nt() = default; + /*! + * @ru @brief Явный конструктор из С-строки. + * @param p - указатель на C-строку (нуль-терминированная строка). + * @details Это единственный конструктор из всех строковых объектов, принимающий C-строку. + * Вычисляет её длину при инициализации. Все остальные строковые объекты не инициализируются + * C-строками. Это для того, чтобы `strlen` вызывалась только в одном месте библиотеки, + * длина C-строки вычислялась только один раз и далее не терялась случайно при передаче между разными + * типами строковых объектов. + * @en @brief Explicit constructor from C-string. + * @param p - pointer to a C-string (null-terminated string). + * @details This is the only constructor of all string objects that accepts a C-string. + * Calculates its length upon initialization. All other string objects are not initialized + * C-strings. This is to ensure that `strlen` is called only in one place in the library, + * the length of the C-string was calculated only once and was not subsequently lost accidentally when transferred between different + * types of string objects. + */ + template requires std::is_same_v>>, K> + constexpr explicit str_src_nt(T&& p) noexcept { + base::len = p ? static_cast(base::traits::length(p)) : 0; + base::str = base::len ? p : empty_string; + } + /*! + * @ru @brief Конструктор из строкового литерала. + * @en @brief Constructor from a string literal. + */ + template::Count> + constexpr str_src_nt(T&& v) noexcept : base(std::forward(v)) {} + + /*! + * @ru @brief Конструктор из указателя и длины. + * @en @brief Constructor from pointer and length. + */ + constexpr str_src_nt(const K* p, size_t l) noexcept : base(p, l) {} + + template T> + constexpr str_src_nt(T&& t) { + base::str = t.symbols(); + base::len = t.length(); + } + /*! + *@ru @brief Конструктор из std::basic_string. + *@en @brief Constructor from std::basic_string. + */ + template + constexpr str_src_nt(const std::basic_string, A>& s) noexcept : base(s) {} + + static const my_type empty_str; + /*! + * @ru @brief Получить нуль-терминированную строку, сдвинув начало на заданное количество символов. + * @param from - на сколько символов сдвинуть начало строки. + * @return my_type. + * @en @brief Get a null-terminated string by shifting the start by the specified number of characters. + * @param from - by how many characters to shift the beginning of the line. + * @return my_type. + */ + constexpr my_type to_nts(size_t from) { + if (from > base::len) { + from = base::len; + } + return {base::str + from, base::len - from}; + } +}; + +template +inline const str_src_nt str_src_nt::empty_str{str_src_nt::empty_string, 0}; +template struct simple_str_selector; + +#ifndef IN_FULL_SIMSTR + +template +using simple_str = str_src; + +template +struct simple_str_selector { + using type = simple_str; +}; + +template +using simple_str_nt = str_src_nt; + +template +using Splitter = SplitterBase>; + +using ssa = str_src; +using ssb = str_src; +using ssw = str_src; +using ssu = str_src; +using ssuu = str_src; +using stra = str_src_nt; +using strb = str_src_nt; +using strw = str_src_nt; +using stru = str_src_nt; +using struu = str_src_nt; + +inline namespace literals { + +/*! + * @ru @brief Оператор литерал в str_src. + * @param ptr - указатель на строку. + * @param l - длина строки. + * @return str_src. + * @en @brief Operator literal in str_src. + * @param ptr - pointer to a string. + * @param l - string length. + * @return str_src. + */ +SS_CONSTEVAL str_src_nt operator""_ss(const u8s* ptr, size_t l) { + return str_src_nt{ptr, l}; +} +/*! + * @ru @brief Оператор литерал в str_src. + * @param ptr - указатель на строку. + * @param l - длина строки. + * @return str_src. + * @en @brief Operator literal in str_src. + * @param ptr - pointer to a string. + * @param l - string length. + * @return str_src. + */ +SS_CONSTEVAL str_src_nt operator""_ss(const ubs* ptr, size_t l) { + return str_src_nt{ptr, l}; +} +/*! + * @ru @brief Оператор литерал в str_src. + * @param ptr - указатель на строку. + * @param l - длина строки. + * @return str_src. + * @en @brief Operator literal in str_src. + * @param ptr - pointer to a string. + * @param l - string length. + * @return str_src. + */ +SS_CONSTEVAL str_src_nt operator""_ss(const uws* ptr, size_t l) { + return str_src_nt{ptr, l}; +} +/*! + * @ru @brief Оператор литерал в str_src. + * @param ptr - указатель на строку. + * @param l - длина строки. + * @return str_src. + * @en @brief Operator literal in str_src. + * @param ptr - pointer to a string. + * @param l - string length. + * @return str_src. + */ +SS_CONSTEVAL str_src_nt operator""_ss(const u16s* ptr, size_t l) { + return str_src_nt{ptr, l}; +} + +/*! + * @ru @brief Оператор литерал в str_src. + * @param ptr - указатель на строку. + * @param l - длина строки. + * @return str_src. + * @en @brief Operator literal in str_src. + * @param ptr - pointer to a string. + * @param l - string length. + * @return str_src. + */ +SS_CONSTEVAL str_src_nt operator""_ss(const u32s* ptr, size_t l) { + return str_src_nt{ptr, l}; +} + +} // namespace literals + +#endif + +template +struct CheckSpaceTrim { + constexpr bool is_trim_spaces(K s) const { + return s == ' ' || (s >= 9 && s <= 13); // || isspace(s); + } +}; +template +struct CheckSpaceTrim { + constexpr bool is_trim_spaces(K) const { + return false; + } +}; + +template +struct CheckSymbolsTrim { + str_src symbols; + constexpr bool is_trim_symbols(K s) const { + return symbols.len != 0 && str_src::traits::find(symbols.str, symbols.len, s) != nullptr; + } +}; + +template +struct CheckConstSymbolsTrim { + const const_lit_to_array symbols; + + template::Count> requires (M == N + 1) + constexpr CheckConstSymbolsTrim(T&& s) : symbols(std::forward(s)) {} + + constexpr bool is_trim_symbols(K s) const noexcept { + return symbols.contain(s); + } +}; + +template +struct CheckConstSymbolsTrim { + constexpr bool is_trim_symbols(K) const { + return false; + } +}; + +template +struct SymbSelector { + using type = CheckConstSymbolsTrim; +}; + +template +struct SymbSelector { + using type = CheckSymbolsTrim; +}; + +template +struct SymbSelector(-1)> { + using type = CheckConstSymbolsTrim; +}; + +template +struct trim_operator : SymbSelector::type, CheckSpaceTrim { + constexpr bool isTrim(K s) const { + return CheckSpaceTrim::is_trim_spaces(s) || SymbSelector::type::is_trim_symbols(s); + } + constexpr str_src operator()(str_src from) const { + if constexpr ((S & TrimSides::TrimLeft) != 0) { + while (from.len) { + if (isTrim(*from.str)) { + from.str++; + from.len--; + } else + break; + } + } + if constexpr ((S & TrimSides::TrimRight) != 0) { + const K* back = from.str + from.len - 1; + while (from.len) { + if (isTrim(*back)) { + back--; + from.len--; + } else + break; + } + } + return from; + } +}; + +template +using SimpleTrim = trim_operator; + +template::Count> + requires is_const_pattern +constexpr inline auto trimOp(T&& pattern) { + return trim_operator{pattern}; +} + +template +constexpr inline auto trimOp(str_src pattern) { + return trim_operator{pattern}; +} + +template +concept StrSource = StdStrSource || requires { + typename std::remove_cvref_t::symb_type; +}; + +template +struct to_src_str_base { + using symb_type = typename T::symb_type; + static str_src get(const T& s) { + return {s.symbols(), s.length()}; + } +}; + +struct to_src_str_base_none {}; + +template +struct to_src_str : std::conditional_t, to_src_str_base, to_src_str_base_none> { +}; + +template +struct to_src_str> { + using symb_type = K; + static str_src get(const std::basic_string& s) { + return {s.data(), s.length()}; + } +}; + +template +struct to_src_str> { + using symb_type = K; + static str_src get(const std::basic_string_view& s) { + return {s.data(), s.length()}; + } +}; + +template +using src_str_t = to_src_str>::symb_type; + +template +auto get_str_src_from(T&& t) { + return to_src_str>::get(std::forward(t)); +} + +static constexpr size_t FIND_CACHE_SIZE = 16; + +template +struct expr_replaces : expr_to_std_string> { + using symb_type = K; + using my_type = expr_replaces; + str_src what; + const K(&pattern)[N + 1]; + const K(&repl)[L + 1]; + mutable find_all_container matches_; + mutable size_t last_; + + constexpr expr_replaces(str_src w, const K(&p)[N + 1], const K(&r)[L + 1]) : what(w), pattern(p), repl(r) {} + + constexpr size_t length() const { + size_t l = what.length(); + if constexpr (N == L) { + return l; + } + what.find_all_to(matches_, pattern, N, 0, FIND_CACHE_SIZE); + if (matches_.added_) { + last_ = matches_.positions_[matches_.added_ - 1] + N; + l += int(L - N) * matches_.added_; + + if (matches_.added_ == FIND_CACHE_SIZE) { + for (;;) { + size_t next = what.find(pattern, N, last_); + if (next == str::npos) { + break; + } + last_ = next + N; + l += L - N; + } + } + } + if (!l) { + matches_.added_ = -1; + } + return l; + } + constexpr K* place(K* ptr) const noexcept { + if constexpr (N == L) { + const K* from = what.symbols(); + for (size_t start = 0; start < what.length();) { + size_t next = what.find(pattern, N, start); + if (next == str::npos) { + next = what.length(); + } + size_t delta = next - start; + ch_traits::copy(ptr, from + start, delta); + ptr += delta; + ch_traits::copy(ptr, repl, L); + ptr += L; + start = next + N; + } + return ptr; + } + if (matches_.added_ == 0) { + return what.place(ptr); + } else if (matches_.added_ == -1) { + // after replaces text become empty + return ptr; + } + const K* from = what.symbols(); + for (size_t start = 0, offset = matches_.positions_[0], idx = 1; ;) { + ch_traits::copy(ptr, from + start, offset - start); + ptr += offset - start; + ch_traits::copy(ptr, repl, L); + ptr += L; + start = offset + N; + if (start >= last_) { + size_t tail = what.length() - last_; + ch_traits::copy(ptr, from + last_, tail); + ptr += tail; + break; + } else { + offset = idx < FIND_CACHE_SIZE ? matches_.positions_[idx++] : what.find(pattern, N, start); + } + } + return ptr; + } +}; + +/*! + * @ingroup StrExprs + * @ru @brief Получить строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки. + * @tparam K - тип символа, выводится из первого аргумента. + * @param w - начальная строка. + * @param p - строковый литерал, искомая подстрока. + * @param r - строковый литерал, на что заменять. + * @en @brief Get a string expression that generates a string with all occurrences of a given substring replaced. + * @tparam K - the type of the symbol, inferred from the first argument. + * @param w - starting string. + * @param p - string literal, searched substring. + * @param r - string literal, what to replace with. + */ +template, typename T, size_t N = const_lit_for::Count, typename X, size_t L = const_lit_for::Count> + requires(N > 1) +constexpr auto e_repl(A&& w, T&& p, X&& r) { + return expr_replaces{get_str_src_from(std::forward(w)), p, r}; } /*! * @ingroup StrExprs - * @ru @brief Оператор сложения для std::wstring_view и совместимого с wchar_t строкового выражения - * (char16_t или char32_t, в зависимости от компилятора). - * @en @brief Addition operator for std::wstring_view and wchar_t-compatible string expression - * (char16_t or char32_t, depending on the compiler). + * @ru @brief Строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки. + * @tparam K - тип строки. + * @details `e_repl` позволяет заменять только с использование строковых литералов. + * В случае, когда искомая подстрока или строка замены не известны при компиляции, и задаются в runtime, + * следует использовать этот тип, например: + * @en @brief A string expression that generates a string replacing all occurrences of the given substring. + * @tparam K - string type. + * @details `e_repl` only allows replacement using string literals. + * In the case when the required substring or replacement string is not known at compilation, and is set at runtime, + * this type should be used, for example: + * @~ + * ```cpp + * stringa result = "
    " + expr_replaced{source, pattern, repl} + "
    "; + * ``` */ -template A> -constexpr strexprjoin_c, false> operator+(const std::wstring_view& s, const A& a) { - return {a, s}; +template +struct expr_replaced : expr_to_std_string> { + using symb_type = K; + using my_type = expr_replaced; + str_src what; + const str_src pattern; + const str_src repl; + mutable find_all_container matches_; + mutable size_t last_; + /*! + * @ru @brief Конструктор. + * @param w - исходная строка. + * @param p - искомая подстрока. + * @param r - строка замены. + * @en @brief Constructor. + * @param w - source string. + * @param p - the searched substring. + * @param r - replacement string. + */ + constexpr expr_replaced(str_src w, str_src p, str_src r) : what(w), pattern(p), repl(r) {} + + constexpr size_t length() const { + size_t l = what.length(), plen = pattern.length(), rlen = repl.length(); + + if (!plen || plen == rlen) { + return l; + } + what.find_all_to(matches_, pattern.symbols(), plen, 0, FIND_CACHE_SIZE); + if (matches_.added_) { + last_ = matches_.positions_[matches_.added_ - 1] + plen; + l += int(rlen - plen) * matches_.added_; + + if (matches_.added_ == FIND_CACHE_SIZE) { + for (;;) { + size_t next = what.find(pattern.symbols(), plen, last_); + if (next == str::npos) { + break; + } + last_ = next + plen; + l += rlen - plen; + } + } + } + if (!l) { + matches_.added_ = -1; + } + return l; + } + constexpr K* place(K* ptr) const noexcept { + size_t plen = pattern.length(), rlen = repl.length(); + if (plen == rlen) { + const K* from = what.symbols(); + for (size_t start = 0; start < what.length();) { + size_t next = what.find(pattern, start); + if (next == str::npos) { + next = what.length(); + } + size_t delta = next - start; + ch_traits::copy(ptr, from + start, delta); + ptr += delta; + ch_traits::copy(ptr, repl.symbols(), rlen); + ptr += rlen; + start = next + plen; + } + return ptr; + } + if (matches_.added_ == 0) { + return what.place(ptr); + } else if (matches_.added_ == -1) { + // after replaces text become empty + return ptr; + } + const K* from = what.symbols(); + for (size_t start = 0, offset = matches_.positions_[0], idx = 1; ;) { + ch_traits::copy(ptr, from + start, offset - start); + ptr += offset - start; + ch_traits::copy(ptr, repl.symbols(), rlen); + ptr += rlen; + start = offset + plen; + if (start >= last_) { + size_t tail = what.length() - last_; + ch_traits::copy(ptr, from + last_, tail); + ptr += tail; + break; + } else { + offset = idx < FIND_CACHE_SIZE ? matches_.positions_[idx++] : what.find(pattern.symbols(), plen, start); + } + } + return ptr; + } +}; + +/*! + * @ingroup StrExprs + * @ru @brief Получить строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки. + * @tparam K - тип символа, выводится из первого аргумента. + * @param w - начальная строка. + * @param p - строковый литерал, искомая подстрока. + * @param r - строковый объект, может быть рантайм. + * @en @brief Get a string expression that generates a string with all occurrences of a given substring replaced. + * @tparam K - the type of the symbol, inferred from the first argument. + * @param w - starting string. + * @param p - string literal, searched substring. + * @param r - string object, maybe runtime. + */ +template, typename T, size_t N = const_lit_for::Count, StrSource X> + requires std::is_same_v> +constexpr auto e_repl(A&& w, T&& p, X&& r) { + return expr_replaced{get_str_src_from(std::forward
    (w)), p, get_str_src_from(std::forward(r))}; } -}// namespace simstr +/*! + * @ingroup StrExprs + * @ru @brief Получить строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки. + * @tparam K - тип символа, выводится из первого аргумента. + * @param w - начальная строка. + * @param p - строковый объект, может быть рантайм. + * @param r - строковый литерал, на что заменять. + * @en @brief Get a string expression that generates a string with all occurrences of a given substring replaced. + * @tparam K - the type of the symbol, inferred from the first argument. + * @param w - starting string. + * @param p - string object, maybe runtime. + * @param r - string literal, what to replace with. + */ +template, StrSource T, typename X, size_t L = const_lit_for::Count> + requires std::is_same_v> +constexpr auto e_repl(A&& w, T&& p, X&& r) { + return expr_replaced{get_str_src_from(std::forward(w)), get_str_src_from(std::forward(p)), r}; +} + +/*! + * @ingroup StrExprs + * @ru @brief Получить строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки. + * @tparam K - тип символа, выводится из первого аргумента. + * @param w - начальная строка. + * @param p - строковый объект, может быть рантайм. + * @param r - строковый объект, может быть рантайм. + * @en @brief Get a string expression that generates a string with all occurrences of a given substring replaced. + * @tparam K - the type of the symbol, inferred from the first argument. + * @param w - starting string. + * @param p - string object, maybe runtime. + * @param r - string object, maybe runtime. + */ +template, StrSource T, StrSource X> + requires (std::is_same_v> && std::is_same_v>) +constexpr auto e_repl(A&& w, T&& p, X&& r) { + return expr_replaced{get_str_src_from(std::forward(w)), get_str_src_from(std::forward(p)), get_str_src_from(std::forward(r))}; +} + +template +struct replace_search_result_store { + size_t count_{}; + std::pair replaces_[16]; +}; + +template<> +struct replace_search_result_store : std::vector> {}; + +// Строковое выражение для замены символов +// String expression to replace characters +template +struct expr_replace_const_symbols : expr_to_std_string> { + using symb_type = K; + inline static const int BIT_SEARCH_TRESHHOLD = 4; + const K pattern_[N]; + const str_src source_; + const str_src replaces_[N]; + + mutable replace_search_result_store search_results_; + + [[_no_unique_address]] + uu8s bit_mask_[N >= BIT_SEARCH_TRESHHOLD ? (sizeof(K) == 1 ? 32 : 64) : 0]{}; + + template requires (sizeof...(Repl) == N * 2) + constexpr expr_replace_const_symbols(str_src source, Repl&& ... repl) : expr_replace_const_symbols(0, source, std::forward(repl)...) {} + + size_t length() const { + size_t l = source_.length(); + auto [fnd, num] = find_first_of(source_.str, source_.len); + if (fnd == str::npos) { + return l; + } + l += replaces_[num].len - 1; + if constexpr (UseVectorForReplace) { + search_results_.reserve((l >> 4) + 8); + search_results_.emplace_back(fnd, num); + for (size_t start = fnd + 1;;) { + auto [fnd, idx] = find_first_of(source_.str, source_.len, start); + if (fnd == str::npos) { + break; + } + search_results_.emplace_back(fnd, idx); + start = fnd + 1; + l += replaces_[idx].len - 1; + } + } else { + const size_t max_store = std::size(search_results_.replaces_); + search_results_.replaces_[0] = {fnd, num}; + search_results_.count_++; + for (size_t start = fnd + 1;;) { + auto [found, idx] = find_first_of(source_.str, source_.len, start); + if (found == str::npos) { + break; + } + if (search_results_.count_ < max_store) { + search_results_.replaces_[search_results_.count_] = {found, idx}; + } + l += replaces_[idx].len - 1; + search_results_.count_++; + start = found + 1; + } + } + return l; + } + K* place(K* ptr) const noexcept { + size_t start = 0; + const K* text = source_.str; + if constexpr (UseVectorForReplace) { + for (const auto& [pos, num] : search_results_) { + size_t delta = pos - start; + ch_traits::copy(ptr, text + start, delta); + ptr += delta; + ptr = replaces_[num].place(ptr); + start = pos + 1; + } + } else { + const size_t max_store = std::size(search_results_.replaces_); + size_t founded = search_results_.count_; + for (size_t idx = 0, stop = std::min(founded, max_store); idx < stop; idx++) { + const auto [pos, num] = search_results_.replaces_[idx]; + size_t delta = pos - start; + ch_traits::copy(ptr, text + start, delta); + ptr += delta; + ptr = replaces_[num].place(ptr); + start = pos + 1; + } + if (founded > max_store) { + founded -= max_store; + while (founded--) { + auto [fnd, idx] = find_first_of(source_.str, source_.len, start); + size_t delta = fnd - start; + ch_traits::copy(ptr, text + start, delta); + ptr += delta; + ptr = replaces_[idx].place(ptr); + start = fnd + 1; + } + } + } + size_t tail = source_.len - start; + ch_traits::copy(ptr, text + start, tail); + return ptr + tail; + } + +protected: + template + constexpr expr_replace_const_symbols(int, str_src source, K s, str_src r, Repl&&... repl) : + expr_replace_const_symbols(0, source, std::forward(repl)..., std::make_pair(s, r)){} + + template requires (sizeof...(Repl) == N) + constexpr expr_replace_const_symbols(int, str_src source, Repl&&... repl) : + source_(source), pattern_ {repl.first...}, replaces_{repl.second...} + { + if constexpr (N >= BIT_SEARCH_TRESHHOLD) { + for (size_t idx = 0; idx < N; idx++) { + uu8s s = static_cast(pattern_[idx]); + if constexpr (sizeof(K) == 1) { + bit_mask_[s >> 3] |= 1 << (s & 7); + } else { + if (std::make_unsigned_t(pattern_[idx]) > 255) { + bit_mask_[32 + (s >> 3)] |= 1 << (s & 7); + } else { + bit_mask_[s >> 3] |= 1 << (s & 7); + } + } + } + } + } + + template + size_t index_of(K s) const { + if constexpr (Idx < N) { + return pattern_[Idx] == s ? Idx : index_of(s); + } + return -1; + } + bool is_in_mask(uu8s s) const { + return (bit_mask_[s >> 3] & (1 <<(s & 7))) != 0; + } + bool is_in_mask2(uu8s s) const { + return (bit_mask_[32 + (s >> 3)] & (1 <<(s & 7))) != 0; + } + + bool is_in_pattern(K s, size_t& idx) const { + if constexpr (N >= BIT_SEARCH_TRESHHOLD) { + if constexpr (sizeof(K) == 1) { + if (is_in_mask(s)) { + idx = index_of<0>(s); + return true; + } + } else { + if (std::make_unsigned_t(s) > 255) { + if (is_in_mask2(s)) { + return (idx = index_of<0>(s)) != -1; + } + } else { + if (is_in_mask(s)) { + idx = index_of<0>(s); + return true; + } + } + } + } + return false; + } + std::pair find_first_of(const K* text, size_t len, size_t offset = 0) const { + if constexpr (N >= BIT_SEARCH_TRESHHOLD) { + size_t idx; + while (offset < len) { + if (is_in_pattern(text[offset], idx)) { + return {offset, idx}; + } + offset++; + } + } else { + while (offset < len) { + if (size_t idx = index_of<0>(text[offset]); idx != -1) { + return {offset, idx}; + } + offset++; + } + } + return {-1, -1}; + } +}; + +/*! + * @ingroup StrExprs + * @ru @brief Возвращает строковое выражение, генерирующее строку, в которой заданные символы + * заменены на заданные подстроки. + * @tparam UseVector - использовать вектор для сохранения результатов поиска символов. + * Более подробно описано в `expr_replace_symbols`. + * @param src - исходная строка. + * @param symbol - константный символ, который надо заменять. + * @param repl - строковый литерал, на который заменять символ. + * @param ... symbol, repl - другие символы и строки. + * @details Применяется для генерации замены символов на строки, в случае если все они известны + * в compile time. Пример: + * @en @brief Returns a string expression that generates a string containing the given characters + * replaced with given substrings. + * @tparam UseVector - use a vector to save symbol search results. + * Described in more detail in `expr_replace_symbols`. + * @param src - source string. + * @param symbol - constant symbol that needs to be replaced. + * @param repl - string literal to replace the character with. + * @param ... symbol, repl - other symbols and strings. + * @details Used to generate character replacements for strings if all of them are known + * at compile time. Example: + * @~ + * ```cpp + * out += "
    " + e_repl_const_symbols(text, '\"', """, '<', "<", '\'', "'", '&', "&") + "
    "; + * ``` + * @ru В принципе, `e_repl_const_symbols` вполне безопасно возвращать из функции, если исходная строка + * внешняя по отношению к функции. + * @en In principle, `e_repl_const_symbols` is quite safe to return from a function if the source string + * external to function. + * @~ + * ```cpp + * auto repl_html_symbols(ssa text) { + * return e_repl_const_symbols(text, '\"', """, '<', "<", '\'', "'", '&', "&"); + * } + * .... + * out += "
    " + repl_html_symbols(content) + "
    "; + * ``` + */ +template, typename ... Repl> + requires (sizeof...(Repl) % 2 == 0) +auto e_repl_const_symbols(A&& src, Repl&& ... other) { + return expr_replace_const_symbols(get_str_src_from(std::forward
    (src)), std::forward(other)...); +} + +/*! + * @ingroup StrExprs + * @ru @brief Тип для строкового выражения, генерирующее строку, в которой заданные символы заменяются на заданные строки. + * @tparam K - тип символа. + * @tparam UseVectorForReplace - использовать вектор для запоминания результатов поиска вхождений символов. + * @details Этот тип применяется, когда состав символов или соответствующих им замен не известен в compile time, + * а определяется в runtime. В конструктор передается вектор из пар `символ - строка замены`. + * Параметр `UseVectorForReplace` задаёт стратегию реализации. Дело в том, что работа любых строковых выражений + * разбита на две фазы - вызов `length()`, в котором подсчитывается количество символов в результате, + * и вызов `place()`, в котором результат помещается в предоставленный буфер. + * При `UseVectorForReplace == true` во время фазы подcчёта количества символов, позиции найденных вхождений + * сохраняются в векторе, и во время второй фазы поиск уже не выполняется, а позиции берутся из вектора. + * Это, с одной стороны, уменьшает время во второй фазе - не нужно снова выполнять поиск, но увеличивает + * время в первой фазе - добавление элементов в вектор не бесплатно, и требует времени. + * При `UseVectorForReplace == false` во время фазы подcчёта количества символов, в локальном массиве запоминаются позиции + * первых 16 вхождений и их общее количество, а во время второй фазы, если вхождений больше 16, то поиск повторяется, + * но уже только с позиции 16го вхождения. Это может увеличить время во второй фазе, но сокращает время в первой + * фазе - не нужно добавлять элементы в вектор, не нужна динамическая аллокация. + * В разных сценариях использования более оптимальными могут быть та или иная стратегия, и вы можете сами решить, + * что в каждом конкретном случае больше подойдёт. + * @en @brief A type for a string expression that generates a string in which the given characters are replaced by the given strings. + * @tparam K - symbol type. + * @tparam UseVectorForReplace - use a vector to remember the results of searching for occurrences of characters. + * @details This type is used when the composition of symbols or their corresponding replacements is not known at compile time, + * and is defined at runtime. A vector of `character - replacement string` pairs is passed to the constructor. + * The `UseVectorForReplace` parameter specifies the implementation strategy. The point is that the work of any string expressions + * is divided into two phases - the `length()` call, which counts the number of characters in the result, + * and a call to `place()`, which places the result in the provided buffer. + * When `UseVectorForReplace == true` during the phase of counting the number of characters, the position of the found occurrences + * are stored in the vector, and during the second phase the search is no longer performed, and the positions are taken from the vector. + * This, on the one hand, reduces the time in the second phase - there is no need to search again, but it increases + * time in the first phase - adding elements to the vector is not free, and takes time. + * When `UseVectorForReplace == false` during the phase of counting the number of characters, positions in the local array are remembered + * the first 16 occurrences and their total number, and during the second phase, if there are more than 16 occurrences, then the search is repeated, + * but only from the position of the 16th occurrence. This may increase the time in the second phase, but reduces the time in the first + * phase - no need to add elements to the vector, no need for dynamic allocation. + *In different use cases, one or another strategy may be more optimal, and you can decide for yourself + * whichever is more suitable in each specific case. + */ +template +struct expr_replace_symbols : expr_to_std_string> { + using symb_type = K; + using str_t = typename simple_str_selector::type; + inline static const int BIT_SEARCH_TRESHHOLD = 4; + + const str_src source_; + const std::vector>& replaces_; + + std::basic_string, std::allocator> pattern_; + + mutable replace_search_result_store search_results_; + + uu8s bit_mask_[sizeof(K) == 1 ? 32 : 64]{}; + /*! + * @ru @brief Конструктор выражения. + * @param source - исходная строка. + * @param repl - вектор из пар "символ->строка замены". + * @details Пример: + * @en @brief Expression constructor. + * @param source - source string. + * @param repl - a vector of "character->replacement string" pairs. + * @details Example: + * @~ + * ```cpp + stringa result = expr_replace_symbols{source, { + {'-', ""}, + {'<', "<"}, + {'>', ">"}, + {'\'', "'"}, + {'\"', """}, + {'&', "&"}, + }}; + * ``` + * @ru Пример приведен для наглядности использования. В данном случае и заменяемые символы, и строки замены + * известны в compile time, и в этом случае лучше применять e_repl_const_symbols, а этот класс + * используется, когда символы или замены задаются в runtime. + * @en An example is provided for clarity of use. In this case, both the characters to be replaced and the replacement strings + * known at compile time, in which case it is better to use e_repl_const_symbols, and this class + * is used when characters or replacements are specified at runtime. + */ + constexpr expr_replace_symbols(str_t source, const std::vector>& repl ) + : source_(source), replaces_(repl) + { + size_t pattern_len = replaces_.size(); + pattern_.resize(pattern_len); + K* pattern = pattern_.data(); + + for (size_t idx = 0; idx < replaces_.size(); idx++) { + *pattern++ = replaces_[idx].first; + } + + if (pattern_len >= BIT_SEARCH_TRESHHOLD) { + for (size_t idx = 0; idx < pattern_len; idx++) { + uu8s s = static_cast(pattern_[idx]); + if constexpr (sizeof(K) == 1) { + bit_mask_[s >> 3] |= (1 << (s & 7)); + } else { + if (std::make_unsigned_t(pattern_[idx]) > 255) { + bit_mask_[32 + (s >> 3)] |= (1 << (s & 7)); + } else { + bit_mask_[s >> 3] |= (1 << (s & 7)); + } + } + } + } + } + + size_t length() const { + size_t l = source_.length(); + auto [fnd, num] = find_first_of(source_.str, source_.len); + if (fnd == str::npos) { + return l; + } + l += replaces_[num].second.len - 1; + if constexpr (UseVectorForReplace) { + search_results_.reserve((l >> 4) + 8); + search_results_.emplace_back(fnd, num); + for (size_t start = fnd + 1;;) { + auto [fnd, idx] = find_first_of(source_.str, source_.len, start); + if (fnd == str::npos) { + break; + } + search_results_.emplace_back(fnd, idx); + start = fnd + 1; + l += replaces_[idx].second.len - 1; + } + } else { + const size_t max_store = std::size(search_results_.replaces_); + search_results_.replaces_[0] = {fnd, num}; + search_results_.count_++; + for (size_t start = fnd + 1;;) { + auto [found, idx] = find_first_of(source_.str, source_.len, start); + if (found == str::npos) { + break; + } + if (search_results_.count_ < max_store) { + search_results_.replaces_[search_results_.count_] = {found, idx}; + } + l += replaces_[idx].second.len - 1; + search_results_.count_++; + start = found + 1; + } + } + return l; + } + K* place(K* ptr) const noexcept { + size_t start = 0; + const K* text = source_.str; + if constexpr (UseVectorForReplace) { + for (const auto& [pos, num] : search_results_) { + size_t delta = pos - start; + ch_traits::copy(ptr, text + start, delta); + ptr += delta; + ptr = replaces_[num].second.place(ptr); + start = pos + 1; + } + } else { + const size_t max_store = std::size(search_results_.replaces_); + size_t founded = search_results_.count_; + for (size_t idx = 0, stop = std::min(founded, max_store); idx < stop; idx++) { + const auto [pos, num] = search_results_.replaces_[idx]; + size_t delta = pos - start; + ch_traits::copy(ptr, text + start, delta); + ptr += delta; + ptr = replaces_[num].second.place(ptr); + start = pos + 1; + } + if (founded > max_store) { + founded -= max_store; + while (founded--) { + auto [fnd, idx] = find_first_of(source_.str, source_.len, start); + size_t delta = fnd - start; + ch_traits::copy(ptr, text + start, delta); + ptr += delta; + ptr = replaces_[idx].second.place(ptr); + start = fnd + 1; + } + } + } + size_t tail = source_.len - start; + ch_traits::copy(ptr, text + start, tail); + return ptr + tail; + } + +protected: + size_t index_of(K s) const { + return pattern_.find(s); + } + + bool is_in_mask(uu8s s) const { + return (bit_mask_[s >> 3] & (1 << (s & 7))) != 0; + } + bool is_in_mask2(uu8s s) const { + return (bit_mask_[32 + (s >> 3)] & (1 << (s & 7))) != 0; + } + + bool is_in_pattern(K s, size_t& idx) const { + if constexpr (sizeof(K) == 1) { + if (is_in_mask(s)) { + idx = index_of(s); + return true; + } + } else { + if (std::make_unsigned_t(s) > 255) { + if (is_in_mask2(s)) { + return (idx = index_of(s)) != -1; + } + } else { + if (is_in_mask(s)) { + idx = index_of(s); + return true; + } + } + } + return false; + } + + std::pair find_first_of(const K* text, size_t len, size_t offset = 0) const { + size_t pl = pattern_.length(); + if (pl >= BIT_SEARCH_TRESHHOLD) { + size_t idx; + while (offset < len) { + if (is_in_pattern(text[offset], idx)) { + return {offset, idx}; + } + offset++; + } + } else { + while (offset < len) { + if (size_t idx = index_of(text[offset]); idx != -1) { + return {offset, idx}; + } + offset++; + } + } + return {-1, -1}; + } +}; + +} // namespace simstr + +namespace std { +/*! + * @ingroup StrExprs + * @ru @brief Унарный оператор+ для преобразования стандартных строк в строковые выражения. + * @details Стандартные строки могут напрямую участвовать в строковых выражениях только когда + * другой операнд тоже является строковым выражением. Если другой операнд - не строковое выражение, + * используйте этот оператор, чтобы превратить `std::basic_string` или `std::basic_string_view` + * в строковое выражение. + * @en @brief Unary operator + for converting standard strings to string expressions. + * @details Standard strings can only participate directly in string expressions when + * the other operand is also a string expression. If the other operand is not a string expression, + * use this operator to turn `std::basic_string` or `std::basic_string_view` + * into string expression. + * @ru Пример: @en Example @~ + * ```cpp + * std::string make_text(const std::string& text, int count, std::string_view what, std::string_view what_p = ""sv) { + * return +text + " " + count + " " + e_choice(what_p.empty(), what + e_if(count > 1, "s"), e_choice(count > 1, +what_p, +what)); + * } + * ``` + */ +template +simstr::expr_stdstr operator+(const T& str) { + return {str}; +} + +} // namespace std diff --git a/readme.md b/readme.md index 06f8531..14fed39 100644 --- a/readme.md +++ b/readme.md @@ -1,106 +1,320 @@ # simstr - String object and function library +

    Speed up your work with strings by 2-10 times!

    + [![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) -Version 1.3.1. +Version 1.4.0.
    On Russian | По-русски -This library contains the modern implementation of several types of string objects and various algorithms for working with strings. +This library contains a modern implementation of several types of string objects and various algorithms for working with strings. The goal of the library is to make working with strings in C++ as simple and easy as in many other languages, especially -scripting languages, while maintaining optimality and performance at the level of C and C++, and even improving them. +scripting languages, while maintaining optimal performance at the level of C and C++, and even improving them. It's no secret that working with strings in C++ often causes pain. The `std::string` class is often inconvenient or inefficient. -Many functions that are usually necessary when working with strings are simply not there, and everyone has to write them themselves. +Many functions that are usually needed when working with strings are simply not there, and everyone has to write them themselves. +Even concatenating `std::string` and `std::string_view` became possible only with C++26. +That's why I started creating this library for myself around 2012, and now I'm ready to share it with all C++ developers. This library was not made as a universal combine that "can do everything", I implemented what I had to -use at work, trying to do it in the most efficient way, and I modestly hope that I succeeded in something +use in my work, trying to do it in the most efficient way, and I modestly hope that I have succeeded in something and will be useful to other people, either directly or as a source of ideas. -The library does not pretend to be a "change the header and everything works better" solution. I tried to make many methods compatible -with `std::string` and `std::string_view`, but I didn't bother with it much. Rewriting old code to work with simstr -will require some effort, but I assure you that it will pay off. And writing new code with its use is easy and enjoyable :) +The library contains two parts: +- Implementation of [*"String Expressions"*](https://orefkov.github.io/simstr/docs_en/overview.html#autotoc_md68) and algorithms for working + with constant strings.\ + To use this part, just take the file `"include/simstr/strexpr.h"` and write in your code + ```cpp + #include "path/to/file/strexpr.h" + ``` + This will allow you to use powerful and fast *"string expressions"* for concatenation and string construction for standard string types (`std::basic_string`, `std::basic_string_view`), as well as simplified versions of the `simple_str` and + `simple_str_nt` classes, which implement all those string algorithms of the library that do not require storing or modifying strings. + Since this is a header-only part, it does not include working with UTF encodings and simplified Unicode. +- The full version, which requires connecting the entire library (`"include/simstr/sstring.h"`), adds its own string types with + the ability to store and modify strings, works with UTF encodings and simplified Unicode. -The main difference between simstr and std::string is that instead of a single universal class, several -types of objects are used to work with strings, each of which is good for its own purposes, and at the same time interacts well with each other. -If you actively used std::string_view and understood its advantages and disadvantages compared to std::string, -then the simstr approach will also be clear to you. +The library does not pretend to be "changed the header and everything worked better" - it gets along well with standard strings +and does not change the behavior of existing code working with them. I tried to make many methods in it compatible +with `std::string` and `std::string_view`, but I didn't bother with this much. Rewriting your code to work with `simstr` +will require some effort, but I assure you that it will pay off. And thanks to compatibility with standard strings, this work can be done +in stages, in small pieces. Creating new code for working with strings with its use is easy and enjoyable :) + + +The main difference between `simstr` and `std::string` is that not a single universal class is used for working with strings, but several +types of objects, each of which is good for its own purposes, and at the same time interact well with each other. +If you actively used `std::string_view` and understood its advantages and disadvantages compared to `std::string`, +then the `simstr` approach will also be clear to you. ## Main features of the library -- Strings `char`, `char16_t`, `char32_t`, `wchar_t`. -- Transparent conversion of strings from one character type to another, with automatic conversion between UTF-8, UTF-16, UTF-32, - using [simdutf](https://github.com/simdutf/simdutf). -- Extensible "String Expression" system. Allows you to efficiently implement the conversion and addition (concatenation) of strings, literals, - numbers and possibly other objects. -- String functions: +When using only `#include "simstr\strexpr.h"`: +- Support for working with strings `char`, `char8_t`, `char16_t`, `char32_t`, `wchar_t`. +- Powerful and extensible *"String Expressions"* system. + Allows you to efficiently implement the conversion and addition (concatenation) of strings, string literals, numbers (and possibly other objects), + achieving significant acceleration of string operations. + Compatible with both `simstr` string objects and standard strings (`std::basic_string`, + `std::basic_string_view`), which allows you to use fast concatenation even where it is not yet possible to abandon standard strings. + Also allows you to mix strings of compatible character types in operations. +- Constant string functions (do not change the original string): - Getting substrings. + - Comparing strings, comparing strings ignoring the case of ASCII characters. - Searching for substrings and characters - from the beginning or from the end of the string. - - Various string trimming - right, left, everywhere, by whitespace characters, by specified characters. - - Replacing substrings. - - Replacing a set of characters with a set of corresponding substrings. - - Merging (join) containers of strings into a single string, with specifying separators and options - "skip empty", "separator after last". - - Splitting strings into parts by a specified separator. Splitting is possible directly into a container with strings, or by calling a functor for + - Various trimming of strings - right, left, everywhere, by whitespace characters, by specified characters. + - Replacing substrings (creating a copy of the string with the replacement). + - Replacing a set of characters with a set of corresponding substrings (creating a copy of the string with the replacement). + - Merging (join) containers of strings into a single string, with specifying delimiters and options - "skip empty", "delimiter after last". + - Splitting strings into parts by a specified delimiter. Splitting is possible immediately into a container with strings, or by calling a functor for each substring, or by iterating using the `Splitter` iterator. -- Integration with `format` and `sprintf` formatting functions (with automatic buffer increase). - Formatting is possible for `char`, `wchar_t` strings and strings compatible with `wchar_t` in size. - That is, under Windows it is `char16_t`, under Linux - `char32_t`. Writing my own formatting library was not part of my plans. -- Parsing integers with the possibility of "fine" tuning during compilation - you can set options for checking overflow, - skipping whitespace characters, a specific radix or auto-selection by prefixes `0x`, `0`, `0b`, `0o`, +- Parsing integers with the possibility of "fine" tuning at compile time - you can set options for checking overflow, + skipping whitespace characters, a specific base or auto-selection by prefixes `0x`, `0`, `0b`, `0o`, admissibility of the `+` sign. Parsing is implemented for all types of strings and characters. -- Parsing doubles for all types of characters. -- Minimal Unicode support is included when converting `upper`, `lower` and case-insensitive string comparison. - It only works for characters in the first plane of Unicode (up to 0xFFFF), and when changing case, it does not take into account cases where one code point +- Parsing double for `char` and `wchar_t`, as well as character types compatible with them in size. + +When using the full version of the library: +- Everything that is listed above, plus +- Additional efficient string objects - `sstring` (shared string), `lstring` (local string). +- `lstring` - supports many mutable operations with strings - various replacements, insertions, deletions, etc. + Allows you to set the size for the internal character buffer, which can turn *Small String Optimization* into *Big String Optimization* :). +- Transparent conversion of strings from one character type to another, with automatic conversion between UTF-8, UTF-16, UTF-32, + using [simdutf](https://github.com/simdutf/simdutf). Strings of "compatible" types are converted by simple copying: + `char <-> char8_t`, `wchar_t <-> char32_t` in Linux, `wchar_t <-> char16_t` in Windows. +- Integration with `format` and `sprintf` formatting functions (with automatic buffer increase). + Formatting is possible for `char`, `wchar_t` strings and strings compatible with them in size. + 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 + characters was not part of my plans). +- Contains minimal Unicode support when converting `upper`, `lower` and case-insensitive string comparison. + 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 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. - Implemented `hash map` for string type keys, based on `std::unordered_map`, with the possibility of more efficient storage and - comparison of keys compared to `std::string` keys. Case-insensitive key comparison is supported (Ascii or + comparison of keys compared to `std::string` keys. The possibility of case-insensitive comparison of keys is supported (Ascii or minimal Unicode (see previous paragraph)). +## String expressions +These are special objects that efficiently implement string concatenation using `operator+`. +The main principle, due to which efficient work is achieved - no matter how many operands are included in the entire expression, +no temporary (intermediate) strings are created, the total length of the entire result is calculated only once, +memory is allocated for the character buffer of the result only once, after which the characters are copied immediately to the buffer of the result +to its place. No memory reallocations, no moving characters in various intermediate buffers - everything is +as efficient as possible. Thanks to the capabilities of C++ templates and operator overloading, the expression is written as close as possible +to the usual string addition syntax. +In addition, there are special overloads for adding string objects and string literals, strings and numbers, +for copying with replacement, for merging containers of strings and much more. +Thanks to the extensibility of this system, it is possible to create new options for building strings, development is constantly ongoing. + +All string objects from `simstr` are themselves string expressions, that is, they can be used in concatenation operations +of string expressions directly. Standard strings (`std::basic_string`, `std::basic_string_view`) can also serve as operands +in addition operations with string expressions. Or they can be easily converted into a string expression by placing a +unary `+` in front of them. + +## Usage examples +### Adding strings with numbers +```cpp +std::string s1 = "start "; +int i; +.... +// Was + std::string str = s1 + std::to_string(i) + " end"; +// Became + std::string str = +s1 + i + " end"; +``` +`+s1` - converts `std::string` into an object - a string expression, for which there is an efficient concatenation with numbers and string literals. + +According to benchmarks, [acceleration is 1.6 - 2 times](https://orefkov.github.io/simstr/results.html#bs70109915512075798510). + +### Adding strings with numbers in hex format +```cpp +.... +// Was + std::string str = s1 + std::format("0x{:x}", i) + " end"; +// Became + std::string str = +s1 + e_hex(i) + " end"; +``` +Acceleration in [**9 - 14 times!!!**](https://orefkov.github.io/simstr/results.html#bs146911715078927772520) + +### Adding multiple literals and searching in `std::string_view` +```cpp +// It was like this +size_t find_pos(std::string_view src, std::string_view name) { + // before C++26 we can not concatenate string and string_view... + return src.find("\n- "s + std::string{name} + " -\n"); +} +// When using only "strexpr.h" it became like this +size_t find_pos(ssa src, ssa name) { + return src.find(std::string{"\n- " + name + " -\n"}); +} + +// And when using the full library, you can do this +size_t find_pos(ssa src, ssa name) { + // In this version, if the result of the concatenation fits into 207 characters, it is produced in a buffer on the stack, + // without allocation and deallocation of memory, acceleration is several times. And only if the result is longer than 207 characters - + // there will be only one allocation, and the concatenation will be immediately into the allocated buffer, without copying characters. + return src.find(lstringa<200>{"\n- " + name + " -\n"}); +} +``` +`ssa` - alias for `simple_str` - analogue of `std::string_view`, allows you to accept any string object as a function parameter with minimal costs, +which does not need to be modified or passed to the C-API: `std::string`, `std::string_view`, `"string literal"`, +`simple_str_nt`, `sstring`, `lstring`. Also, since it is also a "string expression", it allows you to easily +build concatenations with its participation. + +According to measurements, [acceleration is 1.5 - 9 times](https://orefkov.github.io/simstr/results.html#bs68116594352702954700). + +### Addition with conditions +```cpp +// Was +std::string buildTypeName(std::string_view type_name, size_t prec, size_t scale) { + std::string res{type_name}; + if (prec) { + res += "(" + std::to_string(prec); + if (scale) { + res += "," + std::to_string(scale); + } + res += ")"; + } + return res; +} +// Became when using only strexpr.h and wanting to use only standard strings +std::string buildTypeName(std::string_view type_name, size_t prec, size_t scale) { + if (prec) { + // + turns type_name from string_view into a string expression + return +type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +} +// Became when using only strexpr.h and simple_str string +std::string buildTypeName(ssa type_name, size_t prec, size_t scale) { + if (prec) { + // ssa is already a string expression, + before it is not needed + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +} +// Became when using the full library +stringa buildTypeName(ssa type_name, size_t prec, size_t scale) { + if (prec) { + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +} +``` +When `prec != 0`, [acceleration is 1.5 - 2.2 times](https://orefkov.github.io/simstr/results.html#bs145290966789248325200). + +### Addition with replacements +```cpp +// Was +// There is no standard analogue of the replace function from other programming languages, let's write our own "head-on". +std::string str_replace(std::string_view from, std::string_view pattern, std::string_view repl) { + std::string result; + for (size_t offset = 0;;) { + size_t pos = from.find(pattern, offset); + if (pos == std::string::npos) { + result += from.substr(offset); + break; + } + result += from.substr(offset, pos - offset); + result += repl; + offset = pos + pattern.length(); + } + return result; +} + +std::string make_str_str(std::string_view from, std::string_view pattern, std::string_view repl) { + return "<" + str_replace(from, pattern, repl) + ">"; +} +// Became - copying with replacements +std::string make_str_exp(std::string_view from, std::string_view pattern, std::string_view repl) { + return "<" + e_repl(from, pattern, repl) + ">"; +} +``` +[Acceleration from 1.5 times and higher](https://orefkov.github.io/simstr/results.html#bs54035654251116789780) - depending on the content of the strings. + +### Splitting strings into parts, parsing numbers +```cpp +// Was - split the string by delimiter and calculate the sum of numbers +int split_and_calc_total_str(std::string_view numbers, std::string_view delimiter) { + int total = 0; + for (size_t start = 0; start < numbers.length(); ) { + int delim = numbers.find(delimiter, start); + if (delim == std::string::npos) { + delim = numbers.size(); + } + std::string part{numbers.substr(start, delim - start)}; + total += std::strtol(part.c_str(), nullptr, 0); + start = delim + delimiter.length(); + } + return total; +} +// Became +int split_and_calc_total_sim(ssa numbers, ssa delimiter) { + int total = 0; + for (auto splitter = numbers.splitter(delimiter); !splitter.is_done();) { + total += splitter.next().as_int(); + } + return total; +} +``` +[Acceleration in 2-3 times](https://orefkov.github.io/simstr/results.html#bs7106975351756760120). + +In addition to the individual examples given here, you can look at the sources: +- [tests of the entire library](https://github.com/orefkov/simstr/blob/main/tests/test_str.cpp) +- [tests of only the strexpr part](https://github.com/orefkov/simstr/blob/main/tests/test_expr_only.cpp) +- [benchmarks](https://github.com/orefkov/simstr/blob/main/bench/bench_str.cpp) +- [utility for preparing html](https://github.com/orefkov/simstr/blob/main/bench/process_result.cpp) from benchmark results. + ## Main objects of the library -- simple_str<K> - the simplest string (or piece of string), immutable, not owning, analogue of `std::string_view`. -- simple_str_nt<K> - the same, only declares that it ends with 0. For working with third-party C-API. -- sstring<K> - shared string, immutable, owning, with shared character buffer, SSO support. -- lstring<K, N> - local string, mutable, owning, with a specified size of the SSO buffer. +Available with any use: +- `simple_str` - the simplest string (or piece of string), immutable, not owning, analogue of `std::string_view`. +- `simple_str_nt` - the same, only declares that it ends with 0. For working with third-party C-API. + +Available when using the entire library: +- `sstring` - shared string, immutable, owning, with shared character buffer, SSO support. +- `lstring` - local string, mutable, owning, with a specified size of the SSO buffer. + +When connecting only `strexpr.h` - the types `simple_str` and `simple_str_nt` do not contain methods for working with UTF and Unicode. ## Articles - [Overview and introduction](docs/overview.md) -- [Overview article on Habr](https://habr.com/ru/articles/935590) -- [Description of the "Expression Templates" technique used](https://habr.com/ru/articles/936468/) +- [Overview article on Habr](https://habr.com/ru/articles/935590) (On Russian) +- [Description of the "Expression Templates" technique used](https://habr.com/ru/articles/936468/) (On Russian) ## Usage -`simstr` consists of three header files and two source files. You can connect as a CMake project via `add_subdirectory` (the `simstr` library), +The library can be used partially, just by taking the file `"include\simstr\strexpr.h"` and including it in your sources +```cpp +#include "include\simstr\strexpr.h" +``` +This will only connect string expressions and simplified implementations of `simple_str` and `simple_str_nt`, without UTF and Unicode functions. + +The full version of the `simstr` library consists of three header files and two source files. +You can connect as a CMake project via `add_subdirectory` (the `simstr` library), you can simply include the files in your project. Building also requires [simdutf](https://github.com/simdutf/simdutf) (when using CMake it is downloaded automatically). -The library is included in [vcpkg](https://vcpkg.io), use as `orefkov-simstr`. +The library is included in [vcpkg](https://vcpkg.io), connected as `orefkov-simstr`. -`simstr` requires a compiler of standard no lower than C++20 to work - concepts and std::format are used. +`simstr` requires a compiler of at least the C++20 standard - concepts and std::format are used. The work was tested under Windows on MSVC-19 and Clang-19, under Linux - on GCC-13 and Clang-21. The work in WASM was also tested, built in Emscripten 4.0.6, Clang-21. + ## Convenient debugging -Along with the library, two files are supplied that allow viewing simstr string objects in debuggers +Together with the library, two files are supplied that make viewing simstr string objects in debuggers more convenient.\ -It is described in more detail in [here](for_debug/readme.md). +More details are described [here](for_debug/readme_ru.md). ## Benchmarks Benchmarks are performed using the [Google benchmark](https://github.com/google/benchmark) framework. -I tried to make measurements for the most typical operations that occur in normal work. I took measurements on my equipment, under +I tried to take measurements for the most typical operations that occur in normal work. I took measurements on my equipment, under Windows and Linux (in WSL), using MSVC, Clang, GCC compilers. Third-party results are welcome. I also took measurements in WASM, built in Emscripten. I draw your attention to the fact that a 32-bit build is assembled under WASM in Emscripten, which means that the sizes of SSO buffers in objects are smaller. -- [Benchmark source code](bench/bench_str.cpp) -- [Benchmark results](https://snegopat.ru/simstr/results.html) +- [Source code of benchmarks](bench/bench_str.cpp) +- [Benchmark results](https://orefkov.github.io/simstr/results.html) -## Usage examples -While no separate usage examples have been prepared, you can look at the texts of [tests](https://github.com/orefkov/simstr/blob/main/tests/test_str.cpp), -[benchmarks](https://github.com/orefkov/simstr/blob/main/bench/bench_str.cpp), and -[html preparation utilities](https://github.com/orefkov/simstr/blob/main/bench/process_result.cpp) from the benchmark results. - -Also simstr is used in my projects: +Also, simstr is used in my projects: - [simjson](https://github.com/orefkov/simjson) - a library for simple work with JSON using simstr strings. -- [simrex](https://github.com/orefkov/simrex) - a wrapper for working with [Oniguruma](https://github.com/kkos/oniguruma) regular expressions using simstr strings. +- [simrex](https://github.com/orefkov/simrex) - wrapper for working with regular expressions [Oniguruma](https://github.com/kkos/oniguruma) using simstr strings. - [v8sqlite](https://github.com/orefkov/v8sqlite) - external component for 1C-Enterprise V8 for working with sqlite. + ## Generated documentation -[Located here](https://snegopat.ru/simstr/docs/) +[Located here](https://orefkov.github.io/simstr/docs_en/) diff --git a/readme_ru.md b/readme_ru.md index 61f8515..88939e1 100644 --- a/readme_ru.md +++ b/readme_ru.md @@ -1,7 +1,9 @@ # simstr - библиотека строковых объектов и функций +

    Ускорь работу со строками в 2-10 раз!

    + [![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) -Версия 1.3.1. +Версия 1.4.0. On English | По-английски @@ -12,42 +14,75 @@ Не секрет, что работа со строками в С++ зачастую доставляет боль. Класс `std::string` часто неудобен либо неэффективен. Многих функций, обычно необходимых при работе со строками, просто нет, и их каждому приходится писать самому. +Даже элементарно конкатенировать `std::string` и `std::string_view` стало возможно только с C++26. +Именно поэтому я начал примерно в 2012 году создавать для себя эту библиотеку, и теперь готов поделится ею со всеми C++ разработчиками. Эта библиотека не делалась как универсальный комбайн, который "может всё", я реализовывал то, что мне приходилось использовать в работе, стараясь сделать это наиболее эффективным способом, и скромно надеюсь, что кое-что у меня получилось и пригодится другим людям, либо напрямую, либо как источник идей. -Библиотека не претендует на роль "поменял хедер и всё заработало лучше". Многие методы я старался делать совместимыми -с `std::string` и `std::string_view`, но особо с этим не заморачивался. Переписывание старого кода на работу с simstr -потребует некоторых усилий, но уверяю, что они окупятся. А новый код писать с её применением легко и доставляет удовольствие :) +Библиотека содержит две части: +- Реализация [*"Строковых выражений"*](https://orefkov.github.io/simstr/docs_ru/overview.html#autotoc_md27) и алгоритмов работы + с константными строками.\ + Для использования этой части достаточно просто взять файл `"include/simstr/strexpr.h"` и написать в своём коде + ```cpp + #include "путь/к файлу/strexpr.h" + ``` + Это позволит вам для стандартных строковых типов (`std::basic_string`, `std::basic_string_view`) использовать + мощные и быстрые *"строковые выражения"* для конкатенации и построения строк, а также упрощенные варианты классов `simple_str` и + `simple_str_nt`, которые реализуют все те строковые алгоритмы библиотеки, которые не требуют хранения или модификации строк. + Так как это header-only часть, она не включает в себя работу с UTF-кодировками и упрощённый Unicode. +- Полная версия, требующая подключения всей библиотеки (`"include/simstr/sstring.h"`), добавляет свои строковые типы с + возможностями хранения и модификации строк, работает с UTF-кодировками и упрощённым Unicode. -Основное отличие simstr от std::string - для работы со строками используется не единый универсальный класс, а несколько +Библиотека не претендует на роль "поменял хедер и всё заработало лучше" - она прекрасно уживается вместе со стандартными строками +и не меняет поведение уже существующего кода, работающего с ними. Многие методы в ней я старался делать совместимыми +с `std::string` и `std::string_view`, но особо с этим не заморачивался. Переписывание вашего кода на работу с `simstr` +потребует некоторых усилий, но уверяю, что они окупятся. А благодаря совместимости со стандартными строками эту работу можно делать +поэтапно, небольшими кусками. Новый же код работы со строками создавать с её применением легко и доставляет удовольствие :) + + +Основное отличие `simstr` от `std::string` - для работы со строками используется не единый универсальный класс, а несколько видов объектов, каждый из которых хорош для своих целей, и при этом хорошо взаимодействующих друг с другом. -Если вы активно использовали std::string_view и понимали, в чём его преимущество и недостатки по сравнению с std::string, -то подход simstr вам также будет понятен. +Если вы активно использовали `std::string_view` и понимали, в чём его преимущества и недостатки по сравнению с `std::string`, +то подход `simstr` вам также будет понятен. ## Основные возможности библиотеки -- Строки `char`, `char16_t`, `char32_t`, `wchar_t`. -- Прозрачное преобразование строк из одного типа символов в другой, с автоматической конвертацией между UTF-8, UTF-16, UTF-32, - используя [simdutf](https://github.com/simdutf/simdutf). -- Расширяемая система "Строковых выражений". Позволяет эффективно реализовать преобразование и сложение (конкатенацию) строк, литералов, - чисел и возможно других объектов. -- Строковые функции: +При использовании только `#include "simstr\strexpr.h"`: +- Поддержка работы со строками `char`, `char8_t`, `char16_t`, `char32_t`, `wchar_t`. +- Мощная и расширяемая система *"Строковых выражений"*. + Позволяет эффективно реализовать преобразование и сложение (конкатенацию) строк, строковых литералов, чисел (и возможно других объектов), + добиваясь значительного ускорения строковых операций. + Совместима как со строковыми объектами `simstr`, так и со стандартными строками (`std::basic_string`, + `std::basic_string_view`), что позволяет применять быструю конкатенацию и там, где пока не получается отказаться от стандартных строк. + Тоже позволяет смешивать в операциях строки совместимых типов символов. +- Константные строковые функции (не меняют исходную строку): - Получение подстрок. + - Сравнение строк, сравнение строк без учёта регистра ASCII-символов. - Поиск подстрок и символов - с начала или с конца строки. - Различный тримминг строк - справа, слева, везде, по пробельным символам, по заданным символам. - - Замена подстрок. - - Замена набора символов на набор соответствующих подстрок. + - Замена подстрок (созданием копии строки с заменой). + - Замена набора символов на набор соответствующих подстрок (созданием копии строки с заменой). - Слияние (join) контейнеров строк в единую строку, с заданием разделителей и опций - "пропускать пустые", "разделитель после последней". - Разбиение (split) строк на части по заданному разделителю. Разбиение возможно сразу в контейнер со строками, либо вызовом функтора для каждой подстроки, либо путем итерации с помощью итератора `Splitter`. -- Интеграция с функциями форматирования `format` и `sprintf` (с автоматическим увеличением буфера). - Форматирование возможно для строк `char`, `wchar_t` и строк, совместимых с `wchar_t` по размеру. - То есть под Windows это `char16_t`, под Linux - `char32_t`. Писать свою библиотеку форматирования не входило в мои замыслы. - Парсинг целых чисел с возможностью "тонкой" настройки при компиляции - можно задавать опции проверки переполнения, пропуск пробельных символов, конкретное основание счисления либо автовыбор по префиксам `0x`, `0`, `0b`, `0o`, допустимость знака `+`. Парсинг реализован для всех видов строк и символов. -- Парсинг double для всех типов символов. +- Парсинг double для `char` и `wchar_t`, а также совместимых с ними по размеру типов символов. + +При использовании полной версии библиотеки: +- Всё то же, что и перечислено выше, плюс +- Дополнительные эффективные строковые объекты - `sstring` (shared string), `lstring` (local string). +- `lstring` - поддерживает множество мутабельных операций со строками - различные замены, вставки, удаления и т.п. + Позволяет задавать размер для внутреннего буфера символов, что может превращать *Small String Optimization* в *Big String Optimization* :). +- Прозрачное преобразование строк из одного типа символов в другой, с автоматической конвертацией между UTF-8, UTF-16, UTF-32, + используя [simdutf](https://github.com/simdutf/simdutf). Строки "совместимых" типов преобразуются простым копированием: + `char <-> char8_t`, `wchar_t <-> char32_t` в Linux, `wchar_t <-> char16_t` в Windows. +- Интеграция с функциями форматирования `format` и `sprintf` (с автоматическим увеличением буфера). + Форматирование возможно для строк `char`, `wchar_t` и строк, совместимых с ними по размеру. + То есть под Windows это `char8_t`, `char16_t`, под Linux - `char8_t`, `char32_t` (писать свою библиотеку форматирования для всех видов + символов не входило в мои замыслы). - Содержится минимальная поддержка Unicode при преобразовании `upper`, `lower` и регистро-независимом сравнении строк. Работает только для символов первой плоскости Unicode (до 0xFFFF), а при смене регистра не учитываются случаи, когда один code point может преобразовываться в несколько, то есть преобразование регистра символов соответствует `std::towupper`, `std::towlower` для unicode локали, только быстрее и может работать с любым видом символов. @@ -55,11 +90,187 @@ сравнения ключей по сравнению с ключами `std::string`. Поддерживается возможность регистро-независимого сравнения ключей (Ascii или минимальный Unicode (см. предыдущий пункт)). +## Строковые выражения +Это специальные объекты, которые эффективно реализуют конкатенацию строк, с помощью `operator+`. +Главный принцип, за счёт которого достигается эффективная работа - сколько бы операндов не входило во всё выражение, +никаких временных (промежуточных) строк не создаётся, общая длина всего результата подсчитывается только один раз, +один раз выделяется память под буфер символов результата, после чего символы копируются сразу в буфер результата +на своё место. Никаких перевыделений памяти, никакого передвигания символов в различных промежуточных буферах - всё +максимально эффективно. Благодаря возможностям шаблонов C++ и перегрузке операторов, выражение пишется максимально +приближённо к обычному синтаксису сложения строк. +Кроме того, есть специальные перегрузки для сложения строковых объектов и строковых литералов, строк и чисел, +для копирования с заменой, для слияния контейнеров строк и многое другое. +Благодаря расширяемости этой системы - возможно создание новых вариантов построения строк, развитие постоянно продолжается. + +Все строковые объекты из `simstr` - сами являются строковыми выражениями, то есть их можно использовать в операциях конкатенации +строковых выражений напрямую. Стандартные строки (`std::basic_string`, `std::basic_string_view`) - тоже могут служить операндами +в операциях сложения со строковыми выражениями. Либо их можно легко преобразовать в строковое выражение, поставив перед ними +унарный `+`. + +## Примеры использования +### Сложение строк с числами +```cpp +std::string s1 = "start "; +int i; +.... +// Было + std::string str = s1 + std::to_string(i) + " end"; +// Стало + std::string str = +s1 + i + " end"; +``` +`+s1` - преобразует `std::string` в объект - строковое выражение, для которого есть эффективная конкатенация с числами и строковыми литералами. + +По бенчмаркам [ускорение 1.6 - 2 раза](https://orefkov.github.io/simstr/results.html#bs70109915512075798510). + +### Сложение строк с числами в hex-формате +```cpp +.... +// Было + std::string str = s1 + std::format("0x{:x}", i) + " end"; +// Стало + std::string str = +s1 + e_hex(i) + " end"; +``` +Ускорение в [**9 - 14 раз!!!**](https://orefkov.github.io/simstr/results.html#bs146911715078927772520) + +### Сложение нескольких литералов и поиск в `std::string_view` +```cpp +// Было так +size_t find_pos(std::string_view src, std::string_view name) { + // before C++26 we can not concatenate string and string_view... + return src.find("\n- "s + std::string{name} + " -\n"); +} +// При использовании только "strexpr.h" стало так +size_t find_pos(ssa src, ssa name) { + return src.find(std::string{"\n- " + name + " -\n"}); +} + +// А при использовании полной библиотеки можно сделать так +size_t find_pos(ssa src, ssa name) { + // В этом варианте если результат конкатенации вмещается в 207 символов - она производится в буфере на стеке, + // без алокации и освобождения памяти, ускорение в несколько раз. И только если результат длиннее 207 символов - + // будет всего одна аллокация, и конкатенация будет сразу в алоцированный буфер, без перекопирования символов. + return src.find(lstringa<200>{"\n- " + name + " -\n"}); +} +``` +`ssa` - псевдоним для `simple_str` - аналог `std::string_view`, позволяет с минимальными расходами принимать параметром функции +любой строковый объект, который не нужно модифицировать или передавать в C-API: `std::string`, `std::string_view`, `"строковый литерал"`, +`simple_str_nt`, `sstring`, `lstring`. Также так как он при этом является ещё и "строковым выражением", то позволяет легко +строить конкатенации с его участием. + +По замерам [ускорение 1.5 - 9 раз](https://orefkov.github.io/simstr/results.html#bs68116594352702954700). + +### Сложение с условиями +```cpp +// Было +std::string buildTypeName(std::string_view type_name, size_t prec, size_t scale) { + std::string res{type_name}; + if (prec) { + res += "(" + std::to_string(prec); + if (scale) { + res += "," + std::to_string(scale); + } + res += ")"; + } + return res; +} +// Стало при использовании только strexpr.h и желании использовать только стандартные строки +std::string buildTypeName(std::string_view type_name, size_t prec, size_t scale) { + if (prec) { + // + превращает type_name из string_view в строковое выражение + return +type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +} +// Стало при использовании только strexpr.h и simple_str строки +std::string buildTypeName(ssa type_name, size_t prec, size_t scale) { + if (prec) { + // ssa уже является строковым выражением, + перед ним не нужен + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +} +// Стало при использовании полной библиотеки +stringa buildTypeName(ssa type_name, size_t prec, size_t scale) { + if (prec) { + return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; + } + return type_name; +} +``` +При `prec != 0`, [ускорение 1.5 - 2.2 раза](https://orefkov.github.io/simstr/results.html#bs145290966789248325200). + +### Сложение с заменами +```cpp +// Было +// Стандартной аналога функции replace из других ЯП нет, напишем свою "в лоб". +std::string str_replace(std::string_view from, std::string_view pattern, std::string_view repl) { + std::string result; + for (size_t offset = 0;;) { + size_t pos = from.find(pattern, offset); + if (pos == std::string::npos) { + result += from.substr(offset); + break; + } + result += from.substr(offset, pos - offset); + result += repl; + offset = pos + pattern.length(); + } + return result; +} + +std::string make_str_str(std::string_view from, std::string_view pattern, std::string_view repl) { + return "<" + str_replace(from, pattern, repl) + ">"; +} +// Стало - копирование с заменами +std::string make_str_exp(std::string_view from, std::string_view pattern, std::string_view repl) { + return "<" + e_repl(from, pattern, repl) + ">"; +} +``` +[Ускорение от 1.5 раз и выше](https://orefkov.github.io/simstr/results.html#bs54035654251116789780) - в зависимости от содержимого строк. + +### Разбиение строк на части, парсинг чисел +```cpp +// Было - разбить строку по разделителю и подсчитать сумму чисел +int split_and_calc_total_str(std::string_view numbers, std::string_view delimiter) { + int total = 0; + for (size_t start = 0; start < numbers.length(); ) { + int delim = numbers.find(delimiter, start); + if (delim == std::string::npos) { + delim = numbers.size(); + } + std::string part{numbers.substr(start, delim - start)}; + total += std::strtol(part.c_str(), nullptr, 0); + start = delim + delimiter.length(); + } + return total; +} +// Стало +int split_and_calc_total_sim(ssa numbers, ssa delimiter) { + int total = 0; + for (auto splitter = numbers.splitter(delimiter); !splitter.is_done();) { + total += splitter.next().as_int(); + } + return total; +} +``` +[Ускорение в 2-3 раза](https://orefkov.github.io/simstr/results.html#bs7106975351756760120). + +Помимо приведённых здесь отдельных примеров, можно посмотреть исходники: +- [тестов всей библиотеки](https://github.com/orefkov/simstr/blob/main/tests/test_str.cpp) +- [тестов только strexpr части](https://github.com/orefkov/simstr/blob/main/tests/test_expr_only.cpp) +- [бенчмарков](https://github.com/orefkov/simstr/blob/main/bench/bench_str.cpp) +- [утилиты подготовки html](https://github.com/orefkov/simstr/blob/main/bench/process_result.cpp) из результатов бенчмарков. + ## Основные объекты библиотеки -- simple_str<K> - самая простая строка (или кусок строки), иммутабельная, не владеющая, аналог `std::string_view`. -- simple_str_nt<K> - то же самое, только заявляет, что заканчивается 0. Для работы со сторонними C-API. -- sstring<K> - shared string, иммутабельная, владеющая, с разделяемым буфером символов, поддержка SSO. -- lstring<K, N> - local string, мутабельная, владеющая, с задаваемым размером SSO буфера. +Доступны при любом использовании: +- `simple_str` - самая простая строка (или кусок строки), иммутабельная, не владеющая, аналог `std::string_view`. +- `simple_str_nt` - то же самое, только заявляет, что заканчивается 0. Для работы со сторонними C-API. + +Доступны при использовании всей библиотеки: +- `sstring` - shared string, иммутабельная, владеющая, с разделяемым буфером символов, поддержка SSO. +- `lstring` - local string, мутабельная, владеющая, с задаваемым размером SSO буфера. + +При подключении только `strexpr.h` - типы `simple_str` и `simple_str_nt` не содержат методов для работы с UTF и Unicode. ## Статьи - [Обзор и введение](docs/overview_ru.md) @@ -67,7 +278,14 @@ - [Описание применяемой техники "Expression Templates"](https://habr.com/ru/articles/936468/) ## Использование -`simstr` состоит из трёх заголовочных файлов и двух исходников. Можно подключать как CMake проект через `add_subdirectory` (библиотека `simstr`), +Библиотеку можно использовать частично, просто взяв файл `"include\simstr\strexpr.h"` и включив в свои исходники +```cpp +#include "include\simstr\strexpr.h" +``` +Это подключит только строковые выражения и упрощённые реализации `simple_str` и `simple_str_nt`, без функций работы с UTF и Unicode. + +Полная же версия библиотеки `simstr` состоит из трёх заголовочных файлов и двух исходников. +Можно подключать как CMake проект через `add_subdirectory` (библиотека `simstr`), можно просто включить файлы в свой проект. Для сборки также требуется [simdutf](https://github.com/simdutf/simdutf) (при использовании CMake скачивается автоматически). @@ -83,7 +301,6 @@ более удобным.\ Более подробно описано [здесь](for_debug/readme_ru.md). - ## Бенчмарки Бенчмарки производятся с использованием фреймворка [Google benchmark](https://github.com/google/benchmark). Постарался сделать замеры для наиболее типичных операций, встречающихся в обычной работе. Я проводил замеры на своём оборудовании, под @@ -92,12 +309,7 @@ Windows и Linux (в WSL), с использованием компилятор размеры буферов SSO в объектах меньше. - [Исходный код бенчмарков](bench/bench_str.cpp) -- [Результаты бенчмарков](https://snegopat.ru/simstr/results.html) - -## Примеры использования -Пока отдельных примеров использования не подготовлено, можно посмотреть тексты [тестов](https://github.com/orefkov/simstr/blob/main/tests/test_str.cpp), -[бенчмарков](https://github.com/orefkov/simstr/blob/main/bench/bench_str.cpp), и -[утилиты подготовки html](https://github.com/orefkov/simstr/blob/main/bench/process_result.cpp) из результатов бенчмарков. +- [Результаты бенчмарков](https://orefkov.github.io/simstr/results.html) Также simstr используется в моих проектах: - [simjson](https://github.com/orefkov/simjson) - библиотека для простой работы с JSON с использованием строк simstr. @@ -106,4 +318,4 @@ Windows и Linux (в WSL), с использованием компилятор ## Сгенерированная документация -[Находится здесь](https://snegopat.ru/simstr/docs_ru/) +[Находится здесь](https://orefkov.github.io/simstr/docs_ru/) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 42e6e50..ab70cae 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,17 +2,25 @@ # project specific logic here. # -add_executable(testStr test_str.cpp) +add_executable(test_str test_str.cpp) +add_executable(test_expr_only test_expr_only.cpp) -target_link_libraries(testStr simstr::simstr GTest::gtest_main) +target_link_libraries(test_str simstr::simstr GTest::gtest_main) +target_link_libraries(test_expr_only GTest::gtest_main) +target_compile_features(test_str PUBLIC cxx_std_23) +target_compile_features(test_expr_only PUBLIC cxx_std_23) -add_test(NAME testStr COMMAND testStr) +add_test(NAME test_str COMMAND test_str) +add_test(NAME test_expr_only COMMAND test_expr_only) if (EMSCRIPTEN) - set_target_properties (testStr PROPERTIES SUFFIX .html) - target_compile_options(testStr PUBLIC -Wno-warn-absolute-paths -Wno-unknown-warning-option -msimd128 -msse4.2 -msse3) + set_target_properties (test_str PROPERTIES SUFFIX .html) + target_compile_options(test_str PUBLIC -Wno-warn-absolute-paths -Wno-unknown-warning-option -msimd128 -msse4.2 -msse3) + set_target_properties (test_expr_only PROPERTIES SUFFIX .html) + target_compile_options(test_expr_only PUBLIC -Wno-warn-absolute-paths -Wno-unknown-warning-option -msimd128 -msse4.2 -msse3) if(SIMSTR_EMSCRIPTEN_MT) - target_compile_options(testStr PUBLIC -pthread) + target_compile_options(test_str PUBLIC -pthread) + target_compile_options(test_expr_only PUBLIC -pthread) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread -sPTHREAD_POOL_SIZE=navigator.hardwareConcurrency-1") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sENVIRONMENT=web,worker") endif() diff --git a/tests/test_expr_only.cpp b/tests/test_expr_only.cpp new file mode 100644 index 0000000..a22207c --- /dev/null +++ b/tests/test_expr_only.cpp @@ -0,0 +1,239 @@ +#include "../include/simstr/strexpr.h" +#include +#include + +using namespace std::literals; + +namespace simstr::tests { + +TEST(StrExpr, Empty) { + std::string testa = eea; + EXPECT_EQ(testa, ""); + + std::u8string testb = eeb; + EXPECT_EQ(testb, u8""); + + std::u16string testu = eeu; + EXPECT_EQ(testu, u""); + + std::u32string testuu = eeuu; + EXPECT_EQ(testuu, U""); + + std::wstring testw = eew; + EXPECT_EQ(testw, L""); +} + +TEST(StrExpr, OpPlusChar) { + std::string testa = "test"_ss + 'a'; + EXPECT_EQ(testa, "testa"); + testa += +testa + u8'b'; + EXPECT_EQ(testa, "testatestab"); + + std::u8string testb = u8"test"_ss + u8'a'; + EXPECT_EQ(testb, u8"testa"); +#ifdef _WIN32 + std::wstring testw = L"test"_ss + u'a' + L'b'; + EXPECT_EQ(testw, L"testab"); + + std::u16string testu = +u"test"sv + L'a'; + EXPECT_EQ(testu, u"testa"); +#else + std::wstring testw = L"test"_ss + U'a' + U'b'; + EXPECT_EQ(testw, L"testab"); + + std::u32string testu = U"test"_ss + L'a'; + EXPECT_EQ(testu, U"testa"); +#endif +} + +TEST(StrExpr, Spaces) { + std::string testa = "abc" + e_spca<10>() + "cde"; + EXPECT_EQ(testa, "abc cde"); + + std::u16string testu = u"abc" + e_c(10, u'_') + u"cde"; + EXPECT_EQ(testu, u"abc__________cde"); +} + +TEST(StrExpr, Repeat) { + std::string testa = "abc"; + testa = e_repeat(+testa + " " + 10 + "s.", 3); + EXPECT_EQ(testa, "abc 10s.abc 10s.abc 10s."); + std::wstring testw = L"abc"; + testw += L" " + e_repeat(+testw + L" " + 10 + L"s.", 3); + EXPECT_EQ(testw, L"abc abc 10s.abc 10s.abc 10s."); +} + +TEST(StrExpr, OpPlusDifferentTypes) { + std::string testa = "test"_ss + u8"test"; + EXPECT_EQ(testa, "testtest"); + + std::u8string testb = "test"_ss + u8"test"; + EXPECT_EQ(testb, u8"testtest"); +#ifdef _WIN32 + std::wstring testw = L"test"_ss + u"test"; + EXPECT_EQ(testw, L"testtest"); + + std::u16string testu = +u"test"sv + L"test"; + EXPECT_EQ(testu, u"testtest"); +#else + std::wstring testw = L"test"_ss + U"test"; + EXPECT_EQ(testw, L"testtest"); + + std::u32string testu = U"test"_ss + L"test"; + EXPECT_EQ(testu, U"testtest"); +#endif +} + +TEST(StrExpr, AddNumber) { + std::string testa = "test"_ss + 10; + EXPECT_EQ(testa, "test10"); + + std::u8string testb = u8"test"_ss + 10; + EXPECT_EQ(testb, u8"test10"); + + std::u16string testu = u"test"_ss + 10; + EXPECT_EQ(testu, u"test10"); + + std::u32string testuu = U"test"_ss + 10; + EXPECT_EQ(testuu, U"test10"); + + std::wstring testw = L"test"_ss + 10; + EXPECT_EQ(testw, L"test10"); +} +TEST(StrExpr, Choice) { + std::string testa = "t = " + e_choice(true, "test", "t") + " " + 10 + e_if(true, " from "_ss + 20); + EXPECT_EQ(testa, "t = test 10 from 20"); + testa = "t = " + e_choice(false, "test", "t") + " " + 10 + e_if(false, " from "_ss + 20); + EXPECT_EQ(testa, "t = t 10"); +} + +TEST(StrExpr, Fill) { + std::string testa = "t = " + e_fill_left(+"test"s, 10); + EXPECT_EQ(testa, "t = test"); + testa = "t = " + e_fill_right(+"test"s, 10, '-'); + EXPECT_EQ(testa, "t = test------"); + + std::u16string testu = u"t = " + e_fill_left(e_repl(u"test"sv, u"t", u"--"), 10); + EXPECT_EQ(testu, u"t = --es--"); +} + +TEST(StrExpr, Join) { + std::vector lst = {"abc", "def", "ghi"}; + std::string testa = "/" + e_join(lst, "-") + "/"; + EXPECT_EQ(testa, "/abc-def-ghi/"); + + std::vector ulst = {u"abc", u"def", u"ghi"}; + std::u16string testu = u"/" + e_join(ulst, u"-") + u"/"; + EXPECT_EQ(testu, u"/abc-def-ghi/"); + + std::list wlst = {L"abc", L"def", L"ghi"}; + std::wstring testw = L"/" + e_join(wlst, L"-") + L"/" + e_join(wlst, L"++"); + EXPECT_EQ(testw, L"/abc-def-ghi/abc++def++ghi"); +} + +TEST(StrExpr, Replace) { + std::string testa = e_repl("test"_ss, "t"sv, "-|-"s) + 10; + EXPECT_EQ(testa, "-|-es-|-10"); + testa = e_repl("aaaaaaaaaaaaaaaa"_ss, "a", "bb"); + EXPECT_EQ(testa, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); + + testa = e_repl("aaaaaaaaaaaaaaaa"_ss, "a", "") + "-"; + EXPECT_EQ(testa, "-"); + + testa = e_repl("aaaaaaaaaaaaaaaaaad"_ss, "a", "bb"); + EXPECT_EQ(testa, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbd"); + testa = e_repl(testa, "bb", "a"); + EXPECT_EQ(testa, "aaaaaaaaaaaaaaaaaad"); + + std::u8string testb = e_repl(u8"test"sv, u8"t", u8"-|-") + 10; + EXPECT_EQ(testb, u8"-|-es-|-10"); + + std::u16string testu = e_repl(u"test"sv, u"t", u"-|-") + 10; + EXPECT_EQ(testu, u"-|-es-|-10"); + + std::u32string testuu = e_repl(U"test"sv, U"t", U"-|-") + 10; + EXPECT_EQ(testuu, U"-|-es-|-10"); + + std::wstring testw = e_repl(L"test"s, L"t", L"-|-") + 10; + EXPECT_EQ(testw, L"-|-es-|-10"); +} + +size_t find_pos_str(const std::string& src, std::string_view name) { + return src.find("\n- " + std::string(name) + " -\n"); +} + +size_t find_pos_exp(const std::string& src, ssa name) { + return src.find("\n- " + name + " -\n"); +} + +TEST(StrExpr, FindConcatThree) { + std::string src = "sdfsdf\n- testtest -\nsfrgdgfsg"; + EXPECT_EQ(find_pos_str(src, "testtest"sv), 6); + EXPECT_EQ(find_pos_exp(src, "testtest"sv), 6); +} + +std::string buildTypeNameStr(std::string_view type_name, size_t prec, size_t scale) { + std::string res{type_name}; + if (prec) { + res += "(" + std::to_string(prec); + if (scale) { + res += "," + std::to_string(scale); + } + res += ")"; + } + return res; +} + +std::string buildTypeNameExp(std::string_view type_name, size_t prec, size_t scale) { + if (prec) { + return type_name + "("_ss + prec + e_if(scale, ","_ss + scale) + ")"; + } + return std::string{type_name}; +} + +TEST(StrExpr, MultiConcat) { + EXPECT_EQ(buildTypeNameStr("integer", 0, 0), "integer"); + EXPECT_EQ(buildTypeNameStr("numeric", 10, 2), "numeric(10,2)"); + EXPECT_EQ(buildTypeNameExp("integer", 0, 0), "integer"); + EXPECT_EQ(buildTypeNameExp("numeric", 10, 2), "numeric(10,2)"); +} + +int split_and_calc_total_str(std::string_view numbers, std::string_view delimiter) { + int total = 0; + for (size_t start = 0; start < numbers.length(); ) { + int delim = numbers.find(delimiter, start); + if (delim == std::string::npos) { + delim = numbers.size(); + } + std::string part{numbers.substr(start, delim - start)}; + total += std::strtol(part.c_str(), nullptr, 0); + start = delim + delimiter.length(); + } + return total; +} + +int split_and_calc_total_sim(ssa numbers, ssa delimiter) { + int total = 0; + for (auto splitter = numbers.splitter(delimiter); !splitter.is_done();) { + total += splitter.next().as_int(); + } + return total; +} + +TEST(StrExpr, SplitCalcTotal) { + const char NUMBER_LIST[] = "1-!- 2-!- 3-!- 4 -!- 5-!- 6 -!- 7-!- -8-!- 0xaF-!- 15-!- 010"; // 218 + const char delim[] = "-!-"; + EXPECT_EQ(split_and_calc_total_str(NUMBER_LIST, delim), 218); + EXPECT_EQ(split_and_calc_total_sim(NUMBER_LIST, delim), 218); +} + +TEST(StrExpr, StdToSimplestr) { + std::string test = " sdfsg "; + std::string_view res = ssa{test}.trimmed(); + EXPECT_EQ(res, "sdfsg"); + + size_t fnd = test.find(" " + std::string{res}); + EXPECT_EQ(fnd, 2); +} + +} // namespace simstr::tests diff --git a/tests/test_str.cpp b/tests/test_str.cpp index d8982b6..266f08b 100644 --- a/tests/test_str.cpp +++ b/tests/test_str.cpp @@ -1,9 +1,10 @@ #include #include -namespace simstr::tests { using namespace std::literals; +namespace simstr::tests { + class Tstringa: public stringa { public: using stringa::stringa; @@ -563,7 +564,7 @@ TEST(SimStr, ChangeCase) { TEST(SimStr, Replace) { EXPECT_EQ(ssa{"testing"}.replaced("t", "--"), "--es--ing"); EXPECT_EQ(ssa{"testing"}.replaced("t", ""), "esing"); - EXPECT_EQ(stringa{ssa{"testing"}.replace_init("t", "--")}, "--es--ing"); + EXPECT_EQ(stringa{e_repl(ssa{"testing"}, "t", "--")}, "--es--ing"); } TEST(SimStr, Trim) { @@ -1279,6 +1280,39 @@ TEST(SimStr, LStrFormat) { text.format(L"{}", L"tested"); EXPECT_EQ(text, L"tested"); } +#ifdef _WIN32 + { + // char16_t в Windows совместим по размеру с wchar_t, поэтому для его форматирования можно использовать + // L"format_string", и передавать char16_t строковые объекты + // char16_t on Windows is compatible in size with wchar_t, so you can use L"format_string" to format it + // and pass char16_t string objects + lstringu<2> text; + text.format(L"{}{}", 'a', 'b'); + EXPECT_EQ(text, u"ab"); + text.format(L"{}{}", L"tested", text); + EXPECT_EQ(text, u"testedab"); + + lstringw<10> tew; + tew.format(L"-{}-", text); + EXPECT_EQ(tew, L"-testedab-"); + } +#else + { + // char32_t в Windows совместим по размеру с wchar_t, поэтому для его форматирования можно использовать + // L"format_string", и передавать char32_t строковые объекты + // char32_t on Windows is compatible in size with wchar_t, so you can use L"format_string" to format it + // and pass char32_t string objects + lstringuu<2> text; + text.format(L"{}{}", 'a', 'b'); + EXPECT_EQ(text, U"ab"); + text.format(L"{}{}", L"tested", text); + EXPECT_EQ(text, U"testedab"); + + lstringw<10> tew; + tew.format(L"-{}-", text); + EXPECT_EQ(tew, L"-testedab-"); + } +#endif { lstringa<40> text = "tested"; text.format_from(4, "{}{}", 'a', 'b'); @@ -1703,6 +1737,10 @@ TEST(SimStr, StdStringExpr) { lstringa<20> res = eea + "test"s; EXPECT_EQ(res, "test"); } + { + lstringa<20> res = +"test"s; + EXPECT_EQ(res, "test"); + } { lstringa<20> res = "test"s + eea; EXPECT_EQ(res, "test"); @@ -1711,55 +1749,20 @@ TEST(SimStr, StdStringExpr) { lstringa<20> res = eea + "test"sv; EXPECT_EQ(res, "test"); } + { + lstringa<20> res = +"test"sv; + EXPECT_EQ(res, "test"); + } + { + lstringu<20> res = +u"test"sv; + EXPECT_EQ(res, u"test"); + } { lstringa<20> res = "test"sv + eea; EXPECT_EQ(res, "test"); } } -static std::string checker_str = "str"; -static std::string_view checker_view; - -static std::string get_string_val(); -static std::string& get_string_ref(){return checker_str;} -static const std::string get_string_cval(); -static const std::string& get_string_cref(){return checker_str;} - -template -requires requires{new simple_str(std::string{""});} -char check_lvalue_str(); - -template -requires requires{new simple_str(""s);} -char check_lvalue_str(); - -template -requires requires{new simple_str(get_string_val());} -char check_lvalue_str(); - -template -requires requires{new simple_str(get_string_cval());} -char check_lvalue_str(); - -template -requires requires{new simple_str(checker_str);} -int check_lvalue_str(); - -template -requires requires{new simple_str(std::string_view{""});} -char check_lvalue_view(); - -template -requires requires{new simple_str(checker_view);} -int check_lvalue_view(); - -TEST(SimStr, InitFromLValueStdStrings) { - EXPECT_EQ(sizeof(check_lvalue_str()), sizeof(int)); - EXPECT_EQ(sizeof(check_lvalue_view()), sizeof(int)); - EXPECT_EQ(ssa(get_string_ref()), "str"); - EXPECT_EQ(ssa(get_string_cref()), "str"); -} - TEST(SimStr, HashStrMapAt) { hashStrMapA test = { {"Test"_h, 1} @@ -1773,6 +1776,7 @@ TEST(SimStr, ExprRepeat) { EXPECT_EQ(stringa{e_repeat("aa", 3)}, "aaaaaa"); int t = 1; EXPECT_EQ(lstringa<40>{e_repeat("aa"_ss + t + "_", 3)}, "aa1_aa1_aa1_"); + EXPECT_EQ(std::string{e_repeat("aa"_ss + t + "_", 3)}, "aa1_aa1_aa1_"); } TEST(SimStr, Constexpr) { @@ -1782,6 +1786,182 @@ TEST(SimStr, Constexpr) { static_assert(aa == "asd"); static_assert(aa.length() == 3); constexpr stringa bb = ""; + constexpr int k = "123"_ss.to_int().value; + static_assert(k == 123); +} + +TEST(SimStr, StrExpToStdString) { + std::basic_string, std::pmr::polymorphic_allocator> test = "count = "_ss + 10 + " times"; + EXPECT_EQ(test, "count = 10 times"); + + test = "aaa"_ss; + EXPECT_EQ(test, "aaa"); + EXPECT_EQ("aaa"_ss.to_sv(), "aaa"); + + std::string auto_utf = e_utf(u"Привет"_ss); + EXPECT_EQ(auto_utf, "Привет"); + auto_utf = e_utf(L"Досвидания"_ss); + EXPECT_EQ(auto_utf, "Досвидания"); + + std::string res = +"test "s + 10 + e_if(true, " times"); + EXPECT_EQ(res, "test 10 times"); + + res = +"test "sv + 10 + e_if(true, " times"); + EXPECT_EQ(res, "test 10 times"); +} +std::string make_text(const std::string& text, int count, std::string_view what, std::string_view what_p = ""sv) { + return +text + " " + count + " " + e_choice(what_p.empty(), what + e_if(count > 1, "s"), e_choice(count > 1, +what_p, +what)); +} + +std::string make_answer(const std::string& text, int count, std::string_view what, std::string_view what_p = ""sv) { + return "Answer is: " + +text + " " + count + " " + e_choice(what_p.empty(), what + e_if(count > 1, "s"), e_choice(count > 1, +what_p, +what)); +} + +TEST(SimStr, StrPrintfU8) { + stringb tt = u8"asdf"; + stringa tr = tt; + EXPECT_EQ(tr, "asdf"); + tt = tr; + EXPECT_EQ(tt, u8"asdf"); + + lstringb<100> res; + res.printf(u8"asd %i", 10); + EXPECT_EQ(res, u8"asd 10"); + + std::u8string std_bstr = u8"def"; + std::vector ll = {"qwe", "rty"}; + + stringb bstring = eea + "abc" + u8"def" + 10 + e_spca<3>() + e_join(ll, "-"); + EXPECT_EQ(bstring, u8"abcdef10 qwe-rty"); + + stringa check_choice = e_choice(true, eea + 10, u8"aaa"); + EXPECT_EQ(check_choice, "10"); + + check_choice = e_choice(false, eea + 10, u8"aaa"); + EXPECT_EQ(check_choice, "aaa"); + + check_choice = e_choice(true, "aaa", u8"aaa"); + EXPECT_EQ(check_choice, "aaa"); + + check_choice = eea + e_if(true, u8"aaa"); + EXPECT_EQ(check_choice, "aaa"); + + check_choice = eeb + e_if(true, "aaa"); + EXPECT_EQ(check_choice, "aaa"); + std::wstring wstr = L"test"sv + +#if WIN32 + u"test"_ss +#else + U"test"_ss +#endif + ; + EXPECT_EQ(wstr, L"testtest"); + + EXPECT_EQ(make_text("got"s, 10, "apple"sv), "got 10 apples"); + EXPECT_EQ(make_answer("got"s, 10, "aloe"sv, "aloe"sv), "Answer is: got 10 aloe"); +} + +TEST(SimStr, ExprReal) { + stringa a = e_num(1.1); + EXPECT_EQ(a, "1.1"); + + stringb b = e_num(1.1); + EXPECT_EQ(b, u8"1.1"); + + stringuu uu = e_num(1.1); + EXPECT_EQ(uu, U"1.1"); + + stringu u = e_num(1.1); + EXPECT_EQ(u, u"1.1"); + + stringw w = e_num(1.1); + EXPECT_EQ(w, L"1.1"); +} + +TEST(SimStr, StrRepl) { + std::string r = e_repl("test"s, "t", "-t-"); + EXPECT_EQ(r, "-t-es-t-"); + + r = e_repl("test"sv, "t", "-t-"); + EXPECT_EQ(r, "-t-es-t-"); + + r = e_repl("test"sv, "t"s, "-t-"); + EXPECT_EQ(r, "-t-es-t-"); + + r = e_repl("test"sv, "t", "-t-"sv); + EXPECT_EQ(r, "-t-es-t-"); + + r = e_repl("test"s, "t"sv, "-t-"s); + EXPECT_EQ(r, "-t-es-t-"); + + stringa a = e_repl("test"_ss, "t", "-t-"); + EXPECT_EQ(a, "-t-es-t-"); + + a = e_repl("test"_ss, "t"_ss, "-t-"); + EXPECT_EQ(a, "-t-es-t-"); + + a = e_repl("test"_ss, "t", "-t-"_ss); + EXPECT_EQ(a, "-t-es-t-"); + + a = e_repl("test"_ss, "t"_ss, "-t-"_ss); + EXPECT_EQ(a, "-t-es-t-"); +} + +TEST(SimStr, HexEpr) { + stringa hexa = expr_hex{0xabcd0102}; + EXPECT_EQ(hexa, "0xABCD0102"); + + stringu hexu = expr_hex{0xabcd0102}; + EXPECT_EQ(hexu, u"0xABCD0102"); + + stringuu hexuu = expr_hex{0xabcd0102}; + EXPECT_EQ(hexuu, U"0xABCD0102"); + + stringb hexb = expr_hex{0xcd0102}; + EXPECT_EQ(hexb, u8"0x00CD0102"); + + hexa = expr_hex{0xabcd0102}; + EXPECT_EQ(hexa, "00000000abcd0102"); + + hexa = expr_hex{0}; + EXPECT_EQ(hexa, "0"); + hexa = expr_hex{0}; + EXPECT_EQ(hexa, "0x0"); + hexa = expr_hex{0}; + EXPECT_EQ(hexa, "0x00000000"); + + std::string text = +"val = "sv + e_hex(10u); + EXPECT_EQ(text, "val = 0x0000000A"); + + stringu textu = u"val = 0X"_ss + e_hex(0x12Au); + EXPECT_EQ(textu, u"val = 0X12a"); + + std::u32string textuu = +U"val = 0X"sv + e_hex(0x12Au); + EXPECT_EQ(textuu, U"val = 0X12A"); + + text = +"ptr = "sv + (const void*)0xdeadbeefcafe01; + EXPECT_EQ(text, "ptr = 0x00DEADBEEFCAFE01"); + + const char* ptr = (const char*)0xdeadbeefcafe01; + std::u16string utext = ptr + +u" freed"sv; + EXPECT_EQ(utext, u"0x00DEADBEEFCAFE01 freed"); +} + +TEST(SimStr, EFill) { + int k = 10; + stringa test = "<" + e_fill_left("t="_ss + k, 10, '_'); + EXPECT_EQ(test, "<______t=10"); + test = e_fill_right("t="_ss + k, 10, '_') + ">"; + EXPECT_EQ(test, "t=10______>"); } } // namespace simstr::tests + +TEST(SimStr, StrNoNamespace) { + std::string str = "test"; + std::string test = +str + " = " + 10; + EXPECT_EQ(test, "test = 10"); + + std::u16string textu = +u"val = 0X"sv + simstr::e_hex(0x12Au); + EXPECT_EQ(textu, u"val = 0X12a"); +}