mirror of https://github.com/orefkov/simstr.git
- Updated to 1.6.6.
- Improved UTF conversion. - Fixed a number of bugs. - Improved Emscripten benchmark compilation. --- - Обновление до 1.6.6. - Доработал UTF-конвертацию. - Исправил ряд ошибок. - Доработал Emscripten сборку бенчмарков.
This commit is contained in:
parent
2148718b32
commit
8cf026f2c6
|
|
@ -5,7 +5,7 @@ include(FetchContent)
|
||||||
|
|
||||||
project(
|
project(
|
||||||
simstr
|
simstr
|
||||||
VERSION 1.6.5
|
VERSION 1.6.6
|
||||||
DESCRIPTION "Yet another modern C++ string library"
|
DESCRIPTION "Yet another modern C++ string library"
|
||||||
HOMEPAGE_URL "https://github.com/orefkov/simstr"
|
HOMEPAGE_URL "https://github.com/orefkov/simstr"
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.6.5
|
* ver. 1.6.6
|
||||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||||
* Бенчмарки
|
* Бенчмарки
|
||||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||||
|
|
@ -14,15 +14,14 @@
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <fmt/compile.h>
|
#include <fmt/compile.h>
|
||||||
|
|
||||||
|
using namespace simstr;
|
||||||
|
using namespace std::literals;
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
static void DoTeardown(const benchmark::State& state) {
|
static void DoTeardown(const benchmark::State& state) {
|
||||||
emscripten_sleep(1);
|
// Это нужно чтобы интерфейс браузера обновился
|
||||||
}
|
// This is necessary for the browser interface to refresh.
|
||||||
static void DoSetup(const benchmark::State& state) {
|
|
||||||
EM_ASM({
|
|
||||||
on_begin_benchmark(UTF8ToString($0));
|
|
||||||
}, state.name().c_str());
|
|
||||||
emscripten_sleep(1);
|
emscripten_sleep(1);
|
||||||
}
|
}
|
||||||
#undef BENCHMARK
|
#undef BENCHMARK
|
||||||
|
|
@ -31,11 +30,18 @@ static void DoSetup(const benchmark::State& state) {
|
||||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||||
::benchmark::internal::make_unique< \
|
::benchmark::internal::make_unique< \
|
||||||
::benchmark::internal::FunctionBenchmark>(#__VA_ARGS__, \
|
::benchmark::internal::FunctionBenchmark>(#__VA_ARGS__, \
|
||||||
__VA_ARGS__)))->Setup(DoSetup)->Teardown(DoTeardown)
|
__VA_ARGS__)))->Teardown(DoTeardown)
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace simstr;
|
#undef BENCHMARK_CAPTURE
|
||||||
using namespace std::literals;
|
#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
|
||||||
|
BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
|
||||||
|
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||||
|
::benchmark::internal::make_unique< \
|
||||||
|
::benchmark::internal::FunctionBenchmark>( \
|
||||||
|
#func "/" #test_case_name, \
|
||||||
|
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))->Teardown(DoTeardown)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TEST_TEXT "Test text"
|
#define TEST_TEXT "Test text"
|
||||||
#define LONG_TEXT "123456789012345678901234567890"
|
#define LONG_TEXT "123456789012345678901234567890"
|
||||||
|
|
@ -769,7 +775,6 @@ void ToIntNoOverflow(benchmark::State& state, ssa t, int c) {
|
||||||
benchmark::DoNotOptimize(t);
|
benchmark::DoNotOptimize(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK(__)->Name("----- Convert to int '1234567' ---------")->Repetitions(1);
|
BENCHMARK(__)->Name("----- Convert to int '1234567' ---------")->Repetitions(1);
|
||||||
BENCHMARK_CAPTURE(ToIntStr10, , std::string{"123456789"}, 123456789) ->Name("std::string s = \"123456789\"; int res = std::strtol(s.c_str(), 0, 10);");
|
BENCHMARK_CAPTURE(ToIntStr10, , std::string{"123456789"}, 123456789) ->Name("std::string s = \"123456789\"; int res = std::strtol(s.c_str(), 0, 10);");
|
||||||
BENCHMARK_CAPTURE(ToIntFromChars10, , std::string_view{"123456789"}, 123456789) ->Name("std::string_view s = \"123456789\"; std::from_chars(s.data(), s.data() + s.size(), res, 10);");
|
BENCHMARK_CAPTURE(ToIntFromChars10, , std::string_view{"123456789"}, 123456789) ->Name("std::string_view s = \"123456789\"; std::from_chars(s.data(), s.data() + s.size(), res, 10);");
|
||||||
|
|
@ -2475,7 +2480,9 @@ int main(int argc, char** argv) {
|
||||||
::benchmark::RunSpecifiedBenchmarks();
|
::benchmark::RunSpecifiedBenchmarks();
|
||||||
::benchmark::Shutdown();
|
::benchmark::Shutdown();
|
||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
|
std::cout << "Done!\n";
|
||||||
EM_ASM({ on_done(); });
|
EM_ASM({ on_done(); });
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,96 +1,244 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en-us">
|
<html lang="en-us">
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
||||||
<title>SimStr Bencjmarks</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
color: white;
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
#output {
|
|
||||||
position: absolute;
|
|
||||||
left: 10px;
|
|
||||||
top: 80px;
|
|
||||||
right: 10px;
|
|
||||||
bottom: 10px;
|
|
||||||
margin: 0 auto;
|
|
||||||
border: 0;
|
|
||||||
display: block;
|
|
||||||
background-color: black;
|
|
||||||
color: white;
|
|
||||||
font-family: 'Cascadia Code', 'Consolas', 'Lucida Console', Monaco, monospace;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
.ctr {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 16pt;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="ctr" id="bs_name"></div><div class="ctr" id="b_name"></div>
|
|
||||||
<textarea class="emscripten" id="output" rows="20"></textarea>
|
|
||||||
<script type='text/javascript'>
|
|
||||||
var outputElement = document.getElementById('output');
|
|
||||||
var bsNameEl= document.getElementById('bs_name');
|
|
||||||
var bNameEl= document.getElementById('b_name');
|
|
||||||
if (outputElement) outputElement.value = ''; // clear browser cache
|
|
||||||
var Module = {
|
|
||||||
print(...args) {
|
|
||||||
console.log(...args);
|
|
||||||
if (outputElement) {
|
|
||||||
var text = args.join(' ').replace('_mean', ' ');
|
|
||||||
var rpt = text.indexOf("/repeats");
|
|
||||||
if (rpt != -1)
|
|
||||||
text = text.substr(0, rpt);
|
|
||||||
if (text.indexOf('_median ') == -1 && text.indexOf('_stddev ') == -1 && text.indexOf('_cv ') == -1) {
|
|
||||||
outputElement.value += text + "\n";
|
|
||||||
outputElement.scrollTop = outputElement.scrollHeight; // focus on bottom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setStatus(text) {
|
|
||||||
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
|
|
||||||
if (text === Module.setStatus.last.text) return;
|
|
||||||
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
|
|
||||||
var now = Date.now();
|
|
||||||
if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon
|
|
||||||
Module.setStatus.last.time = now;
|
|
||||||
Module.setStatus.last.text = text;
|
|
||||||
if (m) {
|
|
||||||
text = m[1];
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
totalDependencies: 0,
|
|
||||||
monitorRunDependencies(left) {
|
|
||||||
this.totalDependencies = Math.max(this.totalDependencies, left);
|
|
||||||
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Module.setStatus('Downloading...');
|
|
||||||
window.onerror = () => {
|
|
||||||
Module.setStatus('Exception thrown, see JavaScript console');
|
|
||||||
Module.setStatus = (text) => {
|
|
||||||
if (text) console.error('[post-exception status] ' + text);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
function on_begin_benchmark(name) {
|
|
||||||
if (name.substr(0, 3) == "---") {
|
|
||||||
bsNameEl.innerText = name.match(/^[- ]+(.+?)[ -]+$/)[1];
|
|
||||||
bNameEl.innerText = "";
|
|
||||||
} else {
|
|
||||||
bNameEl.innerText = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function on_done() {
|
|
||||||
bsNameEl.innerText = "Done";
|
|
||||||
bNameEl.innerText = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
<head>
|
||||||
{{{ SCRIPT }}}
|
<meta charset="utf-8">
|
||||||
</body>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<title>SimStr Benchmarks</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: auto;
|
||||||
|
font-size: 12pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: 1px black;
|
||||||
|
text-align: right;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:nth-child(odd) {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:nth-child(even) {
|
||||||
|
background: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip a:any-link {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip a:link {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip a:visited {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:hover td {
|
||||||
|
background-color: lightcyan;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.header {
|
||||||
|
max-width: 960px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
max-width: 2000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benchset {
|
||||||
|
max-width: 960px;
|
||||||
|
padding: 1px;
|
||||||
|
margin: 5px auto;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: gainsboro;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benchset h4 {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test_platforms {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test_platforms ul {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test_platforms li {
|
||||||
|
display: table-row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test_platforms li:before {
|
||||||
|
content: "\2022";
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test_platforms span.tooltip {
|
||||||
|
padding-left: 20px;
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.platform {
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
border-radius: 3px;
|
||||||
|
border: solid 1px lightgrey;
|
||||||
|
background-color: beige;
|
||||||
|
color: brown;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
font-family: 'Cascadia Code', Consolas, 'Courier New', Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip .tooltiptext {
|
||||||
|
visibility: hidden;
|
||||||
|
background-color: beige;
|
||||||
|
color: black;
|
||||||
|
text-align: left;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 15px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 35px;
|
||||||
|
right: 0;
|
||||||
|
white-space: pre;
|
||||||
|
border: 1px solid darkgray;
|
||||||
|
box-shadow: 4px 4px 8px 0px rgba(34, 60, 80, 0.2);
|
||||||
|
transform: translate(50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip:hover .tooltiptext {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#output {
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
top: 50px;
|
||||||
|
right: 10px;
|
||||||
|
bottom: 60%;
|
||||||
|
margin: 0 auto;
|
||||||
|
border: 0;
|
||||||
|
display: block;
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
font-family: 'Cascadia Code', 'Consolas', 'Lucida Console', Monaco, monospace;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#results {
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
top: 42%;
|
||||||
|
right: 10px;
|
||||||
|
bottom: 10px;
|
||||||
|
margin: 0 auto;
|
||||||
|
border: 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.head {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.head h3 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.head span {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="head">
|
||||||
|
<h3>SimStr 1.6.6 Benchmark</h3>
|
||||||
|
<span><a href="https://orefkov.github.io/simstr/results.html" target="blank">All results</a></span>
|
||||||
|
<span><a href="https://github.com/orefkov/simstr/blob/main/bench/bench_str.cpp" target="blank">Sources for
|
||||||
|
benchmarks</a></span>
|
||||||
|
<textarea id="output"></textarea>
|
||||||
|
</div>
|
||||||
|
<div id="results"></div>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
var outputElement = document.getElementById('output');
|
||||||
|
var resultEl = document.getElementById('results');
|
||||||
|
if (outputElement) outputElement.value = ''; // clear browser cache
|
||||||
|
var Module = {
|
||||||
|
print(...args) {
|
||||||
|
console.log(...args);
|
||||||
|
var text = args.join(' ')
|
||||||
|
try {
|
||||||
|
if (text.match(/^--+[^-]/)) {
|
||||||
|
add_benchset(text.match(/^-+ +(.+?) +-+\/repeats/)[1]);
|
||||||
|
} else {
|
||||||
|
var im = text.indexOf("_mean ");
|
||||||
|
if (im != -1) {
|
||||||
|
add_benchmark(text.substr(0, im), text.match(/ ([^ ]+?) ns/)[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
if (outputElement) {
|
||||||
|
outputElement.value += text + "\n";
|
||||||
|
outputElement.scrollTop = outputElement.scrollHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function on_done() {
|
||||||
|
resultEl.scrollTop = 0;
|
||||||
|
}
|
||||||
|
function escapeHtml(unsafe) {
|
||||||
|
return unsafe
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
}
|
||||||
|
function add_benchset(bs_name) {
|
||||||
|
resultEl.insertAdjacentHTML("beforeend", `<div class="benchset"><h4>${escapeHtml(bs_name)}</h4><table width="100%"><thead><tr><th>Benchmark name</th><th width="8%">Time(ns)</th></tr></thead><tbody></tbody></table></div>`);
|
||||||
|
resultEl.scrollTop = resultEl.scrollHeight;
|
||||||
|
}
|
||||||
|
function add_benchmark(name, result) {
|
||||||
|
resultEl.querySelector("div:last-child table tbody").insertAdjacentHTML("beforeend", `<tr><td>${escapeHtml(name)}</td><td>${result}</td></tr>`);
|
||||||
|
resultEl.scrollTop = resultEl.scrollHeight;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{{{ SCRIPT }}}
|
||||||
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
1342
bench/results.html
1342
bench/results.html
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -48,7 +48,7 @@ PROJECT_NAME = "simstr"
|
||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 1.6.5
|
PROJECT_NUMBER = 1.6.6
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# 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
|
# for a project that appears at the top of each page and should give viewers a
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ PROJECT_NAME = "simstr"
|
||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 1.6.5
|
PROJECT_NUMBER = 1.6.6
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# 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
|
# for a project that appears at the top of each page and should give viewers a
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||||
* ver. 1.6.5
|
* ver. 1.6.6
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.6.5
|
* ver. 1.6.6
|
||||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||||
* Классы для работы со строками
|
* Классы для работы со строками
|
||||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||||
|
|
@ -386,7 +386,7 @@ struct simple_str : str_algs<K, simple_str<K>, simple_str<K>, false> {
|
||||||
* @en @brief Constructor from a string literal.
|
* @en @brief Constructor from a string literal.
|
||||||
*/
|
*/
|
||||||
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
||||||
constexpr simple_str(T&& v) noexcept : str(v), len(N - 1) {}
|
constexpr simple_str(T&& v) noexcept : str((const K*)v), len(N - 1) {}
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Конструктор из указателя и длины.
|
* @ru @brief Конструктор из указателя и длины.
|
||||||
* @en @brief Constructor from pointer and length.
|
* @en @brief Constructor from pointer and length.
|
||||||
|
|
@ -597,6 +597,17 @@ using struu = simple_str_nt<u32s>;
|
||||||
template<typename Src, typename Dest>
|
template<typename Src, typename Dest>
|
||||||
struct utf_convert_selector;
|
struct utf_convert_selector;
|
||||||
|
|
||||||
|
template<typename Src>
|
||||||
|
struct utf_convert_selector<Src, Src> {
|
||||||
|
static size_t need_len(const Src* src, size_t srcLen) {
|
||||||
|
return srcLen;
|
||||||
|
}
|
||||||
|
static size_t convert(const Src* src, size_t srcLen, Src* dest) {
|
||||||
|
ch_traits<Src>::copy(dest, src, srcLen + 1);
|
||||||
|
return srcLen;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct utf_convert_selector<u8s, u16s> {
|
struct utf_convert_selector<u8s, u16s> {
|
||||||
static SIMSTR_API size_t need_len(const u8s* src, size_t srcLen);
|
static SIMSTR_API size_t need_len(const u8s* src, size_t srcLen);
|
||||||
|
|
@ -609,16 +620,6 @@ struct utf_convert_selector<u8s, u32s> {
|
||||||
static SIMSTR_API size_t convert(const u8s* src, size_t srcLen, u32s* dest);
|
static SIMSTR_API size_t convert(const u8s* src, size_t srcLen, u32s* dest);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<u8s, wchar_t> {
|
|
||||||
static size_t need_len(const u8s* src, size_t srcLen) {
|
|
||||||
return utf_convert_selector<u8s, wchar_type>::need_len(src, srcLen);
|
|
||||||
}
|
|
||||||
static size_t convert(const u8s* src, size_t srcLen, wchar_t* dest) {
|
|
||||||
return utf_convert_selector<u8s, wchar_type>::convert(src, srcLen, to_w(dest));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct utf_convert_selector<u16s, u8s> {
|
struct utf_convert_selector<u16s, u8s> {
|
||||||
static SIMSTR_API size_t need_len(const u16s* src, size_t srcLen);
|
static SIMSTR_API size_t need_len(const u16s* src, size_t srcLen);
|
||||||
|
|
@ -631,42 +632,6 @@ struct utf_convert_selector<u16s, u32s> {
|
||||||
static SIMSTR_API size_t convert(const u16s* src, size_t srcLen, u32s* dest);
|
static SIMSTR_API size_t convert(const u16s* src, size_t srcLen, u32s* dest);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<u16s, u16s> {
|
|
||||||
// При конвертации char16_t в wchar_t под windows будет вызываться эта реализация
|
|
||||||
// When converting char16_t to wchar_t under windows this implementation will be called
|
|
||||||
static size_t need_len(const u16s* src, size_t srcLen) {
|
|
||||||
return srcLen;
|
|
||||||
}
|
|
||||||
static size_t convert(const u16s* src, size_t srcLen, u16s* dest) {
|
|
||||||
ch_traits<u16s>::copy(dest, src, srcLen + 1);
|
|
||||||
return srcLen;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<u32s, u32s> {
|
|
||||||
// При конвертации char32_t в wchar_t под linux будет вызываться эта реализация
|
|
||||||
// When converting char32_t to wchar_t under Linux, this implementation will be called
|
|
||||||
static size_t need_len(const u32s* src, size_t srcLen) {
|
|
||||||
return srcLen;
|
|
||||||
}
|
|
||||||
static size_t convert(const u32s* src, size_t srcLen, u32s* dest) {
|
|
||||||
ch_traits<u32s>::copy(dest, src, srcLen + 1);
|
|
||||||
return srcLen;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<u16s, wchar_t> {
|
|
||||||
static size_t need_len(const u16s* src, size_t srcLen) {
|
|
||||||
return utf_convert_selector<u16s, wchar_type>::need_len(src, srcLen);
|
|
||||||
}
|
|
||||||
static size_t convert(const u16s* src, size_t srcLen, wchar_t* dest) {
|
|
||||||
return utf_convert_selector<u16s, wchar_type>::convert(src, srcLen, to_w(dest));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct utf_convert_selector<u32s, u8s> {
|
struct utf_convert_selector<u32s, u8s> {
|
||||||
static SIMSTR_API size_t need_len(const u32s* src, size_t srcLen);
|
static SIMSTR_API size_t need_len(const u32s* src, size_t srcLen);
|
||||||
|
|
@ -679,68 +644,6 @@ struct utf_convert_selector<u32s, u16s> {
|
||||||
static SIMSTR_API size_t convert(const u32s* src, size_t srcLen, u16s* dest);
|
static SIMSTR_API size_t convert(const u32s* src, size_t srcLen, u16s* dest);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<u32s, wchar_t> {
|
|
||||||
static size_t need_len(const u32s* src, size_t srcLen) {
|
|
||||||
return utf_convert_selector<u32s, wchar_type>::need_len(src, srcLen);
|
|
||||||
}
|
|
||||||
static size_t convert(const u32s* src, size_t srcLen, wchar_t* dest) {
|
|
||||||
return utf_convert_selector<u32s, wchar_type>::convert(src, srcLen, to_w(dest));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<wchar_t, u8s> {
|
|
||||||
static size_t need_len(const wchar_t* src, size_t srcLen) {
|
|
||||||
return utf_convert_selector<wchar_type, u8s>::need_len(to_w(src), srcLen);
|
|
||||||
}
|
|
||||||
static size_t convert(const wchar_t* src, size_t srcLen, u8s* dest) {
|
|
||||||
return utf_convert_selector<wchar_type, u8s>::convert(to_w(src), srcLen, dest);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<wchar_t, u16s> {
|
|
||||||
static size_t need_len(const wchar_t* src, size_t srcLen) {
|
|
||||||
return utf_convert_selector<wchar_type, u16s>::need_len(to_w(src), srcLen);
|
|
||||||
}
|
|
||||||
static size_t convert(const wchar_t* src, size_t srcLen, u16s* dest) {
|
|
||||||
return utf_convert_selector<wchar_type, u16s>::convert(to_w(src), srcLen, dest);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<wchar_t, u32s> {
|
|
||||||
static size_t need_len(const wchar_t* src, size_t srcLen) {
|
|
||||||
return utf_convert_selector<wchar_type, u32s>::need_len(to_w(src), srcLen);
|
|
||||||
}
|
|
||||||
static size_t convert(const wchar_t* src, size_t srcLen, u32s* dest) {
|
|
||||||
return utf_convert_selector<wchar_type, u32s>::convert(to_w(src), srcLen, dest);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<u8s, ubs> {
|
|
||||||
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<u8s>::copy((u8s*)dest, src, srcLen);
|
|
||||||
return srcLen;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct utf_convert_selector<ubs, u8s> {
|
|
||||||
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<u8s>::copy(dest, (const u8s*)src, srcLen);
|
|
||||||
return srcLen;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Базовый класс для строк, могущих конвертироваться из другого типа символов.
|
* @ru @brief Базовый класс для строк, могущих конвертироваться из другого типа символов.
|
||||||
* @tparam K - тип символов.
|
* @tparam K - тип символов.
|
||||||
|
|
@ -769,16 +672,19 @@ protected:
|
||||||
template<typename O>
|
template<typename O>
|
||||||
requires(!std::is_same_v<O, K>)
|
requires(!std::is_same_v<O, K>)
|
||||||
void init_from_utf_convertible(simple_str<O> init) {
|
void init_from_utf_convertible(simple_str<O> init) {
|
||||||
using worker = utf_convert_selector<O, K>;
|
using from_t = to_base_char_t<O>;
|
||||||
|
using to_t = to_base_char_t<K>;
|
||||||
|
|
||||||
|
using worker = utf_convert_selector<from_t, to_t>;
|
||||||
Impl* d = static_cast<Impl*>(this);
|
Impl* d = static_cast<Impl*>(this);
|
||||||
size_t len = init.length();
|
size_t len = init.length();
|
||||||
if (!len)
|
if (!len)
|
||||||
d->create_empty();
|
d->create_empty();
|
||||||
else {
|
else {
|
||||||
size_t need = worker::need_len(init.symbols(), len);
|
size_t need = worker::need_len((const from_t*)init.symbols(), len);
|
||||||
K* str = d->init(need);
|
K* str = d->init(need);
|
||||||
str[need] = 0;
|
str[need] = 0;
|
||||||
worker::convert(init.symbols(), len, str);
|
worker::convert((const from_t*)init.symbols(), len, (to_t*)str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -794,17 +700,19 @@ protected:
|
||||||
template<typename From, typename To> requires (!std::is_same_v<From, To>)
|
template<typename From, typename To> requires (!std::is_same_v<From, To>)
|
||||||
struct expr_utf : expr_to_std_string<expr_utf<From, To>> {
|
struct expr_utf : expr_to_std_string<expr_utf<From, To>> {
|
||||||
using symb_type = To;
|
using symb_type = To;
|
||||||
using worker = utf_convert_selector<From, To>;
|
using from_t = to_base_char_t<From>;
|
||||||
|
using to_t = to_base_char_t<To>;
|
||||||
|
using worker = utf_convert_selector<from_t, to_t>;
|
||||||
|
|
||||||
simple_str<From> source_;
|
simple_str<From> source_;
|
||||||
|
|
||||||
constexpr expr_utf(simple_str<From> source) : source_(source){}
|
constexpr expr_utf(simple_str<From> source) : source_(source){}
|
||||||
|
|
||||||
size_t length() const noexcept {
|
size_t length() const noexcept {
|
||||||
return worker::need_len(source_.symbols(), source_.length());
|
return worker::need_len((const from_t*)source_.symbols(), source_.length());
|
||||||
}
|
}
|
||||||
To* place(To* ptr) const noexcept {
|
To* place(To* ptr) const noexcept {
|
||||||
return ptr + worker::convert(source_.symbols(), source_.length(), ptr);
|
return ptr + worker::convert((const from_t*)source_.symbols(), source_.length(), (to_t*)ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1376,24 +1284,6 @@ inline size_t grow2(size_t ret, size_t currentCapacity) {
|
||||||
return ret <= currentCapacity ? ret : ret * 2;
|
return ret <= currentCapacity ? ret : ret * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K>
|
|
||||||
struct to_std_char_type : std::type_identity<K>{};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct to_std_char_type<char8_t>{
|
|
||||||
using type = char;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct to_std_char_type<char16_t>{
|
|
||||||
using type = std::conditional_t<sizeof(char16_t) == sizeof(wchar_t), wchar_t, void>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct to_std_char_type<char32_t>{
|
|
||||||
using type = std::conditional_t<sizeof(char32_t) == sizeof(wchar_t), wchar_t, void>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Базовый класс работы с изменяемыми строками
|
* @ru @brief Базовый класс работы с изменяемыми строками
|
||||||
* @tparam K - тип символов
|
* @tparam K - тип символов
|
||||||
|
|
@ -2391,7 +2281,7 @@ public:
|
||||||
writer& operator=(writer&&) noexcept = default;
|
writer& operator=(writer&&) noexcept = default;
|
||||||
using difference_type = int;
|
using difference_type = int;
|
||||||
};
|
};
|
||||||
using fmt_type = typename to_std_char_type<K>::type;
|
using fmt_type = to_std_char_t<K>;
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Добавляет отформатированный с помощью std::format вывод, начиная с указанной позиции.
|
* @ru @brief Добавляет отформатированный с помощью std::format вывод, начиная с указанной позиции.
|
||||||
* @param from - начальная позиция добавления.
|
* @param from - начальная позиция добавления.
|
||||||
|
|
@ -2715,14 +2605,15 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr K* init(size_t s) {
|
constexpr K* init(size_t s) {
|
||||||
size_ = s;
|
size_t need_cap = s;
|
||||||
if (size_ > LocalCapacity) {
|
if (need_cap > LocalCapacity) {
|
||||||
s = calc_capacity(s);
|
need_cap = calc_capacity(s);
|
||||||
data_ = alloc_place(s);
|
data_ = alloc_place(need_cap);
|
||||||
capacity_ = s;
|
capacity_ = need_cap;
|
||||||
} else {
|
} else {
|
||||||
data_ = local_;
|
data_ = local_;
|
||||||
}
|
}
|
||||||
|
size_ = s;
|
||||||
return str();
|
return str();
|
||||||
}
|
}
|
||||||
// Методы для себя | Methods for yourself
|
// Методы для себя | Methods for yourself
|
||||||
|
|
@ -2886,7 +2777,14 @@ public:
|
||||||
*/
|
*/
|
||||||
constexpr lstring(const my_type& other) : base_storable(other.allocator()) {
|
constexpr lstring(const my_type& other) : base_storable(other.allocator()) {
|
||||||
if (other.size_) {
|
if (other.size_) {
|
||||||
traits::copy(init(other.size_), other.symbols(), other.size_ + 1);
|
K* buf = init(other.size_);
|
||||||
|
const size_t short_str = 16 / sizeof(K);
|
||||||
|
if (LocalCapacity >= short_str - 1 && other.size_ < short_str) {
|
||||||
|
struct copy { char buf[16]; };
|
||||||
|
*reinterpret_cast<copy*>(buf) = *reinterpret_cast<const copy*>(other.symbols());
|
||||||
|
} else {
|
||||||
|
traits::copy(buf, other.symbols(), other.size_ + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -2917,7 +2815,7 @@ public:
|
||||||
constexpr lstring(T&& value, Args&&... args) : base_storable(std::forward<Args>(args)...) {
|
constexpr lstring(T&& value, Args&&... args) : base_storable(std::forward<Args>(args)...) {
|
||||||
if constexpr (I > 1) {
|
if constexpr (I > 1) {
|
||||||
K* ptr = init(I - 1);
|
K* ptr = init(I - 1);
|
||||||
traits::copy(ptr, value, I - 1);
|
traits::copy(ptr, (const K*)value, I - 1);
|
||||||
ptr[I - 1] = 0;
|
ptr[I - 1] = 0;
|
||||||
} else
|
} else
|
||||||
create_empty();
|
create_empty();
|
||||||
|
|
@ -3057,7 +2955,7 @@ public:
|
||||||
*/
|
*/
|
||||||
template<typename T, size_t S = const_lit_for<K, T>::Count>
|
template<typename T, size_t S = const_lit_for<K, T>::Count>
|
||||||
my_type& operator=(T&& other) {
|
my_type& operator=(T&& other) {
|
||||||
return assign(other, S - 1);
|
return assign((const K*)other, S - 1);
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Оператор присваивания строкового выражения.
|
* @ru @brief Оператор присваивания строкового выражения.
|
||||||
|
|
@ -3636,7 +3534,7 @@ public:
|
||||||
sstring(T&& s, Args&&... args) : base_storable(std::forward<Args>(args)...) {
|
sstring(T&& s, Args&&... args) : base_storable(std::forward<Args>(args)...) {
|
||||||
type_ = Constant;
|
type_ = Constant;
|
||||||
localRemain_ = 0;
|
localRemain_ = 0;
|
||||||
cstr_ = s;
|
cstr_ = (const K*)s;
|
||||||
bigLen_ = N - 1;
|
bigLen_ = N - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3696,7 +3594,7 @@ public:
|
||||||
*/
|
*/
|
||||||
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
||||||
constexpr my_type& operator=(T&& other) {
|
constexpr my_type& operator=(T&& other) {
|
||||||
return operator=(my_type{other, base_storable::allocator()});
|
return operator=(my_type{std::forward<T>(other), base_storable::allocator()});
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Оператор присвоения другой строки типа lstring.
|
* @ru @brief Оператор присвоения другой строки типа lstring.
|
||||||
|
|
@ -3790,7 +3688,7 @@ public:
|
||||||
* @return my_type.
|
* @return my_type.
|
||||||
*/
|
*/
|
||||||
template<typename... T>
|
template<typename... T>
|
||||||
static my_type format(const FmtString<typename to_std_char_type<K>::type, T...>& fmtString, T&&... args) {
|
static my_type format(const FmtString<to_std_char_t<K>, T...>& fmtString, T&&... args) {
|
||||||
return my_type{lstring<K, 256, true, Allocator>{}.format(fmtString, std::forward<T>(args)...)};
|
return my_type{lstring<K, 256, true, Allocator>{}.format(fmtString, std::forward<T>(args)...)};
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -3964,7 +3862,7 @@ public:
|
||||||
* @details In this case, we simply remember the pointer to the string and its length.
|
* @details In this case, we simply remember the pointer to the string and its length.
|
||||||
*/
|
*/
|
||||||
template<typename T, size_t M = const_lit_for<K, T>::Count>
|
template<typename T, size_t M = const_lit_for<K, T>::Count>
|
||||||
constexpr cestring(T&& s) : base_storable(), cstr_(s), size_(M - 1), is_cstr_(true), local_{0} {}
|
constexpr cestring(T&& s) : base_storable(), cstr_((const K*)s), size_(M - 1), is_cstr_(true), local_{0} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename K>
|
template<typename K>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.6.5
|
* ver. 1.6.6
|
||||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||||
* База для строковых конкатенаций через выражения времени компиляции
|
* База для строковых конкатенаций через выражения времени компиляции
|
||||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||||
|
|
@ -116,6 +116,43 @@ auto to_one_of_std_char(const From* from) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename K>
|
||||||
|
struct to_std_char_type : std::type_identity<K>{};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct to_std_char_type<char8_t>{
|
||||||
|
using type = char;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct to_std_char_type<char16_t>{
|
||||||
|
using type = std::conditional_t<sizeof(char16_t) == sizeof(wchar_t), wchar_t, void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct to_std_char_type<char32_t>{
|
||||||
|
using type = std::conditional_t<sizeof(char32_t) == sizeof(wchar_t), wchar_t, void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename K>
|
||||||
|
using to_std_char_t = typename to_std_char_type<K>::type;
|
||||||
|
|
||||||
|
template<typename K>
|
||||||
|
struct to_base_char_type : std::type_identity<K>{};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct to_base_char_type<char8_t>{
|
||||||
|
using type = char;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct to_base_char_type<wchar_t>{
|
||||||
|
using type = std::conditional_t<sizeof(char16_t) == sizeof(wchar_t), char16_t, char32_t>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename K>
|
||||||
|
using to_base_char_t = typename to_base_char_type<K>::type;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @ingroup StrExprs
|
* @ingroup StrExprs
|
||||||
* @ru @brief Проверка, являются ли два типа совместимыми строковыми типами.
|
* @ru @brief Проверка, являются ли два типа совместимыми строковыми типами.
|
||||||
|
|
@ -226,7 +263,7 @@ public:
|
||||||
|
|
||||||
template<typename T, size_t M = const_lit_for<K, T>::Count> requires (M == N + 1)
|
template<typename T, size_t M = const_lit_for<K, T>::Count> requires (M == N + 1)
|
||||||
constexpr const_lit_to_array(T&& s)
|
constexpr const_lit_to_array(T&& s)
|
||||||
: symbols_(s) {}
|
: symbols_((const K(&)[M])s) {}
|
||||||
|
|
||||||
constexpr bool contain(K s) const {
|
constexpr bool contain(K s) const {
|
||||||
return exist<0>(s);
|
return exist<0>(s);
|
||||||
|
|
@ -3569,7 +3606,7 @@ public:
|
||||||
*/
|
*/
|
||||||
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
||||||
constexpr bool operator==(T&& other) const noexcept {
|
constexpr bool operator==(T&& other) const noexcept {
|
||||||
return N - 1 == _len() && traits::compare(_str(), other, N - 1) == 0;
|
return N - 1 == _len() && traits::compare(_str(), (const K*)other, N - 1) == 0;
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Оператор сравнения строки и строкового литерала.
|
* @ru @brief Оператор сравнения строки и строкового литерала.
|
||||||
|
|
@ -3580,7 +3617,7 @@ public:
|
||||||
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
||||||
constexpr auto operator<=>(T&& other) const noexcept {
|
constexpr auto operator<=>(T&& other) const noexcept {
|
||||||
size_t myLen = _len();
|
size_t myLen = _len();
|
||||||
int cmp = traits::compare(_str(), other, std::min(myLen, N - 1));
|
int cmp = traits::compare(_str(), (const K*)other, std::min(myLen, N - 1));
|
||||||
int res = cmp == 0 ? (myLen > N - 1 ? 1 : myLen == N - 1 ? 0 : -1) : cmp;
|
int res = cmp == 0 ? (myLen > N - 1 ? 1 : myLen == N - 1 ? 0 : -1) : cmp;
|
||||||
return res <=> 0;
|
return res <=> 0;
|
||||||
}
|
}
|
||||||
|
|
@ -4799,7 +4836,7 @@ struct str_src : str_src_algs<K, str_src<K>, str_src<K>, false> {
|
||||||
* @en @brief Constructor from a string literal.
|
* @en @brief Constructor from a string literal.
|
||||||
*/
|
*/
|
||||||
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
template<typename T, size_t N = const_lit_for<K, T>::Count>
|
||||||
constexpr str_src(T&& v) noexcept : str(v), len(N - 1) {}
|
constexpr str_src(T&& v) noexcept : str((const K*)v), len(N - 1) {}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Конструктор из указателя и длины.
|
* @ru @brief Конструктор из указателя и длины.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
||||||
|
|
||||||
Version 1.6.5.
|
Version 1.6.6.
|
||||||
|
|
||||||
<h2>Speed up your work with strings by 2-10 times!</h2>
|
<h2>Speed up your work with strings by 2-10 times!</h2>
|
||||||
|
|
||||||
|
|
@ -32,7 +32,8 @@ The library contains two parts:
|
||||||
```cpp
|
```cpp
|
||||||
#include "path/to file/strexpr.h"
|
#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
|
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.
|
`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.
|
Since this is a header-only part, it does not include working with UTF encodings and simplified Unicode.
|
||||||
- The full version, requiring the connection of the entire library (`"include/simstr/sstring.h"`), adds its string types with
|
- The full version, requiring the connection of the entire library (`"include/simstr/sstring.h"`), adds its string types with
|
||||||
|
|
@ -322,8 +323,8 @@ function(add_simstr)
|
||||||
simstr
|
simstr
|
||||||
GIT_REPOSITORY https://github.com/orefkov/simstr.git
|
GIT_REPOSITORY https://github.com/orefkov/simstr.git
|
||||||
GIT_SHALLOW TRUE
|
GIT_SHALLOW TRUE
|
||||||
GIT_TAG tags/rel1.6.5 # Specify the desired release
|
GIT_TAG tags/rel1.6.6 # Specify the desired release
|
||||||
FIND_PACKAGE_ARGS NAMES simstr 1.6.5
|
FIND_PACKAGE_ARGS NAMES simstr 1.6.6
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(simstr)
|
FetchContent_MakeAvailable(simstr)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
||||||
|
|
||||||
Версия 1.6.5.
|
Версия 1.6.6.
|
||||||
|
|
||||||
<h2>Ускорь работу со строками в 2-10 раз!</h2>
|
<h2>Ускорь работу со строками в 2-10 раз!</h2>
|
||||||
|
|
||||||
|
|
@ -323,8 +323,8 @@ function(add_simstr)
|
||||||
simstr
|
simstr
|
||||||
GIT_REPOSITORY https://github.com/orefkov/simstr.git
|
GIT_REPOSITORY https://github.com/orefkov/simstr.git
|
||||||
GIT_SHALLOW TRUE
|
GIT_SHALLOW TRUE
|
||||||
GIT_TAG tags/rel1.6.5 # Укажите нужный релиз
|
GIT_TAG tags/rel1.6.6 # Укажите нужный релиз
|
||||||
FIND_PACKAGE_ARGS NAMES simstr 1.6.5
|
FIND_PACKAGE_ARGS NAMES simstr 1.6.6
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(simstr)
|
FetchContent_MakeAvailable(simstr)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.6.5
|
* ver. 1.6.6
|
||||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||||
* Реализация строковых функций
|
* Реализация строковых функций
|
||||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.6.5
|
* ver. 1.6.6
|
||||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||||
* Тесты simstr
|
* Тесты simstr
|
||||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.6.5
|
* ver. 1.6.6
|
||||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||||
* Тесты simstr
|
* Тесты simstr
|
||||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||||
|
|
@ -958,13 +958,23 @@ TEST(SimStr, LStringAssign) {
|
||||||
|
|
||||||
TEST(SimStr, UtfConvert) {
|
TEST(SimStr, UtfConvert) {
|
||||||
EXPECT_EQ(stringa{ssu{u"testпройден"}}, "testпройден");
|
EXPECT_EQ(stringa{ssu{u"testпройден"}}, "testпройден");
|
||||||
|
EXPECT_EQ(stringa{ssb{u8"testпройден"}}, "testпройден");
|
||||||
EXPECT_EQ(stringa{ssw{L"testпройден"}}, "testпройден");
|
EXPECT_EQ(stringa{ssw{L"testпройден"}}, "testпройден");
|
||||||
EXPECT_EQ(stringa{stringu{u"testпройден"}}, "testпройден");
|
EXPECT_EQ(stringa{stringu{u"testпройден"}}, "testпройден");
|
||||||
EXPECT_EQ(stringa{stringw{L"testпройден"}}, "testпройден");
|
EXPECT_EQ(stringa{stringw{L"testпройден"}}, "testпройден");
|
||||||
EXPECT_EQ(stringa{lstringu<40>{u"testпройден"}}, "testпройден");
|
EXPECT_EQ(stringa{lstringu<40>{u"testпройден"}}, "testпройден");
|
||||||
EXPECT_EQ(stringa{lstringw<40>{L"testпройден"}}, "testпройден");
|
EXPECT_EQ(stringa{lstringw<40>{L"testпройден"}}, "testпройден");
|
||||||
|
|
||||||
|
EXPECT_EQ(stringb{ssu{u"testпройден"}}, u8"testпройден");
|
||||||
|
EXPECT_EQ(stringb{ssa{u8"testпройден"}}, u8"testпройден");
|
||||||
|
EXPECT_EQ(stringb{ssw{L"testпройден"}}, u8"testпройден");
|
||||||
|
EXPECT_EQ(stringb{stringu{u"testпройден"}}, u8"testпройден");
|
||||||
|
EXPECT_EQ(stringb{stringw{L"testпройден"}}, u8"testпройден");
|
||||||
|
EXPECT_EQ(stringb{lstringu<40>{u"testпройден"}}, u8"testпройден");
|
||||||
|
EXPECT_EQ(stringb{lstringw<40>{L"testпройден"}}, u8"testпройден");
|
||||||
|
|
||||||
EXPECT_EQ(stringu{ssa{"testпройден"}}, u"testпройден");
|
EXPECT_EQ(stringu{ssa{"testпройден"}}, u"testпройден");
|
||||||
|
EXPECT_EQ(stringu{ssb{u8"testпройден"}}, u"testпройден");
|
||||||
EXPECT_EQ(stringu{ssw{L"testпройден"}}, u"testпройден");
|
EXPECT_EQ(stringu{ssw{L"testпройден"}}, u"testпройден");
|
||||||
EXPECT_EQ(stringu{stringa{"testпройден"}}, u"testпройден");
|
EXPECT_EQ(stringu{stringa{"testпройден"}}, u"testпройден");
|
||||||
EXPECT_EQ(stringu{stringw{L"testпройден"}}, u"testпройден");
|
EXPECT_EQ(stringu{stringw{L"testпройден"}}, u"testпройден");
|
||||||
|
|
@ -1384,7 +1394,7 @@ TEST(SimStr, LStrJoinAndExpressions) {
|
||||||
|
|
||||||
int k = 10;
|
int k = 10;
|
||||||
double d = 12.1;
|
double d = 12.1;
|
||||||
lstringa<10> test = ">" + e_repl(buffer.to_str(), "<>", "-") + k + ", " + d;
|
lstringa<10> test = ">" + e_repl(buffer, "<>", "-") + k + ", " + d;
|
||||||
EXPECT_EQ(test, ">asd-fgh-jkl10, 12.1");
|
EXPECT_EQ(test, ">asd-fgh-jkl10, 12.1");
|
||||||
|
|
||||||
buffer.prepend(e_choice(test.length() > 2, eea + 99, eea + 12.1 + "asd"));
|
buffer.prepend(e_choice(test.length() > 2, eea + 99, eea + 12.1 + "asd"));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.6.5
|
* ver. 1.6.6
|
||||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||||
* Тесты simstr
|
* Тесты simstr
|
||||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue