mirror of https://github.com/orefkov/simstr.git
- Add new string class - cestring, constexpr string. Worked in consteval.
- Change lstring allocation align to 16 bytes. - Update version to 1.6.1
This commit is contained in:
parent
ce3fe2204c
commit
928ed1af23
|
|
@ -5,7 +5,7 @@ include(FetchContent)
|
|||
|
||||
project(
|
||||
simstr
|
||||
VERSION 1.6.0
|
||||
VERSION 1.6.1
|
||||
DESCRIPTION "Yet another modern C++ string library"
|
||||
HOMEPAGE_URL "https://github.com/orefkov/simstr"
|
||||
LANGUAGES CXX
|
||||
|
|
|
|||
|
|
@ -69,24 +69,54 @@ BENCHMARK(ConcatSimToStd) ->Name("Concat std::string and number by StrExpr
|
|||
BENCHMARK(ConcatSimToSim) ->Name("Concat stringa and number by StrExpr to simstr::stringa");
|
||||
BENCHMARK(ConcatSimToSimConcat) ->Name("Concat stringa and number by e_concat to simstr::stringa");
|
||||
|
||||
void ConcatStdToStdHex(benchmark::State& state) {
|
||||
void ConcatStdToFmtHex(benchmark::State& state) {
|
||||
// We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer.
|
||||
std::string s1 = "art ";
|
||||
for (auto _: state) {
|
||||
for (unsigned i = 1; i <= 100'000; i *= 10) {
|
||||
benchmark::DoNotOptimize(s1);
|
||||
// What is standard method to get hex number?
|
||||
std::string str = std::format("{}0x{:x} end", s1, i);
|
||||
// It is not worked for char8_t, char16_t, char32_t :(
|
||||
std::string str = s1 + std::format("{:#x}", i) + " end";
|
||||
benchmark::DoNotOptimize(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConcatAllFmtToHex(benchmark::State& state) {
|
||||
// We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer.
|
||||
std::string s1 = "art ";
|
||||
for (auto _: state) {
|
||||
for (unsigned i = 1; i <= 100'000; i *= 10) {
|
||||
benchmark::DoNotOptimize(s1);
|
||||
// It is not worked for char8_t, char16_t, char32_t :(
|
||||
std::string str = std::format("{}{:#x} end", s1, i);
|
||||
benchmark::DoNotOptimize(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ConcatStdToCharsHex(benchmark::State& state) {
|
||||
// We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer.
|
||||
std::string s1 = "art ";
|
||||
for (auto _: state) {
|
||||
for (unsigned i = 1; i <= 100'000; i *= 10) {
|
||||
benchmark::DoNotOptimize(s1);
|
||||
// it worked only for char :(
|
||||
char buf[40];
|
||||
size_t len = std::to_chars(buf, buf + std::size(buf), i, 16).ptr - buf;
|
||||
std::string str = s1 + "0x" + std::string(buf, len) + " end";
|
||||
benchmark::DoNotOptimize(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConcatSimToStdHex(benchmark::State& state) {
|
||||
// We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer.
|
||||
std::string s1 = "art ";
|
||||
for (auto _: state) {
|
||||
for (unsigned i = 1; i <= 100'000; i *= 10) {
|
||||
benchmark::DoNotOptimize(s1);
|
||||
// Can work for all types of symbols
|
||||
std::string str = +s1 + e_hex<HexFlags::Short>(i) + " end";
|
||||
benchmark::DoNotOptimize(str);
|
||||
}
|
||||
|
|
@ -99,6 +129,7 @@ void ConcatSimToSimHex(benchmark::State& state) {
|
|||
for (auto _: state) {
|
||||
for (unsigned i = 1; i <= 100'000; i *= 10) {
|
||||
benchmark::DoNotOptimize(s1);
|
||||
// Can work for all types of symbols
|
||||
stringa str = s1 + e_hex<HexFlags::Short>(i) + " end";
|
||||
benchmark::DoNotOptimize(str);
|
||||
}
|
||||
|
|
@ -111,6 +142,7 @@ void ConcatSimToSimHexC(benchmark::State& state) {
|
|||
for (auto _: state) {
|
||||
for (unsigned i = 1; i <= 100'000; i *= 10) {
|
||||
benchmark::DoNotOptimize(s1);
|
||||
// Can work for all types of symbols
|
||||
stringa str = e_concat("", s1, e_hex<HexFlags::Short>(i), " end");
|
||||
benchmark::DoNotOptimize(str);
|
||||
}
|
||||
|
|
@ -130,11 +162,13 @@ void ConcatSimToSimHexS(benchmark::State& state) {
|
|||
}
|
||||
|
||||
BENCHMARK(__)->Name("----- Concatenate string + Hex Number + \"Literal\" ---------")->Repetitions(1);
|
||||
BENCHMARK(ConcatStdToStdHex) ->Name("Concat std::string and hex number by std to std::string");
|
||||
BENCHMARK(ConcatSimToStdHex) ->Name("Concat std::string and hex number by StrExpr to std::string");
|
||||
BENCHMARK(ConcatSimToSimHex) ->Name("Concat stringa and hex number by StrExpr to simstr::stringa");
|
||||
BENCHMARK(ConcatSimToSimHexC) ->Name("Concat stringa and hex number by e_concat to simstr::stringa");
|
||||
BENCHMARK(ConcatSimToSimHexS) ->Name("Concat stringa and hex number by e_subst to simstr::stringa");
|
||||
BENCHMARK(ConcatStdToFmtHex) ->Name("Concat std::string and format hex number and literal to std::string");
|
||||
BENCHMARK(ConcatAllFmtToHex) ->Name("std::format std::string and hex number by literal to std::string");
|
||||
BENCHMARK(ConcatStdToCharsHex) ->Name("Concat std::string and std::tochars and string to std::string");
|
||||
BENCHMARK(ConcatSimToStdHex) ->Name("Concat std::string and hex number and literal by StrExpr to std::string");
|
||||
BENCHMARK(ConcatSimToSimHex) ->Name("Concat stringa and hex number and literal by StrExpr to simstr::stringa");
|
||||
BENCHMARK(ConcatSimToSimHexC) ->Name("Concat stringa and hex number and literal by e_concat to simstr::stringa");
|
||||
BENCHMARK(ConcatSimToSimHexS) ->Name("Subst stringa and hex number by e_subst literal to simstr::stringa");
|
||||
|
||||
void ConcatStdToStdS(benchmark::State& state) {
|
||||
std::string s1 = "start ";
|
||||
|
|
|
|||
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.0
|
||||
PROJECT_NUMBER = 1.6.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
|
||||
|
|
|
|||
|
|
@ -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.0
|
||||
PROJECT_NUMBER = 1.6.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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* ver. 1.6.0
|
||||
* ver. 1.6.1
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* ver. 1.6.0
|
||||
* ver. 1.6.1
|
||||
* Классы для работы со строками
|
||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||
* ver. 1.6.0
|
||||
* ver. 1.6.1
|
||||
* Classes for working with strings
|
||||
*/
|
||||
|
||||
|
|
@ -767,10 +767,9 @@ protected:
|
|||
init(size_t size)
|
||||
set_size(size_t size)
|
||||
*/
|
||||
public:
|
||||
template<typename O>
|
||||
requires(!std::is_same_v<O, K>)
|
||||
from_utf_convertible(simple_str<O> init) {
|
||||
void init_from_utf_convertible(simple_str<O> init) {
|
||||
using worker = utf_convert_selector<O, K>;
|
||||
Impl* d = static_cast<Impl*>(this);
|
||||
size_t len = init.length();
|
||||
|
|
@ -783,9 +782,6 @@ public:
|
|||
worker::convert(init.symbols(), len, str);
|
||||
}
|
||||
}
|
||||
template<typename O, typename I, bool M>
|
||||
requires(!std::is_same_v<O, K>)
|
||||
from_utf_convertible(const str_algs<O, simple_str<O>, I, M>& init) : from_utf_convertible(init.to_str()) {}
|
||||
};
|
||||
|
||||
/*!
|
||||
|
|
@ -2700,8 +2696,6 @@ protected:
|
|||
friend class sstring<K, Allocator>;
|
||||
|
||||
K* data_;
|
||||
// Поле не должно инициализироваться, так как может устанавливаться в базовых конструкторах
|
||||
// The field should not be initialized, as it can be set in base constructors
|
||||
size_t size_;
|
||||
|
||||
union {
|
||||
|
|
@ -2715,8 +2709,9 @@ protected:
|
|||
local_[0] = 0;
|
||||
}
|
||||
constexpr static size_t calc_capacity(size_t s) {
|
||||
const int al = alignof(std::max_align_t) < 16 ? 16 : alignof(std::max_align_t);
|
||||
size_t real_need = (s + 1) * sizeof(K) + extra;
|
||||
size_t aligned_alloced = (real_need + alignof(std::max_align_t) - 1) / alignof(std::max_align_t) * alignof(std::max_align_t);
|
||||
size_t aligned_alloced = (real_need + al - 1) / al * al;
|
||||
return (aligned_alloced - extra) / sizeof(K) - 1;
|
||||
}
|
||||
|
||||
|
|
@ -2778,8 +2773,6 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
using base_utf::base_utf;
|
||||
|
||||
/*!
|
||||
* @ru @brief Создать пустой объект.
|
||||
* @param ...args - параметры для инициализации аллокатора.
|
||||
|
|
@ -2965,6 +2958,17 @@ public:
|
|||
create_empty();
|
||||
this->operator<<(op);
|
||||
}
|
||||
template<typename O>
|
||||
requires(!std::is_same_v<O, K>)
|
||||
lstring(simple_str<O> init) {
|
||||
this->init_from_utf_convertible(init);
|
||||
}
|
||||
|
||||
template<typename O, typename I, bool M>
|
||||
requires(!std::is_same_v<O, K>)
|
||||
lstring(const str_algs<O, simple_str<O>, I, M>& init) {
|
||||
this->init_from_utf_convertible(init.to_str());
|
||||
}
|
||||
|
||||
// copy and swap для присваиваний здесь не очень применимо, так как для строк с большим локальным буфером лишняя копия даже перемещением будет дорого стоить
|
||||
// Поэтому реализуем копирующее и перемещающее присваивание отдельно
|
||||
|
|
@ -3057,7 +3061,7 @@ public:
|
|||
return assign(other, S - 1);
|
||||
}
|
||||
/*!
|
||||
* @ru @brief Оператор присаивания строкового выражения.
|
||||
* @ru @brief Оператор присваивания строкового выражения.
|
||||
* @param expr - строковое выражение, материализуемое в буфер строки.
|
||||
* @return my_type& - ссылку на себя же.
|
||||
* @details Если в строковом выражении что-либо ссылается на части этой же строки, то результат не определён.
|
||||
|
|
@ -3439,7 +3443,6 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
using base_utf::base_utf;
|
||||
|
||||
sstring() {
|
||||
create_empty();
|
||||
|
|
@ -3638,6 +3641,21 @@ public:
|
|||
bigLen_ = N - 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @ru @brief Инициализация из строкового источника с другим типом символов. Конвертирует через UTF.
|
||||
* @tparam O - тип жругих символов.
|
||||
* @en @brief Initialization from a string source with a different character type. Converts via UTF.
|
||||
* @tparam O - type of other characters. */
|
||||
template<typename O> requires(!std::is_same_v<O, K>)
|
||||
sstring(simple_str<O> init) {
|
||||
this->init_from_utf_convertible(init);
|
||||
}
|
||||
|
||||
template<typename O, typename I, bool M> requires(!std::is_same_v<O, K>)
|
||||
sstring(const str_algs<O, simple_str<O>, I, M>& init) {
|
||||
this->init_from_utf_convertible(init.to_str());
|
||||
}
|
||||
|
||||
constexpr void swap(my_type&& other) noexcept {
|
||||
char buf[sizeof(buf_) + sizeof(K)];
|
||||
memcpy(buf, buf_, sizeof(buf));
|
||||
|
|
@ -3795,6 +3813,160 @@ public:
|
|||
template<typename K, Allocatorable Allocator>
|
||||
inline const sstring<K> sstring<K, Allocator>::empty_str{};
|
||||
|
||||
struct no_alloc{};
|
||||
|
||||
template<typename K, size_t N>
|
||||
class decl_empty_bases cestring :
|
||||
public str_algs<K, simple_str<K>, cestring<K, N>, true>,
|
||||
public str_storable<K, cestring<K, N>, no_alloc>,
|
||||
public null_terminated<K, lstring<K, N>>
|
||||
//, public from_utf_convertible<K, lstring<K, N, forShared, Allocator>>
|
||||
{
|
||||
using symb_type = K;
|
||||
using my_type = cestring<K, N>;
|
||||
|
||||
enum : size_t {
|
||||
/// @ru Размер внутреннего буфера в символах @en Size of internal buffer
|
||||
LocalCapacity = N | (sizeof(void*) / sizeof(K) - 1),
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
using base_algs = str_algs<K, simple_str<K>, my_type, true>;
|
||||
using base_storable = str_storable<K, my_type, no_alloc>;
|
||||
//using base_utf = from_utf_convertible<K, my_type>;
|
||||
using traits = ch_traits<K>;
|
||||
using s_str = base_storable::s_str;
|
||||
|
||||
friend base_storable;
|
||||
//friend base_utf;
|
||||
const K* cstr_{};
|
||||
size_t size_{};
|
||||
bool is_cstr_{};
|
||||
K local_[LocalCapacity + 1]{};
|
||||
|
||||
constexpr void create_empty() {
|
||||
is_cstr_ = false;
|
||||
size_ = 0;
|
||||
local_[0] = 0;
|
||||
}
|
||||
|
||||
constexpr K* init(size_t s) {
|
||||
size_ = s;
|
||||
if (size_ > LocalCapacity) {
|
||||
throw std::bad_alloc{};
|
||||
}
|
||||
is_cstr_ = false;
|
||||
return local_;
|
||||
}
|
||||
public:
|
||||
/// @ru Длина строки. @en String length.
|
||||
constexpr size_t length() const noexcept {
|
||||
return size_;
|
||||
}
|
||||
/// @ru Указатель на константные символы. @en Pointer to constant characters.
|
||||
constexpr const K* symbols() const noexcept {
|
||||
return is_cstr_ ? cstr_ : local_;
|
||||
}
|
||||
/// @ru Пустая ли строка. @en Is the string empty?
|
||||
constexpr bool is_empty() const noexcept {
|
||||
return size_ == 0;
|
||||
}
|
||||
/// @ru Пустая ли строка, для совместимости с std::string. @en Whether the string is empty, for compatibility with std::string.
|
||||
constexpr bool empty() const noexcept {
|
||||
return size_ == 0;
|
||||
}
|
||||
/// @ru Текущая ёмкость буфера строки. @en Current row buffer capacity.
|
||||
constexpr size_t capacity() const noexcept {
|
||||
return LocalCapacity;
|
||||
}
|
||||
/*!
|
||||
* @ru @brief Конструктор пустой строки.
|
||||
* @en @brief Constructor for the empty string.
|
||||
*/
|
||||
constexpr cestring() noexcept = default;
|
||||
|
||||
/*!
|
||||
* @ru @brief Конструктор из другого строкового объекта.
|
||||
* @param other - другой строковый объект, simple_str.
|
||||
* @en @brief A constructor from another string object.
|
||||
* @param other - another string object, simple_str.
|
||||
*/
|
||||
constexpr cestring(s_str other) : base_storable() {
|
||||
base_storable::init_from_str_other(other);
|
||||
}
|
||||
/*!
|
||||
* @ru @brief Конструктор повторения строки.
|
||||
* @param repeat - количество повторов.
|
||||
* @param pattern - строка, которую надо повторить.
|
||||
* @en @brief String repetition constructor.
|
||||
* @param repeat - number of repetitions.
|
||||
* @param pattern - the line to be repeated.
|
||||
*/
|
||||
constexpr cestring(size_t repeat, s_str pattern) : base_storable() {
|
||||
base_storable::init_str_repeat(repeat, pattern);
|
||||
}
|
||||
/*!
|
||||
* @ru @brief Конструктор повторения символа.
|
||||
* @param count - количество повторов.
|
||||
* @param pad - символ, который надо повторить.
|
||||
* @en @brief Character repetition constructor.
|
||||
* @param count - number of repetitions.
|
||||
* @param pad - the character to be repeated.
|
||||
*/
|
||||
constexpr cestring(size_t count, K pad) : base_storable() {
|
||||
base_storable::init_symb_repeat(count, pad);
|
||||
}
|
||||
/*!
|
||||
* @ru @brief Конструктор из строкового выражения.
|
||||
* @param expr - строковое выражение.
|
||||
* @details Конструктор запрашивает у строкового выражения `length()`,
|
||||
* выделяет память нужного размера, и вызывает метод `place()` для размещения
|
||||
* результата в буфере.
|
||||
* @en @brief Constructor from a string expression.
|
||||
* @param expr - string expression.
|
||||
* @details The constructor queries the string expression `length()`,
|
||||
* allocates memory of the required size, and calls the `place()` method to allocate
|
||||
* result in buffer.
|
||||
*/
|
||||
constexpr cestring(const StrExprForType<K> auto& expr) : base_storable() {
|
||||
base_storable::init_str_expr(expr);
|
||||
}
|
||||
/*!
|
||||
* @ru @brief Конструктор из строкового источника с заменой.
|
||||
* @param f - строковый объект, из которого берётся исходная строка.
|
||||
* @param pattern - подстрока, которую надо заменить.
|
||||
* @param repl - строка, на которую надо заменить.
|
||||
* @param offset - начальная позиция для поиска подстрок.
|
||||
* @param maxCount - максимальное количество замен, 0 - без ограничений.
|
||||
* @en @brief Constructor from string source with replacement.
|
||||
* @param f - the string object from which the source string is taken.
|
||||
* @param pattern - substring to be replaced.
|
||||
* @param repl - the string to be replaced with.
|
||||
* @param offset - starting position for searching substrings.
|
||||
* @param maxCount - maximum number of replacements, 0 - no restrictions.
|
||||
*/
|
||||
template<StrType<K> From>
|
||||
constexpr cestring(const From& f, s_str pattern, s_str repl, size_t offset = 0, size_t maxCount = 0)
|
||||
: base_storable() {
|
||||
base_storable::init_replaced(f, pattern, repl, offset, maxCount);
|
||||
}
|
||||
|
||||
/// @ru Деструктор строки. @en String destructor.
|
||||
constexpr ~cestring() {}
|
||||
|
||||
/*!
|
||||
* @ru @brief Инициализация из строкового литерала.
|
||||
* @param s - строковый литерал.
|
||||
* @details В этом случае просто запоминаем указатель на строку и её длину.
|
||||
* @en @brief Initialize from a string literal.
|
||||
* @param s - string literal.
|
||||
* @details In this case, we simply remember the pointer to the string and its length.
|
||||
*/
|
||||
template<typename T, size_t M = const_lit_for<K, T>::Count>
|
||||
constexpr cestring(T&& s) : base_storable(), cstr_(s), size_(M - 1), is_cstr_(true), local_{0} {}
|
||||
};
|
||||
|
||||
template<typename K>
|
||||
consteval simple_str_nt<K> select_str(simple_str_nt<u8s> s8, simple_str_nt<ubs> sb, simple_str_nt<uws> sw, simple_str_nt<u16s> s16, simple_str_nt<u32s> s32) {
|
||||
if constexpr (std::is_same_v<K, u8s>)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.0
|
||||
* ver. 1.6.1
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* База для строковых конкатенаций через выражения времени компиляции
|
||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||
|
|
@ -1759,7 +1759,7 @@ template<typename K, FromIntNumber Val, bool All, bool Ucase, bool Ox>
|
|||
struct expr_hex : expr_to_std_string<expr_hex<K, Val, All, Ucase, Ox>> {
|
||||
using symb_type = K;
|
||||
mutable need_sign<K, std::is_signed_v<Val>, Val> v_;
|
||||
mutable K buf_[sizeof(Val) * 2];
|
||||
mutable K buf_[sizeof(Val) * 2]{};
|
||||
|
||||
explicit constexpr expr_hex(Val v) : v_(v){}
|
||||
constexpr expr_hex(const expr_hex_src<Val, All, Ucase, Ox>& v) : v_(v.v_){}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
||||
|
||||
Version 1.6.0.
|
||||
Version 1.6.1.
|
||||
|
||||
<h2>Speed up your work with strings by 2-10 times!</h2>
|
||||
|
||||
|
|
@ -323,8 +323,8 @@ function(add_simstr)
|
|||
simstr
|
||||
GIT_REPOSITORY https://github.com/orefkov/simstr.git
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_TAG tags/rel1.6.0 # Specify the desired release
|
||||
FIND_PACKAGE_ARGS NAMES simstr 1.6.0
|
||||
GIT_TAG tags/rel1.6.1 # Specify the desired release
|
||||
FIND_PACKAGE_ARGS NAMES simstr 1.6.1
|
||||
)
|
||||
FetchContent_MakeAvailable(simstr)
|
||||
endfunction()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
[](https://github.com/orefkov/simstr/actions/workflows/cmake-multi-platform.yml)
|
||||
|
||||
Версия 1.6.0.
|
||||
Версия 1.6.1.
|
||||
|
||||
<h2>Ускорь работу со строками в 2-10 раз!</h2>
|
||||
|
||||
|
|
@ -324,8 +324,8 @@ function(add_simstr)
|
|||
simstr
|
||||
GIT_REPOSITORY https://github.com/orefkov/simstr.git
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_TAG tags/rel1.6.0 # Укажите нужный релиз
|
||||
FIND_PACKAGE_ARGS NAMES simstr 1.6.0
|
||||
GIT_TAG tags/rel1.6.1 # Укажите нужный релиз
|
||||
FIND_PACKAGE_ARGS NAMES simstr 1.6.1
|
||||
)
|
||||
FetchContent_MakeAvailable(simstr)
|
||||
endfunction()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.0
|
||||
* ver. 1.6.1
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* Реализация строковых функций
|
||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.0
|
||||
* ver. 1.6.1
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* Тесты simstr
|
||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.0
|
||||
* ver. 1.6.1
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* Тесты simstr
|
||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||
|
|
@ -1999,6 +1999,59 @@ TEST(SimStr, Subst) {
|
|||
EXPECT_EQ(u16t, u"Test 1 from 100, success.");
|
||||
}
|
||||
|
||||
void check_equal(stra a, stra b) {
|
||||
EXPECT_EQ(a, b);
|
||||
}
|
||||
|
||||
inline constexpr cestring<char, 100> ce_sample = "sample " + e_subst(S_FRM("test = {}"), e_hex(10)) + ", done";
|
||||
|
||||
TEST(SimStr, ConstEval) {
|
||||
constexpr cestring<char, 100> ce_empty;
|
||||
static_assert(ce_empty.length() == 0);
|
||||
static_assert(ce_empty == "");
|
||||
static_assert(ce_empty.find("aa") == -1);
|
||||
|
||||
constexpr cestring<char, 100> ce_lit = "test";
|
||||
static_assert(ce_lit.length() == 4);
|
||||
static_assert(ce_lit == "test");
|
||||
static_assert(ce_lit.find("st") == 2);
|
||||
static_assert(ce_lit(1, 2) == "es");
|
||||
|
||||
constexpr cestring<char, 100> ce_str = "tester"_ss;
|
||||
static_assert(ce_str.length() == 6);
|
||||
static_assert(ce_str == "tester");
|
||||
static_assert(ce_str.find("te") == 0);
|
||||
static_assert(ce_str.find("ter") == 3);
|
||||
static_assert(ce_str(1, -1) == "este");
|
||||
|
||||
constexpr cestring<char, 100> ce_repeat{10, "tu"};
|
||||
static_assert(ce_repeat.length() == 20);
|
||||
|
||||
constexpr cestring<char, 100> ce_expr = "test = "_ss + 10 + " times";
|
||||
static_assert(ce_expr == "test = 10 times");
|
||||
|
||||
constexpr cestring<char, 100> ce_subst = e_subst(S_FRM("test = {}"), 10);
|
||||
static_assert(ce_subst == "test = 10");
|
||||
|
||||
constexpr cestring<char, 100> ce_hex = e_subst(S_FRM("test = {}"), e_hex(10));
|
||||
static_assert(ce_hex == "test = 0x0000000A");
|
||||
|
||||
constexpr cestring<char, 100> ce_concat = e_concat("", "test = ", 10, " times");
|
||||
static_assert(ce_concat == "test = 10 times");
|
||||
static_assert(ce_concat(6, 3).to_int<int>().value == 10);
|
||||
|
||||
char arr[ce_concat.length()] = {};
|
||||
|
||||
static constexpr cestring<char, 40> ce_copy{ce_concat};
|
||||
static_assert(ce_copy == "test = 10 times");
|
||||
|
||||
check_equal(ce_copy, "test = 10 times");
|
||||
EXPECT_TRUE(ce_copy == "test = 10 times");
|
||||
|
||||
stringa test_copy = ce_sample(0, 10);
|
||||
EXPECT_EQ(test_copy, "sample tes");
|
||||
}
|
||||
|
||||
} // namespace simstr::tests
|
||||
|
||||
TEST(SimStr, StrNoNamespace) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* ver. 1.6.0
|
||||
* ver. 1.6.1
|
||||
* (c) Проект "SimStr", Александр Орефков orefkov@gmail.com
|
||||
* Тесты simstr
|
||||
* (c) Project "SimStr", Aleksandr Orefkov orefkov@gmail.com
|
||||
|
|
|
|||
Loading…
Reference in New Issue