Compare commits

..

No commits in common. "main" and "rel1.8.1" have entirely different histories.

14 changed files with 55 additions and 350 deletions

View File

@ -5,7 +5,7 @@ include(FetchContent)
project(
simstr
VERSION 1.9.1
VERSION 1.8.1
DESCRIPTION "Yet another modern C++ string library"
HOMEPAGE_URL "https://github.com/orefkov/simstr"
LANGUAGES CXX

View File

@ -1,5 +1,5 @@
/*
* ver. 1.9.1
* ver. 1.8.1
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
* Бенчмарки
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com

View File

@ -38,7 +38,7 @@ struct result_info {
}
// Текущее положение поставим сразу за cpuinfo и откинем завершающие переводы строк
// We will put the current position immediately after cpuinfo and discard the final line feeds
current_text_ = current_text_.get(cpu_info_.end() - current_text_.begin() + 1, to_end).trimmed_right("\n");
current_text_ = current_text_(cpu_info_.end() - current_text_.begin() + 1).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
if (auto delimiter = fileName.find('-'); delimiter + 1 > 1) {
if (fileName.prefix(delimiter).to_int<unsigned, false, 10, false, false>().ec == IntConvertResult::Success) {
if (fileName(0, delimiter).to_int<unsigned, false, 10, false, false>().ec == IntConvertResult::Success) {
fileName.remove_prefix(delimiter + 1);
}
}
results.emplace_back(get_file_content(lstringa<128>{dirForResults + f}), fileName.get(0, from_end(suffix.length())));
results.emplace_back(get_file_content(lstringa<128>{dirForResults + f}), fileName(0, -suffix.length()));
}
}
return results;
@ -117,7 +117,7 @@ void write_platforms_cpu(out_t& out, const results_vector& results) {
for (const auto& r : results) {
size_t rp = r.cpu_info_.find('(') + 1, lp = r.cpu_info_.find(')', rp);
ssa shortCpuInfo = r.cpu_info_.from_to(rp, lp);
ssa cpuInfo = r.cpu_info_.get(lp + 2, to_end);
ssa cpuInfo = r.cpu_info_(lp + 2);
out += e_subst(R"--(
<li><span class="platform">{}</span><span class="tooltip">{}<span class="tooltiptext">{}</span></span>&nbsp;Include in charts: <input type="checkbox" id="pl{}" checked onchange="buildCharts()"/></li>)--",
r.platform_, shortCpuInfo, cpuInfo, counter++);
@ -167,7 +167,7 @@ ssa extract_name_result(ssa line, ssa& result) {
line.len = ns;
if (inNs) {
size_t end = line.find_last(' ');
result = line.get(end + 1, to_end);
result = line(end + 1);
if (auto rp = line.find("/repeats"); rp != str::npos) {
line.len = rp;
} else {
@ -182,7 +182,7 @@ ssa extract_name_result(ssa line, ssa& result) {
ssa extract_comment(ssa commentsText, ssa benchmarkName) {
size_t idx = commentsText.find_end(lstringa<120>{"- " + benchmarkName + "\n"});
if (idx != str::npos) {
if (commentsText[idx] != '\n' && commentsText.get(idx, 2) != "- ") {
if (commentsText[idx] != '\n' && commentsText(idx, 2) != "- ") {
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('/');
if (delim != str::npos && benchName.get(delim + 1, to_end).to_int<unsigned, false, 10, false, false>().ec == IntConvertResult::Success) {
if (delim != str::npos && benchName(delim + 1).to_int<unsigned, false, 10, false, false>().ec == IntConvertResult::Success) {
benchName.len = delim;
}
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;
return {stra::empty_str, 0};
}
start = sourceText.prefix(start).find('(', sourceText.find_last('\n', start - 1));
start = sourceText(0, start).find('(', sourceText.find_last('\n', start - 1));
if (start == str::npos) {
std::cerr << "Can not found benchmark function name for " << benchName << std::endl;
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);
size_t templ_start = sourceText.find_last('\n', start) + 1;
if (sourceText.get(templ_start, to_end).starts_with("template")) {
if (sourceText(templ_start).starts_with("template")) {
start = templ_start;
} else {
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"};
}
lstringa<2048> text{sourceText.from_to(beginLine, end + indent.length() + 1), indent, "\n"};
func_it->second.first = repl_html_symbols(text.get(1, to_end));
func_it->second.first = repl_html_symbols(text(1));
} else {
end = sourceText.find("\n}\n", start);
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) {
ssa releaseVersion = sourceText.get(sourceText.find_end("\n * ver. "), to_end).until("\n").trimmed();
ssa releaseVersion = sourceText(sourceText.find_end("\n * ver. ")).until("\n").trimmed();
if (!releaseVersion) {
std::cerr << "Not found release version in sources" << std::endl;
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()) {
ssa line = splitters[0].next(), benchName, result;
if (auto rm = line.find("_mean"); rm != str::npos) {
benchName = extract_name_result(line, result).prefix(rm);
benchName = extract_name_result(line, result)(0, rm);
auto [source, line_num] = extract_source_for_benchmark(benchName, sourceText);
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"};
}
line = splitters[idx].next();
ssa rbench_name = extract_name_result(line, result).prefix(rm);
ssa rbench_name = extract_name_result(line, result)(0, rm);
if (rbench_name != benchName) {
while (line.find("_mean") == str::npos && !splitters[idx].is_done()) {
line = splitters[idx].next();
}
rbench_name = extract_name_result(line, result).prefix(rm);
rbench_name = extract_name_result(line, result)(0, rm);
if (rbench_name != benchName) {
std::cerr << "In results for " << results[idx].platform_ << " benchmark '" << rbench_name
<< "' does not match with other results" << std::endl;

View File

@ -48,7 +48,7 @@ PROJECT_NAME = "simstr"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 1.9.1
PROJECT_NUMBER = 1.8.1
# 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
@ -2928,7 +2928,7 @@ MAX_DOT_GRAPH_DEPTH = 0
# 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
# makes dot run faster, but since only newer versions of dot (>1.8.20) support
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.

View File

@ -48,7 +48,7 @@ PROJECT_NAME = "simstr"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 1.9.1
PROJECT_NUMBER = 1.8.1
# 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
@ -2928,7 +2928,7 @@ MAX_DOT_GRAPH_DEPTH = 0
# 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
# makes dot run faster, but since only newer versions of dot (>1.8.20) support
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.

View File

@ -1,6 +1,6 @@
/*
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
* ver. 1.9.1
* ver. 1.8.1
*/
#pragma once

View File

@ -1,5 +1,5 @@
/*
* ver. 1.9.1
* ver. 1.8.1
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
* Классы для работы со строками
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
@ -3257,7 +3257,7 @@ public:
}
/*!
* @ru @brief Определить длину строки.
* Ищет символ 0 в буфере строки до его ёмкости, после чего устанавливает длину строки по найденному 0.
* Ищет символ 0 в буфере строки до его ёмкости, после чего устаналивает длину строки по найденному 0.
* @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.
*/
@ -3283,7 +3283,7 @@ public:
if (is_alloced() && capacity_ > need_capacity) {
K* newData = size_ <= LocalCapacity ? local_ : alloc_place(need_capacity);
traits::copy(newData, data_, size_ + 1);
dealloc();
base_storable::allocator().deallocate(to_real_address(data_));
data_ = newData;
if (size_ > LocalCapacity) {
@ -4365,7 +4365,8 @@ public:
}
auto erase(const InStore& key) {
if (auto it = hash_t::find(key); it != hash_t::end()) {
auto it = hash_t::find(key);
if (it != hash_t::end()) {
((sstring<K>*)it->first.node)->~sstring();
hash_t::erase(it);
return 1;
@ -4377,151 +4378,15 @@ public:
return erase(toStoreType(key));
}
/*!
* @ru @brief Поиск и извлечение значения.
* @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()) {
bool lookup(simple_str<K> txt, T& val) const {
auto it = find(txt);
if (it != hash_t::end()) {
val = it->second;
return true;
}
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() {
for (auto& k: *this)
((sstring<K>*)k.first.node)->~sstring();

View File

@ -1,5 +1,5 @@
/*
* ver. 1.9.1
* ver. 1.8.1
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
* База для строковых конкатенаций через выражения времени компиляции
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
@ -3274,20 +3274,6 @@ 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 Класс с базовыми константными строковыми алгоритмами.
* @details Является базой для классов, могущих выполнять константные операции со строками.
@ -3459,7 +3445,6 @@ public:
* "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 {
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;
@ -3469,83 +3454,6 @@ public:
idxStart = idxEnd;
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 Получить часть строки как "кусок строки".
* @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку.
@ -3592,7 +3500,7 @@ public:
* @return Substring, str_src.
*/
constexpr str_piece until(str_piece pattern, size_t offset = 0) const noexcept {
return get(0, find_or_all(pattern, offset));
return (*this)(0, find_or_all(pattern, offset));
}
/*!
* @ru @brief Проверка на пустоту.
@ -3818,7 +3726,7 @@ public:
* @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...>
constexpr size_t find_or_throw(str_piece pattern, size_t offset = 0, Args&& ... args) const {
constexpr size_t find_or_throw(str_piece pattern, size_t offset = 0, Args&& ... args) const noexcept {
if (auto fnd = find(pattern.symbols(), pattern.length(), offset); fnd != str::npos) {
return fnd;
}
@ -4163,14 +4071,9 @@ 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.
* @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
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.
* @param from - количество символов от начала строки. При превышении размера строки вернёт пустую строку.
@ -4694,7 +4597,7 @@ public:
template<typename R = str_piece>
constexpr std::optional<R> strip_prefix(str_piece prefix) const {
if (starts_with(prefix)) {
return R{get(prefix.length(), to_end)};
return R{operator()(prefix.length())};
}
return {};
}
@ -4713,7 +4616,7 @@ public:
template<typename R = str_piece>
constexpr std::optional<R> strip_prefix_ia(str_piece prefix) const {
if (starts_with_ia(prefix)) {
return R{get(prefix.length(), to_end)};
return R{operator()(prefix.length())};
}
return {};
}
@ -4732,7 +4635,7 @@ public:
template<typename R = str_piece>
constexpr std::optional<R> strip_suffix(str_piece suffix) const {
if (ends_with(suffix)) {
return R{get(0, from_end{suffix.length()})};
return R{operator()(0, -suffix.length())};
}
return {};
}
@ -4751,7 +4654,7 @@ public:
template<typename R = str_piece>
constexpr std::optional<R> strip_suffix_ia(str_piece suffix) const {
if (ends_with_ia(suffix)) {
return R{get(0, from_end{suffix.length()})};
return R{operator()(0, -suffix.length())};
}
return {};
}
@ -5036,7 +4939,7 @@ public:
constexpr R trimmed_prefix(str_piece prefix, size_t max_count = 0) const {
str_piece res = *this;
while(res.starts_with(prefix)) {
res.remove_prefix(prefix.length());
res = res(prefix.length());
if (--max_count == 0) {
break;
}
@ -5059,7 +4962,7 @@ public:
constexpr R trimmed_prefix_ia(str_piece prefix, size_t max_count = 0) const {
str_piece res = *this;
while(res.starts_with_ia(prefix)) {
res.remove_prefix(prefix.length());
res = res(prefix.length());
if (--max_count == 0) {
break;
}
@ -5082,7 +4985,7 @@ public:
constexpr R trimmed_suffix(str_piece suffix) const {
str_piece res = *this;
while(res.ends_with(suffix)) {
res.remove_suffix(suffix.length());
res = res(0, -suffix.length());
}
return res;
}
@ -5102,7 +5005,7 @@ public:
constexpr R trimmed_suffix_ia(str_piece suffix) const {
str_piece res = *this;
while(res.ends_with_ia(suffix)) {
res.remove_suffix(suffix.length());
res = res(0, -suffix.length());
}
return res;
}

View File

@ -3,7 +3,7 @@
[![CMake on multiple platforms](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml/badge.svg)](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
Version 1.9.1
Version 1.8.1.
<h2>Speed up your work with strings by 2-10 times!</h2>
@ -325,8 +325,8 @@ function(add_simstr)
simstr
GIT_REPOSITORY https://github.com/orefkov/simstr.git
GIT_SHALLOW TRUE
GIT_TAG tags/rel1.9.1# Specify the desired release
FIND_PACKAGE_ARGS NAMES simstr 1.9.1
GIT_TAG tags/rel1.8.1 # Specify the desired release
FIND_PACKAGE_ARGS NAMES simstr 1.8.1
)
FetchContent_MakeAvailable(simstr)
endfunction()

View File

@ -3,7 +3,7 @@
[![CMake on multiple platforms](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml/badge.svg)](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
Версия 1.9.1
Версия 1.8.1.
<h2>Ускорь работу со строками в 2-10 раз!</h2>
@ -326,8 +326,8 @@ function(add_simstr)
simstr
GIT_REPOSITORY https://github.com/orefkov/simstr.git
GIT_SHALLOW TRUE
GIT_TAG tags/rel1.9.1# Укажите нужный релиз
FIND_PACKAGE_ARGS NAMES simstr 1.9.1
GIT_TAG tags/rel1.8.1 # Укажите нужный релиз
FIND_PACKAGE_ARGS NAMES simstr 1.8.1
)
FetchContent_MakeAvailable(simstr)
endfunction()

View File

@ -1,5 +1,5 @@
/*
* ver. 1.9.1
* ver. 1.8.1
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
* Реализация строковых функций
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com

View File

@ -1,5 +1,5 @@
/*
* ver. 1.9.1
* ver. 1.8.1
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
* Тесты simstr
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
@ -452,22 +452,4 @@ TEST(StrExpr, StartWithAnd) {
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

View File

@ -1,5 +1,5 @@
/*
* ver. 1.9.1
* ver. 1.8.1
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
* Тесты simstr
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
@ -274,7 +274,6 @@ TEST(SimStr, SimpleFind) {
EXPECT_EQ("abccccc"_ss.find_last("ab"), 0);
}
#if 0
TEST(SimStr, SubPiece) {
ssa testa{"test"};
EXPECT_EQ(testa(1), "est");
@ -290,83 +289,39 @@ TEST(SimStr, SubPiece) {
EXPECT_EQ(testw(1), L"est");
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) {
ssa testa = "test";
#if 0
EXPECT_EQ(testa.substr(1, 0), "est");
EXPECT_EQ(testa.substr(1, 2), "es");
EXPECT_EQ(testa.substr(0, -1), "tes");
EXPECT_EQ(testa.substr(-2), "st");
EXPECT_EQ(testa.substr(-3, 2), "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, 0), "");
EXPECT_EQ(testa.str_mid(1, 2), "es");
EXPECT_EQ(testa.str_mid(2, 2), "st");
ssu testu = u"test";
#if 0
EXPECT_EQ(testu.substr(1, 0), u"est");
EXPECT_EQ(testu.substr(1, 2), u"es");
EXPECT_EQ(testu.substr(0, -1), u"tes");
EXPECT_EQ(testu.substr(-2), u"st");
EXPECT_EQ(testu.substr(-3, 2), 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, 0), u"");
EXPECT_EQ(testu.str_mid(1, 2), u"es");
EXPECT_EQ(testu.str_mid(2, 2), u"st");
ssw testw = L"test";
#if 0
EXPECT_EQ(testw.substr(1, 0), L"est");
EXPECT_EQ(testw.substr(1, 2), L"es");
EXPECT_EQ(testw.substr(0, -1), L"tes");
EXPECT_EQ(testw.substr(-2), L"st");
EXPECT_EQ(testw.substr(-3, 2), 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, 0), L"");
EXPECT_EQ(testw.str_mid(1, 2), L"es");
@ -375,7 +330,7 @@ TEST(SimStr, SimpleSubstr) {
TEST(SimStr, ToInt) {
EXPECT_EQ(ssa{" 123"}.as_int<int>(), 123);
EXPECT_EQ(ssa{" 123"}.get(0, from_end(1)).as_int<int>(), 12);
EXPECT_EQ(ssa{" 123"}(0, -1).as_int<int>(), 12);
EXPECT_EQ(ssa{"+123"}.as_int<int>(), 123);
EXPECT_EQ(ssa{" -123aa"}.as_int<int>(), -123);
EXPECT_EQ(ssa{"123"}.as_int<size_t>(), 123u);
@ -858,7 +813,7 @@ TEST(SimStr, AssignSstring) {
EXPECT_EQ(test = ssa{"other"}, "other");
EXPECT_EQ(test = stringa{"trtr"_ss + 10}, "trtr10");
EXPECT_EQ(test = "trtr"_ss + 20, "trtr20");
EXPECT_EQ(test = test.get(2, to_end), "tr20");
EXPECT_EQ(test = test(2), "tr20");
EXPECT_EQ(test = lstringa<10>{"func"}, "func");
EXPECT_EQ(test = lstringsa<10>{"func"}, "func");
lstringsa<10> sample{15, "1234"};
@ -987,10 +942,10 @@ TEST(SimStr, LStringAssign) {
test = lstringa<1>{"next step"};
EXPECT_EQ(test, "next step");
test = test.get(0, to_end);
test = test(0);
EXPECT_EQ(test, "next step");
test = test.get(1, 2);
test = test(1, 2);
EXPECT_EQ(test, "ex");
test = e_c(100, 'a');
@ -1450,7 +1405,7 @@ TEST(SimStr, LStrJoinAndExpressions) {
buffer.prepend(e_choice(test.length() > 2, eea + 99, eea + 12.1 + "asd"));
EXPECT_EQ(buffer, "99asd<>fgh<>jkl");
buffer.change(2, 4, test.get(0, 3) + "__" + 1 + ',');
buffer.change(2, 4, test(0, 3) + "__" + 1 + ',');
EXPECT_EQ(buffer, "99>as__1,>fgh<>jkl");
}

View File

@ -1,5 +1,5 @@
/*
* ver. 1.9.1
* ver. 1.8.1
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
* Тесты simstr
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com