mirror of https://github.com/orefkov/simstr.git
Compare commits
4 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
e9eaa6c4cb | |
|
|
00a4a008a9 | |
|
|
86deccbac3 | |
|
|
a779aa7320 |
|
|
@ -5,7 +5,7 @@ include(FetchContent)
|
||||||
|
|
||||||
project(
|
project(
|
||||||
simstr
|
simstr
|
||||||
VERSION 1.8.1
|
VERSION 1.9.1
|
||||||
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.8.1
|
* ver. 1.9.1
|
||||||
* (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
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ struct result_info {
|
||||||
}
|
}
|
||||||
// Текущее положение поставим сразу за cpuinfo и откинем завершающие переводы строк
|
// Текущее положение поставим сразу за cpuinfo и откинем завершающие переводы строк
|
||||||
// We will put the current position immediately after cpuinfo and discard the final line feeds
|
// We will put the current position immediately after cpuinfo and discard the final line feeds
|
||||||
current_text_ = current_text_(cpu_info_.end() - current_text_.begin() + 1).trimmed_right("\n");
|
current_text_ = current_text_.get(cpu_info_.end() - current_text_.begin() + 1, to_end).trimmed_right("\n");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -96,11 +96,11 @@ results_vector get_results_infos() {
|
||||||
// В начале имени файла может идти число и дефис, для сортировки, уберём их
|
// В начале имени файла может идти число и дефис, для сортировки, уберём их
|
||||||
// At the beginning of the file name there can be a number and a hyphen, for sorting, remove them
|
// At the beginning of the file name there can be a number and a hyphen, for sorting, remove them
|
||||||
if (auto delimiter = fileName.find('-'); delimiter + 1 > 1) {
|
if (auto delimiter = fileName.find('-'); delimiter + 1 > 1) {
|
||||||
if (fileName(0, delimiter).to_int<unsigned, false, 10, false, false>().ec == IntConvertResult::Success) {
|
if (fileName.prefix(delimiter).to_int<unsigned, false, 10, false, false>().ec == IntConvertResult::Success) {
|
||||||
fileName.remove_prefix(delimiter + 1);
|
fileName.remove_prefix(delimiter + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
results.emplace_back(get_file_content(lstringa<128>{dirForResults + f}), fileName(0, -suffix.length()));
|
results.emplace_back(get_file_content(lstringa<128>{dirForResults + f}), fileName.get(0, from_end(suffix.length())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
|
|
@ -117,7 +117,7 @@ void write_platforms_cpu(out_t& out, const results_vector& results) {
|
||||||
for (const auto& r : results) {
|
for (const auto& r : results) {
|
||||||
size_t rp = r.cpu_info_.find('(') + 1, lp = r.cpu_info_.find(')', rp);
|
size_t rp = r.cpu_info_.find('(') + 1, lp = r.cpu_info_.find(')', rp);
|
||||||
ssa shortCpuInfo = r.cpu_info_.from_to(rp, lp);
|
ssa shortCpuInfo = r.cpu_info_.from_to(rp, lp);
|
||||||
ssa cpuInfo = r.cpu_info_(lp + 2);
|
ssa cpuInfo = r.cpu_info_.get(lp + 2, to_end);
|
||||||
out += e_subst(R"--(
|
out += e_subst(R"--(
|
||||||
<li><span class="platform">{}</span><span class="tooltip">{}<span class="tooltiptext">{}</span></span> Include in charts: <input type="checkbox" id="pl{}" checked onchange="buildCharts()"/></li>)--",
|
<li><span class="platform">{}</span><span class="tooltip">{}<span class="tooltiptext">{}</span></span> Include in charts: <input type="checkbox" id="pl{}" checked onchange="buildCharts()"/></li>)--",
|
||||||
r.platform_, shortCpuInfo, cpuInfo, counter++);
|
r.platform_, shortCpuInfo, cpuInfo, counter++);
|
||||||
|
|
@ -167,7 +167,7 @@ ssa extract_name_result(ssa line, ssa& result) {
|
||||||
line.len = ns;
|
line.len = ns;
|
||||||
if (inNs) {
|
if (inNs) {
|
||||||
size_t end = line.find_last(' ');
|
size_t end = line.find_last(' ');
|
||||||
result = line(end + 1);
|
result = line.get(end + 1, to_end);
|
||||||
if (auto rp = line.find("/repeats"); rp != str::npos) {
|
if (auto rp = line.find("/repeats"); rp != str::npos) {
|
||||||
line.len = rp;
|
line.len = rp;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -182,7 +182,7 @@ ssa extract_name_result(ssa line, ssa& result) {
|
||||||
ssa extract_comment(ssa commentsText, ssa benchmarkName) {
|
ssa extract_comment(ssa commentsText, ssa benchmarkName) {
|
||||||
size_t idx = commentsText.find_end(lstringa<120>{"- " + benchmarkName + "\n"});
|
size_t idx = commentsText.find_end(lstringa<120>{"- " + benchmarkName + "\n"});
|
||||||
if (idx != str::npos) {
|
if (idx != str::npos) {
|
||||||
if (commentsText[idx] != '\n' && commentsText(idx, 2) != "- ") {
|
if (commentsText[idx] != '\n' && commentsText.get(idx, 2) != "- ") {
|
||||||
return commentsText.from_to(idx, commentsText.find("\n\n", idx));
|
return commentsText.from_to(idx, commentsText.find("\n\n", idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -206,7 +206,7 @@ std::pair<ssa, size_t> extract_source_for_benchmark(ssa benchName, ssa sourceTex
|
||||||
}();
|
}();
|
||||||
|
|
||||||
size_t delim = benchName.find_last('/');
|
size_t delim = benchName.find_last('/');
|
||||||
if (delim != str::npos && benchName(delim + 1).to_int<unsigned, false, 10, false, false>().ec == IntConvertResult::Success) {
|
if (delim != str::npos && benchName.get(delim + 1, to_end).to_int<unsigned, false, 10, false, false>().ec == IntConvertResult::Success) {
|
||||||
benchName.len = delim;
|
benchName.len = delim;
|
||||||
}
|
}
|
||||||
auto [it, not_exist] = textes.try_emplace(benchName, stringa{}, 0);
|
auto [it, not_exist] = textes.try_emplace(benchName, stringa{}, 0);
|
||||||
|
|
@ -218,7 +218,7 @@ std::pair<ssa, size_t> extract_source_for_benchmark(ssa benchName, ssa sourceTex
|
||||||
std::cerr << "Can not found benchmark function name for " << benchName << std::endl;
|
std::cerr << "Can not found benchmark function name for " << benchName << std::endl;
|
||||||
return {stra::empty_str, 0};
|
return {stra::empty_str, 0};
|
||||||
}
|
}
|
||||||
start = sourceText(0, start).find('(', sourceText.find_last('\n', start - 1));
|
start = sourceText.prefix(start).find('(', sourceText.find_last('\n', start - 1));
|
||||||
if (start == str::npos) {
|
if (start == str::npos) {
|
||||||
std::cerr << "Can not found benchmark function name for " << benchName << std::endl;
|
std::cerr << "Can not found benchmark function name for " << benchName << std::endl;
|
||||||
return {stra::empty_str, 0};
|
return {stra::empty_str, 0};
|
||||||
|
|
@ -237,7 +237,7 @@ std::pair<ssa, size_t> extract_source_for_benchmark(ssa benchName, ssa sourceTex
|
||||||
}
|
}
|
||||||
start = sourceText.find_last('\n', start);
|
start = sourceText.find_last('\n', start);
|
||||||
size_t templ_start = sourceText.find_last('\n', start) + 1;
|
size_t templ_start = sourceText.find_last('\n', start) + 1;
|
||||||
if (sourceText(templ_start).starts_with("template")) {
|
if (sourceText.get(templ_start, to_end).starts_with("template")) {
|
||||||
start = templ_start;
|
start = templ_start;
|
||||||
} else {
|
} else {
|
||||||
start++;
|
start++;
|
||||||
|
|
@ -261,7 +261,7 @@ std::pair<ssa, size_t> extract_source_for_benchmark(ssa benchName, ssa sourceTex
|
||||||
throw std::runtime_error{"Not found end of func"};
|
throw std::runtime_error{"Not found end of func"};
|
||||||
}
|
}
|
||||||
lstringa<2048> text{sourceText.from_to(beginLine, end + indent.length() + 1), indent, "\n"};
|
lstringa<2048> text{sourceText.from_to(beginLine, end + indent.length() + 1), indent, "\n"};
|
||||||
func_it->second.first = repl_html_symbols(text(1));
|
func_it->second.first = repl_html_symbols(text.get(1, to_end));
|
||||||
} else {
|
} else {
|
||||||
end = sourceText.find("\n}\n", start);
|
end = sourceText.find("\n}\n", start);
|
||||||
func_it->second.first = repl_html_symbols(sourceText.from_to(start, end + 2));
|
func_it->second.first = repl_html_symbols(sourceText.from_to(start, end + 2));
|
||||||
|
|
@ -274,7 +274,7 @@ std::pair<ssa, size_t> extract_source_for_benchmark(ssa benchName, ssa sourceTex
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_benchmarks(out_t& out, const results_vector& results, ssa sourceText, ssa commentsText) {
|
void write_benchmarks(out_t& out, const results_vector& results, ssa sourceText, ssa commentsText) {
|
||||||
ssa releaseVersion = sourceText(sourceText.find_end("\n * ver. ")).until("\n").trimmed();
|
ssa releaseVersion = sourceText.get(sourceText.find_end("\n * ver. "), to_end).until("\n").trimmed();
|
||||||
if (!releaseVersion) {
|
if (!releaseVersion) {
|
||||||
std::cerr << "Not found release version in sources" << std::endl;
|
std::cerr << "Not found release version in sources" << std::endl;
|
||||||
throw std::runtime_error{"Not found release version in sources"};
|
throw std::runtime_error{"Not found release version in sources"};
|
||||||
|
|
@ -292,7 +292,7 @@ void write_benchmarks(out_t& out, const results_vector& results, ssa sourceText,
|
||||||
while(!splitters[0].is_done()) {
|
while(!splitters[0].is_done()) {
|
||||||
ssa line = splitters[0].next(), benchName, result;
|
ssa line = splitters[0].next(), benchName, result;
|
||||||
if (auto rm = line.find("_mean"); rm != str::npos) {
|
if (auto rm = line.find("_mean"); rm != str::npos) {
|
||||||
benchName = extract_name_result(line, result)(0, rm);
|
benchName = extract_name_result(line, result).prefix(rm);
|
||||||
auto [source, line_num] = extract_source_for_benchmark(benchName, sourceText);
|
auto [source, line_num] = extract_source_for_benchmark(benchName, sourceText);
|
||||||
auto comment = extract_comment(commentsText, benchName);
|
auto comment = extract_comment(commentsText, benchName);
|
||||||
// Нужно вывести название бенча и коммент
|
// Нужно вывести название бенча и коммент
|
||||||
|
|
@ -312,12 +312,12 @@ void write_benchmarks(out_t& out, const results_vector& results, ssa sourceText,
|
||||||
throw std::runtime_error{"Not expected end of file"};
|
throw std::runtime_error{"Not expected end of file"};
|
||||||
}
|
}
|
||||||
line = splitters[idx].next();
|
line = splitters[idx].next();
|
||||||
ssa rbench_name = extract_name_result(line, result)(0, rm);
|
ssa rbench_name = extract_name_result(line, result).prefix(rm);
|
||||||
if (rbench_name != benchName) {
|
if (rbench_name != benchName) {
|
||||||
while (line.find("_mean") == str::npos && !splitters[idx].is_done()) {
|
while (line.find("_mean") == str::npos && !splitters[idx].is_done()) {
|
||||||
line = splitters[idx].next();
|
line = splitters[idx].next();
|
||||||
}
|
}
|
||||||
rbench_name = extract_name_result(line, result)(0, rm);
|
rbench_name = extract_name_result(line, result).prefix(rm);
|
||||||
if (rbench_name != benchName) {
|
if (rbench_name != benchName) {
|
||||||
std::cerr << "In results for " << results[idx].platform_ << " benchmark '" << rbench_name
|
std::cerr << "In results for " << results[idx].platform_ << " benchmark '" << rbench_name
|
||||||
<< "' does not match with other results" << std::endl;
|
<< "' does not match with other results" << std::endl;
|
||||||
|
|
|
||||||
|
|
@ -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.8.1
|
PROJECT_NUMBER = 1.9.1
|
||||||
|
|
||||||
# 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
|
||||||
|
|
@ -2928,7 +2928,7 @@ MAX_DOT_GRAPH_DEPTH = 0
|
||||||
|
|
||||||
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
|
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
|
||||||
# files in one run (i.e. multiple -o and -T options on the command line). This
|
# files in one run (i.e. multiple -o and -T options on the command line). This
|
||||||
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
|
# makes dot run faster, but since only newer versions of dot (>1.8.20) support
|
||||||
# this, this feature is disabled by default.
|
# this, this feature is disabled by default.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
|
||||||
|
|
@ -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.8.1
|
PROJECT_NUMBER = 1.9.1
|
||||||
|
|
||||||
# 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
|
||||||
|
|
@ -2928,7 +2928,7 @@ MAX_DOT_GRAPH_DEPTH = 0
|
||||||
|
|
||||||
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
|
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
|
||||||
# files in one run (i.e. multiple -o and -T options on the command line). This
|
# files in one run (i.e. multiple -o and -T options on the command line). This
|
||||||
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
|
# makes dot run faster, but since only newer versions of dot (>1.8.20) support
|
||||||
# this, this feature is disabled by default.
|
# this, this feature is disabled by default.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||||
* ver. 1.8.1
|
* ver. 1.9.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.8.1
|
* ver. 1.9.1
|
||||||
* (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
|
||||||
|
|
@ -3257,7 +3257,7 @@ public:
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Определить длину строки.
|
* @ru @brief Определить длину строки.
|
||||||
* Ищет символ 0 в буфере строки до его ёмкости, после чего устаналивает длину строки по найденному 0.
|
* Ищет символ 0 в буфере строки до его ёмкости, после чего устанавливает длину строки по найденному 0.
|
||||||
* @en @brief Determine the length of the string.
|
* @en @brief Determine the length of the string.
|
||||||
* Searches for the character 0 in the string buffer to its capacity, and then sets the length of the string to the found 0.
|
* Searches for the character 0 in the string buffer to its capacity, and then sets the length of the string to the found 0.
|
||||||
*/
|
*/
|
||||||
|
|
@ -3283,7 +3283,7 @@ public:
|
||||||
if (is_alloced() && capacity_ > need_capacity) {
|
if (is_alloced() && capacity_ > need_capacity) {
|
||||||
K* newData = size_ <= LocalCapacity ? local_ : alloc_place(need_capacity);
|
K* newData = size_ <= LocalCapacity ? local_ : alloc_place(need_capacity);
|
||||||
traits::copy(newData, data_, size_ + 1);
|
traits::copy(newData, data_, size_ + 1);
|
||||||
base_storable::allocator().deallocate(to_real_address(data_));
|
dealloc();
|
||||||
data_ = newData;
|
data_ = newData;
|
||||||
|
|
||||||
if (size_ > LocalCapacity) {
|
if (size_ > LocalCapacity) {
|
||||||
|
|
@ -4365,8 +4365,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
auto erase(const InStore& key) {
|
auto erase(const InStore& key) {
|
||||||
auto it = hash_t::find(key);
|
if (auto it = hash_t::find(key); it != hash_t::end()) {
|
||||||
if (it != hash_t::end()) {
|
|
||||||
((sstring<K>*)it->first.node)->~sstring();
|
((sstring<K>*)it->first.node)->~sstring();
|
||||||
hash_t::erase(it);
|
hash_t::erase(it);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -4378,15 +4377,151 @@ public:
|
||||||
return erase(toStoreType(key));
|
return erase(toStoreType(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lookup(simple_str<K> txt, T& val) const {
|
/*!
|
||||||
auto it = find(txt);
|
* @ru @brief Поиск и извлечение значения.
|
||||||
if (it != hash_t::end()) {
|
* @param key - искомый ключ.
|
||||||
|
* @param val - ссылка на приёмник значения.
|
||||||
|
* @details Если ключ существует, присваивает переданной ссылке хранимое значение и возвращает true.
|
||||||
|
* Иначе возвращает false.
|
||||||
|
* @en @brief Finding and retrieving the value.
|
||||||
|
* @param key - the key you are looking for.
|
||||||
|
* @param val - reference to the value receiver.
|
||||||
|
* @details If the key exists, assigns the stored value to the passed reference and returns true.
|
||||||
|
* Otherwise returns false.
|
||||||
|
*/
|
||||||
|
template<typename Dst> requires std::is_assignable_v<T, Dst>
|
||||||
|
bool lookup(simple_str<K> key, Dst& val) const {
|
||||||
|
if (auto it = find(key); it != hash_t::end()) {
|
||||||
val = it->second;
|
val = it->second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @ru @brief Поиск и извлечение значения.
|
||||||
|
* @param key - искомый ключ.
|
||||||
|
* @details Если ключ существует, присваивает переданной ссылке хранимое значение и возвращает true.
|
||||||
|
* Иначе возвращает false.
|
||||||
|
* @en @brief Finding and retrieving the value.
|
||||||
|
* @param key - the key you are looking for.
|
||||||
|
* @param val - reference to the value receiver.
|
||||||
|
* @details If the key exists, assigns the stored value to the passed reference and returns true.
|
||||||
|
* Otherwise returns false.
|
||||||
|
*/
|
||||||
|
template<typename Dst> requires std::is_assignable_v<T, Dst>
|
||||||
|
bool lookup(const InStore& key, Dst& val) const {
|
||||||
|
if (auto it = find(key); it != hash_t::end()) {
|
||||||
|
val = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @ru @brief Поиск и извлечение значения.
|
||||||
|
* @param key - искомый ключ.
|
||||||
|
* @details Если ключ существует, возвращает std::optional указанного типа с копией значения.
|
||||||
|
* Иначе возвращает std::nullopt.
|
||||||
|
* @en @brief Finding and retrieving the value.
|
||||||
|
* @param key - the key you are looking for.
|
||||||
|
* @details If the key exists, return a std::optional of the specified type with a copy of the value.
|
||||||
|
* Otherwise returns std::nullopt.
|
||||||
|
*/
|
||||||
|
template<typename Dst = T> requires std::is_constructible_v<Dst, T>
|
||||||
|
std::optional<Dst> get(simple_str<K> key) const {
|
||||||
|
if (auto it = find(key); it != hash_t::end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @ru @brief Поиск и извлечение значения.
|
||||||
|
* @param key - искомый ключ.
|
||||||
|
* @details Если ключ существует, возвращает std::optional указанного типа с копией значения.
|
||||||
|
* Иначе возвращает std::nullopt.
|
||||||
|
* @en @brief Finding and retrieving the value.
|
||||||
|
* @param s - the key you are looking for.
|
||||||
|
* @details If the key exists, return a std::optional of the specified type with a copy of the value.
|
||||||
|
* Otherwise returns std::nullopt.
|
||||||
|
*/
|
||||||
|
template<typename Dst = T> requires std::is_constructible_v<Dst, T>
|
||||||
|
std::optional<Dst> get(const InStore& key) const {
|
||||||
|
if (auto it = find(key); it != hash_t::end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @ru @brief Поиск существующего значения.
|
||||||
|
* @param key - искомый ключ.
|
||||||
|
* @details Если ключ существует, возвращает указатель на хранимое значение.
|
||||||
|
* Иначе возвращает nullptr.
|
||||||
|
* @en @brief Finding an existing value.
|
||||||
|
* @param s - the key you are looking for.
|
||||||
|
* @details If the key exists, returns a pointer to the stored value.
|
||||||
|
* Otherwise returns nullptr.
|
||||||
|
*/
|
||||||
|
T* existed(simple_str<K> key) {
|
||||||
|
if (auto it = find(key); it != hash_t::end()) {
|
||||||
|
return std::addressof(it->second);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @ru @brief Поиск существующего значения.
|
||||||
|
* @param key - искомый ключ.
|
||||||
|
* @details Если ключ существует, возвращает указатель на хранимое значение.
|
||||||
|
* Иначе возвращает nullptr.
|
||||||
|
* @en @brief Finding an existing value.
|
||||||
|
* @param s - the key you are looking for.
|
||||||
|
* @details If the key exists, returns a pointer to the stored value.
|
||||||
|
* Otherwise returns nullptr.
|
||||||
|
*/
|
||||||
|
T* existed(const InStore& key) {
|
||||||
|
if (auto it = find(key); it != hash_t::end()) {
|
||||||
|
return std::addressof(it->second);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @ru @brief Поиск существующего значения.
|
||||||
|
* @param key - искомый ключ.
|
||||||
|
* @details Если ключ существует, возвращает константный указатель на хранимое значение.
|
||||||
|
* Иначе возвращает nullptr.
|
||||||
|
* @en @brief Finding an existing value.
|
||||||
|
* @param s - the key you are looking for.
|
||||||
|
* @details If the key exists, returns a constant pointer to the stored value.
|
||||||
|
* Otherwise returns nullptr.
|
||||||
|
*/
|
||||||
|
const T* existed(simple_str<K> key) const {
|
||||||
|
if (auto it = find(key); it != hash_t::end()) {
|
||||||
|
return std::addressof(it->second);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @ru @brief Поиск существующего значения.
|
||||||
|
* @param key - искомый ключ.
|
||||||
|
* @details Если ключ существует, возвращает константный указатель на хранимое значение.
|
||||||
|
* Иначе возвращает nullptr.
|
||||||
|
* @en @brief Finding an existing value.
|
||||||
|
* @param s - the key you are looking for.
|
||||||
|
* @details If the key exists, returns a constant pointer to the stored value.
|
||||||
|
* Otherwise returns nullptr.
|
||||||
|
*/
|
||||||
|
const T* existed(const InStore& key) const {
|
||||||
|
if (auto it = find(key); it != hash_t::end()) {
|
||||||
|
return std::addressof(it->second);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
for (auto& k: *this)
|
for (auto& k: *this)
|
||||||
((sstring<K>*)k.first.node)->~sstring();
|
((sstring<K>*)k.first.node)->~sstring();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.8.1
|
* ver. 1.9.1
|
||||||
* (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
|
||||||
|
|
@ -3274,6 +3274,20 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct from_begin {
|
||||||
|
size_t idx_;
|
||||||
|
};
|
||||||
|
struct from_end {
|
||||||
|
size_t idx_;
|
||||||
|
};
|
||||||
|
inline constexpr from_end to_end{0};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept first_index_in_str = std::is_same_v<T, from_end> || std::is_convertible_v<T, size_t>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept last_index_in_str = first_index_in_str<T> || std::is_same_v<T, from_begin>;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Класс с базовыми константными строковыми алгоритмами.
|
* @ru @brief Класс с базовыми константными строковыми алгоритмами.
|
||||||
* @details Является базой для классов, могущих выполнять константные операции со строками.
|
* @details Является базой для классов, могущих выполнять константные операции со строками.
|
||||||
|
|
@ -3445,6 +3459,7 @@ public:
|
||||||
* "0123456789"_ss(-4, -1) == "678";
|
* "0123456789"_ss(-4, -1) == "678";
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
[[deprecated("Use 'get' or [start, end] in C++23")]]
|
||||||
constexpr str_piece operator()(ptrdiff_t from, ptrdiff_t len = 0) const noexcept {
|
constexpr str_piece operator()(ptrdiff_t from, ptrdiff_t len = 0) const noexcept {
|
||||||
size_t myLen = _len(), idxStart = from >= 0 ? from : (ptrdiff_t)myLen > -from ? myLen + from : 0,
|
size_t myLen = _len(), idxStart = from >= 0 ? from : (ptrdiff_t)myLen > -from ? myLen + from : 0,
|
||||||
idxEnd = len > 0 ? idxStart + len : (ptrdiff_t)myLen > -len ? myLen + len : 0;
|
idxEnd = len > 0 ? idxStart + len : (ptrdiff_t)myLen > -len ? myLen + len : 0;
|
||||||
|
|
@ -3454,6 +3469,83 @@ public:
|
||||||
idxStart = idxEnd;
|
idxStart = idxEnd;
|
||||||
return str_piece{_str() + idxStart, idxEnd - idxStart};
|
return str_piece{_str() + idxStart, idxEnd - idxStart};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @ru @brief Получить часть строки как "str_src".
|
||||||
|
* @param start - начальная позиция в строке.
|
||||||
|
* @param end - конечная позиция в строке.
|
||||||
|
* @return Подстроку, str_src.
|
||||||
|
* @details В качестве начальной позиции может задаваться или число - отсчитывается от начала строки, но не далее её конца,
|
||||||
|
* или `from_end(число)` - отсчитывается от конца строки, но не ранее её начала.
|
||||||
|
* В качестве конечной позиции может задаваться или число - отсчитывается от начальной позиции, но не далее конца строки,
|
||||||
|
* или `from_end(число)` - отсчитывается от конца строки, но не ранее начальной позиции,
|
||||||
|
* или `from_begin(число)` - отсчитывается от начала строки, но не ранее начальной позиции и не далее конца строки.
|
||||||
|
* Также можно использовать `to_end` - эквивалентно from_end(0).
|
||||||
|
* @en @brief Get part of a string as "str_src".
|
||||||
|
* @param start - starting position in the string.
|
||||||
|
* @param end - the end position in the string.
|
||||||
|
* @return Substring, str_src.
|
||||||
|
* @details Either a number can be specified as the starting position - it is counted from the beginning of the string, but not further than its end,
|
||||||
|
* or `from_end(number)` - counted from the end of the string, but not earlier than its beginning.
|
||||||
|
* The ending position can be either a number - counted from the starting position, but not further than the end of the string,
|
||||||
|
* or `from_end(number)` - counted from the end of the string, but not earlier than the starting position,
|
||||||
|
* or `from_begin(number)` - counted from the beginning of the string, but not earlier than the starting position and not further than the end of the string.
|
||||||
|
* You can also use `to_end` - equivalent to from_end(0).
|
||||||
|
* @~
|
||||||
|
* ```cpp
|
||||||
|
* "0123456789"_ss.get(5, 2) == "56";
|
||||||
|
* "0123456789"_ss.get(5, to_end) == "56789";
|
||||||
|
* "0123456789"_ss.get(5, from_end(1)) == "5678";
|
||||||
|
* "0123456789"_ss.get(from_end(3), to_end) == "789";
|
||||||
|
* "0123456789"_ss.get(from_end(3), 2) == "78";
|
||||||
|
* "0123456789"_ss.get(from_end(4), from_end(1)) == "678";
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
template<first_index_in_str S, last_index_in_str E>
|
||||||
|
constexpr str_piece get(S start, E end) const noexcept {
|
||||||
|
size_t idxStart, idxEnd, len = _len();
|
||||||
|
if constexpr (std::is_same_v<S, from_end>) {
|
||||||
|
idxStart = start.idx_ > len ? 0 : len - start.idx_;
|
||||||
|
} else {
|
||||||
|
idxStart = std::min(size_t(start), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<E, from_begin>) {
|
||||||
|
idxEnd = std::max(idxStart, std::min(end.idx_, len));
|
||||||
|
} else if constexpr (std::is_same_v<E, from_end>) {
|
||||||
|
idxEnd = std::max(idxStart, end.idx_ > len ? 0 : len - end.idx_);
|
||||||
|
} else {
|
||||||
|
size_t e = end;
|
||||||
|
idxEnd = len - idxStart < e ? len : idxStart + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_piece{_str() + idxStart, idxEnd - idxStart};
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cpp_multidimensional_subscript) && __cpp_multidimensional_subscript >= 202211L
|
||||||
|
/*!
|
||||||
|
* @ru @brief Обертка вокруг `get` в виде многомерного оператора [].
|
||||||
|
* @en @brief Wraps `get` as a multidimensional operator [].
|
||||||
|
*/
|
||||||
|
template<first_index_in_str S, last_index_in_str E>
|
||||||
|
constexpr str_piece operator[](S start, E end) const noexcept {
|
||||||
|
return get(start, end);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*!
|
||||||
|
* @ru @brief Обертка вокруг `get(0, count)`.
|
||||||
|
* @en @brief Wraps `get(0, count)`.
|
||||||
|
*/
|
||||||
|
constexpr str_piece prefix(size_t count) const noexcept {
|
||||||
|
return get(0, count);
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
* @ru @brief Обертка вокруг `get(from_end(count), to_end)`.
|
||||||
|
* @en @brief Wraps `get(from_end(count), to_end)`.
|
||||||
|
*/
|
||||||
|
constexpr str_piece suffix(size_t count) const noexcept {
|
||||||
|
return get(from_end(count), to_end);
|
||||||
|
}
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Получить часть строки как "кусок строки".
|
* @ru @brief Получить часть строки как "кусок строки".
|
||||||
* @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку.
|
* @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку.
|
||||||
|
|
@ -3500,7 +3592,7 @@ public:
|
||||||
* @return Substring, str_src.
|
* @return Substring, str_src.
|
||||||
*/
|
*/
|
||||||
constexpr str_piece until(str_piece pattern, size_t offset = 0) const noexcept {
|
constexpr str_piece until(str_piece pattern, size_t offset = 0) const noexcept {
|
||||||
return (*this)(0, find_or_all(pattern, offset));
|
return get(0, find_or_all(pattern, offset));
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Проверка на пустоту.
|
* @ru @brief Проверка на пустоту.
|
||||||
|
|
@ -3726,7 +3818,7 @@ public:
|
||||||
* @return size_t - the position of the beginning of the substring occurrence, or throws an Exc exception if not found.
|
* @return size_t - the position of the beginning of the substring occurrence, or throws an Exc exception if not found.
|
||||||
*/
|
*/
|
||||||
template<typename Exc, typename ... Args> requires std::is_constructible_v<Exc, Args...>
|
template<typename Exc, typename ... Args> requires std::is_constructible_v<Exc, Args...>
|
||||||
constexpr size_t find_or_throw(str_piece pattern, size_t offset = 0, Args&& ... args) const noexcept {
|
constexpr size_t find_or_throw(str_piece pattern, size_t offset = 0, Args&& ... args) const {
|
||||||
if (auto fnd = find(pattern.symbols(), pattern.length(), offset); fnd != str::npos) {
|
if (auto fnd = find(pattern.symbols(), pattern.length(), offset); fnd != str::npos) {
|
||||||
return fnd;
|
return fnd;
|
||||||
}
|
}
|
||||||
|
|
@ -4071,9 +4163,14 @@ public:
|
||||||
* @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 string.
|
* @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 string.
|
||||||
* @return my_type - a substring, an object of the same type to which the method is applied.
|
* @return my_type - a substring, an object of the same type to which the method is applied.
|
||||||
*/
|
*/
|
||||||
|
[[deprecated("Use sub(start, end)")]]
|
||||||
constexpr my_type substr(ptrdiff_t from, ptrdiff_t len = 0) const { // индексация в code units | indexing in code units
|
constexpr my_type substr(ptrdiff_t from, ptrdiff_t len = 0) const { // индексация в code units | indexing in code units
|
||||||
return my_type{d()(from, len)};
|
return my_type{d()(from, len)};
|
||||||
}
|
}
|
||||||
|
template<first_index_in_str S, last_index_in_str E>
|
||||||
|
constexpr my_type sub(S start, E end) const noexcept {
|
||||||
|
return my_type{get(start, end)};
|
||||||
|
}
|
||||||
/*!
|
/*!
|
||||||
* @ru @brief Получить часть строки объектом того же типа, к которому применён метод, аналогично mid.
|
* @ru @brief Получить часть строки объектом того же типа, к которому применён метод, аналогично mid.
|
||||||
* @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку.
|
* @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку.
|
||||||
|
|
@ -4597,7 +4694,7 @@ public:
|
||||||
template<typename R = str_piece>
|
template<typename R = str_piece>
|
||||||
constexpr std::optional<R> strip_prefix(str_piece prefix) const {
|
constexpr std::optional<R> strip_prefix(str_piece prefix) const {
|
||||||
if (starts_with(prefix)) {
|
if (starts_with(prefix)) {
|
||||||
return R{operator()(prefix.length())};
|
return R{get(prefix.length(), to_end)};
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -4616,7 +4713,7 @@ public:
|
||||||
template<typename R = str_piece>
|
template<typename R = str_piece>
|
||||||
constexpr std::optional<R> strip_prefix_ia(str_piece prefix) const {
|
constexpr std::optional<R> strip_prefix_ia(str_piece prefix) const {
|
||||||
if (starts_with_ia(prefix)) {
|
if (starts_with_ia(prefix)) {
|
||||||
return R{operator()(prefix.length())};
|
return R{get(prefix.length(), to_end)};
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -4635,7 +4732,7 @@ public:
|
||||||
template<typename R = str_piece>
|
template<typename R = str_piece>
|
||||||
constexpr std::optional<R> strip_suffix(str_piece suffix) const {
|
constexpr std::optional<R> strip_suffix(str_piece suffix) const {
|
||||||
if (ends_with(suffix)) {
|
if (ends_with(suffix)) {
|
||||||
return R{operator()(0, -suffix.length())};
|
return R{get(0, from_end{suffix.length()})};
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -4654,7 +4751,7 @@ public:
|
||||||
template<typename R = str_piece>
|
template<typename R = str_piece>
|
||||||
constexpr std::optional<R> strip_suffix_ia(str_piece suffix) const {
|
constexpr std::optional<R> strip_suffix_ia(str_piece suffix) const {
|
||||||
if (ends_with_ia(suffix)) {
|
if (ends_with_ia(suffix)) {
|
||||||
return R{operator()(0, -suffix.length())};
|
return R{get(0, from_end{suffix.length()})};
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -4939,7 +5036,7 @@ public:
|
||||||
constexpr R trimmed_prefix(str_piece prefix, size_t max_count = 0) const {
|
constexpr R trimmed_prefix(str_piece prefix, size_t max_count = 0) const {
|
||||||
str_piece res = *this;
|
str_piece res = *this;
|
||||||
while(res.starts_with(prefix)) {
|
while(res.starts_with(prefix)) {
|
||||||
res = res(prefix.length());
|
res.remove_prefix(prefix.length());
|
||||||
if (--max_count == 0) {
|
if (--max_count == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -4962,7 +5059,7 @@ public:
|
||||||
constexpr R trimmed_prefix_ia(str_piece prefix, size_t max_count = 0) const {
|
constexpr R trimmed_prefix_ia(str_piece prefix, size_t max_count = 0) const {
|
||||||
str_piece res = *this;
|
str_piece res = *this;
|
||||||
while(res.starts_with_ia(prefix)) {
|
while(res.starts_with_ia(prefix)) {
|
||||||
res = res(prefix.length());
|
res.remove_prefix(prefix.length());
|
||||||
if (--max_count == 0) {
|
if (--max_count == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -4985,7 +5082,7 @@ public:
|
||||||
constexpr R trimmed_suffix(str_piece suffix) const {
|
constexpr R trimmed_suffix(str_piece suffix) const {
|
||||||
str_piece res = *this;
|
str_piece res = *this;
|
||||||
while(res.ends_with(suffix)) {
|
while(res.ends_with(suffix)) {
|
||||||
res = res(0, -suffix.length());
|
res.remove_suffix(suffix.length());
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -5005,7 +5102,7 @@ public:
|
||||||
constexpr R trimmed_suffix_ia(str_piece suffix) const {
|
constexpr R trimmed_suffix_ia(str_piece suffix) const {
|
||||||
str_piece res = *this;
|
str_piece res = *this;
|
||||||
while(res.ends_with_ia(suffix)) {
|
while(res.ends_with_ia(suffix)) {
|
||||||
res = res(0, -suffix.length());
|
res.remove_suffix(suffix.length());
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.8.1.
|
Version 1.9.1
|
||||||
|
|
||||||
<h2>Speed up your work with strings by 2-10 times!</h2>
|
<h2>Speed up your work with strings by 2-10 times!</h2>
|
||||||
|
|
||||||
|
|
@ -325,8 +325,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.8.1 # Specify the desired release
|
GIT_TAG tags/rel1.9.1# Specify the desired release
|
||||||
FIND_PACKAGE_ARGS NAMES simstr 1.8.1
|
FIND_PACKAGE_ARGS NAMES simstr 1.9.1
|
||||||
)
|
)
|
||||||
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.8.1.
|
Версия 1.9.1
|
||||||
|
|
||||||
<h2>Ускорь работу со строками в 2-10 раз!</h2>
|
<h2>Ускорь работу со строками в 2-10 раз!</h2>
|
||||||
|
|
||||||
|
|
@ -326,8 +326,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.8.1 # Укажите нужный релиз
|
GIT_TAG tags/rel1.9.1# Укажите нужный релиз
|
||||||
FIND_PACKAGE_ARGS NAMES simstr 1.8.1
|
FIND_PACKAGE_ARGS NAMES simstr 1.9.1
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(simstr)
|
FetchContent_MakeAvailable(simstr)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.8.1
|
* ver. 1.9.1
|
||||||
* (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.8.1
|
* ver. 1.9.1
|
||||||
* (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
|
||||||
|
|
@ -452,4 +452,22 @@ TEST(StrExpr, StartWithAnd) {
|
||||||
EXPECT_TRUE("Begin[ --end"_ss.starts_with_ia_and_oneof("begin", "/*[]"_ss));
|
EXPECT_TRUE("Begin[ --end"_ss.starts_with_ia_and_oneof("begin", "/*[]"_ss));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SimStr, Get) {
|
||||||
|
ssa testa{"test"};
|
||||||
|
EXPECT_EQ(testa.get(1, to_end), "est");
|
||||||
|
EXPECT_EQ(testa.get(1, 2), "es");
|
||||||
|
EXPECT_EQ(testa.get(1, from_end(1)), "es");
|
||||||
|
EXPECT_EQ(testa.get(1, from_end(10)), "");
|
||||||
|
EXPECT_EQ(testa.get(from_end(3), from_end(1)), "es");
|
||||||
|
|
||||||
|
ssu testu{u"test"};
|
||||||
|
EXPECT_EQ(testu.get(1, to_end), u"est");
|
||||||
|
EXPECT_EQ(testu.get(1, 2), u"es");
|
||||||
|
EXPECT_EQ(testu.get(from_end(3), from_end(1)), u"es");
|
||||||
|
|
||||||
|
ssw testw{L"test"};
|
||||||
|
EXPECT_EQ(testw.get(1, to_end), L"est");
|
||||||
|
EXPECT_EQ(testw.get(1, 2), L"es");
|
||||||
|
EXPECT_EQ(testw.get(from_end(3), from_end(1)), L"es");
|
||||||
|
}
|
||||||
} // namespace simstr::tests
|
} // namespace simstr::tests
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.8.1
|
* ver. 1.9.1
|
||||||
* (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
|
||||||
|
|
@ -274,6 +274,7 @@ TEST(SimStr, SimpleFind) {
|
||||||
EXPECT_EQ("abccccc"_ss.find_last("ab"), 0);
|
EXPECT_EQ("abccccc"_ss.find_last("ab"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
TEST(SimStr, SubPiece) {
|
TEST(SimStr, SubPiece) {
|
||||||
ssa testa{"test"};
|
ssa testa{"test"};
|
||||||
EXPECT_EQ(testa(1), "est");
|
EXPECT_EQ(testa(1), "est");
|
||||||
|
|
@ -289,39 +290,83 @@ TEST(SimStr, SubPiece) {
|
||||||
EXPECT_EQ(testw(1), L"est");
|
EXPECT_EQ(testw(1), L"est");
|
||||||
EXPECT_EQ(testw(1, 2), L"es");
|
EXPECT_EQ(testw(1, 2), L"es");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST(SimStr, Get) {
|
||||||
|
ssa testa{"test"};
|
||||||
|
EXPECT_EQ(testa.get(1, to_end), "est");
|
||||||
|
EXPECT_EQ(testa.get(1, 2), "es");
|
||||||
|
EXPECT_EQ(testa.get(1, from_end(1)), "es");
|
||||||
|
EXPECT_EQ(testa.get(1, from_end(10)), "");
|
||||||
|
|
||||||
|
ssu testu{u"test"};
|
||||||
|
EXPECT_EQ(testu.get(1, to_end), u"est");
|
||||||
|
EXPECT_EQ(testu.get(1, 2), u"es");
|
||||||
|
|
||||||
|
ssw testw{L"test"};
|
||||||
|
EXPECT_EQ(testw.get(1, to_end), L"est");
|
||||||
|
EXPECT_EQ(testw.get(1, 2), L"es");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SimStr, SimpleSubstr) {
|
TEST(SimStr, SimpleSubstr) {
|
||||||
ssa testa = "test";
|
ssa testa = "test";
|
||||||
|
#if 0
|
||||||
EXPECT_EQ(testa.substr(1, 0), "est");
|
EXPECT_EQ(testa.substr(1, 0), "est");
|
||||||
EXPECT_EQ(testa.substr(1, 2), "es");
|
EXPECT_EQ(testa.substr(1, 2), "es");
|
||||||
EXPECT_EQ(testa.substr(0, -1), "tes");
|
EXPECT_EQ(testa.substr(0, -1), "tes");
|
||||||
EXPECT_EQ(testa.substr(-2), "st");
|
EXPECT_EQ(testa.substr(-2), "st");
|
||||||
EXPECT_EQ(testa.substr(-3, 2), "es");
|
EXPECT_EQ(testa.substr(-3, 2), "es");
|
||||||
EXPECT_EQ(testa.substr(-3, -1), "es");
|
EXPECT_EQ(testa.substr(-3, -1), "es");
|
||||||
|
#endif
|
||||||
|
EXPECT_EQ(testa.sub(1, to_end), "est");
|
||||||
|
EXPECT_EQ(testa.sub(1, 2), "es");
|
||||||
|
EXPECT_EQ(testa.sub(0, from_end(1)), "tes");
|
||||||
|
EXPECT_EQ(testa.sub(from_end(2), to_end), "st");
|
||||||
|
EXPECT_EQ(testa.sub(from_end(3), 2), "es");
|
||||||
|
EXPECT_EQ(testa.sub(from_end(3), from_end(1)), "es");
|
||||||
|
|
||||||
EXPECT_EQ(testa.str_mid(1), "est");
|
EXPECT_EQ(testa.str_mid(1), "est");
|
||||||
EXPECT_EQ(testa.str_mid(1, 0), "");
|
EXPECT_EQ(testa.str_mid(1, 0), "");
|
||||||
EXPECT_EQ(testa.str_mid(1, 2), "es");
|
EXPECT_EQ(testa.str_mid(1, 2), "es");
|
||||||
EXPECT_EQ(testa.str_mid(2, 2), "st");
|
EXPECT_EQ(testa.str_mid(2, 2), "st");
|
||||||
|
|
||||||
ssu testu = u"test";
|
ssu testu = u"test";
|
||||||
|
#if 0
|
||||||
EXPECT_EQ(testu.substr(1, 0), u"est");
|
EXPECT_EQ(testu.substr(1, 0), u"est");
|
||||||
EXPECT_EQ(testu.substr(1, 2), u"es");
|
EXPECT_EQ(testu.substr(1, 2), u"es");
|
||||||
EXPECT_EQ(testu.substr(0, -1), u"tes");
|
EXPECT_EQ(testu.substr(0, -1), u"tes");
|
||||||
EXPECT_EQ(testu.substr(-2), u"st");
|
EXPECT_EQ(testu.substr(-2), u"st");
|
||||||
EXPECT_EQ(testu.substr(-3, 2), u"es");
|
EXPECT_EQ(testu.substr(-3, 2), u"es");
|
||||||
EXPECT_EQ(testu.substr(-3, -1), u"es");
|
EXPECT_EQ(testu.substr(-3, -1), u"es");
|
||||||
|
#endif
|
||||||
|
EXPECT_EQ(testu.sub(1, to_end), u"est");
|
||||||
|
EXPECT_EQ(testu.sub(1, 2), u"es");
|
||||||
|
EXPECT_EQ(testu.sub(0, from_end(1)), u"tes");
|
||||||
|
EXPECT_EQ(testu.sub(from_end(2), to_end), u"st");
|
||||||
|
EXPECT_EQ(testu.sub(from_end(3), 2), u"es");
|
||||||
|
EXPECT_EQ(testu.sub(from_end(3), from_end(1)), u"es");
|
||||||
|
|
||||||
EXPECT_EQ(testu.str_mid(1), u"est");
|
EXPECT_EQ(testu.str_mid(1), u"est");
|
||||||
EXPECT_EQ(testu.str_mid(1, 0), u"");
|
EXPECT_EQ(testu.str_mid(1, 0), u"");
|
||||||
EXPECT_EQ(testu.str_mid(1, 2), u"es");
|
EXPECT_EQ(testu.str_mid(1, 2), u"es");
|
||||||
EXPECT_EQ(testu.str_mid(2, 2), u"st");
|
EXPECT_EQ(testu.str_mid(2, 2), u"st");
|
||||||
|
|
||||||
ssw testw = L"test";
|
ssw testw = L"test";
|
||||||
|
#if 0
|
||||||
EXPECT_EQ(testw.substr(1, 0), L"est");
|
EXPECT_EQ(testw.substr(1, 0), L"est");
|
||||||
EXPECT_EQ(testw.substr(1, 2), L"es");
|
EXPECT_EQ(testw.substr(1, 2), L"es");
|
||||||
EXPECT_EQ(testw.substr(0, -1), L"tes");
|
EXPECT_EQ(testw.substr(0, -1), L"tes");
|
||||||
EXPECT_EQ(testw.substr(-2), L"st");
|
EXPECT_EQ(testw.substr(-2), L"st");
|
||||||
EXPECT_EQ(testw.substr(-3, 2), L"es");
|
EXPECT_EQ(testw.substr(-3, 2), L"es");
|
||||||
EXPECT_EQ(testw.substr(-3, -1), L"es");
|
EXPECT_EQ(testw.substr(-3, -1), L"es");
|
||||||
|
#endif
|
||||||
|
EXPECT_EQ(testw.sub(1, to_end), L"est");
|
||||||
|
EXPECT_EQ(testw.sub(1, 2), L"es");
|
||||||
|
EXPECT_EQ(testw.sub(0, from_end(1)), L"tes");
|
||||||
|
EXPECT_EQ(testw.sub(from_end(2), to_end), L"st");
|
||||||
|
EXPECT_EQ(testw.sub(from_end(3), 2), L"es");
|
||||||
|
EXPECT_EQ(testw.sub(from_end(3), from_end(1)), L"es");
|
||||||
|
|
||||||
EXPECT_EQ(testw.str_mid(1), L"est");
|
EXPECT_EQ(testw.str_mid(1), L"est");
|
||||||
EXPECT_EQ(testw.str_mid(1, 0), L"");
|
EXPECT_EQ(testw.str_mid(1, 0), L"");
|
||||||
EXPECT_EQ(testw.str_mid(1, 2), L"es");
|
EXPECT_EQ(testw.str_mid(1, 2), L"es");
|
||||||
|
|
@ -330,7 +375,7 @@ TEST(SimStr, SimpleSubstr) {
|
||||||
|
|
||||||
TEST(SimStr, ToInt) {
|
TEST(SimStr, ToInt) {
|
||||||
EXPECT_EQ(ssa{" 123"}.as_int<int>(), 123);
|
EXPECT_EQ(ssa{" 123"}.as_int<int>(), 123);
|
||||||
EXPECT_EQ(ssa{" 123"}(0, -1).as_int<int>(), 12);
|
EXPECT_EQ(ssa{" 123"}.get(0, from_end(1)).as_int<int>(), 12);
|
||||||
EXPECT_EQ(ssa{"+123"}.as_int<int>(), 123);
|
EXPECT_EQ(ssa{"+123"}.as_int<int>(), 123);
|
||||||
EXPECT_EQ(ssa{" -123aa"}.as_int<int>(), -123);
|
EXPECT_EQ(ssa{" -123aa"}.as_int<int>(), -123);
|
||||||
EXPECT_EQ(ssa{"123"}.as_int<size_t>(), 123u);
|
EXPECT_EQ(ssa{"123"}.as_int<size_t>(), 123u);
|
||||||
|
|
@ -813,7 +858,7 @@ TEST(SimStr, AssignSstring) {
|
||||||
EXPECT_EQ(test = ssa{"other"}, "other");
|
EXPECT_EQ(test = ssa{"other"}, "other");
|
||||||
EXPECT_EQ(test = stringa{"trtr"_ss + 10}, "trtr10");
|
EXPECT_EQ(test = stringa{"trtr"_ss + 10}, "trtr10");
|
||||||
EXPECT_EQ(test = "trtr"_ss + 20, "trtr20");
|
EXPECT_EQ(test = "trtr"_ss + 20, "trtr20");
|
||||||
EXPECT_EQ(test = test(2), "tr20");
|
EXPECT_EQ(test = test.get(2, to_end), "tr20");
|
||||||
EXPECT_EQ(test = lstringa<10>{"func"}, "func");
|
EXPECT_EQ(test = lstringa<10>{"func"}, "func");
|
||||||
EXPECT_EQ(test = lstringsa<10>{"func"}, "func");
|
EXPECT_EQ(test = lstringsa<10>{"func"}, "func");
|
||||||
lstringsa<10> sample{15, "1234"};
|
lstringsa<10> sample{15, "1234"};
|
||||||
|
|
@ -942,10 +987,10 @@ TEST(SimStr, LStringAssign) {
|
||||||
test = lstringa<1>{"next step"};
|
test = lstringa<1>{"next step"};
|
||||||
EXPECT_EQ(test, "next step");
|
EXPECT_EQ(test, "next step");
|
||||||
|
|
||||||
test = test(0);
|
test = test.get(0, to_end);
|
||||||
EXPECT_EQ(test, "next step");
|
EXPECT_EQ(test, "next step");
|
||||||
|
|
||||||
test = test(1, 2);
|
test = test.get(1, 2);
|
||||||
EXPECT_EQ(test, "ex");
|
EXPECT_EQ(test, "ex");
|
||||||
|
|
||||||
test = e_c(100, 'a');
|
test = e_c(100, 'a');
|
||||||
|
|
@ -1405,7 +1450,7 @@ TEST(SimStr, LStrJoinAndExpressions) {
|
||||||
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"));
|
||||||
EXPECT_EQ(buffer, "99asd<>fgh<>jkl");
|
EXPECT_EQ(buffer, "99asd<>fgh<>jkl");
|
||||||
|
|
||||||
buffer.change(2, 4, test(0, 3) + "__" + 1 + ',');
|
buffer.change(2, 4, test.get(0, 3) + "__" + 1 + ',');
|
||||||
EXPECT_EQ(buffer, "99>as__1,>fgh<>jkl");
|
EXPECT_EQ(buffer, "99>as__1,>fgh<>jkl");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ver. 1.8.1
|
* ver. 1.9.1
|
||||||
* (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