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(
|
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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
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
|
# 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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 - поток вывода.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
||||||
|
|
||||||
Version 1.6.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()
|
||||||
|
|
|
||||||
10
readme_ru.md
10
readme_ru.md
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
||||||
|
|
||||||
Версия 1.6.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()
|
||||||
|
|
|
||||||
|
|
@ -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,6 +187,8 @@ 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ȺⱥȾⱦɐⱯɑⱭɫⱢɱⱮɽⱤẞßιΙΩωKkÅåⱢɫⱤɽⱥȺⱦȾⱭɑⱮɱⱯɐ"
|
* "İiıIſSȺⱥȾⱦɐⱯɑⱭɫⱢɱⱮɽⱤẞßιΙΩωKkÅåⱢɫⱤɽⱥȺⱦȾⱭɑⱮɱⱯɐ"
|
||||||
l2u ıI ſS ɐⱯ ɑⱭ ɫⱢ ɱⱮ ɽⱤ ιΙ ⱥȺ ⱦȾ
|
l2u ıI ſS ɐⱯ ɑⱭ ɫⱢ ɱⱮ ɽⱤ ιΙ ⱥȺ ⱦȾ
|
||||||
u2l İi Ⱥⱥ Ⱦⱦ ẞß Ωω Kk Åå Ɫɫ Ɽɽ Ɑɑ Ɱɱ Ɐɐ
|
u2l İi Ⱥⱥ Ⱦⱦ ẞß Ωω Kk Åå Ɫɫ Ɽɽ Ɑɑ Ɱɱ Ɐɐ
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,6 +2023,27 @@ TEST(SimStr, EIntFmt) {
|
||||||
EXPECT_EQ(textu, u"val = 0x0000012A");
|
EXPECT_EQ(textu, u"val = 0x0000012A");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue