mirror of https://github.com/orefkov/simstr.git
1.7.0
- 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:
parent
8610bea2a9
commit
7bb7ddb766
|
|
@ -5,7 +5,7 @@ include(FetchContent)
|
|||
|
||||
project(
|
||||
simstr
|
||||
VERSION 1.6.7
|
||||
VERSION 1.7.0
|
||||
DESCRIPTION "Yet another modern C++ string library"
|
||||
HOMEPAGE_URL "https://github.com/orefkov/simstr"
|
||||
LANGUAGES CXX
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.7
|
||||
* ver. 1.7.0
|
||||
* (c) Проект "SimStr", Александр Орефков 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(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) {
|
||||
std::cout << "Benchmarks of simstr, version " SIMSTR_VERSION << "\n"
|
||||
<< "Sources: https://github.com/orefkov/simstr\n"
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@
|
|||
|
||||
<body>
|
||||
<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://github.com/orefkov/simstr/blob/main/bench/bench_str.cpp" target="blank">Sources for
|
||||
benchmarks</a></span>
|
||||
|
|
|
|||
1437
bench/results.html
1437
bench/results.html
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -48,7 +48,7 @@ PROJECT_NAME = "simstr"
|
|||
# could be handy for archiving the generated documentation or if some version
|
||||
# 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
|
||||
# for a project that appears at the top of each page and should give viewers a
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ PROJECT_NAME = "simstr"
|
|||
# could be handy for archiving the generated documentation or if some version
|
||||
# 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
|
||||
# for a project that appears at the top of each page and should give viewers a
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* ver. 1.6.7
|
||||
* ver. 1.7.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.7
|
||||
* ver. 1.7.0
|
||||
* (c) Проект "SimStr", Александр Орефков 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
|
||||
// processed characters to resume work again,
|
||||
// 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 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);
|
||||
|
||||
|
|
@ -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
|
||||
template<typename K, typename... Args>
|
||||
|
|
@ -4884,6 +4911,94 @@ inline HashKeyIU<uws> operator""_iu(const uws* ptr, size_t l) {
|
|||
}
|
||||
} // 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.
|
||||
* @param stream - поток вывода.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.7
|
||||
* ver. 1.7.0
|
||||
* (c) Проект "SimStr", Александр Орефков 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)
|
||||
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 Небольшое пространство для методов работы со стандартными строками.
|
||||
* @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);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @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 simstr
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
[](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>
|
||||
|
||||
|
|
@ -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.
|
||||
|
||||
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.\
|
||||
To use this part, just take the file `"include/simstr/strexpr.h"` and write in your code
|
||||
```cpp
|
||||
|
|
@ -75,6 +75,7 @@ When using only `#include "simstr/strexpr.h"`:
|
|||
for example `str::append(text, "count = "_ss + count)`.
|
||||
- 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.
|
||||
- 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,
|
||||
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.
|
||||
|
|
@ -323,8 +324,8 @@ function(add_simstr)
|
|||
simstr
|
||||
GIT_REPOSITORY https://github.com/orefkov/simstr.git
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_TAG tags/rel1.6.7 # Specify the desired release
|
||||
FIND_PACKAGE_ARGS NAMES simstr 1.6.7
|
||||
GIT_TAG tags/rel1.7.0 # Specify the desired release
|
||||
FIND_PACKAGE_ARGS NAMES simstr 1.7.0
|
||||
)
|
||||
FetchContent_MakeAvailable(simstr)
|
||||
endfunction()
|
||||
|
|
|
|||
10
readme_ru.md
10
readme_ru.md
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
||||
|
||||
Версия 1.6.7.
|
||||
Версия 1.7.0.
|
||||
|
||||
<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"` и написать в своём коде
|
||||
```cpp
|
||||
|
|
@ -70,11 +70,13 @@
|
|||
- Слияние (join) контейнеров строк в единую строку, с заданием разделителей и опций - "пропускать пустые", "разделитель после последней".
|
||||
- Разбиение (split) строк на части по заданному разделителю. Разбиение возможно сразу в контейнер со строками, либо вызовом функтора для
|
||||
каждой подстроки, либо путем итерации с помощью итератора `Splitter`.
|
||||
- Создании копии со сменой регистра ASCII символов.
|
||||
- Функции модификации стандартных строк строковыми выражениями:
|
||||
- str::append, str::prepend, str::insert, str::change - меняют str::string строковыми выражениями,
|
||||
например `str::append(text, "count = "_ss + count)`.
|
||||
- str::replace - заменяет вхождения искомой подстроки на строку замены или строковое выражение.
|
||||
Если подстрока не найдена, строковое выражение даже не вычисляется.
|
||||
- str::make_ascii_upper, str::make_ascii_lower - смена регистра ASCII символов.
|
||||
- Парсинг целых чисел с возможностью "тонкой" настройки при компиляции - можно задавать опции проверки переполнения,
|
||||
пропуск пробельных символов, конкретное основание счисления либо автовыбор по префиксам `0x`, `0`, `0b`, `0o`,
|
||||
допустимость знака `+`. Парсинг реализован для всех видов строк и символов.
|
||||
|
|
@ -323,8 +325,8 @@ function(add_simstr)
|
|||
simstr
|
||||
GIT_REPOSITORY https://github.com/orefkov/simstr.git
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_TAG tags/rel1.6.7 # Укажите нужный релиз
|
||||
FIND_PACKAGE_ARGS NAMES simstr 1.6.7
|
||||
GIT_TAG tags/rel1.7.0 # Укажите нужный релиз
|
||||
FIND_PACKAGE_ARGS NAMES simstr 1.7.0
|
||||
)
|
||||
FetchContent_MakeAvailable(simstr)
|
||||
endfunction()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.7
|
||||
* ver. 1.7.0
|
||||
* (c) Проект "SimStr", Александр Орефков 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 преобразовании
|
||||
* вот они нашлись
|
||||
* Search for utf-8 codepoints that change their code units length during upper/lower conversion
|
||||
* here they are found
|
||||
* "İiıIſSȺⱥȾⱦɐⱯɑⱭɫⱢɱⱮɽⱤẞßιΙΩωKkÅåⱢɫⱤɽⱥȺⱦȾⱭɑⱮɱⱯɐ"
|
||||
l2u ıIſSɐⱯɑⱭɫⱢɱⱮɽⱤιΙⱥȺⱦȾ
|
||||
u2l İiȺⱥȾⱦẞßΩωKkÅåⱢɫⱤɽⱭɑⱮɱⱯɐ
|
||||
l2u ıI ſS ɐⱯ ɑⱭ ɫⱢ ɱⱮ ɽⱤ ιΙ ⱥȺ ⱦȾ
|
||||
u2l İi Ⱥⱥ Ⱦⱦ ẞß Ωω Kk Åå Ɫɫ Ɽɽ Ɑɑ Ɱɱ Ɐɐ
|
||||
void findStrange() {
|
||||
u16s badsL2U[100], * pBadslu = badsL2U;
|
||||
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);
|
||||
}
|
||||
|
||||
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>
|
||||
void utf16_change_case(const u16s* src, size_t len, u16s* dest) {
|
||||
if (dest != src) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.7
|
||||
* ver. 1.7.0
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* Тесты simstr
|
||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||
|
|
@ -406,4 +406,25 @@ TEST(StrExpr, EIntFmt) {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.7
|
||||
* ver. 1.7.0
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* Тесты simstr
|
||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||
|
|
@ -2023,7 +2023,28 @@ TEST(SimStr, EIntFmt) {
|
|||
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) {
|
||||
EXPECT_EQ(a, b);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.7
|
||||
* ver. 1.7.0
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* Тесты simstr
|
||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||
|
|
|
|||
Loading…
Reference in New Issue