- Add e_upper, e_lower, e_ascii_upper, e_ascii_lower sting expressions.
- Add str::make_ascii_upper, str::make_ascii_lower functions for std::string.

- Добавлены строковые выражения e_upper, e_lower, e_ascii_upper, e_ascii_lower.
- Добавлены функции str::make_ascii_upper, str::make_ascii_lower functions для std::string.
This commit is contained in:
Aleksandr Orefkov 2026-02-15 17:13:54 +03:00
parent 8610bea2a9
commit 7bb7ddb766
20 changed files with 5743 additions and 5311 deletions

View File

@ -5,7 +5,7 @@ include(FetchContent)
project( project(
simstr simstr
VERSION 1.6.7 VERSION 1.7.0
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

View File

@ -1,5 +1,5 @@
/* /*
* ver. 1.6.7 * ver. 1.7.0
* (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
@ -2607,6 +2607,46 @@ BENCHMARK(BuildFuncNameStream) ->Name("Build func full name std::stream;
BENCHMARK(BuildFuncNameSimStr) ->Name("Build func full name stringa;"); BENCHMARK(BuildFuncNameSimStr) ->Name("Build func full name stringa;");
BENCHMARK(BuildFuncNameSimStr1) ->Name("Build func full name stringa 1;"); BENCHMARK(BuildFuncNameSimStr1) ->Name("Build func full name stringa 1;");
void UpperCaseStd(benchmark::State& state) {
static const auto& loc = std::locale("en_US.utf8");
for (auto _: state) {
std::wstring test = L"TestПриветTest";
benchmark::DoNotOptimize(test);
std::transform(test.begin(), test.end(), test.begin(), [](wchar_t s) {
return std::toupper(s, loc);
});
benchmark::DoNotOptimize(test);
#ifdef CHECK_RESULT
if (test != L"TESTПРИВЕТTEST") {
state.SkipWithError("Bad upper case");
}
#endif
}
}
void UpperCaseSim(benchmark::State& state) {
for (auto _: state) {
lstringw<15> test = L"TestПриветTest";
benchmark::DoNotOptimize(test);
test.upper();
benchmark::DoNotOptimize(test);
#ifdef CHECK_RESULT
if (test != L"TESTПРИВЕТTEST") {
state.SkipWithError("Bad upper case");
}
#endif
}
}
BENCHMARK(__)->Name("----- Make Upper ---------")->Repetitions(1);
BENCHMARK(UpperCaseStd)->Name("To upper case std::wstring");
BENCHMARK(UpperCaseSim)->Name("To upper case lstringw<15>");
int main(int argc, char** argv) { int main(int argc, char** argv) {
std::cout << "Benchmarks of simstr, version " SIMSTR_VERSION << "\n" std::cout << "Benchmarks of simstr, version " SIMSTR_VERSION << "\n"
<< "Sources: https://github.com/orefkov/simstr\n" << "Sources: https://github.com/orefkov/simstr\n"

View File

@ -185,7 +185,7 @@
<body> <body>
<div class="head"> <div class="head">
<h3>SimStr 1.6.7 Benchmark</h3> <h3>SimStr 1.7.0 Benchmark</h3>
<span><a href="https://orefkov.github.io/simstr/results.html" target="blank">All results</a></span> <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 <span><a href="https://github.com/orefkov/simstr/blob/main/bench/bench_str.cpp" target="blank">Sources for
benchmarks</a></span> benchmarks</a></span>

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

View File

@ -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.7 PROJECT_NUMBER = 1.7.0
# 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

View File

@ -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.7 PROJECT_NUMBER = 1.7.0
# 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

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* ver. 1.6.7 * ver. 1.7.0
* (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
@ -86,8 +86,10 @@ struct unicode_traits<u8s> {
// If the resulting string does not fit into the allocated buffer, pointers are set to the last // If the resulting string does not fit into the allocated buffer, pointers are set to the last
// processed characters to resume work again, // processed characters to resume work again,
// and for the remaining characters the required buffer size is calculated. // and for the remaining characters the required buffer size is calculated.
static SIMSTR_API size_t upper(const u8s*& src, size_t lenStr, u8s*& dest, size_t lenBuf); static SIMSTR_API size_t upper(const u8s*& src, size_t len, u8s*& dest, size_t lenBuf);
static SIMSTR_API size_t lower(const u8s*& src, size_t len, u8s*& dest, size_t lenBuf); static SIMSTR_API size_t lower(const u8s*& src, size_t len, u8s*& dest, size_t lenBuf);
static SIMSTR_API size_t upper_len(const u8s* src, size_t len);
static SIMSTR_API size_t lower_len(const u8s* src, size_t len);
static SIMSTR_API int compareiu(const u8s* text1, size_t len1, const u8s* text2, size_t len2); static SIMSTR_API int compareiu(const u8s* text1, size_t len1, const u8s* text2, size_t len2);
@ -135,6 +137,31 @@ struct unicode_traits<wchar_t> {
} }
}; };
template<>
struct unicode_traits<char8_t> {
static size_t upper(const ubs*& src, size_t lenStr, ubs*& dest, size_t lenBuf) {
return unicode_traits<char>::upper((const u8s*&)src, lenStr, (u8s*&)dest, lenBuf);
}
static size_t lower(const ubs*& src, size_t len, ubs*& dest, size_t lenBuf) {
return unicode_traits<char>::lower((const u8s*&)src, len, (u8s*&)dest, lenBuf);
}
static size_t upper_len(const ubs* src, size_t len) {
return unicode_traits<char>::upper_len((const u8s*)src, len);
}
static size_t lower_len(const ubs* src, size_t len) {
return unicode_traits<char>::lower_len((const u8s*)src, len);
}
static int compareiu(const char8_t* text1, size_t len1, const char8_t* text2, size_t len2) {
return unicode_traits<char>::compareiu((const char*)text1, len1, (const char*)text2, len2);
}
static size_t hashia(const char8_t* src, size_t s) {
return unicode_traits<char>::hashia((const char*)src, s);
}
static size_t hashiu(const char8_t* src, size_t s) {
return unicode_traits<char>::hashiu((const char*)src, s);
}
};
#if defined(_MSC_VER) && _MSC_VER <= 1933 #if defined(_MSC_VER) && _MSC_VER <= 1933
template<typename K, typename... Args> template<typename K, typename... Args>
@ -4884,6 +4911,94 @@ inline HashKeyIU<uws> operator""_iu(const uws* ptr, size_t l) {
} }
} // namespace literals } // namespace literals
template<is_one_of_char_v K, bool upper>
struct expr_change_case : expr_to_std_string<expr_change_case<K, upper>>{
using symb_type = K;
str_src<K> src_;
mutable size_t len_{};
template<StrSource S>
expr_change_case(S&& s) : src_(std::forward<S>(s)){}
constexpr size_t length() const noexcept {
if constexpr (sizeof(K) > 1) {
return src_.length();
} else {
if constexpr (upper) {
len_ = unicode_traits<K>::upper_len(src_.str, src_.len);
} else {
len_ = unicode_traits<K>::lower_len(src_.str, src_.len);
}
return len_;
}
}
constexpr K* place(K* ptr) const noexcept {
if constexpr (sizeof(K) > 1) {
if constexpr (upper) {
unicode_traits<K>::upper(src_.str, src_.len, ptr);
} else {
unicode_traits<K>::lower(src_.str, src_.len, ptr);
}
return ptr + src_.len;
} else {
const K* src = src_.str;
if constexpr (upper) {
unicode_traits<K>::upper(src, src_.len, ptr, len_);
} else {
unicode_traits<K>::lower(src, src_.len, ptr, len_);
}
return ptr;
}
}
};
/*!
* @ru @brief Генерирует строку на основе исходной, заменяя все строчные буквы первой плоскости Юникода на прописные.
* @tparam K - тип символов, выводится на основе исходной строки.
* @details Берёт исходную строку и копирует её, заменяя строчные буквы первой плоскости Юникода на прописные.
* В качестве исходной строки может браться любой строковый объект.
* @en @brief Generates a string based on the original one, replacing all lowercase letters of the first Unicode plane with uppercase ones.
* @tparam K - character type, inferred based on the source string.
* @details Takes the original string and copies it, replacing the lowercase letters of the first Unicode plane with uppercase ones.
* Any string object can be taken as the source string.
* @ru Пример @en Example @~
* ```cpp
* stringa upper = "Upper case version is: '" + e_upper(source_str) + "'.";
* ```
*/
template<is_one_of_char_v K>
struct e_upper : expr_change_case<K, true> {
using base = expr_change_case<K, true>;
using base::base;
};
template<StrSource S>
e_upper(S&&) -> e_upper<symb_type_from_src_t<S>>;
/*!
* @ru @brief Генерирует строку на основе исходной, заменяя все прописные буквы первой плоскости Юникода на строчные.
* @tparam K - тип символов, выводится на основе исходной строки.
* @details Берёт исходную строку и копирует её, заменяя прописные буквы первой плоскости Юникода на строчные.
* В качестве исходной строки может браться любой строковый объект.
* @ru @brief Generate a string from the original one, replacing all uppercase letters of the first Unicode plane with lowercase ones.
* @tparam K - character type, inferred based on the source string.
* @details Takes the original string and copies it, replacing the uppercase letters of the first Unicode plane with lowercase ones.
* Any string object can be taken as the source string.
* @ru Пример @en Example @~
* ```cpp
* stringa lower = "Lower case version is: '" + e_lower(source_str) + "'.";
* ```
*/
template<is_one_of_char_v K>
struct e_lower : expr_change_case<K, false> {
using base = expr_change_case<K, false>;
using base::base;
};
template<StrSource S>
e_lower(S&&) -> e_lower<symb_type_from_src_t<S>>;
/*! /*!
* @ru @brief Оператор вывода в поток simple_str. * @ru @brief Оператор вывода в поток simple_str.
* @param stream - поток вывода. * @param stream - поток вывода.

View File

@ -1,5 +1,5 @@
/* /*
* ver. 1.6.7 * ver. 1.7.0
* (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
@ -6648,6 +6648,77 @@ struct e_vsubst : expr_to_std_string<e_vsubst<K, Args...>> {
template<StrSourceNoLiteral T, typename...Args> requires (sizeof...(Args) > 0) template<StrSourceNoLiteral T, typename...Args> requires (sizeof...(Args) > 0)
e_vsubst(T&&, Args&&...) -> e_vsubst<symb_type_from_src_t<T>, Args...>; e_vsubst(T&&, Args&&...) -> e_vsubst<symb_type_from_src_t<T>, Args...>;
template<is_one_of_char_v K, bool upper>
struct expr_change_case_ascii : expr_to_std_string<expr_change_case_ascii<K, upper>>{
using symb_type = K;
str_src<K> src_;
template<StrSource S>
expr_change_case_ascii(S&& s) : src_(std::forward<S>(s)){}
constexpr size_t length() const noexcept {
return src_.length();
}
constexpr K* place(K* ptr) const noexcept {
const K* read = src_.str;
for (size_t l = src_.len; l--;) {
if constexpr (upper) {
*ptr++ = makeAsciiUpper(*read++);
} else {
*ptr++ = makeAsciiLower(*read++);
}
}
return ptr;
}
};
/*!
* @ru @brief Генерирует строку на основе исходной, заменяя все ASCII строчные буквы (a-z) на прописные.
* @tparam K - тип символов, выводится на основе исходной строки.
* @details Берёт исходную строку и копирует её, заменяя ASCII строчные буквы (a-z) на прописные.
* В качестве исходной строки может браться любой строковый объект.
* @en @brief Generate a string based on the original one, replacing all ASCII lowercase letters (a-z) with uppercase ones.
* @tparam K - character type, deduced on the source string.
* @details Takes the original string and copies it, replacing the ASCII lowercase letters (a-z) with uppercase ones.
* Any string object can be taken as the source string.
* @ru Пример @en Example @~
* ```cpp
* stringa upper = "Upper case version is: '" + e_ascii_upper(source_str) + "'.";
* ```
*/
template<is_one_of_char_v K>
struct e_ascii_upper : expr_change_case_ascii<K, true> {
using base = expr_change_case_ascii<K, true>;
using base::base;
};
template<StrSource S>
e_ascii_upper(S&&) -> e_ascii_upper<symb_type_from_src_t<S>>;
/*!
* @ru @brief Генерирует строку на основе исходной, заменяя все ASCII прописные буквы (A-Z) на строчные.
* @tparam K - тип символов, выводится на основе исходной строки.
* @details Берёт исходную строку и копирует её, заменяя ASCII прописные буквы (A-Z) на строчные.
* В качестве исходной строки может браться любой строковый объект.
* @en @brief Generate a string based on the original one, replacing all ASCII uppercase letters (A-Z) with lowercase ones.
* @tparam K - character type, deduced on the source string.
* @details Takes the original string and copies it, replacing the ASCII uppercase letters (A-Z) with lowercase ones.
* Any string object can be taken as the source string.
* @ru Пример @en Example @~
* ```cpp
* stringa lower = "Lower case version is: '" + e_ascii_lower(source_str) + "'.";
* ```
*/
template<is_one_of_char_v K>
struct e_ascii_lower : expr_change_case_ascii<K, false> {
using base = expr_change_case_ascii<K, false>;
using base::base;
};
template<StrSource S>
e_ascii_lower(S&&) -> e_ascii_lower<symb_type_from_src_t<S>>;
/*! /*!
* @ru @brief Небольшое пространство для методов работы со стандартными строками. * @ru @brief Небольшое пространство для методов работы со стандартными строками.
* @en @brief Small namespace for standard string methods. * @en @brief Small namespace for standard string methods.
@ -7146,6 +7217,52 @@ std::basic_string<K, std::char_traits<K>, A>& replace(std::basic_string<K, std::
return replace(str, str_src<K>{std::forward<T>(pattern)}, str_src<K>{std::forward<M>(repl)}, offset, max_count); return replace(str, str_src<K>{std::forward<T>(pattern)}, str_src<K>{std::forward<M>(repl)}, offset, max_count);
} }
/*!
* @ru @brief Изменить строчные ASCII символы строки (a-z) на прописные.
* @param str - стандартная строка
* @param from - позиция начала замены, по умолчанию 0.
* @param to - по какую позицию (не включительно) заменять (по умолчанию до каонца строки).
* @return переданную строку
* @en @brief Change lowercase ASCII string characters (a-z) to uppercase.
* @param str - standard string
* @param from - replacement start position, default 0.
* @param to - at what position (not inclusive) to replace (by default until the end of the line).
* @return the passed string
*/
template<typename K, typename A>
std::basic_string<K, std::char_traits<K>, A>& make_ascii_upper(std::basic_string<K, std::char_traits<K>, A>& str, size_t from = 0, size_t to = -1) {
for (K *ptr = str.data() + std::min(from, str.length()), *end = str.data() + std::min(to, str.length()); ptr < end; ptr++) {
K s = *ptr;
if (isAsciiLower(s)) {
*ptr = s & ~0x20;
}
}
return str;
}
/*!
* @ru @brief Изменить прописные ASCII символы строки (A-Z) на строчные.
* @param str - стандартная строка
* @param from - позиция начала замены, по умолчанию 0.
* @param to - по какую позицию (не включительно) заменять (по умолчанию до каонца строки).
* @return переданную строку
* @en @brief Change uppercase ASCII string characters (A-Z) to lowercase.
* @param str - standard string
* @param from - replacement start position, default 0.
* @param to - at what position (not inclusive) to replace (by default until the end of the line).
* @return the passed string
*/
template<typename K, typename A>
std::basic_string<K, std::char_traits<K>, A>& make_ascii_lower(std::basic_string<K, std::char_traits<K>, A>& str, size_t from = 0, size_t to = -1) {
for (K *ptr = str.data() + std::min(from, str.length()), *end = str.data() + std::min(to, str.length()); ptr < end; ptr++) {
K s = *ptr;
if (isAsciiUpper(s)) {
*ptr = s | 0x20;
}
}
return str;
}
} // namespace str } // namespace str
} // namespace simstr } // namespace simstr

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) [![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.6.7. Version 1.7.0.
<h2>Speed up your work with strings by 2-10 times!</h2> <h2>Speed up your work with strings by 2-10 times!</h2>
@ -26,7 +26,7 @@ use in my work, trying to do it in the most efficient way, and I modestly hope t
and will be useful to other people, either directly or as a source of ideas. and will be useful to other people, either directly or as a source of ideas.
The library contains two parts: The library contains two parts:
- Implementation of [*"String Expressions"*](https://orefkov.github.io/simstr/docs_ru/overview.html#autotoc_md27) and algorithms for working - Implementation of [*"String Expressions"*](https://orefkov.github.io/simstr/articles/fast_concat.html) and algorithms for working
with constant strings.\ with constant strings.\
To use this part, just take the file `"include/simstr/strexpr.h"` and write in your code To use this part, just take the file `"include/simstr/strexpr.h"` and write in your code
```cpp ```cpp
@ -75,6 +75,7 @@ When using only `#include "simstr/strexpr.h"`:
for example `str::append(text, "count = "_ss + count)`. for example `str::append(text, "count = "_ss + count)`.
- str::replace - replaces occurrences of the search substring with a replacement string or string expression. - str::replace - replaces occurrences of the search substring with a replacement string or string expression.
If the substring is not found, the string expression is not even evaluated. If the substring is not found, the string expression is not even evaluated.
- str::make_ascii_upper, str::make_ascii_lower - change the case of ASCII characters.
- Parsing integers with the possibility of "fine" tuning at compile time - you can set options for checking overflow, - Parsing integers with the possibility of "fine" tuning at compile time - you can set options for checking overflow,
skipping whitespace characters, a specific radix or auto-selection by prefixes `0x`, `0`, `0b`, `0o`, skipping whitespace characters, a specific radix or auto-selection by prefixes `0x`, `0`, `0b`, `0o`,
the admissibility of the `+` sign. Parsing is implemented for all types of strings and characters. the admissibility of the `+` sign. Parsing is implemented for all types of strings and characters.
@ -323,8 +324,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.7 # Specify the desired release GIT_TAG tags/rel1.7.0 # Specify the desired release
FIND_PACKAGE_ARGS NAMES simstr 1.6.7 FIND_PACKAGE_ARGS NAMES simstr 1.7.0
) )
FetchContent_MakeAvailable(simstr) FetchContent_MakeAvailable(simstr)
endfunction() 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) [![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.6.7. Версия 1.7.0.
<h2>Ускорь работу со строками в 2-10 раз!</h2> <h2>Ускорь работу со строками в 2-10 раз!</h2>
@ -26,7 +26,7 @@
и пригодится другим людям, либо напрямую, либо как источник идей. и пригодится другим людям, либо напрямую, либо как источник идей.
Библиотека содержит две части: Библиотека содержит две части:
- Реализация [*"Строковых выражений"*](https://orefkov.github.io/simstr/docs_ru/overview.html#autotoc_md27) и алгоритмов работы - Реализация [*"Строковых выражений"*](https://orefkov.github.io/simstr/articles/fast_concat_ru.html) и алгоритмов работы
с константными строками.\ с константными строками.\
Для использования этой части достаточно просто взять файл `"include/simstr/strexpr.h"` и написать в своём коде Для использования этой части достаточно просто взять файл `"include/simstr/strexpr.h"` и написать в своём коде
```cpp ```cpp
@ -70,11 +70,13 @@
- Слияние (join) контейнеров строк в единую строку, с заданием разделителей и опций - "пропускать пустые", "разделитель после последней". - Слияние (join) контейнеров строк в единую строку, с заданием разделителей и опций - "пропускать пустые", "разделитель после последней".
- Разбиение (split) строк на части по заданному разделителю. Разбиение возможно сразу в контейнер со строками, либо вызовом функтора для - Разбиение (split) строк на части по заданному разделителю. Разбиение возможно сразу в контейнер со строками, либо вызовом функтора для
каждой подстроки, либо путем итерации с помощью итератора `Splitter`. каждой подстроки, либо путем итерации с помощью итератора `Splitter`.
- Создании копии со сменой регистра ASCII символов.
- Функции модификации стандартных строк строковыми выражениями: - Функции модификации стандартных строк строковыми выражениями:
- str::append, str::prepend, str::insert, str::change - меняют str::string строковыми выражениями, - str::append, str::prepend, str::insert, str::change - меняют str::string строковыми выражениями,
например `str::append(text, "count = "_ss + count)`. например `str::append(text, "count = "_ss + count)`.
- str::replace - заменяет вхождения искомой подстроки на строку замены или строковое выражение. - str::replace - заменяет вхождения искомой подстроки на строку замены или строковое выражение.
Если подстрока не найдена, строковое выражение даже не вычисляется. Если подстрока не найдена, строковое выражение даже не вычисляется.
- str::make_ascii_upper, str::make_ascii_lower - смена регистра ASCII символов.
- Парсинг целых чисел с возможностью "тонкой" настройки при компиляции - можно задавать опции проверки переполнения, - Парсинг целых чисел с возможностью "тонкой" настройки при компиляции - можно задавать опции проверки переполнения,
пропуск пробельных символов, конкретное основание счисления либо автовыбор по префиксам `0x`, `0`, `0b`, `0o`, пропуск пробельных символов, конкретное основание счисления либо автовыбор по префиксам `0x`, `0`, `0b`, `0o`,
допустимость знака `+`. Парсинг реализован для всех видов строк и символов. допустимость знака `+`. Парсинг реализован для всех видов строк и символов.
@ -323,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.6.7 # Укажите нужный релиз GIT_TAG tags/rel1.7.0 # Укажите нужный релиз
FIND_PACKAGE_ARGS NAMES simstr 1.6.7 FIND_PACKAGE_ARGS NAMES simstr 1.7.0
) )
FetchContent_MakeAvailable(simstr) FetchContent_MakeAvailable(simstr)
endfunction() endfunction()

View File

@ -1,5 +1,5 @@
/* /*
* ver. 1.6.7 * ver. 1.7.0
* (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
@ -187,9 +187,11 @@ inline u32s makeFoldU(u32s s) {
/* /*
* Поиск utf-8 symbols, которые меняют свою длину при upper/lower преобразовании * Поиск utf-8 symbols, которые меняют свою длину при upper/lower преобразовании
* вот они нашлись * вот они нашлись
* Search for utf-8 codepoints that change their code units length during upper/lower conversion
* here they are found
* "İiıIſSȺⱥȾⱦɐⱯɑⱭɫⱢɱⱮɽⱤẞßΙΩωkÅåⱢɫⱤɽⱥȺⱦȾⱭɑⱮɱⱯɐ" * "İiıIſSȺⱥȾⱦɐⱯɑⱭɫⱢɱⱮɽⱤẞßΙΩωkÅåⱢɫⱤɽⱥȺⱦȾⱭɑⱮɱⱯɐ"
l2u ıIſSɐⱯɑⱭɫⱢɱⱮɽⱤΙⱥȺⱦȾ l2u ıI ſS ɐ ɑ ɫ ɱ ɽ Ι Ⱥ Ⱦ
u2l İiȺⱥȾⱦẞßΩωkÅåⱢɫⱤɽⱭɑⱮɱⱯɐ u2l İi Ⱥ Ⱦ ß ω k å ɫ ɽ ɑ ɱ ɐ
void findStrange() { void findStrange() {
u16s badsL2U[100], * pBadslu = badsL2U; u16s badsL2U[100], * pBadslu = badsL2U;
u16s badsU2L[100], * pBadsul = badsU2L; u16s badsU2L[100], * pBadsul = badsU2L;
@ -386,6 +388,32 @@ SIMSTR_API size_t unicode_traits<u8s>::lower(const u8s*& src, size_t len, u8s*&
return utf8_case_change<makeLowerU>(src, len, dest, lenBuffer); return utf8_case_change<makeLowerU>(src, len, dest, lenBuffer);
} }
SIMSTR_API size_t unicode_traits<u8s>::upper_len(const u8s* src, size_t len) {
size_t l = 0;
for (const uu8s *ptr = (const uu8s*)src, *start = ptr, *end = ptr + len; ptr < end; start = ptr) {
u32s s = readUtf8Symbol(ptr, end), su = makeUpperU(s);
if (s == su) {
l += ptr - start;
} else {
l += utf8len(su);
}
}
return l;
}
SIMSTR_API size_t unicode_traits<u8s>::lower_len(const u8s* src, size_t len) {
size_t l = 0;
for (const uu8s *ptr = (const uu8s*)src, *start = ptr, *end = ptr + len; ptr < end; start = ptr) {
u32s s = readUtf8Symbol(ptr, end), su = makeLowerU(s);
if (s == su) {
l += ptr - start;
} else {
l += utf8len(su);
}
}
return l;
}
template<auto Op> template<auto Op>
void utf16_change_case(const u16s* src, size_t len, u16s* dest) { void utf16_change_case(const u16s* src, size_t len, u16s* dest) {
if (dest != src) { if (dest != src) {

View File

@ -1,5 +1,5 @@
/* /*
* ver. 1.6.7 * ver. 1.7.0
* (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
@ -406,4 +406,25 @@ TEST(StrExpr, EIntFmt) {
EXPECT_EQ(test, "0b01100100"); EXPECT_EQ(test, "0b01100100");
} }
TEST(StrExpr, ChangeCase) {
std::string res = e_ascii_upper("teSt");
EXPECT_EQ(res, "TEST");
res = "/" + e_ascii_lower(res) + "/";
EXPECT_EQ(res, "/test/");
EXPECT_EQ(str::make_ascii_upper(res), "/TEST/");
str::make_ascii_lower(res, 1, 3);
EXPECT_EQ(res, "/teST/");
std::wstring wres = e_ascii_lower(L"TeSt"_ss);
EXPECT_EQ(wres, L"test");
std::u16string ures = u"/test/";
EXPECT_EQ(str::make_ascii_upper(ures), u"/TEST/");
str::make_ascii_lower(ures, 1, 3);
EXPECT_EQ(ures, u"/teST/");
}
} // namespace simstr::tests } // namespace simstr::tests

View File

@ -1,5 +1,5 @@
/* /*
* ver. 1.6.7 * ver. 1.7.0
* (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
@ -2023,7 +2023,28 @@ TEST(SimStr, EIntFmt) {
EXPECT_EQ(textu, u"val = 0x0000012A"); EXPECT_EQ(textu, u"val = 0x0000012A");
} }
#ifndef _MSC_VER TEST(SimStr, EChangeCase) {
stringa test = e_upper("teSt");
EXPECT_EQ(test, "TEST");
test = e_lower(test);
EXPECT_EQ(test, "test");
test = e_upper("ɐ ɑ ı ſ");
EXPECT_EQ(test, "Ɐ Ɑ I S");
test = "-" + e_lower("İ Ⱥ Ⱦ ẞ") + "-";
EXPECT_EQ(test, "-i ⱥ ⱦ ß-");
stringu utest = e_upper(u"teSt");
EXPECT_EQ(utest, u"TEST");
utest = e_lower(utest);
EXPECT_EQ(utest, u"test");
utest = e_upper(u"ı ſ ɐ ɑ");
EXPECT_EQ(utest, u"I S Ɐ Ɑ");
utest = u"-" + e_lower(u"İ Ⱥ Ⱦ ẞ") + u"-";
EXPECT_EQ(utest, u"-i ⱥ ⱦ ß-");
}
#ifndef _MSC_VER
void check_equal(stra a, stra b) { void check_equal(stra a, stra b) {
EXPECT_EQ(a, b); EXPECT_EQ(a, b);
} }

View File

@ -1,5 +1,5 @@
/* /*
* ver. 1.6.7 * ver. 1.7.0
* (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