2025-04-05 14:21:11 +00:00
/*
2026-02-15 14:13:54 +00:00
* ver . 1.7 .0
2025-04-05 14:21:11 +00:00
* ( c ) П р о е к т " SimStr " , А л е к с а н д р О р е ф к о в orefkov @ gmail . com
* К л а с с ы д л я р а б о т ы с о с т р о к а м и
2025-11-17 09:01:31 +00:00
* ( c ) Project " SimStr " , Aleksandr Orefkov orefkov @ gmail . com
* Classes for working with strings
2025-04-05 14:21:11 +00:00
*/
2025-11-17 09:01:31 +00:00
/*!
* @ ru @ mainpage Б и б л и о т е к а simstr .
* @ include { doc } " ../readme_ru.md "
2025-04-05 14:21:11 +00:00
* @ page overview О б з о р
2025-11-17 09:01:31 +00:00
* @ includedoc { doc } " overview_ru.md "
* @ en @ mainpage Simstr lib .
* @ include { doc } " ../readme.md "
* @ page overview Overview
2025-04-05 14:21:11 +00:00
* @ includedoc { doc } " overview.md "
*/
# pragma once
2026-01-21 11:59:17 +00:00
2025-04-05 14:21:11 +00:00
# ifndef __has_declspec_attribute
# define __has_declspec_attribute(x) 0
# endif
2026-01-21 11:59:17 +00:00
const bool isWindowsOs = // NOLINT
# ifdef _WIN32
true
# else
false
# endif
;
2025-04-05 14:21:11 +00:00
2025-11-13 14:57:42 +00:00
# ifdef SIMSTR_IN_SHARED
2025-04-05 14:21:11 +00:00
# if defined(_MSC_VER) || (defined(__clang__) && __has_declspec_attribute(dllexport))
# ifdef SIMSTR_EXPORT
# define SIMSTR_API __declspec(dllexport)
# else
# define SIMSTR_API __declspec(dllimport)
# endif
# elif (defined(__GNUC__) || defined(__GNUG__)) && defined(SIMSTR_EXPORT)
# define SIMSTR_API __attribute__((visibility("default")))
# else
# define SIMSTR_API
# endif
# else
# define SIMSTR_API
# endif
2026-01-21 11:59:17 +00:00
# define IN_FULL_SIMSTR
2025-04-05 14:21:11 +00:00
# include "strexpr.h"
# include <format>
# include <unordered_map>
# include <atomic>
# include <memory>
# include <string.h>
# include <iostream>
2025-11-24 13:18:02 +00:00
# include <cmath>
2025-04-05 14:21:11 +00:00
# ifdef _WIN32
# include <stdio.h>
# endif
# ifdef _MSC_VER
// warning C4201 : nonstandard extension used : nameless struct / union
# pragma warning(disable : 4201)
# endif
namespace simstr {
template < typename T >
struct unicode_traits { } ; // NOLINT
template < >
struct unicode_traits < u8s > {
// Эти операции с utf-8 могут изменить длину строки
// Поэтому их специализации отличаются
// В функцию помимо текста и адреса буфера для записи передается размер буфера
// Возвращает длину получающейся строки.
// Если получающеюся строка не влезает в отведенный буфер, указатели устанавливаются на последние
// обработанные символы, для повторного возобновления работы,
// а для оставшихся символов считается нужный размер буфера.
2025-11-17 09:01:31 +00:00
// These utf-8 operations can change the length of the string
// Therefore their specializations are different
// In addition to the text and address of the buffer for writing, the buffer size is passed to the function
// Returns the length of the resulting string.
// 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.
2026-02-15 14:13:54 +00:00
static SIMSTR_API size_t upper ( const u8s * & src , size_t len , u8s * & dest , size_t lenBuf ) ;
2025-04-05 14:21:11 +00:00
static SIMSTR_API size_t lower ( const u8s * & src , size_t len , u8s * & dest , size_t lenBuf ) ;
2026-02-15 14:13:54 +00:00
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 ) ;
2025-04-05 14:21:11 +00:00
static SIMSTR_API int compareiu ( const u8s * text1 , size_t len1 , const u8s * text2 , size_t len2 ) ;
static SIMSTR_API size_t hashia ( const u8s * src , size_t l ) ;
static SIMSTR_API size_t hashiu ( const u8s * src , size_t l ) ;
} ;
template < >
struct unicode_traits < u16s > {
static SIMSTR_API void upper ( const u16s * src , size_t len , u16s * dest ) ;
static SIMSTR_API void lower ( const u16s * src , size_t len , u16s * dest ) ;
static SIMSTR_API int compareiu ( const u16s * text1 , size_t len1 , const u16s * text2 , size_t len2 ) ;
static SIMSTR_API size_t hashia ( const u16s * src , size_t l ) ;
static SIMSTR_API size_t hashiu ( const u16s * src , size_t l ) ;
} ;
template < >
struct unicode_traits < u32s > {
static SIMSTR_API void upper ( const u32s * src , size_t len , u32s * dest ) ;
static SIMSTR_API void lower ( const u32s * src , size_t len , u32s * dest ) ;
static SIMSTR_API int compareiu ( const u32s * text1 , size_t len1 , const u32s * text2 , size_t len2 ) ;
static SIMSTR_API size_t hashia ( const u32s * src , size_t s ) ;
static SIMSTR_API size_t hashiu ( const u32s * src , size_t s ) ;
} ;
template < >
struct unicode_traits < wchar_t > {
static void upper ( const wchar_t * src , size_t len , wchar_t * dest ) {
unicode_traits < wchar_type > : : upper ( to_w ( src ) , len , to_w ( dest ) ) ;
}
static void lower ( const wchar_t * src , size_t len , wchar_t * dest ) {
unicode_traits < wchar_type > : : lower ( to_w ( src ) , len , to_w ( dest ) ) ;
}
static int compareiu ( const wchar_t * text1 , size_t len1 , const wchar_t * text2 , size_t len2 ) {
return unicode_traits < wchar_type > : : compareiu ( to_w ( text1 ) , len1 , to_w ( text2 ) , len2 ) ;
}
static size_t hashia ( const wchar_t * src , size_t s ) {
return unicode_traits < wchar_type > : : hashia ( to_w ( src ) , s ) ;
}
static size_t hashiu ( const wchar_t * src , size_t s ) {
return unicode_traits < wchar_type > : : hashiu ( to_w ( src ) , s ) ;
}
} ;
2026-02-15 14:13:54 +00:00
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 ) ;
}
} ;
2025-04-05 14:21:11 +00:00
# if defined(_MSC_VER) && _MSC_VER <= 1933
template < typename K , typename . . . Args >
using FmtString = std : : _Basic_format_string < K , std : : type_identity_t < Args > . . . > ;
# elif __clang_major__ >= 15 || _MSC_VER > 1933 || __GNUC__ >= 13
template < typename K , typename . . . Args >
using FmtString = std : : basic_format_string < K , std : : type_identity_t < Args > . . . > ;
# else
template < typename K , typename . . . Args >
using FmtString = std : : basic_string_view < K > ;
# endif
2025-11-25 15:55:16 +00:00
template < typename K >
SIMSTR_API std : : optional < double > impl_to_double ( const K * start , const K * end ) ;
2025-04-05 14:21:11 +00:00
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief К л а с с с д о п о л н и т е л ь н ы м и к о н с т а н т н ы м и с т р о к о в ы м и а л г о р и т м а м и .
* @ details Д о п о л н я е т а л г о р и т м ы и з str_src_algs т е м и , к о т о р ы е с в я з а н ы с у п р о щ ё н н ы м ю н и к о д о м и п а р с и н г о м double .
2025-11-17 09:01:31 +00:00
* @ tparam K - т и п с и м в о л о в .
* @ tparam StrRef - т и п х р а н и л и щ а к у с к а с т р о к и .
* @ tparam Impl - к о н е ч н ы й к л а с с н а с л е д н и к .
2026-01-21 11:59:17 +00:00
* @ en @ brief A class with additional constant string algorithms .
* @ details Supplements the algorithms from str_src_algs with those related to simplified Unicode and double parsing .
2025-11-17 09:01:31 +00:00
* @ tparam K - character type .
* @ tparam StrRef - storage type for the string chunk .
* @ tparam Impl - the final class is the successor .
2025-04-05 14:21:11 +00:00
*/
template < typename K , typename StrRef , typename Impl , bool Mutable >
2026-01-21 11:59:17 +00:00
class str_algs : public str_src_algs < K , StrRef , Impl , Mutable > {
2026-01-04 09:20:36 +00:00
constexpr const Impl & d ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return * static_cast < const Impl * > ( this ) ;
}
2026-01-04 09:20:36 +00:00
constexpr size_t _len ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return d ( ) . length ( ) ;
}
2026-01-04 09:20:36 +00:00
constexpr const K * _str ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return d ( ) . symbols ( ) ;
}
2026-01-04 09:20:36 +00:00
constexpr bool _is_empty ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return d ( ) . is_empty ( ) ;
}
public :
using symb_type = K ;
using str_piece = StrRef ;
using traits = ch_traits < K > ;
using uni = unicode_traits < K > ;
using uns_type = std : : make_unsigned_t < K > ;
using my_type = Impl ;
2026-01-21 11:59:17 +00:00
using base = str_src_algs < K , StrRef , Impl , Mutable > ;
2025-04-05 14:21:11 +00:00
str_algs ( ) = default ;
2026-01-21 11:59:17 +00:00
int compare_iu ( const K * text , size_t len ) const noexcept { // NOLINT
if ( ! len )
return _is_empty ( ) ? 0 : 1 ;
return uni : : compareiu ( _str ( ) , _len ( ) , text , len ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief С р а в н е н и е с т р о к п о с и м в о л ь н о б е з у ч ё т а р е г и с т р а Unicode с и м в о л о в п е р в о й п л о с к о с т и ( < 0xFFFF ) .
* @ param text - д р у г а я с т р о к а .
* @ return < 0 э т а с т р о к а м е н ь ш е , = = 0 - с т р о к и р а в н ы , > 0 - э т а с т р о к а б о л ь ш е .
* @ en @ brief Compare strings character by character without taking into account the case of Unicode characters of the first plane ( < 0xFFFF ) .
* @ param text - another line .
* @ return < 0 this string is less , = = 0 - strings are equal , > 0 - this string is greater .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
int compare_iu ( str_piece text ) const noexcept { // NOLINT
return compare_iu ( text . symbols ( ) , text . length ( ) ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief Р а в н а л и с т р о к а д р у г о й с т р о к е п о с и м в о л ь н о б е з у ч ё т а р е г и с т р а Unicode с и м в о л о в п е р в о й п л о с к о с т и ( < 0xFFFF ) .
* @ param text - д р у г а я с т р о к а .
* @ return р а в н ы л и с т р о к и .
* @ en @ brief Whether a string is equal to another string , character - by - character - insensitive , of the Unicode characters of the first plane ( < 0xFFFF ) .
* @ param text - another line .
* @ return whether the strings are equal .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
bool equal_iu ( str_piece text ) const noexcept { // NOLINT
return text . length ( ) = = _len ( ) & & compare_iu ( text . symbols ( ) , text . length ( ) ) = = 0 ;
2025-04-05 14:21:11 +00:00
}
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief М е н ь ш е л и с т р о к а д р у г о й с т р о к и п о с и м в о л ь н о б е з у ч ё т а р е г и с т р а Unicode с и м в о л о в п е р в о й п л о с к о с т и ( < 0xFFFF ) .
* @ param text - д р у г а я с т р о к а .
* @ return м е н ь ш е л и с т р о к а .
* @ en @ brief Whether a string is smaller than another string , character - by - character - insensitive , of the Unicode characters of the first plane ( < 0xFFFF ) .
* @ param text - another line .
* @ return whether the string is smaller .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
bool less_iu ( str_piece text ) const noexcept { // NOLINT
return compare_iu ( text . symbols ( ) , text . length ( ) ) < 0 ;
}
// Начинается ли эта строка с указанной подстроки без учета unicode регистра
// Does this string begin with the specified substring, insensitive to unicode case
bool starts_with_iu ( const K * prefix , size_t len ) const noexcept {
return _len ( ) > = len & & 0 = = uni : : compareiu ( _str ( ) , len , prefix , len ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief Н а ч и н а е т с я л и с т р о к а с з а д а н н о й п о д с т р о к и б е з у ч ё т а р е г и с т р а Unicode с и м в о л о в п е р в о й п л о с к о с т и ( < 0xFFFF ) .
* @ param prefix - п о д с т р о к а .
* @ en @ brief Whether the string starts with the given substring , case - insensitive Unicode characters of the first plane ( < 0xFFFF ) .
* @ param prefix - substring .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
bool starts_with_iu ( str_piece prefix ) const noexcept {
return starts_with_iu ( prefix . symbols ( ) , prefix . length ( ) ) ;
}
// Заканчивается ли строка указанной подстрокой без учета регистра UNICODE
// Whether the string ends with the specified substring, case insensitive UNICODE
constexpr bool ends_with_iu ( const K * suffix , size_t len ) const noexcept {
size_t myLen = _len ( ) ;
return myLen > = len & & 0 = = uni : : compareiu ( _str ( ) + myLen - len , len , suffix , len ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief З а к а н ч и в а е т с я л и с т р о к а у к а з а н н о й п о д с т р о к о й б е з у ч ё т а р е г и с т р а Unicode с и м в о л о в п е р в о й п л о с к о с т и ( < 0xFFFF ) .
* @ param suffix - п о д с т р о к а .
* @ en @ brief Whether the string ends with the specified substring , case - insensitive Unicode characters of the first plane ( < 0xFFFF ) .
* @ param suffix - substring .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
constexpr bool ends_with_iu ( str_piece suffix ) const noexcept {
return ends_with_iu ( suffix . symbols ( ) , suffix . length ( ) ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief П о л у ч и т ь к о п и ю с т р о к и в в е р х н е м р е г и с т р е Unicode с и м в о л о в п е р в о й п л о с к о с т и ( < 0xFFFF ) .
* @ tparam R - ж е л а е м ы й т и п с т р о к и , п о у м о л ч а н и ю т о т ж е , ч е й м е т о д в ы з ы в а л с я .
* @ return R - к о п и ю с т р о к и в в е р х н е м р е г и с т р е .
* @ en @ brief Get a copy of the string in upper case Unicode characters of the first plane ( < 0xFFFF ) .
* @ tparam R - the desired string type , by default the same whose method was called .
* @ return R - uppercase copy of the string .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
template < typename R = my_type >
R upperred ( ) const {
return R : : upperred_from ( d ( ) ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief П о л у ч и т ь к о п и ю с т р о к и в н и ж н е м р е г и с т р е Unicode с и м в о л о в п е р в о й п л о с к о с т и ( < 0xFFFF ) .
* @ tparam R - ж е л а е м ы й т и п с т р о к и , п о у м о л ч а н и ю т о т ж е , ч е й м е т о д в ы з ы в а л с я .
* @ return R - к о п и ю с т р о к и в н и ж н е м р е г и с т р е .
* @ en @ brief Get a copy of the string in lowercase Unicode characters of the first plane ( < 0xFFFF ) .
* @ tparam R - the desired string type , by default the same whose method was called .
* @ return R - lowercase copy of the string .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
template < typename R = my_type >
R lowered ( ) const {
return R : : lowered_from ( d ( ) ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р е о б р а з о в а т ь с т р о к у в double .
2025-11-25 15:55:16 +00:00
* @ return std : : optional < double > .
2025-11-17 09:01:31 +00:00
* @ en @ brief Convert string to double .
2025-11-25 15:55:16 +00:00
* @ return std : : optional < double > .
*/
2025-11-26 19:15:50 +00:00
template < bool SkipWS = true , bool AllowPlus = true >
2025-11-25 15:55:16 +00:00
std : : optional < double > to_double ( ) const noexcept {
size_t len = _len ( ) ;
const K * ptr = _str ( ) ;
if constexpr ( SkipWS ) {
while ( len & & uns_type ( * ptr ) < = ' ' ) {
len - - ;
ptr + + ;
2025-11-24 13:18:02 +00:00
}
2025-11-25 15:55:16 +00:00
}
2025-11-26 19:15:50 +00:00
if constexpr ( AllowPlus ) {
if ( len & & * ptr = = K ( ' + ' ) ) {
ptr + + ;
len - - ;
}
2025-11-25 15:55:16 +00:00
}
2025-11-26 19:15:50 +00:00
if ( ! len ) {
return { } ;
}
# ifdef __linux__
if constexpr ( sizeof ( K ) = = 1 ) {
double d { } ;
2026-02-11 08:24:57 +00:00
if ( std : : from_chars ( ( const u8s * ) ptr , ( const u8s * ) ptr + len , d ) . ec = = std : : errc { } ) {
2025-11-26 19:15:50 +00:00
return d ;
}
return { } ;
}
# endif
2026-01-25 10:39:22 +00:00
if constexpr ( sizeof ( K ) = = 1 ) {
return impl_to_double ( ( const char * ) ptr , ( const char * ) ptr + len ) ;
} else if constexpr ( sizeof ( K ) = = 2 ) {
return impl_to_double ( ( const char16_t * ) ptr , ( const char16_t * ) ptr + len ) ;
} else {
return impl_to_double ( ( const char32_t * ) ptr , ( const char32_t * ) ptr + len ) ;
}
2025-11-25 15:55:16 +00:00
}
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief П р е о б р а з о в а т ь с т р о к у в double .
* @ param t - п е р е м е н н а я , в к о т о р у ю з а п и с ы в а е т с я р е з у л ь т а т .
* @ en @ brief Convert string to double .
* @ param t - the variable into which the result is written .
2025-11-25 15:55:16 +00:00
*/
2026-01-21 11:59:17 +00:00
void as_number ( double & t ) const {
auto res = to_double ( ) ;
t = res ? * res : std : : nan ( " 0 " ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р е о б р а з о в а т ь с т р о к у в ц е л о е ч и с л о .
2026-01-21 11:59:17 +00:00
* @ details Т а к к а к ` as_number ( double & t ) ` п е р е к р ы в а е т в и д и м о с т ь ` as_number ` и з б а з о в о г о к л а с с а ,
* п р и д ё т с я д о б а в и т ь е г о е щ ё р а з .
2025-11-17 09:01:31 +00:00
* @ tparam T - т и п ч и с л а , в ы в о д и т с я и з а р г у м е н т а .
* @ param t - п е р е м е н н а я , в к о т о р у ю з а п и с ы в а е т с я р е з у л ь т а т .
* @ en @ brief Convert a string to an integer .
2026-01-21 11:59:17 +00:00
* @ details Since ` as_number ( double & t ) ` overrides the visibility of ` as_number ` from the base class ,
* will have to add it again .
2025-11-17 09:01:31 +00:00
* @ tparam T - number type , inferred from the argument .
* @ param t - the variable into which the result is written .
2025-04-05 14:21:11 +00:00
*/
template < ToIntNumber T >
2026-01-04 09:20:36 +00:00
constexpr void as_number ( T & t ) const {
2026-01-21 11:59:17 +00:00
base : : as_number ( t ) ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
} ;
/*
* Б а з о в а я с т р у к т у р а с и н ф о р м а ц и е й о с т р о к е .
* Э т о с т р у к т у р а д л я н е в л а д е ю щ и х с т р о к .
* Т а к к а к з д е с ь т о л ь к о о д и н б а з о в ы й к л а с с , MSVC к о м п и л я т о р а в т о м а т о м п р и м е н я е т empty base optimization ,
* в р е з у л ь т а т е р а з м е р к л а с с а н е у в е л и ч и в а е т с я
* Basic structure with string information .
* This is the structure for non - owning strings .
* Since there is only one base class , the MSVC compiler automatically applies empty base optimization ,
* as a result the class size does not increase
*/
/*!
* @ ru @ brief П р о с т е й ш и й к л а с с и м м у т а б е л ь н о й н е в л а д е ю щ е й с т р о к и .
* @ details А н а л о г std : : string_view . С о д е р ж и т т о л ь к о у к а з а т е л ь и д л и н у .
* К а к н а с л е д н и к о т str_algs п о д д е р ж и в а е т в с е к о н с т а н т н ы е с т р о к о в ы е м е т о д ы .
* @ tparam K - т и п с и м в о л о в с т р о к и .
* @ en @ brief The simplest immutable non - owning string class .
* @ details Similar to std : : string_view . Contains only a pointer and a length .
* As a descendant of str_algs , it supports all constant string methods .
* @ tparam K - the character type of the string .
*/
template < typename K >
struct simple_str : str_algs < K , simple_str < K > , simple_str < K > , false > {
using symb_type = K ;
using my_type = simple_str < K > ;
const symb_type * str ;
size_t len ;
constexpr simple_str ( ) = default ;
constexpr simple_str ( str_src < K > src ) : str ( src . str ) , len ( src . len ) { }
2025-04-05 14:21:11 +00:00
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief К о н с т р у к т о р и з с т р о к о в о г о л и т е р а л а .
* @ en @ brief Constructor from a string literal .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
template < typename T , size_t N = const_lit_for < K , T > : : Count >
2026-02-10 20:35:02 +00:00
constexpr simple_str ( T & & v ) noexcept : str ( ( const K * ) v ) , len ( N - 1 ) { }
2025-04-05 14:21:11 +00:00
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief К о н с т р у к т о р и з у к а з а т е л я и д л и н ы .
* @ en @ brief Constructor from pointer and length .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
constexpr simple_str ( const K * p , size_t l ) noexcept : str ( p ) , len ( l ) { }
2025-04-05 14:21:11 +00:00
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief К о н с т р у к т о р и з std : : basic_string .
* @ en @ brief Constructor from std : : basic_string .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
template < typename A >
constexpr simple_str ( const std : : basic_string < K , std : : char_traits < K > , A > & s ) noexcept : str ( s . data ( ) ) , len ( s . length ( ) ) { }
2025-04-05 14:21:11 +00:00
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief К о н с т р у к т о р и з std : : basic_string_view .
* @ en @ brief Constructor from std : : basic_string_view .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
constexpr simple_str ( const std : : basic_string_view < K , std : : char_traits < K > > & s ) noexcept : str ( s . data ( ) ) , len ( s . length ( ) ) { }
2025-04-05 14:21:11 +00:00
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief П о л у ч и т ь д л и н у с т р о к и .
* @ en @ brief Get the length of the string .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
constexpr size_t length ( ) const noexcept {
return len ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь у к а з а т е л ь н а к о н с т а н т н ы й б у ф е р с с и м в о л а м и с т р о к и .
* @ en @ brief Get a pointer to a constant buffer containing string characters .
2025-04-05 14:21:11 +00:00
*/
constexpr const symb_type * symbols ( ) const noexcept {
return str ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р о в е р и т ь , н е п у с т а л и с т р о к а .
* @ en @ brief Check if a string is empty .
2025-04-05 14:21:11 +00:00
*/
constexpr bool is_empty ( ) const noexcept {
return len = = 0 ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р о в е р и т ь , н е у к а з ы в а ю т л и д в а о б ъ е к т а н а о д н у с т р о к у .
* @ param other - д р у г а я с т р о к а .
* @ en @ brief Check if two objects point to the same string .
* @ param other - another string .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr bool is_same ( simple_str < K > other ) const noexcept {
2025-04-05 14:21:11 +00:00
return str = = other . str & & len = = other . len ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р о в е р и т ь , н е я в л я е т с я л и с т р о к а ч а с т ь ю д р у г о й с т р о к и .
* @ param other - д р у г а я с т р о к а .
* @ en @ brief Check if a string is part of another string .
* @ param other - another string .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr bool is_part_of ( simple_str < K > other ) const noexcept {
2025-04-05 14:21:11 +00:00
return str > = other . str & & str + len < = other . str + other . len ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь с и м в о л и з у к а з а н н о й п о з и ц и и . П р о в е р к а г р а н и ц н е в ы п о л н я е т с я .
* @ param idx - п о з и ц и я с и м в о л а .
* @ return K - с и м в о л .
* @ en @ brief Get the character from the specified position . Bounds checking is not performed .
* @ param idx - position of the symbol .
* @ return K is a symbol .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr K operator [ ] ( size_t idx ) const {
2025-04-05 14:21:11 +00:00
return str [ idx ] ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С д в и г а е т н а ч а л о с т р о к и н а з а д а н н о е к о л и ч е с т в о с и м в о л о в .
* @ param delta - к о л и ч е с т в о с и м в о л о в .
* @ return my_type & .
* @ en @ brief Shifts the start of a line by the specified number of characters .
* @ param delta - number of characters .
* @ return my_type & .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr my_type & remove_prefix ( size_t delta ) {
2025-04-05 14:21:11 +00:00
str + = delta ;
len - = delta ;
return * this ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У к о р а ч и в а е т с т р о к у н а з а д а н н о е к о л и ч е с т в о с и м в о л о в .
* @ param delta - к о л и ч е с т в о с и м в о л о в .
* @ return my_type & .
* @ en @ brief Shortens the string by the specified number of characters .
* @ param delta - number of characters .
* @ return my_type & .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr my_type & remove_suffix ( size_t delta ) {
2025-04-05 14:21:11 +00:00
len - = delta ;
return * this ;
}
} ;
2026-01-21 11:59:17 +00:00
template < typename K >
struct simple_str_selector {
using type = simple_str < K > ;
} ;
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К л а с с , з а я в л я ю щ и й , ч т о с с ы л а е т с я н а н у л ь - т е р м и н и р о в а н н у ю с т р о к у .
* @ tparam K - т и п с и м в о л о в с т р о к и .
2025-04-05 14:21:11 +00:00
* @ details С л у ж и т д л я п о к а з а т о г о , ч т о ф у н к ц и я п а р а м е т р о м х о ч е т п о л у ч и т ь
* с т р о к у с н у л е м в к о н ц е , н а п р и м е р , е й н а д о д а л ь ш е п е р е д а в а т ь е г о в
* с т о р о н н е е API . Б е з э т о г о е й н а д о б ы л о б ы л и б о у к а з ы в а т ь п а р а м е т р о м
* к о н к р е т н ы й к л а с с с т р о к и , ч т о л и ш а е т у н и в е р с а л ь н о с т и , л и б о п р и в о д и л о б ы
* к п о с т о я н н ы м н а к л а д н ы м р а с х о д а м н а и з л и ш н е е к о п и р о в а н и е с т р о к в о в р е м е н н ы й
* б у ф е р . И с т о ч н и к о м н у л ь - т е р м и н и р о в а н н ы х с т р о к м о г у т б ы т ь с т р о к о в ы е л и т е р а л ы
* п р и к о м п и л я ц и и , л и б о к л а с с ы , х р а н я щ и е с т р о к и .
2025-11-17 09:01:31 +00:00
* @ en @ brief A class that claims to refer to a null - terminated string .
* @ tparam K - the character type of the string .
* @ details Shows what the function wants to receive as a parameter
* a string with a zero at the end , for example , she needs to further transfer it to
* third party API . Without this , she would have to either specify the parameter
* specific string class , which deprives universality , or would lead
* to the constant overhead of unnecessary copying of string into the temporary
* buffer . Null - terminated strings can be sourced from string literals
* during compilation , or classes that store strings .
2025-04-05 14:21:11 +00:00
*/
template < typename K >
2025-12-27 13:34:35 +00:00
struct simple_str_nt : simple_str < K > , null_terminated < K , simple_str_nt < K > > {
2025-04-05 14:21:11 +00:00
using symb_type = K ;
using my_type = simple_str_nt < K > ;
using base = simple_str < K > ;
constexpr static const K empty_string [ 1 ] = { 0 } ;
simple_str_nt ( ) = default ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Я в н ы й к о н с т р у к т о р и з С - с т р о к и .
* @ param p - у к а з а т е л ь н а C - с т р о к у ( н у л ь - т е р м и н и р о в а н н а я с т р о к а ) .
2025-04-05 14:21:11 +00:00
* @ details Э т о е д и н с т в е н н ы й к о н с т р у к т о р и з в с е х с т р о к о в ы х о б ъ е к т о в , п р и н и м а ю щ и й C - с т р о к у .
* В ы ч и с л я е т е ё д л и н у п р и и н и ц и а л и з а ц и и . В с е о с т а л ь н ы е с т р о к о в ы е о б ъ е к т ы н е и н и ц и а л и з и р у ю т с я
* C - с т р о к а м и . Э т о д л я т о г о , ч т о б ы ` strlen ` в ы з ы в а л а с ь т о л ь к о в о д н о м м е с т е б и б л и о т е к и ,
2025-11-24 12:46:16 +00:00
* д л и н а C - с т р о к и в ы ч и с л я л а с ь т о л ь к о о д и н р а з и д а л е е н е т е р я л а с ь с л у ч а й н о п р и п е р е д а ч е м е ж д у р а з н ы м и
2025-04-05 14:21:11 +00:00
* т и п а м и с т р о к о в ы х о б ъ е к т о в .
2025-11-17 09:01:31 +00:00
* @ en @ brief Explicit constructor from C - string .
* @ param p - pointer to a C - string ( null - terminated string ) .
* @ details This is the only constructor of all string objects that accepts a C - string .
* Calculates its length upon initialization . All other string objects are not initialized
* C - strings . This is to ensure that ` strlen ` is called only in one place in the library ,
* the length of the C - string was calculated only once and was not subsequently lost accidentally when transferred between different
* types of string objects .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
template < typename T > requires is_one_of_type < std : : remove_cvref_t < T > , const K * , K * > : : value
2026-01-04 09:20:36 +00:00
constexpr explicit simple_str_nt ( T & & p ) noexcept {
2025-04-05 14:21:11 +00:00
base : : len = p ? static_cast < size_t > ( base : : traits : : length ( p ) ) : 0 ;
base : : str = base : : len ? p : empty_string ;
}
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief К о н с т р у к т о р и з с т р о к о в о г о л и т е р а л а .
* @ en @ brief Constructor from a string literal .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
template < typename T , size_t N = const_lit_for < K , T > : : Count >
constexpr simple_str_nt ( T & & v ) noexcept : base ( std : : forward < T > ( v ) ) { }
2025-04-05 14:21:11 +00:00
/*!
2026-01-21 11:59:17 +00:00
* @ ru @ brief К о н с т р у к т о р и з у к а з а т е л я и д л и н ы .
* @ en @ brief Constructor from pointer and length .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
constexpr simple_str_nt ( const K * p , size_t l ) noexcept : base ( p , l ) { }
template < StrType < K > T >
constexpr simple_str_nt ( T & & t ) {
base : : str = t . symbols ( ) ;
base : : len = t . length ( ) ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/*!
* @ ru @ brief К о н с т р у к т о р и з std : : basic_string .
* @ en @ brief Constructor from std : : basic_string .
*/
template < typename A >
constexpr simple_str_nt ( const std : : basic_string < K , std : : char_traits < K > , A > & s ) noexcept : base ( s ) { }
static const my_type empty_str ;
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь н у л ь - т е р м и н и р о в а н н у ю с т р о к у , с д в и н у в н а ч а л о н а з а д а н н о е к о л и ч е с т в о с и м в о л о в .
* @ param from - н а с к о л ь к о с и м в о л о в с д в и н у т ь н а ч а л о с т р о к и .
* @ return my_type .
* @ en @ brief Get a null - terminated string by shifting the start by the specified number of characters .
* @ param from - by how many characters to shift the beginning of the line .
* @ return my_type .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr my_type to_nts ( size_t from ) {
2025-04-05 14:21:11 +00:00
if ( from > base : : len ) {
from = base : : len ;
}
return { base : : str + from , base : : len - from } ;
}
} ;
template < typename K >
inline const simple_str_nt < K > simple_str_nt < K > : : empty_str { simple_str_nt < K > : : empty_string , 0 } ;
2026-01-21 11:59:17 +00:00
template < typename K >
using Splitter = SplitterBase < K , simple_str < K > > ;
2025-04-05 14:21:11 +00:00
using ssa = simple_str < u8s > ;
2026-01-21 11:59:17 +00:00
using ssb = simple_str < ubs > ;
2025-04-05 14:21:11 +00:00
using ssw = simple_str < wchar_t > ;
using ssu = simple_str < u16s > ;
using ssuu = simple_str < u32s > ;
using stra = simple_str_nt < u8s > ;
2026-01-21 11:59:17 +00:00
using strb = simple_str_nt < ubs > ;
2025-04-05 14:21:11 +00:00
using strw = simple_str_nt < wchar_t > ;
using stru = simple_str_nt < u16s > ;
using struu = simple_str_nt < u32s > ;
2026-01-21 11:59:17 +00:00
template < typename Src , typename Dest >
struct utf_convert_selector ;
2025-04-05 14:21:11 +00:00
2026-02-10 20:35:02 +00:00
template < typename Src >
struct utf_convert_selector < Src , Src > {
static size_t need_len ( const Src * src , size_t srcLen ) {
return srcLen ;
}
static size_t convert ( const Src * src , size_t srcLen , Src * dest ) {
ch_traits < Src > : : copy ( dest , src , srcLen + 1 ) ;
return srcLen ;
}
} ;
2026-01-21 11:59:17 +00:00
template < >
struct utf_convert_selector < u8s , u16s > {
static SIMSTR_API size_t need_len ( const u8s * src , size_t srcLen ) ;
static SIMSTR_API size_t convert ( const u8s * src , size_t srcLen , u16s * dest ) ;
2025-04-05 14:21:11 +00:00
} ;
2026-01-21 11:59:17 +00:00
template < >
struct utf_convert_selector < u8s , u32s > {
static SIMSTR_API size_t need_len ( const u8s * src , size_t srcLen ) ;
static SIMSTR_API size_t convert ( const u8s * src , size_t srcLen , u32s * dest ) ;
2025-04-05 14:21:11 +00:00
} ;
template < >
struct utf_convert_selector < u16s , u8s > {
static SIMSTR_API size_t need_len ( const u16s * src , size_t srcLen ) ;
static SIMSTR_API size_t convert ( const u16s * src , size_t srcLen , u8s * dest ) ;
} ;
template < >
struct utf_convert_selector < u16s , u32s > {
static SIMSTR_API size_t need_len ( const u16s * src , size_t srcLen ) ;
static SIMSTR_API size_t convert ( const u16s * src , size_t srcLen , u32s * dest ) ;
} ;
template < >
struct utf_convert_selector < u32s , u8s > {
static SIMSTR_API size_t need_len ( const u32s * src , size_t srcLen ) ;
static SIMSTR_API size_t convert ( const u32s * src , size_t srcLen , u8s * dest ) ;
} ;
template < >
struct utf_convert_selector < u32s , u16s > {
static SIMSTR_API size_t need_len ( const u32s * src , size_t srcLen ) ;
static SIMSTR_API size_t convert ( const u32s * src , size_t srcLen , u16s * dest ) ;
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Б а з о в ы й к л а с с д л я с т р о к , м о г у щ и х к о н в е р т и р о в а т ь с я и з д р у г о г о т и п а с и м в о л о в .
* @ tparam K - т и п с и м в о л о в .
* @ tparam Impl - к о н е ч н ы й к л а с с .
2025-04-05 14:21:11 +00:00
* @ details К о н в е р т а ц и я в ы п о л н я е т с я ч е р е з UTF п р е о б р а з о в а н и е .
* С ч и т а е м , ч т о с т р о к и ` char ` - в UTF - 8 , ` char16_t ` - в UTF - 16 , ` char32_t ` - в UTF - 32.
* ` wchar_t ` - п о д Windows UTF - 16 , в Linux - UTF - 32.
2025-11-17 09:01:31 +00:00
* @ en @ brief Base class for strings that can be converted from another character type .
* @ tparam K - character type .
* @ tparam Impl - final class .
* @ details Conversion is performed via UTF conversion .
* We assume that the strings ` char ` are in UTF - 8 , ` char16_t ` - in UTF - 16 , ` char32_t ` - in UTF - 32.
* ` wchar_t ` - in Windows UTF - 16 , in Linux - UTF - 32.
2025-04-05 14:21:11 +00:00
*/
template < typename K , typename Impl >
2025-12-27 13:34:35 +00:00
class from_utf_convertible {
2025-04-05 14:21:11 +00:00
protected :
2025-12-27 13:34:35 +00:00
from_utf_convertible ( ) = default ;
2025-04-05 14:21:11 +00:00
using my_type = Impl ;
/*
Э т и м е т о д ы д о л ж е н р е а л и з о в а т ь к л а с с - н а с л е д н и к .
в ы з ы в а е т с я т о л ь к о п р и с о з д а н и и о б ъ е к т а
init ( size_t size )
set_size ( size_t size )
*/
template < typename O >
requires ( ! std : : is_same_v < O , K > )
2026-01-30 14:30:09 +00:00
void init_from_utf_convertible ( simple_str < O > init ) {
2026-02-10 20:35:02 +00:00
using from_t = to_base_char_t < O > ;
using to_t = to_base_char_t < K > ;
using worker = utf_convert_selector < from_t , to_t > ;
2025-04-05 14:21:11 +00:00
Impl * d = static_cast < Impl * > ( this ) ;
size_t len = init . length ( ) ;
if ( ! len )
d - > create_empty ( ) ;
else {
2026-02-10 20:35:02 +00:00
size_t need = worker : : need_len ( ( const from_t * ) init . symbols ( ) , len ) ;
2025-04-05 14:21:11 +00:00
K * str = d - > init ( need ) ;
str [ need ] = 0 ;
2026-02-10 20:35:02 +00:00
worker : : convert ( ( const from_t * ) init . symbols ( ) , len , ( to_t * ) str ) ;
2025-04-05 14:21:11 +00:00
}
}
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С т р о к о в о е в ы р а ж е н и е д л я к о н в е р т а ц и и с т р о к в р а з н ы е в и д ы UTF .
* @ tparam From - Т и п к а к о й с т р о к и к о н в е р т и р у е м .
* @ tparam To - В к а к о г о т и п а с т р о к у к о н в е р т и р у е м .
* @ en @ brief String expression to convert strings to different UTF types .
* @ tparam From - The type of which string we are converting .
* @ tparam To - What type of string we convert to .
2025-04-05 14:21:11 +00:00
*/
template < typename From , typename To > requires ( ! std : : is_same_v < From , To > )
2026-01-21 11:59:17 +00:00
struct expr_utf : expr_to_std_string < expr_utf < From , To > > {
2025-04-05 14:21:11 +00:00
using symb_type = To ;
2026-02-10 20:35:02 +00:00
using from_t = to_base_char_t < From > ;
using to_t = to_base_char_t < To > ;
using worker = utf_convert_selector < from_t , to_t > ;
2025-04-05 14:21:11 +00:00
simple_str < From > source_ ;
2026-01-21 11:59:17 +00:00
constexpr expr_utf ( simple_str < From > source ) : source_ ( source ) { }
2025-04-05 14:21:11 +00:00
size_t length ( ) const noexcept {
2026-02-10 20:35:02 +00:00
return worker : : need_len ( ( const from_t * ) source_ . symbols ( ) , source_ . length ( ) ) ;
2025-04-05 14:21:11 +00:00
}
To * place ( To * ptr ) const noexcept {
2026-02-10 20:35:02 +00:00
return ptr + worker : : convert ( ( const from_t * ) source_ . symbols ( ) , source_ . length ( ) , ( to_t * ) ptr ) ;
2025-04-05 14:21:11 +00:00
}
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief В о з в р а щ а е т с т р о к о в о е в ы р а ж е н и е , п р е о б р а з у ю щ у ю с т р о к у и з о д н о г о т и п а с и м в о л о в
2025-04-05 14:21:11 +00:00
* в д р у г о й т и п , ч е р е з UTF - к о н в е р т и р о в а н и е .
2025-11-17 09:01:31 +00:00
* @ tparam To - т и п с т р о к и , в к о т о р у ю н а д о к о н в е р т и р о в а т ь .
2025-04-05 14:21:11 +00:00
* @ tparam From - т и п с т р о к и , и з к о т о р о г о н а д о к о н в е р т и р о в а т ь . В ы в о д и т с я и з а р г у м е н т а .
* @ param from - с т р о к а , и з к о т о р о й н а д о к о н в е р т и р о в а т ь .
2025-11-17 09:01:31 +00:00
* @ en @ brief Returns a string expression that converts a string of one character type
* to another type , via UTF conversion .
* @ tparam To - the type of string to convert to .
* @ tparam From - the type of string to convert from . Derived from the argument .
* @ param from - the string from which to convert .
2025-04-05 14:21:11 +00:00
*/
template < typename To , typename From > requires ( ! std : : is_same_v < From , To > )
2026-01-21 11:59:17 +00:00
expr_utf < From , To > e_utf ( simple_str < From > from ) {
return { from } ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н ц е п т т и п а , к о т о р ы й м о ж е т с о х р а н и т ь с т р о к у .
* @ en @ brief A type concept that can store a string .
2025-04-05 14:21:11 +00:00
*/
template < typename A , typename K >
concept storable_str = requires {
A : : is_str_storable = = true ;
std : : is_same_v < typename A : : symb_type , K > ;
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н ц е п т т и п а , к о т о р ы й м о ж е т м о д и ф и ц и р о в а т ь х р а н и м у ю с т р о к у .
* @ en @ brief A type concept that can modify a stored string .
2025-04-05 14:21:11 +00:00
*/
template < typename A , typename K >
concept mutable_str = storable_str < A , K > & & requires { A : : is_str_mutable = = true ; } ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н ц е п т т и п а , к о т о р ы й н е м о ж е т м о д и ф и ц и р о в а т ь х р а н и м у ю с т р о к у .
* @ en @ brief A type concept that cannot modify a stored string .
2025-04-05 14:21:11 +00:00
*/
template < typename A , typename K >
concept immutable_str = storable_str < A , K > & & ! mutable_str < A , K > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Б а з а д л я о б ъ е к т о в , в л а д е ю щ и х с т р о к о й .
* @ tparam K - т и п с и м в о л о в .
* @ tparam Impl - к о н е ч н ы й к л а с с н а с л е д н и к .
* @ tparam Allocator - т и п а л л о к а т о р а .
2025-04-05 14:21:11 +00:00
* @ details П о п р е ж н е м у н и ч е г о н е з н а е т о т о м , г д е н а с л е д н и к х р а н и т с т р о к у и е ё р а з м е р .
* П р о с т о в ы з ы в а е т е г о м е т о д ы д л я п о л у ч е н и я м е с т а , и з а п о л н я е т е г о п р и н е о б х о д и м о с т и .
* Р а б о т а е т т о л ь к о п р и с о з д а н и и о б ъ е к т а , н е р а б о т а е т с м о д и ф и к а ц и е й с т р о к и п о с л е
* е е с о з д а н и я и г а р а н т и р у е т , ч т о е с л и в ы з ы в а ю т с я э т и м е т о д ы , о б ъ е к т е щ е т о л ь к о
* с о з д а е т с я , и к а к о г о - л и б о р а с ш а р и в а н и я д а н н ы х е щ е н е б ы л о .
*
* Э т и м е т о д ы д о л ж е н р е а л и з о в а т ь к л а с с - н а с л е д н и к , в ы з ы в а ю т с я т о л ь к о п р и с о з д а н и и о б ъ е к т а
* - ` K * init ( size_t size ) ` - в ы д е л и т ь м е с т о д л я с т р о к и у к а з а н н о г о р а з м е р а , в е р н у т ь а д р е с
* - ` void create_empty ( ) ` - с о з д а т ь п у с т о й о б ъ е к т
* - ` K * set_size ( size_t size ) ` - п е р е в ы д е л и т ь м е с т о д л я с т р о к и , е с л и п р и с о з д а н и и н е у г а д а л и
* н у ж н ы й р а з м е р и м е с т о н у ж н о б о л ь ш е и л и м е н ь ш е .
* С о д е р ж и м о е с т р о к и н у ж н о о с т а в и т ь .
* Х о т я т и п а л л о к а т о р а и з а д а ё т с я п а р а м е т р о м ш а б л о н а , д е л а е т с я э т о т о л ь к о д л я п р о б р о с а
* е г о т и п а в к о н с т р у к т о р ы , м е т о д ы а л л о к а т о р а н е в ы з ы в а ю т с я . Е с л и н а с л е д н и к н е п о л ь з у е т с я
* а л л о к а т о р о м , а с а м в ` init ` и ` set_size ` к а к - т о в ы д е л я е т м е с т о , м о ж е т у к а з а т ь т и п о м а л л о к а т о р а
* к а к о й - л и б о п у с т о й к л а с с .
2025-11-17 09:01:31 +00:00
* @ en @ brief The base for the objects that own the string .
* @ tparam K - character type .
* @ tparam Impl - the final class is the successor .
* @ tparam Allocator - type of allocator .
* @ details Still knows nothing about where the heir stores the string and its size .
* Simply calls its methods to get the space , and fills it as needed .
* Works only when creating an object , does not work with string modification after
* its creation and ensures that if these methods are called , the object is only
* is being created and no data sharing has yet taken place .
*
* These methods must be implemented by the descendant class and are called only when an object is created
* - ` K * init ( size_t size ) ` - allocate space for a line of the specified size , return the address
* - ` void create_empty ( ) ` - create an empty object
* - ` K * set_size ( size_t size ) ` - re - allocate space for the line if you didn ’ t guess correctly when creating
* the size you need and the space you need is larger or smaller .
* The contents of the line must be left .
* Although the allocator type is specified by the template parameter , this is done only for forwarding
* of its type in constructors , allocator methods are not called . If the heir does not use
* an allocator , and in ` init ` and ` set_size ` it somehow allocates space , can indicate the type of the allocator
* any empty class .
2025-04-05 14:21:11 +00:00
*/
template < typename K , typename Impl , typename Allocator >
2025-09-23 22:35:12 +00:00
class str_storable : protected Allocator {
2025-04-05 14:21:11 +00:00
public :
using my_type = Impl ;
using traits = ch_traits < K > ;
using allocator_t = Allocator ;
2026-01-04 09:20:36 +00:00
using s_str = simple_str < K > ;
using s_str_nt = simple_str_nt < K > ;
2025-04-05 14:21:11 +00:00
protected :
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь а л л о к а т о р .
* @ en @ brief Get the allocator .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr allocator_t & allocator ( ) {
2025-09-23 22:35:12 +00:00
return * static_cast < Allocator * > ( this ) ;
2025-04-05 14:21:11 +00:00
}
2026-01-04 09:20:36 +00:00
constexpr const allocator_t & allocator ( ) const {
2025-09-23 22:35:12 +00:00
return * static_cast < const Allocator * > ( this ) ;
2025-04-05 14:21:11 +00:00
}
using uni = unicode_traits < K > ;
2026-01-04 09:20:36 +00:00
constexpr Impl & d ( ) noexcept {
2025-04-05 14:21:11 +00:00
return * static_cast < Impl * > ( this ) ;
}
2026-01-04 09:20:36 +00:00
constexpr const Impl & d ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return * static_cast < const Impl * > ( this ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С о з д а т ь п у с т о й о б ъ е к т .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief Create an empty object .
* @ param . . . args - parameters for initializing the allocator .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . Args >
2026-01-04 09:20:36 +00:00
explicit constexpr str_storable ( Args & & . . . args ) : Allocator ( std : : forward < Args > ( args ) . . . ) { }
2025-04-05 14:21:11 +00:00
/*!
2026-01-04 09:20:36 +00:00
* @ ru @ brief И н и ц и а л и з а ц и я и з д р у г о г о с т р о к о в о г о о б ъ е к т а .
2025-11-17 09:01:31 +00:00
* @ param other - д р у г о й с т р о к о в ы й о б ъ е к т , simple_str .
2026-01-04 09:20:36 +00:00
* @ en @ brief Initialization from another string object .
2025-11-17 09:01:31 +00:00
* @ param other - another string object , simple_str .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr void init_from_str_other ( s_str other ) {
2025-04-05 14:21:11 +00:00
if ( other . length ( ) ) {
K * ptr = d ( ) . init ( other . length ( ) ) ;
traits : : copy ( ptr , other . symbols ( ) , other . length ( ) ) ;
ptr [ other . length ( ) ] = 0 ;
} else
d ( ) . create_empty ( ) ;
}
/*!
2026-01-04 09:20:36 +00:00
* @ ru @ brief И н и ц и а л и з а ц и я п о в т о р е н и е м с т р о к и .
2025-11-17 09:01:31 +00:00
* @ param repeat - к о л и ч е с т в о п о в т о р о в .
* @ param pattern - с т р о к а , к о т о р у ю н а д о п о в т о р и т ь .
2026-01-04 09:20:36 +00:00
* @ en @ brief String repetition initialization .
2025-11-17 09:01:31 +00:00
* @ param repeat - number of repetitions .
* @ param pattern - the line to be repeated .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr void init_str_repeat ( size_t repeat , s_str pattern ) {
2025-04-05 14:21:11 +00:00
size_t l = pattern . length ( ) , allLen = l * repeat ;
if ( allLen ) {
K * ptr = d ( ) . init ( allLen ) ;
for ( size_t i = 0 ; i < repeat ; i + + ) {
traits : : copy ( ptr , pattern . symbols ( ) , l ) ;
ptr + = l ;
}
* ptr = 0 ;
} else
d ( ) . create_empty ( ) ;
}
/*!
2026-01-04 09:20:36 +00:00
* @ ru @ brief И н и ц и а л и з а ц и я п о в т о р е н и е м с и м в о л а .
2025-11-17 09:01:31 +00:00
* @ param count - к о л и ч е с т в о п о в т о р о в .
* @ param pad - с и м в о л , к о т о р ы й н а д о п о в т о р и т ь .
2026-01-04 09:20:36 +00:00
* @ en @ brief Character repetition initialization .
2025-11-17 09:01:31 +00:00
* @ param count - number of repetitions .
* @ param pad - the character to be repeated .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr void init_symb_repeat ( size_t count , K pad ) {
2025-04-05 14:21:11 +00:00
if ( count ) {
K * str = d ( ) . init ( count ) ;
traits : : assign ( str , count , pad ) ;
str [ count ] = 0 ;
} else
d ( ) . create_empty ( ) ;
}
/*!
2026-01-04 09:20:36 +00:00
* @ ru @ brief И н и ц и а л и з а ц и я и з с т р о к о в о г о в ы р а ж е н и я .
2025-11-17 09:01:31 +00:00
* @ param expr - с т р о к о в о е в ы р а ж е н и е .
2026-01-04 09:20:36 +00:00
* @ details З а п р а ш и в а е т у с т р о к о в о г о в ы р а ж е н и я ` length ( ) ` ,
2025-04-05 14:21:11 +00:00
* в ы д е л я е т п а м я т ь н у ж н о г о р а з м е р а , и в ы з ы в а е т м е т о д ` place ( ) ` д л я р а з м е щ е н и я
* р е з у л ь т а т а в б у ф е р е .
2026-01-04 09:20:36 +00:00
* @ en @ brief Initialization from a string expression .
2025-11-17 09:01:31 +00:00
* @ param expr - string expression .
2026-01-04 09:20:36 +00:00
* @ details Queries the string expression ` length ( ) ` ,
2025-11-17 09:01:31 +00:00
* allocates memory of the required size , and calls the ` place ( ) ` method to allocate
* result in buffer .
2025-04-05 14:21:11 +00:00
*/
2026-01-21 11:59:17 +00:00
template < StrExprForType < K > A >
constexpr void init_str_expr ( const A & expr ) {
2025-04-05 14:21:11 +00:00
size_t len = expr . length ( ) ;
if ( len )
2026-01-21 11:59:17 +00:00
* expr . place ( ( typename A : : symb_type * ) d ( ) . init ( len ) ) = 0 ;
2025-04-05 14:21:11 +00:00
else
d ( ) . create_empty ( ) ;
}
/*!
2026-01-04 09:20:36 +00:00
* @ ru @ brief И н и ц и а л и з а ц и я и з с т р о к о в о г о и с т о ч н и к а с з а м е н о й .
2025-11-17 09:01:31 +00:00
* @ param f - с т р о к о в ы й о б ъ е к т , и з к о т о р о г о б е р ё т с я и с х о д н а я с т р о к а .
* @ param pattern - п о д с т р о к а , к о т о р у ю н а д о з а м е н и т ь .
* @ param repl - с т р о к а , н а к о т о р у ю н а д о з а м е н и т ь .
* @ param offset - н а ч а л ь н а я п о з и ц и я д л я п о и с к а п о д с т р о к .
* @ param maxCount - м а к с и м а л ь н о е к о л и ч е с т в о з а м е н , 0 - б е з о г р а н и ч е н и й .
2026-01-04 09:20:36 +00:00
* @ en @ brief Initialization from string source with replacement .
2025-11-17 09:01:31 +00:00
* @ 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 .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
template < StrType < K > From >
void init_replaced ( const From & f , s_str pattern , s_str repl , size_t offset = 0 , size_t maxCount = 0 ) {
2025-04-05 14:21:11 +00:00
auto findes = f . find_all ( pattern , offset , maxCount ) ;
if ( ! findes . size ( ) ) {
new ( this ) my_type { f } ;
return ;
}
size_t srcLen = f . length ( ) ;
size_t newSize = srcLen + static_cast < ptrdiff_t > ( repl . len - pattern . len ) * findes . size ( ) ;
if ( ! newSize ) {
new ( this ) my_type { } ;
return ;
}
K * ptr = d ( ) . init ( newSize ) ;
const K * src = f . symbols ( ) ;
size_t from = 0 ;
for ( const auto & s : findes ) {
size_t copyLen = s - from ;
if ( copyLen ) {
traits : : copy ( ptr , src + from , copyLen ) ;
ptr + = copyLen ;
}
if ( repl . len ) {
traits : : copy ( ptr , repl . str , repl . len ) ;
ptr + = repl . len ;
}
from = s + pattern . len ;
}
srcLen - = from ;
if ( srcLen ) {
traits : : copy ( ptr , src + from , srcLen ) ;
ptr + = srcLen ;
}
* ptr = 0 ;
}
2026-01-04 09:20:36 +00:00
template < StrType < K > From , typename Op1 , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
static my_type changeCaseAscii ( const From & f , const Op1 & opMakeNeedCase , Args & & . . . args ) {
my_type result { std : : forward < Args > ( args ) . . . } ;
size_t len = f . length ( ) ;
if ( len ) {
const K * source = f . symbols ( ) ;
K * destination = result . init ( len ) ;
for ( size_t l = 0 ; l < len ; l + + ) {
destination [ l ] = opMakeNeedCase ( source [ l ] ) ;
}
}
return result ;
}
// GCC до сих пор не даёт делать полную специализацию вложенного шаблонного класса внутри внешнего класса, только частичную.
// Поэтому добавим фиктивный параметр шаблона, чтобы сделать специализацию для u8s прямо в классе.
// GCC still does not allow full specialization of a nested template class inside an outer class, only partial.
// So let's add a dummy template parameter to make the specialization for u8s right in the class.
template < typename T , bool Dummy = true >
struct ChangeCase {
template < typename From , typename Op1 , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
static my_type changeCase ( const From & f , const Op1 & opChangeCase , Args & & . . . args ) {
my_type result { std : : forward < Args > ( args ) . . . } ;
size_t len = f . length ( ) ;
if ( len ) {
opChangeCase ( f . symbols ( ) , len , result . init ( len ) ) ;
}
return result ;
}
} ;
// Для utf8 сделаем отдельную спецификацию, так как при смене регистра может изменится длина строки
// For utf8 we will make a separate specification, since changing the register may change the length of the string
template < bool Dummy >
struct ChangeCase < u8s , Dummy > {
template < typename From , typename Op1 , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
static my_type changeCase ( const From & f , const Op1 & opChangeCase , Args & & . . . args ) {
my_type result { std : : forward < Args > ( args ) . . . } ;
;
size_t len = f . length ( ) ;
if ( len ) {
const K * ptr = f . symbols ( ) ;
K * pWrite = result . init ( len ) ;
const u8s * source = ptr ;
u8s * dest = pWrite ;
size_t newLen = opChangeCase ( source , len , dest , len ) ;
if ( newLen < len ) {
// Строка просто укоротилась
// The string was simply shortened
result . set_size ( newLen ) ;
} else if ( newLen > len ) {
// Строка не влезла в буфер.
// The line did not fit into the buffer.
size_t readed = static_cast < size_t > ( source - ptr ) ;
size_t writed = static_cast < size_t > ( dest - pWrite ) ;
pWrite = result . set_size ( newLen ) ;
dest = pWrite + writed ;
opChangeCase ( source , len - readed , dest , newLen - writed ) ;
}
pWrite [ newLen ] = 0 ;
}
return result ;
}
} ;
public :
inline static constexpr bool is_str_storable = true ;
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р п р е о б р а з о в а н и я в н у л ь - т е р м и н и р о в а н н у ю C - с т р о к у .
* @ return const K * - у к а з а т е л ь н а н а ч а л о с т р о к и .
* @ en @ brief Conversion operator to a null - terminated C string .
* @ return const K * - pointer to the beginning of the line .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr operator const K * ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return d ( ) . symbols ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь simple_str_nt , н а ч и н а я с з а д а н н о г о с и м в о л а .
* @ param from - п о з и ц и я н а ч а л ь н о г о с и м в о л а , п о у м о л ч а н и ю 0.
* @ return simple_str_nt ,
* @ en @ brief Get simple_str_nt starting at the given character .
* @ param from - position of the starting character , default 0.
* @ return simple_str_nt ,
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr s_str_nt to_nts ( size_t from = 0 ) const {
2025-04-05 14:21:11 +00:00
size_t len = d ( ) . length ( ) ;
if ( from > = len ) {
from = len ;
}
return { d ( ) . symbols ( ) + from , len - from } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р е о б р а з о в а т ь в simple_str_nt .
* @ return simple_str_nt .
* @ en @ brief Convert to simple_str_nt .
* @ return simple_str_nt .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr operator s_str_nt ( ) const {
2025-04-05 14:21:11 +00:00
return { d ( ) . symbols ( ) , d ( ) . length ( ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н к а т е н а ц и я с т р о к и з к о н т е й н е р а в о д н у с т р о к у .
* @ param strings - к о н т е й н е р с о с т р о к а м и .
2026-01-21 11:59:17 +00:00
* @ param delimiter - р а з д е л и т е л ь , д о б а в л я е м ы й м е ж д у с т р о к а м и .
2025-11-17 09:01:31 +00:00
* @ param tail - д о б а в и т ь р а з д е л и т е л ь п о с л е п о с л е д н е й с т р о к и .
* @ param skip_empty - п р о п у с к а т ь п у с т ы е с т р о к и б е з д о б а в л е н и я р а з д е л и т е л я .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
2025-04-05 14:21:11 +00:00
* @ details Ф у н к ц и я с л у ж и т д л я с л и я н и я к о н т е й н е р а с т р о к в о д н у с т р о к у с р а з д е л и т е л е м .
* ` ` ` cpp
* std : : vector < ssa > strings = get_strings ( ) ;
2026-01-21 11:59:17 +00:00
* ssa delim = get_current_delimiter ( ) ;
* auto line = lstringa < 200 > : : join ( strings , delimiter ) ;
2025-04-05 14:21:11 +00:00
* ` ` `
* С т о и т о т м е т и т ь , ч т о п р и з а р а н е е и з в е с т н о м р а з д е л и т е л е л у ч ш е п о л ь з о в а т ь с я с т р о к о в ы м в ы р а ж е н и е м ` e_join ` .
* ` ` ` cpp
* std : : vector < ssa > strings = get_strings ( ) ;
* lstringa < 200 > line { e_join ( strings , " / " ) } ;
* ` ` `
* В э т о м с л у ч а е к о м п и л я т о р м о ж е т л у ч ш е о п т и м и з и р о в а т ь к о д с л и я н и я с т р о к .
2025-11-17 09:01:31 +00:00
* @ en @ brief Concatenate strings from the container into one string .
* @ param strings - container with strings .
2026-01-21 11:59:17 +00:00
* @ param delimiter - delimiter added between lines .
2025-11-17 09:01:31 +00:00
* @ param tail - add a separator after the last line .
* @ param skip_empty - skip empty lines without adding a separator .
* @ param . . . args - parameters for initializing the allocator .
* @ details The function is used to merge a container of strings into one delimited string .
* ` ` ` cpp
* std : : vector < ssa > strings = get_strings ( ) ;
2026-01-21 11:59:17 +00:00
* ssa delim = get_current_delimiter ( ) ;
* auto line = lstringa < 200 > : : join ( strings , delimiter ) ;
2025-11-17 09:01:31 +00:00
* ` ` `
* It is worth noting that if the separator is known in advance , it is better to use the string expression ` e_join ` .
* ` ` ` cpp
* std : : vector < ssa > strings = get_strings ( ) ;
* lstringa < 200 > line { e_join ( strings , " / " ) } ;
* ` ` `
* In this case , the compiler can better optimize the string merging code .
2025-04-05 14:21:11 +00:00
*/
template < typename T , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
2026-01-21 11:59:17 +00:00
static my_type join ( const T & strings , s_str delimiter , bool tail = false , bool skip_empty = false , Args & & . . . args ) {
2025-04-05 14:21:11 +00:00
my_type result ( std : : forward < Args > ( args ) . . . ) ;
if ( strings . size ( ) ) {
2026-01-21 11:59:17 +00:00
if ( strings . size ( ) = = 1 & & ( ! delimiter . length ( ) | | ! tail ) ) {
2025-04-05 14:21:11 +00:00
result = strings . front ( ) ;
} else {
size_t commonLen = 0 ;
for ( const auto & t : strings ) {
size_t len = t . length ( ) ;
if ( len > 0 | | ! skip_empty ) {
if ( commonLen > 0 ) {
2026-01-21 11:59:17 +00:00
commonLen + = delimiter . len ;
2025-04-05 14:21:11 +00:00
}
commonLen + = len ;
}
}
2026-01-21 11:59:17 +00:00
commonLen + = ( tail & & delimiter . len > 0 & & ( commonLen > 0 | | ( ! skip_empty & & strings . size ( ) > 0 ) ) ? delimiter . len : 0 ) ;
2025-04-05 14:21:11 +00:00
if ( commonLen ) {
K * ptr = result . init ( commonLen ) ;
K * write = ptr ;
for ( const auto & t : strings ) {
size_t copyLen = t . length ( ) ;
2026-01-21 11:59:17 +00:00
if ( delimiter . len > 0 & & write ! = ptr & & ( copyLen | | ! skip_empty ) ) {
ch_traits < K > : : copy ( write , delimiter . str , delimiter . len ) ;
write + = delimiter . len ;
2025-04-05 14:21:11 +00:00
}
ch_traits < K > : : copy ( write , t . symbols ( ) , copyLen ) ;
write + = copyLen ;
}
2026-01-21 11:59:17 +00:00
if ( delimiter . len > 0 & & tail & & ( write ! = ptr | | ( ! skip_empty & & strings . size ( ) > 0 ) ) ) {
ch_traits < K > : : copy ( write , delimiter . str , delimiter . len ) ;
write + = delimiter . len ;
2025-04-05 14:21:11 +00:00
}
* write = 0 ;
} else {
result . create_empty ( ) ;
}
}
}
return result ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С о з д а т ь с т р о к у , к о п и ю п е р е д а н н о й в в е р х н е м р е г и с т р е с и м в о л о в ASCII .
* @ param f - с т р о к а и с т о ч н и к .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief Create a string copy of the passed in uppercase ASCII characters .
* @ param f - source string .
* @ param . . . args - parameters for initializing the allocator .
2025-04-05 14:21:11 +00:00
*/
template < StrType < K > From , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
2026-01-04 09:20:36 +00:00
static my_type upperred_only_ascii_from ( const From & f , Args & & . . . args ) {
2025-04-05 14:21:11 +00:00
return changeCaseAscii ( f , makeAsciiUpper < K > , std : : forward < Args > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С о з д а т ь к о п и ю п е р е д а н н о й с т р о к и в н и ж н е м р е г и с т р е с и м в о л о в ASCII .
* @ param f - с т р о к а и с т о ч н и к .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief Create a copy of the passed string in lowercase ASCII characters .
* @ param f - source string .
* @ param . . . args - parameters for initializing the allocator .
2025-04-05 14:21:11 +00:00
*/
template < StrType < K > From , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
static my_type lowered_only_ascii_from ( const From & f , Args & & . . . args ) {
return changeCaseAscii ( f , makeAsciiLower < K > , std : : forward < Args > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С о з д а т ь к о п и ю п е р е д а н н о й с т р о к и в в е р х н е м р е г и с т р е с и м в о л о в Unicode п е р в о й п л о с к о с т и ( < 0xFFFF ) .
* @ param f - с т р о к а и с т о ч н и к .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
2025-04-05 14:21:11 +00:00
* @ details Р е г и с т р м е н я е т с я у п р о щ е н н ы м и т а б л и ц а м и , г д е о д и н code_point в с е г д а м е н я е т с я в о д и н code_point
* ( н о д л я UTF - 8 в о з м о ж н о , ч т о д л и н а в code unit ' а х и з м е н и т с я ) .
2025-11-17 09:01:31 +00:00
* @ en @ brief Create a copy of the passed string in uppercase Unicode characters of the first plane ( < 0xFFFF ) .
* @ param f - source string .
* @ param . . . args - parameters for initializing the allocator .
* @ details Case is changed by simplified tables , where one code_point is always changed to one code_point
* ( but for UTF - 8 it is possible that the length in code units will change ) .
2025-04-05 14:21:11 +00:00
*/
template < StrType < K > From , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
2026-01-04 09:20:36 +00:00
static my_type upperred_from ( const From & f , Args & & . . . args ) {
2025-04-05 14:21:11 +00:00
return ChangeCase < K > : : changeCase ( f , uni : : upper , std : : forward < Args > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С о з д а т ь к о п и ю п е р е д а н н о й с т р о к и в н и ж н е м р е г и с т р е с и м в о л о в Unicode п е р в о й п л о с к о с т и ( < 0xFFFF ) .
* @ param f - с т р о к а и с т о ч н и к .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
2025-04-05 14:21:11 +00:00
* @ details Р е г и с т р м е н я е т с я у п р о щ е н н ы м и т а б л и ц а м и , г д е о д и н code_point в с е г д а м е н я е т с я в о д и н code_point
* ( н о д л я UTF - 8 в о з м о ж н о , ч т о д л и н а в code unit ' а х и з м е н и т с я ) .
2025-11-17 09:01:31 +00:00
* @ en @ brief Create a copy of the passed string in lowercase Unicode characters of the first plane ( < 0xFFFF ) .
* @ param f - source string .
* @ param . . . args - parameters for initializing the allocator .
* @ details Case is changed by simplified tables , where one code_point is always changed to one code_point
* ( but for UTF - 8 it is possible that the length in code units will change ) .
2025-04-05 14:21:11 +00:00
*/
template < StrType < K > From , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
static my_type lowered_from ( const From & f , Args & & . . . args ) {
return ChangeCase < K > : : changeCase ( f , uni : : lower , std : : forward < Args > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С о з д а т ь к о п и ю п е р е д а н н о й с т р о к и с з а м е н о й п о д с т р о к .
* @ param f - с т р о к а и с т о ч н и к .
* @ param pattern - п о д с т р о к а , к о т о р у ю н а д о з а м е н и т ь .
* @ param repl - с т р о к а , н а к о т о р у ю н а д о з а м е н и т ь .
* @ param offset - н а ч а л ь н а я п о з и ц и я д л я п о и с к а п о д с т р о к .
* @ param maxCount - м а к с и м а л ь н о е к о л и ч е с т в о з а м е н , 0 - б е з о г р а н и ч е н и й .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief Create a copy of the passed string with substrings replaced .
* @ param f - source string .
* @ 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 .
* @ param . . . args - parameters for initializing the allocator .
2025-04-05 14:21:11 +00:00
*/
template < StrType < K > From , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
static my_type replaced_from ( const From & f , s_str pattern , s_str repl , size_t offset = 0 , size_t maxCount = 0 , Args & & . . . args ) {
return my_type { f , pattern , repl , offset , maxCount , std : : forward < Args > ( args ) . . . } ;
}
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н ц е п т т и п а , у п р а в л я ю щ е г о п а м я т ь ю
* @ en @ brief Concept of a memory management type
2025-04-05 14:21:11 +00:00
*/
template < typename A >
concept Allocatorable = requires ( A & a , size_t size , void * void_ptr ) {
{ a . allocate ( size ) } - > std : : same_as < void * > ;
{ a . deallocate ( void_ptr ) } noexcept - > std : : same_as < void > ;
} ;
struct printf_selector {
template < typename K , typename . . . T > requires ( is_one_of_std_char_v < K > )
static int snprintf ( K * buffer , size_t count , const K * format , T & & . . . args ) {
2026-01-21 11:59:17 +00:00
if constexpr ( sizeof ( K ) = = 1 ) {
2025-04-05 14:21:11 +00:00
# ifndef _WIN32
2026-01-21 11:59:17 +00:00
return std : : snprintf ( to_one_of_std_char ( buffer ) , count , to_one_of_std_char ( format ) , std : : forward < T > ( args ) . . . ) ;
2025-04-05 14:21:11 +00:00
# else
// Поддерживает позиционные параметры
2025-11-17 09:01:31 +00:00
// Supports positional parameters
2026-01-21 11:59:17 +00:00
return _sprintf_p ( to_one_of_std_char ( buffer ) , count , to_one_of_std_char ( format ) , args . . . ) ;
2025-04-05 14:21:11 +00:00
# endif
} else {
# ifndef _WIN32
return std : : swprintf ( to_one_of_std_char ( buffer ) , count , to_one_of_std_char ( format ) , args . . . ) ;
# else
// Поддерживает позиционные параметры
2025-11-17 09:01:31 +00:00
// Supports positional parameters
2025-04-05 14:21:11 +00:00
return _swprintf_p ( to_one_of_std_char ( buffer ) , count , to_one_of_std_char ( format ) , args . . . ) ;
# endif
}
}
template < typename K > requires ( is_one_of_std_char_v < K > )
static int vsnprintf ( K * buffer , size_t count , const K * format , va_list args ) {
if constexpr ( std : : is_same_v < K , u8s > ) {
# ifndef _WIN32
return std : : vsnprintf ( buffer , count , format , args ) ;
# else
// Поддерживает позиционные параметры
2025-11-17 09:01:31 +00:00
// Supports positional parameters
2025-04-05 14:21:11 +00:00
return _vsprintf_p ( buffer , count , format , args ) ;
# endif
} else {
# ifndef _WIN32
return std : : vswprintf ( to_one_of_std_char ( buffer ) , count , to_one_of_std_char ( format ) , args ) ;
# else
// Поддерживает позиционные параметры
2025-11-17 09:01:31 +00:00
// Supports positional parameters
2025-04-05 14:21:11 +00:00
return _vswprintf_p ( buffer , count , format , args ) ;
# endif
}
}
} ;
inline size_t grow2 ( size_t ret , size_t currentCapacity ) {
return ret < = currentCapacity ? ret : ret * 2 ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Б а з о в ы й к л а с с р а б о т ы с и з м е н я е м ы м и с т р о к а м и
2025-04-05 14:21:11 +00:00
* @ tparam K - т и п с и м в о л о в
* @ tparam Impl - к о н е ч н ы й т и п н а с л е д н и к а
* @ details П о п р е ж н е м у н и ч е г о н е з н а е т о т о м , г д е н а с л е д н и к х р а н и т с т р о к у и е ё р а з м е р .
* П р о с т о в ы з ы в а е т е г о м е т о д ы д л я п о л у ч е н и я м е с т а , и з а п о л н я е т е г о п р и н е о б х о д и м о с т и .
* Д л я р а б о т ы к л а с с - н а с л е д н и к д о л ж е н р е а л и з о в а т ь м е т о д ы :
* - ` size_t length ( ) const noexcept ` - в о з в р а щ а е т д л и н у с т р о к и
* - ` const K * symbols ( ) const ` - в о з в р а щ а е т у к а з а т е л ь н а н а ч а л о с т р о к и
* - ` bool is_empty ( ) const noexcept ` - п р о в е р к а , н е п у с т а я л и с т р о к а
* - ` K * str ( ) noexcept ` - Н е к о н с т а н т н ы й у к а з а т е л ь н а н а ч а л о с т р о к и
* - ` K * set_size ( size_t size ) ` - И з м е н и т ь р а з м е р с т р о к и , к а к б о л ь ш е , т а к и м е н ь ш е .
* С о д е р ж и м о е с т р о к и н у ж н о о с т а в и т ь .
* - ` K * reserve_no_preserve ( size_t size ) ` - в ы д е л и т ь м е с т о п о д с т р о к у , с т а р у ю м о ж н о н е с о х р а н я т ь
* - ` K * alloc_for_copy ( size_t size ) ` - в ы д е л и т ь м е с т о д л я к о п и и с т р о к и з а д а н н о г о р а з м е р а , п о к а н е и з м е н я я
* с а м у с т р о к у , м о ж н о в е р н у т ь т е к у щ и й б у ф е р , е с л и м е с т о п о з в о л я е т .
* - ` set_from_copy ( K * str , size_t size ) ` - п р и с в о и т ь с т р о к у и з п а м я т и , р а н е е в ы д е л е н н о й в alloc_for_copy .
* Е с л и м е с т о в ы д е л я л о с ь в т е к у щ е м б у ф е р е , н и ч е г о н е д е л а т ь .
2025-11-17 09:01:31 +00:00
* - ` size_t capacity ( ) const noexcept ` - в е р н у т ь т е к у щ у ю ё м к о с т ь с т р о к и , с к о л ь к о м о ж е т п о м е с т и т с я б е з а л л о к а ц и и .
* @ en @ brief Base class for working with mutable strings
* @ tparam K - character type
* @ tparam Impl - the final type of the successor
* @ details Still knows nothing about where the heir stores the string and its size .
* Simply calls its methods to get the space , and fills it as needed .
* To work , the descendant class must implement the following methods :
* - ` size_t length ( ) const noexcept ` - returns the length of the string
* - ` const K * symbols ( ) const ` - returns a pointer to the beginning of the line
* - ` bool is_empty ( ) const noexcept ` - checks whether the string is empty
* - ` K * str ( ) noexcept ` - Non - const pointer to the beginning of the string
* - ` K * set_size ( size_t size ) ` - Change the size of the string , either larger or smaller .
* The contents of the line must be left .
* - ` K * reserve_no_preserve ( size_t size ) ` - allocate space for a line , you don ’ t have to save the old one
* - ` K * alloc_for_copy ( size_t size ) ` - allocate space for a copy of a string of a given size , without changing it yet
* the string itself , you can return the current buffer if space allows .
* - ` set_from_copy ( K * str , size_t size ) ` - assign a string from memory previously allocated in alloc_for_copy .
* If space was allocated in the current buffer , do nothing .
* - ` size_t capacity ( ) const noexcept ` - return the current capacity of the string , as much as can fit without allocation .
2025-04-05 14:21:11 +00:00
*/
template < typename K , typename Impl >
class str_mutable {
public :
using my_type = Impl ;
private :
Impl & d ( ) {
return * static_cast < Impl * > ( this ) ;
}
const Impl & d ( ) const {
return * static_cast < const Impl * > ( this ) ;
}
size_t _len ( ) const noexcept {
return d ( ) . length ( ) ;
}
const K * _str ( ) const noexcept {
return d ( ) . symbols ( ) ;
}
using str_piece = simple_str < K > ;
using symb_type = K ;
using traits = ch_traits < K > ;
using uni = unicode_traits < K > ;
using uns_type = std : : make_unsigned_t < K > ;
template < typename Op >
Impl & make_trim_op ( const Op & op ) {
2026-01-21 11:59:17 +00:00
str_piece me = d ( ) , pos = op ( me ) ;
2025-04-05 14:21:11 +00:00
if ( me . length ( ) ! = pos . length ( ) ) {
if ( me . symbols ( ) ! = pos . symbols ( ) )
traits : : move ( const_cast < K * > ( me . symbols ( ) ) , pos . symbols ( ) , pos . length ( ) ) ;
d ( ) . set_size ( pos . length ( ) ) ;
}
return d ( ) ;
}
template < auto Op >
Impl & commonChangeCase ( ) {
size_t len = _len ( ) ;
if ( len )
Op ( _str ( ) , len , str ( ) ) ;
return d ( ) ;
}
// GCC до сих пор не позволяет делать внутри класса полную специализацию вложенного класса,
// только частичную. Поэтому добавим неиспользуемый параметр шаблона.
2025-11-17 09:01:31 +00:00
// GCC still does not allow full specialization of a nested class within a class,
// only partial. Resources additive unused parameter template.
2025-04-05 14:21:11 +00:00
template < typename T , bool Dummy = true >
struct CaseTraits {
static Impl & upper ( Impl & obj ) {
return obj . template commonChangeCase < unicode_traits < K > : : upper > ( ) ;
}
static Impl & lower ( Impl & obj ) {
return obj . template commonChangeCase < unicode_traits < K > : : lower > ( ) ;
}
} ;
template < auto Op >
Impl & utf8CaseChange ( ) {
// Для utf-8 такая операция может изменить длину строки, поэтому для них делаем разные специализации
2025-11-17 09:01:31 +00:00
// For utf-8, such an operation can change the length of the string, so we make different specializations for them
2025-04-05 14:21:11 +00:00
size_t len = _len ( ) ;
if ( len ) {
u8s * writePos = str ( ) ;
const u8s * startData = writePos , * readPos = writePos ;
size_t newLen = Op ( readPos , len , writePos , len ) ;
if ( newLen < len ) {
// Строка просто укоротилась
2025-11-17 09:01:31 +00:00
// The string was simply shortened
2025-04-05 14:21:11 +00:00
d ( ) . set_size ( newLen ) ;
} else if ( newLen > len ) {
// Строка не влезла в буфер.
2025-11-17 09:01:31 +00:00
// The line did not fit into the buffer.
2025-04-05 14:21:11 +00:00
size_t readed = static_cast < size_t > ( readPos - startData ) ;
size_t writed = static_cast < size_t > ( writePos - startData ) ;
d ( ) . set_size ( newLen ) ;
2025-11-17 09:01:31 +00:00
startData = str ( ) ; // при изменении размера могло изменится | may change when resizing
2025-04-05 14:21:11 +00:00
readPos = startData + readed ;
writePos = const_cast < u8s * > ( startData ) + writed ;
Op ( readPos , len - readed , writePos , newLen - writed ) ;
}
}
return d ( ) ;
}
template < bool Dummy >
struct CaseTraits < u8s , Dummy > {
static Impl & upper ( Impl & obj ) {
return obj . template utf8CaseChange < unicode_traits < u8s > : : upper > ( ) ;
}
static Impl & lower ( Impl & obj ) {
return obj . template utf8CaseChange < unicode_traits < u8s > : : lower > ( ) ;
}
} ;
template < TrimSides S , bool withSpaces , typename T , size_t N = const_lit_for < K , T > : : Count >
Impl & makeTrim ( T & & pattern ) {
return make_trim_op ( trim_operator < S , K , N - 1 , withSpaces > { pattern } ) ;
}
template < TrimSides S , bool withSpaces >
Impl & makeTrim ( str_piece pattern ) {
return make_trim_op ( trim_operator < S , K , 0 , withSpaces > { { pattern } } ) ;
}
public :
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь у к а з а т е л ь н а б у ф е р с т р о к и .
* @ return K * - у к а з а т е л ь н а б у ф е р с т р о к и .
* @ en @ brief Get a pointer to the string buffer .
* @ return K * - pointer to the string buffer .
2025-04-05 14:21:11 +00:00
*/
K * str ( ) noexcept {
return d ( ) . str ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь у к а з а т е л ь н а б у ф е р с т р о к и .
* @ return K * - у к а з а т е л ь н а б у ф е р с т р о к и .
* @ en @ brief Get a pointer to the string buffer .
* @ return K * - pointer to the string buffer .
2025-04-05 14:21:11 +00:00
*/
explicit operator K * ( ) noexcept {
return str ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь п р о б е л ь н ы е с и м в о л ы в н а ч а л е и в к о н ц е с т р о к и .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Remove whitespace from the beginning and end of a line .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & trim ( ) {
return make_trim_op ( SimpleTrim < TrimSides : : TrimAll , K > { } ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь п р о б е л ь н ы е с и м в о л ы в н а ч а л е с т р о к и .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Remove whitespace at the beginning of a line .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & trim_left ( ) {
return make_trim_op ( SimpleTrim < TrimSides : : TrimLeft , K > { } ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь п р о б е л ь н ы е с и м в о л ы в к о н ц е с т р о к и .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Remove whitespace from the end of a line .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & trim_right ( ) {
return make_trim_op ( SimpleTrim < TrimSides : : TrimRight , K > { } ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в с т р о к о в ы й л и т е р а л , в н а ч а л е и в к о н ц е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к о в ы й л и т е р а л , с о д е р ж а щ и й с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
2025-11-17 09:01:31 +00:00
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Remove characters included in a string literal at the beginning and end of the line .
* @ param pattern is a string literal containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t N = const_lit_for < K , T > : : Count >
requires is_const_pattern < N >
Impl & trim ( T & & pattern ) {
return makeTrim < TrimSides : : TrimAll , false > ( pattern ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в с т р о к о в ы й л и т е р а л , в н а ч а л е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к о в ы й л и т е р а л , с о д е р ж а щ и й с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
2025-11-17 09:01:31 +00:00
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Remove characters included in a string literal at the beginning of the line .
* @ param pattern is a string literal containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t N = const_lit_for < K , T > : : Count >
requires is_const_pattern < N >
Impl & trim_left ( T & & pattern ) {
return makeTrim < TrimSides : : TrimLeft , false > ( pattern ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в с т р о к о в ы й л и т е р а л , в к о н ц е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к о в ы й л и т е р а л , с о д е р ж а щ и й с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
2025-11-17 09:01:31 +00:00
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Remove characters included in a string literal at the end of the line .
* @ param pattern is a string literal containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t N = const_lit_for < K , T > : : Count >
requires is_const_pattern < N >
Impl & trim_right ( T & & pattern ) {
return makeTrim < TrimSides : : TrimRight , false > ( pattern ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в с т р о к о в ы й л и т е р а л , а т а к ж е п р о б е л ь н ы е с и м в о л ы , в н а ч а л е и в к о н ц е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к о в ы й л и т е р а л , с о д е р ж а щ и й с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Remove characters included in a string literal , as well as whitespace , at the beginning and end of the string .
* @ param pattern is a string literal containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t N = const_lit_for < K , T > : : Count >
requires is_const_pattern < N >
Impl & trim_with_spaces ( T & & pattern ) {
return makeTrim < TrimSides : : TrimAll , true > ( pattern ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в с т р о к о в ы й л и т е р а л , а т а к ж е п р о б е л ь н ы е с и м в о л ы , в н а ч а л е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к о в ы й л и т е р а л , с о д е р ж а щ и й с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Remove characters included in a string literal , as well as whitespace , at the beginning of a line .
* @ param pattern is a string literal containing the characters to be removed .
* @ en @ brief * @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t N = const_lit_for < K , T > : : Count >
requires is_const_pattern < N >
Impl & trim_left_with_spaces ( T & & pattern ) {
return makeTrim < TrimSides : : TrimLeft , true > ( pattern ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в с т р о к о в ы й л и т е р а л , а т а к ж е п р о б е л ь н ы е с и м в о л ы , в к о н ц е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к о в ы й л и т е р а л , с о д е р ж а щ и й с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Remove characters included in a string literal , as well as whitespace , at the end of a string .
* @ param pattern is a string literal containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t N = const_lit_for < K , T > : : Count >
requires is_const_pattern < N >
Impl & trim_right_with_wpaces ( T & & pattern ) {
return makeTrim < TrimSides : : TrimRight , true > ( pattern ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в п е р е д а н н у ю с т р о к у , в н а ч а л е и в к о н ц е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к а , с о д е р ж а щ а я с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Remove characters included in the passed string at the beginning and end of the line .
* @ param pattern - a string containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & trim ( str_piece pattern ) {
return pattern . length ( ) ? makeTrim < TrimSides : : TrimAll , false > ( pattern ) : d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в п е р е д а н н у ю с т р о к у , в н а ч а л е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к а , с о д е р ж а щ а я с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Remove characters included in the passed string at the beginning of the line .
* @ param pattern - a string containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & trim_left ( str_piece pattern ) {
return pattern . length ( ) ? makeTrim < TrimSides : : TrimLeft , false > ( pattern ) : d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в п е р е д а н н у ю с т р о к у , в к о н ц е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к а , с о д е р ж а щ а я с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Remove characters included in the passed string from the end of the string .
* @ param pattern - a string containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & trim_right ( str_piece pattern ) {
return pattern . length ( ) ? makeTrim < TrimSides : : TrimRight , false > ( pattern ) : d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в п е р е д а н н у ю с т р о к у , а т а к ж е п р о б е л ь н ы е с и м в о л ы , в н а ч а л е и в к о н ц е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к а , с о д е р ж а щ а я с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Remove characters included in the passed string , as well as whitespace characters , at the beginning and end of the string .
* @ param pattern - a string containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & trim_with_spaces ( str_piece pattern ) {
return makeTrim < TrimSides : : TrimAll , true > ( pattern ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в п е р е д а н н у ю с т р о к у , а т а к ж е п р о б е л ь н ы е с и м в о л ы , в н а ч а л е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к а , с о д е р ж а щ а я с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Remove characters included in the passed string , as well as whitespace , at the beginning of the string .
* @ param pattern - a string containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & trim_left_with_spaces ( str_piece pattern ) {
return makeTrim < TrimSides : : TrimLeft , true > ( pattern ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь с и м в о л ы , в х о д я щ и е в п е р е д а н н у ю с т р о к у , а т а к ж е п р о б е л ь н ы е с и м в о л ы , в к о н ц е с т р о к и .
2025-04-05 14:21:11 +00:00
* @ param pattern - с т р о к а , с о д е р ж а щ а я с и м в о л ы , к о т о р ы е н а д о у д а л и т ь .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Remove characters included in the passed string , as well as whitespace at the end of the string .
* @ param pattern - a string containing the characters to be removed .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & trim_right_with_spaces ( str_piece pattern ) {
return makeTrim < TrimSides : : TrimRight , true > ( pattern ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р е о б р а з о в а т ь в в е р х н и й р е г и с т р ASCII с и м в о л ы .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Convert ASCII characters to uppercase .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & upper_only_ascii ( ) {
K * ptr = str ( ) ;
for ( size_t i = 0 , l = _len ( ) ; i < l ; i + + , ptr + + ) {
K s = * ptr ;
if ( isAsciiLower ( s ) )
* ptr = s & ~ 0x20 ;
}
return d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р е о б р а з о в а т ь в н и ж н и й р е г и с т р ASCII с и м в о л ы .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Convert ASCII characters to lowercase .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & lower_only_ascii ( ) {
K * ptr = str ( ) ;
for ( size_t i = 0 , l = _len ( ) ; i < l ; i + + , ptr + + ) {
K s = * ptr ;
if ( isAsciiUpper ( s ) )
* ptr = s | 0x20 ;
}
return d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р е о б р а з о в а т ь в в е р х н и й р е г и с т р Unicode с и м в о л ы п е р в о й п л о с к о с т и ( < 0xFFFF ) .
2025-04-05 14:21:11 +00:00
* @ details Р е г и с т р м е н я е т с я у п р о щ е н н ы м и т а б л и ц а м и , г д е о д и н code_point в с е г д а м е н я е т с я в о д и н code_point
* ( н о д л я UTF - 8 в о з м о ж н о , ч т о д л и н а в code unit ' а х и з м е н и т с я ) .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Convert first plane characters ( < 0xFFFF ) to uppercase Unicode .
* @ details Case is changed by simplified tables , where one code_point is always changed to one code_point
* ( but for UTF - 8 it is possible that the length in code units will change ) .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & upper ( ) {
// Для utf-8 такая операция может изменить длину строки, поэтому для них делаем разные специализации
2025-11-17 09:01:31 +00:00
// For utf-8, such an operation can change the length of the string, so we make different specializations for them
2025-04-05 14:21:11 +00:00
return CaseTraits < K > : : upper ( d ( ) ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р е о б р а з о в а т ь в н и ж н и й р е г и с т р Unicode с и м в о л ы п е р в о й п л о с к о с т и ( < 0xFFFF ) .
2025-04-05 14:21:11 +00:00
* @ details Р е г и с т р м е н я е т с я у п р о щ е н н ы м и т а б л и ц а м и , г д е о д и н code_point в с е г д а м е н я е т с я в о д и н code_point
* ( н о д л я UTF - 8 в о з м о ж н о , ч т о д л и н а в code unit ' а х и з м е н и т с я ) .
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Convert first plane characters ( < 0xFFFF ) to lowercase Unicode .
* @ details Case is changed by simplified tables , where one code_point is always changed to one code_point
* ( but for UTF - 8 it is possible that the length in code units will change ) .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & lower ( ) {
// Для utf-8 такая операция может изменить длину строки, поэтому для них делаем разные специализации
2025-11-17 09:01:31 +00:00
// For utf-8, such an operation can change the length of the string, so we make different specializations for them
2025-04-05 14:21:11 +00:00
return CaseTraits < K > : : lower ( d ( ) ) ;
}
private :
template < typename T >
Impl & changeImpl ( size_t from , size_t len , T expr ) {
size_t myLen = _len ( ) ;
if ( from > myLen ) {
from = myLen ;
}
if ( from + len > myLen ) {
len = myLen - from ;
}
K * buffer = str ( ) ;
size_t otherLen = expr . length ( ) ;
if ( len = = otherLen ) {
expr . place ( buffer + from ) ;
} else {
size_t tailLen = myLen - from - len ;
if ( len > otherLen ) {
expr . place ( buffer + from ) ;
traits : : move ( buffer + from + otherLen , buffer + from + len , tailLen ) ;
d ( ) . set_size ( myLen - ( len - otherLen ) ) ;
} else {
buffer = d ( ) . set_size ( myLen + otherLen - len ) ;
traits : : move ( buffer + from + otherLen , buffer + from + len , tailLen ) ;
expr . place ( buffer + from ) ;
}
}
return d ( ) ;
}
template < typename T >
Impl & appendImpl ( T expr ) {
if ( size_t len = expr . length ( ) ; len ) {
size_t size = _len ( ) ;
expr . place ( d ( ) . set_size ( size + len ) + size ) ;
}
return d ( ) ;
}
template < typename T >
Impl & appendFromImpl ( size_t pos , T expr ) {
if ( pos > _len ( ) )
pos = _len ( ) ;
if ( size_t len = expr . length ( ) )
expr . place ( d ( ) . set_size ( pos + len ) + pos ) ;
else
d ( ) . set_size ( pos ) ;
return d ( ) ;
}
public :
inline static constexpr bool is_str_mutable = true ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в и т ь д р у г у ю с т р о к у в к о н е ц с т р о к и .
* @ param other - д р у г а я с т р о к а .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Add another line to the end of the line .
* @ param other - another string .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & append ( str_piece other ) {
return appendImpl < str_piece > ( other ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в и т ь с т р о к о в о е в ы р а ж е н и е в к о н е ц с т р о к и .
* @ param expr - с т р о к о в о е в ы р а ж е н и е .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Add a string expression to the end of the line .
* @ param expr - string expression .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < StrExprForType < K > A >
Impl & append ( const A & expr ) {
return appendImpl < const A & > ( expr ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в и т ь д р у г у ю с т р о к у в к о н е ц с т р о к и .
* @ param other - д р у г а я с т р о к а .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Add another line to the end of the line .
* @ param other - another line .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & operator + = ( str_piece other ) {
return appendImpl < str_piece > ( other ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в и т ь с т р о к о в о е в ы р а ж е н и е в к о н е ц с т р о к и .
* @ param expr - с т р о к о в о е в ы р а ж е н и е .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Add a string expression to the end of the line .
* @ param expr - string expression .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < StrExprForType < K > A >
Impl & operator + = ( const A & expr ) {
return appendImpl < const A & > ( expr ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в и т ь д р у г у ю с т р о к у , н а ч и н а я с з а д а н н о й п о з и ц и и .
2025-04-05 14:21:11 +00:00
* @ param pos - п о з и ц и я , с к о т о р о й д о б а в л я т ь . С н а ч а л а с т р о к а у к о р а ч и в а е т с я д о з а д а н н о г о
2025-11-17 09:01:31 +00:00
* р а з м е р а , а п о т о м д о б а в л я е т с я д р у г а я с т р о к а .
* @ param other - д р у г а я с т р о к а .
* @ return Impl & - с с ы л к у н а с е б я ж е .
2025-04-05 14:21:11 +00:00
* @ details Е с л и с т р о к а д л и и н е е ` pos ` , т о о н а у к о р а ч и в а е т с я д о э т о г о р а з м е р а , а п о т о м д о б а в л я е т с я ` other ` .
2025-11-17 09:01:31 +00:00
* @ en @ brief Add another line starting at the given position .
* @ param pos - the position from which to add . First , the string is shortened to the specified value
* size , and then another line is added .
* @ param other - another string .
* @ return Impl & - a reference to yourself .
* @ details If the string is longer than ` pos ` , then it is shortened to this size , and then ` other ` is added .
2025-04-05 14:21:11 +00:00
*/
Impl & append_in ( size_t pos , str_piece other ) {
return appendFromImpl < str_piece > ( pos , other ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в и т ь с т р о к о в о е в ы р а ж е н и е , н а ч и н а я с з а д а н н о й п о з и ц и и .
2025-04-05 14:21:11 +00:00
* @ param pos - п о з и ц и я , с к о т о р о й д о б а в л я т ь . С н а ч а л а с т р о к а у к о р а ч и в а е т с я д о з а д а н н о г о
2025-11-17 09:01:31 +00:00
* р а з м е р а , а п о т о м д о б а в л я е т с я с т р о к о в о е в ы р а ж е н и е .
* @ param expr - с т р о к о в о е в ы р а ж е н и е .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details Е с л и с т р о к а д л и н н е е ` pos ` , т о о н а у к о р а ч и в а е т с я д о э т о г о р а з м е р а , а п о т о м д о б а в л я е т с я ` expr ` .
* @ en @ brief Add a string expression starting at the given position .
* @ param pos - the position from which to add . First , the string is shortened to the specified value
* size , and then a string expression is added .
* @ param expr - string expression .
* @ return Impl & - a reference to yourself .
* @ details If the string is longer than ` pos ` , then it is shortened to this size , and then ` expr ` is added .
2025-04-05 14:21:11 +00:00
*/
template < StrExprForType < K > A >
Impl & append_in ( size_t pos , const A & expr ) {
return appendFromImpl < const A & > ( pos , expr ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief З а м е н и т ь к у с о к с т р о к и н а д р у г у ю с т р о к у .
* @ param from - н а ч а л ь н а я п о з и ц и я д л я з а м е н ы .
* @ param len - д л и н а з а м е н я е м о й ч а с т и .
* @ param other - с т р о к а , н а к о т о р у ю э т а ч а с т ь м е н я е т с я .
2025-04-05 14:21:11 +00:00
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ en @ brief Replace a piece of string with another string .
* @ param from - starting position for replacement .
* @ param len - length of the part to be replaced .
* @ param other - the string this part is changed to .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & change ( size_t from , size_t len , str_piece other ) {
return changeImpl < str_piece > ( from , len , other ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief З а м е н и т ь к у с о к с т р о к и н а с т р о к о в о е в ы р а ж е н и е .
* @ param from - н а ч а л ь н а я п о з и ц и я д л я з а м е н ы .
* @ param len - д л и н а з а м е н я е м о й ч а с т и .
* @ param expr - с т р о к о в о е в ы р а ж е н и е .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Replace a piece of string with a string expression .
* @ param from - starting position for replacement .
* @ param len - length of the part to be replaced .
* @ param expr - string expression .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < StrExprForType < K > A >
Impl & change ( size_t from , size_t len , const A & expr ) {
return changeImpl < const A & > ( from , len , expr ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief В с т а в и т ь с т р о к у в у к а з а н н у ю п о з и ц и ю .
* @ param to - п о з и ц и я д л я в с т а в к и .
* @ param other - в с т а в л я е м а я с т р о к а .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Insert a line at the specified position .
* @ param to - insertion position .
* @ param other - the string to be inserted .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & insert ( size_t to , str_piece other ) {
return changeImpl < str_piece > ( to , 0 , other ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief В с т а в и т ь с т р о к о в о е в ы р а ж е н и е в у к а з а н н у ю п о з и ц и ю .
* @ param to - п о з и ц и я д л я в с т а в к и .
* @ param expr - с т р о к о в о е в ы р а ж е н и е .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Insert a string expression at the specified position .
* @ param to - insertion position .
* @ param expr - string expression .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < StrExprForType < K > A >
Impl & insert ( size_t to , const A & expr ) {
return changeImpl < const A & > ( to , 0 , expr ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У д а л и т ь ч а с т ь с т р о к и .
* @ param from - п о з и ц и я , с к о т о р о й у д а л и т ь .
* @ param len - д л и н а у д а л я е м о й ч а с т и .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Remove part of a line .
* @ param from - the position from which to delete .
* @ param len - length of the part to be deleted .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & remove ( size_t from , size_t len ) {
return changeImpl < const empty_expr < K > & > ( from , len , { } ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в и т ь д р у г у ю с т р о к у в н а ч а л о с т р о к и .
* @ param other - д р у г а я с т р о к а .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Add another line to the beginning of the line .
* @ param other - another string .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & prepend ( str_piece other ) {
return changeImpl < str_piece > ( 0 , 0 , other ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в и т ь с т р о к о в о е в ы р а ж е н и е в н а ч а л о с т р о к и .
* @ param expr - с т р о к о в о е в ы р а ж е н и е .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Add a string expression to the beginning of a line .
* @ param expr - string expression .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < StrExprForType < K > A >
Impl & prepend ( const A & expr ) {
return changeImpl < const A & > ( 0 , 0 , expr ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief З а м е н и т ь в х о ж д е н и я п о д с т р о к и н а д р у г у ю с т р о к у .
* @ param pattern - и с к о м а я п о д с т р о к а .
* @ param repl - с т р о к а з а м е н ы .
* @ param offset - н а ч а л ь н а я п о з и ц и я д л я п о и с к а .
* @ param maxCount - м а к с и м а л ь н о е к о л и ч е с т в о з а м е н , 0 - б е з о г р а н и ч е н и й .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Replace occurrences of a substring with another string .
* @ param pattern - the substring to search for .
* @ param repl - replacement string .
* @ param offset - the starting position for the search .
* @ param maxCount - maximum number of replacements , 0 - no restrictions .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
Impl & replace ( str_piece pattern , str_piece repl , size_t offset = 0 , size_t maxCount = 0 ) {
offset = d ( ) . find ( pattern , offset ) ;
if ( offset = = str : : npos ) {
return d ( ) ;
}
if ( ! maxCount )
maxCount - - ;
size_t replLength = repl . length ( ) , patternLength = pattern . length ( ) ;
if ( patternLength = = replLength ) {
// Заменяем inplace на подстроку такой же длины
2025-11-17 09:01:31 +00:00
// Replace inplace with a substring of the same length
2025-04-05 14:21:11 +00:00
K * ptr = str ( ) ;
2026-01-24 14:59:59 +00:00
while ( maxCount - - ) {
2025-04-05 14:21:11 +00:00
traits : : copy ( ptr + offset , repl . symbols ( ) , replLength ) ;
offset = d ( ) . find ( pattern , offset + replLength ) ; // replLength == patternLength
if ( offset = = str : : npos )
break ;
}
} else if ( patternLength > replLength ) {
// Заменяем на более короткий кусок, длина текста уменьшится, идём слева направо
2025-11-17 09:01:31 +00:00
// Replace with a shorter piece, the length of the text will decrease, go from left to right
2025-04-05 14:21:11 +00:00
K * ptr = str ( ) ;
traits : : copy ( ptr + offset , repl . symbols ( ) , replLength ) ;
size_t posWrite = offset + replLength ;
offset + = patternLength ;
2026-01-24 14:59:59 +00:00
while ( - - maxCount ) {
2025-04-05 14:21:11 +00:00
size_t idx = d ( ) . find ( pattern , offset ) ;
if ( idx = = str : : npos )
break ;
size_t lenOfPiece = idx - offset ;
traits : : move ( ptr + posWrite , ptr + offset , lenOfPiece ) ;
posWrite + = lenOfPiece ;
traits : : copy ( ptr + posWrite , repl . symbols ( ) , replLength ) ;
posWrite + = replLength ;
offset = idx + patternLength ;
}
size_t tailLen = _len ( ) - offset ;
traits : : move ( ptr + posWrite , ptr + offset , tailLen ) ;
d ( ) . set_size ( posWrite + tailLen ) ;
} else {
struct replace_grow_helper {
replace_grow_helper ( my_type & src , str_piece p , str_piece r , size_t mc , size_t d )
: source ( src ) , pattern ( p ) , repl ( r ) , maxCount ( mc ) , delta ( d ) { }
my_type & source ;
const str_piece pattern ;
const str_piece repl ;
size_t maxCount ;
const size_t delta ;
size_t all_delta { } ;
K * reserve_for_copy { } ;
size_t end_of_piece { } ;
size_t total_length { } ;
void replace ( size_t offset ) {
2026-01-24 14:59:59 +00:00
size_t found [ 16 ] = { offset } ;
2025-04-05 14:21:11 +00:00
maxCount - - ;
2026-01-24 14:59:59 +00:00
offset + = pattern . length ( ) ;
2025-04-05 14:21:11 +00:00
all_delta + = delta ;
size_t idx = 1 ;
2026-01-24 14:59:59 +00:00
for ( ; idx < std : : size ( found ) & & maxCount > 0 ; idx + + , maxCount - - ) {
found [ idx ] = source . find ( pattern , offset ) ;
if ( found [ idx ] = = str : : npos ) {
2025-04-05 14:21:11 +00:00
break ;
}
2026-01-24 14:59:59 +00:00
offset = found [ idx ] + pattern . length ( ) ;
2025-04-05 14:21:11 +00:00
all_delta + = delta ;
}
2026-01-24 14:59:59 +00:00
if ( idx = = std : : size ( found ) & & maxCount > 0 & & ( offset = source . find ( pattern , offset ) ) ! = str : : npos ) {
replace ( offset ) ; // здесь произойдут замены в оставшемся хвосте | replacements will be made here in the remaining tail
2025-04-05 14:21:11 +00:00
}
// Теперь делаем свои замены
2025-11-17 09:01:31 +00:00
// Now we make our replacements
2025-04-05 14:21:11 +00:00
if ( ! reserve_for_copy ) {
// Только начинаем
2025-11-17 09:01:31 +00:00
// Just getting started
2025-04-05 14:21:11 +00:00
end_of_piece = source . length ( ) ;
total_length = end_of_piece + all_delta ;
reserve_for_copy = source . alloc_for_copy ( total_length ) ;
}
K * dst_start = reserve_for_copy ;
const K * src_start = source . symbols ( ) ;
while ( idx - - > 0 ) {
2026-01-24 14:59:59 +00:00
size_t pos = found [ idx ] + pattern . length ( ) ;
2025-04-05 14:21:11 +00:00
size_t lenOfPiece = end_of_piece - pos ;
ch_traits < K > : : move ( dst_start + pos + all_delta , src_start + pos , lenOfPiece ) ;
ch_traits < K > : : copy ( dst_start + pos + all_delta - repl . length ( ) , repl . symbols ( ) , repl . length ( ) ) ;
all_delta - = delta ;
2026-01-24 14:59:59 +00:00
end_of_piece = found [ idx ] ;
2025-04-05 14:21:11 +00:00
}
if ( ! all_delta & & reserve_for_copy ! = src_start ) {
2026-01-24 14:59:59 +00:00
ch_traits < K > : : copy ( dst_start , src_start , found [ 0 ] ) ;
2025-04-05 14:21:11 +00:00
}
}
} helper ( d ( ) , pattern , repl , maxCount , repl . length ( ) - pattern . length ( ) ) ;
helper . replace ( offset ) ;
d ( ) . set_from_copy ( helper . reserve_for_copy , helper . total_length ) ;
}
return d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С к о п и р о в а т ь с т р о к у - и с т о ч н и к , з а м е н и в в х о ж д е н и я п о д с т р о к н а д р у г у ю с т р о к у .
* @ param f - с т р о к а - и с т о ч н и к .
* @ param pattern - и с к о м а я п о д с т р о к а .
* @ param repl - с т р о к а з а м е н ы .
* @ param offset - н а ч а л ь н а я п о з и ц и я д л я п о и с к а .
* @ param maxCount - м а к с и м а л ь н о е к о л и ч е с т в о з а м е н , 0 - б е з о г р а н и ч е н и й .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Copy the source string , replacing occurrences of substrings with another string .
* @ param f - source string .
* @ param pattern - the substring to search for .
* @ param repl - replacement string .
* @ param offset - the starting position for the search .
* @ param maxCount - maximum number of replacements , 0 - no restrictions .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < StrType < K > From >
Impl & replace_from ( const From & f , str_piece pattern , str_piece repl , size_t offset = 0 , size_t maxCount = 0 ) {
if ( pattern . length ( ) > = repl . length ( ) ) {
K * dst = d ( ) . reserve_no_preserve ( f . length ( ) ) ;
const K * src = f . symbols ( ) ;
size_t delta = 0 ;
if ( maxCount = = 0 ) {
maxCount - - ;
}
size_t src_length = f . length ( ) , start = 0 ;
while ( maxCount - - ) {
offset = f . find ( pattern , offset ) ;
if ( offset = = str : : npos ) {
break ;
}
size_t piece_len = offset - start ;
if ( piece_len ) {
ch_traits < K > : : copy ( dst , src + start , piece_len ) ;
dst + = piece_len ;
}
if ( repl . length ( ) ) {
ch_traits < K > : : copy ( dst , repl . symbols ( ) , repl . length ( ) ) ;
dst + = repl . length ( ) ;
}
delta + = pattern . length ( ) - repl . length ( ) ;
offset + = pattern . length ( ) ;
start = offset ;
}
if ( start < src_length ) {
ch_traits < K > : : copy ( dst , src + start , src_length - start ) ;
}
d ( ) . set_size ( src_length - delta ) ;
} else {
d ( ) = f ;
replace ( pattern , repl , offset , maxCount ) ;
}
return d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief З а п о л н е н и е б у ф е р а с т р о к и с п о м о щ ь ю ф у н к т о р а .
* @ param from - н а ч а л ь н а я п о з и ц и я д л я з а п о л н е н и я .
2025-04-05 14:21:11 +00:00
* @ param fillFunction - size_t ( K * , size_t ) ф у н к т о р , п о л у ч а ю щ и й а д р е с б у ф е р а с т р о к и и е г о ё м к о с т ь ,
2025-11-17 09:01:31 +00:00
* в о з в р а щ а ю щ и й н е о б х о д и м ы й р а з м е р с т р о к и .
* @ return Impl & - с с ы л к у н а с е б я ж е .
2025-04-05 14:21:11 +00:00
* @ details Ф у н к ц и я в ы з ы в а е т ф у н к т о р , п е р е д а в а я е м у а д р е с б у ф е р а с т р о к и и е г о ё м к о с т ь .
* Ф у н к т о р м о ж е т и з м е н я т ь б у ф е р в п р е д е л а х в ы д е л е н н о й ё м к о с т и , и д о л ж е н в е р н у т ь р а з м е р и т о г о в о й с т р о к и .
* П о к а в о з в р а щ а е м ы й р а з м е р б о л ь ш е ё м к о с т и ( т . е . с т р о к а н е м о ж е т п о м е с т и т ь с я в б у ф е р ) ,
* в ы д е л я т с я п а м я т ь к а к м и н и м у м в о з в р а щ е н н о г о р а з м е р а , и ф у н к т о р в ы з ы в а е т с я с н о в а .
* Д о т е х п о р , п о к а в о з в р а щ ё н н ы й р а з м е р н е б у д е т п о м е щ а т ь с я в б у ф е р с т р о к и .
* Э т о т р а з м е р и с т а н о в и т с я д л и н о й с т р о к и .
2025-11-17 09:01:31 +00:00
* @ en @ brief Fill a string buffer using a functor .
* @ param from - starting position to fill .
* @ param fillFunction - size_t ( K * , size_t ) functor that receives the address of the string buffer and its capacity ,
* returning the required string size .
* @ return Impl & - a reference to yourself .
* @ details The function calls the functor , passing it the address of the string buffer and its capacity .
* The functor can modify the buffer within the allocated capacity , and must return the size of the resulting string .
* As long as the returned size is larger than capacity ( i . e . the string cannot fit into the buffer ) ,
* memory of at least the returned size is allocated and the functor is called again .
* Until the returned size fits into the string buffer .
* This size becomes the length of the line .
2025-04-05 14:21:11 +00:00
*/
template < typename Op >
Impl & fill ( size_t from , const Op & fillFunction ) {
size_t size = _len ( ) ;
if ( from > size )
from = size ;
size_t capacity = d ( ) . capacity ( ) ;
K * ptr = str ( ) ;
capacity - = from ;
for ( ; ; ) {
size_t needSize = ( size_t ) fillFunction ( ptr + from , capacity ) ;
if ( capacity > = needSize ) {
d ( ) . set_size ( from + needSize ) ;
break ;
}
ptr = from = = 0 ? d ( ) . reserve_no_preserve ( needSize ) : d ( ) . set_size ( from + needSize ) ;
capacity = d ( ) . capacity ( ) - from ;
}
return d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief З а п о л н я е т с т р о к у м е т о д о м fill с н у л е в о й п о з и ц и и .
* @ param fillFunction - ф у н к т о р з а п о л н е н и я с т р о к и , size_t ( K * , size_t ) .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Fills a string with the fill method from position zero .
* @ param fillFunction - string filling functor , size_t ( K * , size_t ) .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename Op >
requires std : : is_invocable_v < Op , K * , size_t >
Impl & operator < < ( const Op & fillFunction ) {
return fill ( 0 , fillFunction ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief З а п о л н я е т с т р о к у м е т о д о м fill п о с л е к о н ц а с т р о к и .
* @ param fillFunction - ф у н к т о р з а п о л н е н и я с т р о к и , size_t ( K * , size_t ) .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Fills a string with the fill method after the end of the string .
* @ param fillFunction - string filling functor , size_t ( K * , size_t ) .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename Op >
requires std : : is_invocable_v < Op , K * , size_t >
Impl & operator < < = ( const Op & fillFunction ) {
return fill ( _len ( ) , fillFunction ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief В ы з ы в а е т п е р е д а н н ы й ф у н к т о р , п е р е д а в с с ы л к у н а с е б я .
* @ param fillFunction - ф у к т о р void ( my_type & ) .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Calls the passed functor , passing a reference to itself .
* @ param fillFunction - ф у к т о р void ( my_type & ) .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename Op >
requires std : : is_invocable_v < Op , my_type & >
Impl & operator < < ( const Op & fillFunction ) {
fillFunction ( d ( ) ) ;
return d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в л я е т о т ф о р м а т и р о в а н н ы й с п о м о щ ь ю sprintf в ы в о д , н а ч и н а я с у к а з а н н о й п о з и ц и и .
* @ param from - н а ч а л ь н а я п о з и ц и я д о б а в л е н и я .
* @ param format - ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я sprintf .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Appends sprintf formatted output starting at the specified position .
* @ param from - starting position of adding .
* @ param format - format string .
* @ param . . . args - arguments for sprintf .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
Impl & printf_from ( size_t from , const K * format , T & & . . . args ) {
size_t size = _len ( ) ;
if ( from > size )
from = size ;
size_t capacity = d ( ) . capacity ( ) ;
K * ptr = str ( ) ;
capacity - = from ;
int result = 0 ;
// Тут грязный хак для u8s и wide_char. u8s версия snprintf сразу возвращает размер нужного буфера, если он мал
// а swprintf - возвращает -1. Под windows о б а варианта xxx_p - тоже возвращают -1.
// Поэтому для них надо тупо увеличивать буфер наугад, пока не подойдет
2025-11-17 09:01:31 +00:00
// Here's a dirty hack for u8s and wide_char. u8s version of snprintf immediately returns the size of the required buffer if it is small
// and swprintf returns -1. Under Windows, both options xxx_p also return -1.
// Therefore, for them you need to stupidly increase the buffer at random until it fits
2025-04-05 14:21:11 +00:00
if constexpr ( sizeof ( K ) = = 1 & & ! isWindowsOs ) {
result = printf_selector : : snprintf ( ptr + from , capacity + 1 , format , std : : forward < T > ( args ) . . . ) ;
if ( result > ( int ) capacity ) {
ptr = from = = 0 ? d ( ) . reserve_no_preserve ( result ) : d ( ) . set_size ( from + result ) ;
result = printf_selector : : snprintf ( ptr + from , result + 1 , format , std : : forward < T > ( args ) . . . ) ;
}
} else {
for ( ; ; ) {
result = printf_selector : : snprintf ( ptr + from , capacity + 1 , format , std : : forward < T > ( args ) . . . ) ;
if ( result < 0 ) {
// Н е хватило буфера или ошибка конвертации.
// Попробуем увеличить буфер в два раза
2025-11-17 09:01:31 +00:00
// Not enough buffer or conversion error.
// Let's try to double the buffer
2025-04-05 14:21:11 +00:00
capacity * = 2 ;
ptr = from = = 0 ? d ( ) . reserve_no_preserve ( capacity ) : d ( ) . set_size ( from + capacity ) ;
} else
break ;
}
}
if ( result < 0 )
d ( ) . set_size ( static_cast < size_t > ( traits : : length ( _str ( ) ) ) ) ;
else
d ( ) . set_size ( from + result ) ;
return d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Ф о р м а т и р у е т с т р о к у п о м о щ ь ю sprintf .
* @ param format - ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я sprintf .
2025-04-05 14:21:11 +00:00
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Formats a string using sprintf .
* @ param format - format string .
* @ param . . . args - arguments for sprintf .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
Impl & printf ( const K * format , T & & . . . args ) {
return printf_from ( 0 , format , std : : forward < T > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в л я е т о т ф о р м а т и р о в а н н ы й с п о м о щ ь ю sprintf в ы в о д в к о н е ц с т р о к и .
* @ param format - ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я sprintf .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Appends sprintf formatted output to the end of the line .
* @ param format - format string .
* @ param . . . args - arguments for sprintf .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the row buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
Impl & append_printf ( const K * format , T & & . . . args ) {
return printf_from ( _len ( ) , format , std : : forward < T > ( args ) . . . ) ;
}
struct writer {
my_type * store ;
K * ptr ;
const K * end ;
size_t max_write ;
size_t writed = 0 ;
inline static K pad ;
K & operator * ( ) const {
return * ptr ;
}
writer & operator + + ( ) {
if ( writed < max_write ) {
+ + ptr ;
if ( ptr = = end ) {
size_t l = ptr - store - > begin ( ) ;
store - > set_size ( l ) ;
ptr = store - > set_size ( l + std : : min ( l / 2 , size_t ( 8192 ) ) ) + l ;
end = store - > end ( ) ;
}
} else {
ptr = & pad ;
}
return * this ;
}
writer operator + + ( int ) {
auto ret = * this ;
operator + + ( ) ;
return ret ;
}
writer ( my_type & s , K * p , K * e , size_t ml ) : store ( & s ) , ptr ( p ) , end ( e ) , max_write ( ml ) { }
writer ( ) = default ;
writer ( const writer & ) = delete ;
writer & operator = ( const writer & ) noexcept = delete ;
writer ( writer & & ) noexcept = default ;
writer & operator = ( writer & & ) noexcept = default ;
using difference_type = int ;
} ;
2026-02-10 20:35:02 +00:00
using fmt_type = to_std_char_t < K > ;
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в л я е т о т ф о р м а т и р о в а н н ы й с п о м о щ ь ю std : : format в ы в о д , н а ч и н а я с у к а з а н н о й п о з и ц и и .
* @ param from - н а ч а л ь н а я п о з и ц и я д о б а в л е н и я .
* @ param format - ф о р м а т н а я с т р о к а , к о н с т а н т н а я .
* @ param . . . args - а р г у м е н т ы д л я std : : format .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Appends std : : format - formatted output starting at the specified position .
* @ param from - starting position of adding .
* @ param format - format string , constant .
* @ param . . . args - arguments for std : : format .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
2026-01-21 11:59:17 +00:00
Impl & format_from ( size_t from , const FmtString < fmt_type , T . . . > & format , T & & . . . args ) {
2025-04-05 14:21:11 +00:00
size_t size = _len ( ) ;
if ( from > size )
from = size ;
size_t capacity = d ( ) . capacity ( ) ;
K * ptr = str ( ) ;
2025-11-24 12:46:16 +00:00
2025-04-05 14:21:11 +00:00
auto result = std : : format_to ( writer { d ( ) , ptr + from , ptr + capacity , size_t ( - 1 ) } ,
std : : forward < decltype ( format ) > ( format ) , std : : forward < T > ( args ) . . . ) ;
d ( ) . set_size ( result . ptr - _str ( ) ) ;
return d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в л я е т о т ф о р м а т и р о в а н н ы й с п о м о щ ь ю std : : vformat в ы в о д , н а ч и н а я с у к а з а н н о й п о з и ц и и .
* @ param from - н а ч а л ь н а я п о з и ц и я д о б а в л е н и я .
* @ param max_write - м а к с и м а л ь н о е к о л и ч е с т в о з а п и с ы в а е м ы х с и м в о л о в .
* @ param format - ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я std : : vformat .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Appends std : : vformat formatted output starting at the specified position .
* @ param from - starting position of adding .
* @ param max_write - the maximum number of characters to write .
* @ param format - format string .
* @ param . . . args - arguments for std : : vformat .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
Impl & vformat_from ( size_t from , size_t max_write , str_piece format , T & & . . . args ) {
size_t size = _len ( ) ;
if ( from > size )
from = size ;
size_t capacity = d ( ) . capacity ( ) ;
K * ptr = str ( ) ;
if constexpr ( std : : is_same_v < K , u8s > ) {
auto result = std : : vformat_to (
writer { d ( ) , ptr + from , ptr + capacity , max_write } ,
std : : basic_string_view < K > { format . symbols ( ) , format . length ( ) } ,
std : : make_format_args ( args . . . ) ) ;
d ( ) . set_size ( result . ptr - _str ( ) ) ;
} else {
auto result = std : : vformat_to (
writer { d ( ) , to_one_of_std_char ( ptr + from ) , ptr + capacity , max_write } ,
std : : basic_string_view < wchar_t > { to_one_of_std_char ( format . symbols ( ) ) , format . length ( ) } ,
std : : make_wformat_args ( std : : forward < T > ( args ) . . . ) ) ;
d ( ) . set_size ( result . ptr - _str ( ) ) ;
}
return d ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Ф о р м а т и р у е т с т р о к у с п о м о щ ь ю std : : format .
* @ param pattern - ф о р м а т н а я с т р о к а , к о н с т а н т н а я .
* @ param . . . args - а р г у м е н т ы д л я std : : format .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Formats a string using std : : format .
* @ param pattern - format string , constant .
* @ param . . . args - arguments for std : : format .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
2026-01-21 11:59:17 +00:00
Impl & format ( const FmtString < fmt_type , T . . . > & pattern , T & & . . . args ) {
2025-04-05 14:21:11 +00:00
return format_from ( 0 , pattern , std : : forward < T > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в л я е т о т ф о р м а т и р о в а н н ы й с п о м о щ ь ю std : : format в ы в о д в к о н е ц с т р о к и .
* @ param format - ф о р м а т н а я с т р о к а , к о н с т а н т н а я .
* @ param . . . args - а р г у м е н т ы д л я std : : format .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Appends std : : format - formatted output to the end of the line .
* @ param format - format string , constant .
* @ param . . . args - arguments for std : : format .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
2026-01-21 11:59:17 +00:00
Impl & append_formatted ( const FmtString < fmt_type , T . . . > & format , T & & . . . args ) {
2025-04-05 14:21:11 +00:00
return format_from ( _len ( ) , format , std : : forward < T > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Ф о р м а т и р у е т с т р о к у с п о м о щ ь ю std : : vformat .
* @ param format - ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я std : : vformat .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Formats a string using std : : vformat .
* @ param format - format string .
* @ param . . . args - arguments for std : : vformat .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
Impl & vformat ( str_piece format , T & & . . . args ) {
return vformat_from ( 0 , - 1 , format , std : : forward < T > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в л я е т о т ф о р м а т и р о в а н н ы й с п о м о щ ь ю std : : vformat в ы в о д в к о н е ц с т р о к и .
* @ param format - ф о р м а т н а я с т р о к а .
* @ param . . . - а р г у м е н т ы д л я std : : vformat .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Appends std : : vformat - formatted output to the end of the line .
* @ param format - format string .
* @ param . . . - arguments for std : : vformat .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
Impl & append_vformatted ( str_piece format , T & & . . . args ) {
return vformat_from ( _len ( ) , - 1 , format , std : : forward < T > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Ф о р м а т и р у е т с т р о к у с п о м о щ ь ю std : : vformat н е б о л е е у к а з а н н о г о р а з м е р а .
* @ param max_write - м а к с и м а л ь н о е к о л и ч е с т в о з а п и с ы в а е м ы х с и м в о л о в .
* @ param format - ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я std : : vformat .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Formats a string using std : : vformat up to the specified size .
* @ param max_write - the maximum number of characters to write .
* @ param format - format string .
* @ param . . . args - arguments for std : : vformat .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
Impl & vformat_n ( size_t max_write , str_piece format , T & & . . . args ) {
return vformat_from ( 0 , max_write , format , std : : forward < T > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д о б а в л я е т о т ф о р м а т и р о в а н н ы й с п о м о щ ь ю std : : vformat в ы в о д в к о н е ц с т р о к и , з а п и с ы в а я н е б о л е е у к а з а н н о г о к о л и ч е с т в а с и м в о л о в .
* @ param max_write - м а к с и м а л ь н о е к о л и ч е с т в о з а п и с ы в а е м ы х с и м в о л о в .
* @ param format - ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я std : : vformat .
2025-04-05 14:21:11 +00:00
* @ return Impl & - с с ы л к у н а с е б я ж е
2025-11-17 09:01:31 +00:00
* @ details П р и н е о б х о д и м о с т и а в т о м а т и ч е с к и у в е л и ч и в а е т р а з м е р б у ф е р а с т р о к и .
* @ en @ brief Appends std : : vformat - formatted output to the end of the line , writing no more than the specified number of characters .
* @ param max_write - the maximum number of characters to write .
* @ param format - format string .
* @ param . . . args - arguments for std : : vformat .
* @ return Impl & - a reference to yourself .
* @ details Automatically increases the string buffer size if necessary .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . T > requires ( is_one_of_std_char_v < K > )
Impl & append_vformatted_n ( size_t max_write , str_piece format , T & & . . . args ) {
return vformat_from ( _len ( ) , max_write , format , std : : forward < T > ( args ) . . . ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief В ы з о в ф у н к т о р а с о с т р о к о й и п е р е д а н н ы м и а р г у м е н т а м и .
* @ param fillFunction - ф у н к т о р , п р и н и м а ю щ и й п е р в ы м п а р а м е т р о м с с ы л к у н а с т р о к у .
* @ param . . . args - а р г у м е н т ы , п е р е д а в а е м ы е в ф у н к т о р .
* @ return Impl & - с с ы л к у н а с е б я ж е .
* @ en @ brief Call a functor with a string and passed arguments .
* @ param fillFunction - a functor that takes a string reference as its first parameter .
* @ param . . . args - arguments passed to the functor .
* @ return Impl & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename Op , typename . . . Args >
Impl & with ( const Op & fillFunction , Args & & . . . args ) {
fillFunction ( d ( ) , std : : forward < Args > ( args ) . . . ) ;
return d ( ) ;
}
} ;
template < typename K >
struct SharedStringData {
2025-11-17 09:01:31 +00:00
std : : atomic_size_t ref_ ; // Счетчик ссылок | Reference count
2025-04-05 14:21:11 +00:00
SharedStringData ( ) {
ref_ = 1 ;
}
K * str ( ) const {
return ( K * ) ( this + 1 ) ;
}
void incr ( ) {
ref_ . fetch_add ( 1 , std : : memory_order_relaxed ) ;
}
void decr ( Allocatorable auto & allocator ) {
size_t val = ref_ . fetch_sub ( 1 , std : : memory_order_relaxed ) ;
if ( val = = 1 ) {
allocator . deallocate ( this ) ;
}
}
static SharedStringData < K > * create ( size_t l , Allocatorable auto & allocator ) {
size_t size = sizeof ( SharedStringData < K > ) + ( l + 1 ) * sizeof ( K ) ;
return new ( allocator . allocate ( size ) ) SharedStringData ( ) ;
}
static SharedStringData < K > * from_str ( const K * p ) {
return ( SharedStringData < K > * ) p - 1 ;
}
K * place ( K * p , size_t len ) {
ch_traits < K > : : copy ( p , str ( ) , len ) ;
return p + len ;
}
} ;
// Дефолтный аллокатор для строк, может работать статически
2025-11-17 09:01:31 +00:00
// Default allocator for strings, can work statically
2025-04-05 14:21:11 +00:00
class string_common_allocator {
public :
void * allocate ( size_t bytes ) {
return new char [ bytes ] ;
}
void deallocate ( void * address ) noexcept {
delete [ ] static_cast < char * > ( address ) ;
}
} ;
string_common_allocator default_string_allocator_selector ( . . . ) ;
// Если вы хотите задать свой дефолтный аллокатор для строк, перед включение sstring.h
// объявите функцию
// ва ш_тип_а лло ка то р а default_string_allocator_selector(int);
2025-11-17 09:01:31 +00:00
// If you want to set your default allocator for strings, before including sstring.h
// declare a function
// your_allocator_type default_string_allocator_selector(int);
2025-04-05 14:21:11 +00:00
using allocator_string = decltype ( default_string_allocator_selector ( int ( 0 ) ) ) ;
template < typename K , Allocatorable Allocator >
class sstring ;
/*
* Т а к к а к у к л а с с а н е с к о л ь к о б а з о в ы х к л а с с о в , MSVC н е п р и м е н я е т а в т о м а т о м empty base optimization ,
2025-11-17 09:01:31 +00:00
* и б е з я в н о г о у к а з а н и я - в с т а в и т в н а ч а л о к л а с с а п у с т ы е б а й т ы , с д в и н у в п о л е size н а 4 - 8 б а й т а .
* У к а ж е м е м у я в н о .
* Since a class has several base classes , MSVC does not automatically apply empty base optimization ,
* and without explicit indication - will insert empty bytes at the beginning of the class , shifting the size field by 4 - 8 bytes .
* Let ' s tell him explicitly .
2025-04-05 14:21:11 +00:00
*/
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К л а с с м у т а б е л ь н о й , в л а д е ю щ е й с т р о к и . С о д е р ж и т в н у т р е н н и й б у ф е р д л я с т р о к з а д а н н о г о р а з м е р а .
2025-04-05 14:21:11 +00:00
* @ tparam K - т и п с и м в о л а .
2025-11-17 09:01:31 +00:00
* @ tparam N - р а з м е р в н у т р е н н е г о с т р о к о в о г о б у ф е р а н е м е н е е N .
2025-04-05 14:21:11 +00:00
* @ tparam forShared - а л л о ц и р о в а т ь в н е ш н и й б у ф е р в ф о р м а т е , с о в м е с т и м о м с sstring .
2025-11-17 09:01:31 +00:00
* @ tparam Allocator - т и п а л л о к а т о р а .
2025-04-05 14:21:11 +00:00
* @ details " Локальная " с т р о к а . Х р а н и т в с е б е у к а з а т е л ь н а с и м в о л ы и д л и н у с т р о к и , а з а н е й л и б о с а м и д а н н ы е д о N
* с и м в о л о в + н у л ь , л и б о е с л и д а н н ы е д л и н н е е N , т о р а з м е р в ы д е л е н н о г о б у ф е р а .
* П р и э т о м , е с л и п л а н и р у е т с я п о т о м р е з у л ь т а т п е р е м е с т и т ь в sstring , т о д л я д и н а м и ч е с к о г о б у ф е р а
* в ы д е л я е т с я + n б а й т о в , ч т о б ы п о т о м н е к о п и р о в а т ь д а н н ы е .
2025-11-17 09:01:31 +00:00
* @ en @ brief The mutable , owning string class . Contains an internal buffer for text of a given size .
* @ tparam K - symbol type .
* @ tparam N - the size of the internal string buffer is at least N .
* @ tparam forShared - allocate an external buffer in a format compatible with sstring .
* @ tparam Allocator - allocator type .
* @ details " Local " string . Stores a pointer to characters and the length of the string , followed by either the data itself up to N
* characters + zero , or if the data is longer than N , then the size of the allocated buffer .
* At the same time , if you plan to later move the result to sstring , then for a dynamic buffer
* + n bytes are allocated so as not to copy the data later .
2025-04-05 14:21:11 +00:00
*/
template < typename K , size_t N , bool forShared = false , Allocatorable Allocator = allocator_string >
2025-11-13 14:57:42 +00:00
class decl_empty_bases lstring :
2025-04-05 14:21:11 +00:00
public str_algs < K , simple_str < K > , lstring < K , N , forShared , Allocator > , true > ,
public str_mutable < K , lstring < K , N , forShared , Allocator > > ,
public str_storable < K , lstring < K , N , forShared , Allocator > , Allocator > ,
2025-12-27 13:34:35 +00:00
public null_terminated < K , lstring < K , N , forShared , Allocator > > ,
public from_utf_convertible < K , lstring < K , N , forShared , Allocator > > {
2025-04-05 14:21:11 +00:00
public :
using symb_type = K ;
using my_type = lstring < K , N , forShared , Allocator > ;
using allocator_t = Allocator ;
enum : size_t {
2025-11-17 09:20:31 +00:00
/// @ru Размер внутреннего буфера в символах @en Size of internal buffer
LocalCapacity = N | ( sizeof ( void * ) / sizeof ( K ) - 1 ) ,
2025-04-05 14:21:11 +00:00
} ;
protected :
enum : size_t {
extra = forShared ? sizeof ( SharedStringData < K > ) : 0 ,
} ;
using base_algs = str_algs < K , simple_str < K > , my_type , true > ;
using base_storable = str_storable < K , my_type , Allocator > ;
using base_mutable = str_mutable < K , my_type > ;
2025-12-27 13:34:35 +00:00
using base_utf = from_utf_convertible < K , my_type > ;
2025-04-05 14:21:11 +00:00
using traits = ch_traits < K > ;
2026-01-04 09:20:36 +00:00
using s_str = base_storable : : s_str ;
2025-04-05 14:21:11 +00:00
friend base_storable ;
friend base_mutable ;
friend base_utf ;
friend class sstring < K , Allocator > ;
K * data_ ;
2025-11-17 09:01:31 +00:00
size_t size_ ;
2025-04-05 14:21:11 +00:00
union {
2025-11-17 09:01:31 +00:00
size_t capacity_ ;
2025-04-05 14:21:11 +00:00
K local_ [ LocalCapacity + 1 ] ;
} ;
2026-01-04 09:20:36 +00:00
constexpr void create_empty ( ) {
2025-04-05 14:21:11 +00:00
data_ = local_ ;
size_ = 0 ;
local_ [ 0 ] = 0 ;
}
2026-01-04 09:20:36 +00:00
constexpr static size_t calc_capacity ( size_t s ) {
2026-01-30 14:30:09 +00:00
const int al = alignof ( std : : max_align_t ) < 16 ? 16 : alignof ( std : : max_align_t ) ;
2025-04-05 14:21:11 +00:00
size_t real_need = ( s + 1 ) * sizeof ( K ) + extra ;
2026-01-30 14:30:09 +00:00
size_t aligned_alloced = ( real_need + al - 1 ) / al * al ;
2025-04-05 14:21:11 +00:00
return ( aligned_alloced - extra ) / sizeof ( K ) - 1 ;
}
2026-01-04 09:20:36 +00:00
constexpr K * init ( size_t s ) {
2026-02-10 20:35:02 +00:00
size_t need_cap = s ;
if ( need_cap > LocalCapacity ) {
need_cap = calc_capacity ( s ) ;
data_ = alloc_place ( need_cap ) ;
capacity_ = need_cap ;
2025-04-05 14:21:11 +00:00
} else {
data_ = local_ ;
}
2026-02-10 20:35:02 +00:00
size_ = s ;
2025-04-05 14:21:11 +00:00
return str ( ) ;
}
2025-11-17 09:01:31 +00:00
// Методы для себя | Methods for yourself
2026-01-04 09:20:36 +00:00
constexpr bool is_alloced ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return data_ ! = local_ ;
}
2026-01-04 09:20:36 +00:00
constexpr void dealloc ( ) {
2025-04-05 14:21:11 +00:00
if ( is_alloced ( ) ) {
base_storable : : allocator ( ) . deallocate ( to_real_address ( data_ ) ) ;
data_ = local_ ;
}
}
2026-01-04 09:20:36 +00:00
constexpr static K * to_real_address ( void * ptr ) {
2025-04-05 14:21:11 +00:00
return reinterpret_cast < K * > ( reinterpret_cast < u8s * > ( ptr ) - extra ) ;
}
2026-01-04 09:20:36 +00:00
constexpr static K * from_real_address ( void * ptr ) {
2025-04-05 14:21:11 +00:00
return reinterpret_cast < K * > ( reinterpret_cast < u8s * > ( ptr ) + extra ) ;
}
2026-01-04 09:20:36 +00:00
constexpr K * alloc_place ( size_t newSize ) {
2025-04-05 14:21:11 +00:00
return from_real_address ( base_storable : : allocator ( ) . allocate ( ( newSize + 1 ) * sizeof ( K ) + extra ) ) ;
}
// Вызывается при replace, когда меняют на более длинную замену
2025-11-17 09:01:31 +00:00
// Called on replace when changing to a longer replacement
2026-01-04 09:20:36 +00:00
constexpr K * alloc_for_copy ( size_t newSize ) {
2025-04-05 14:21:11 +00:00
if ( capacity ( ) > = newSize ) {
// Замена войдёт в текущий буфер
2025-11-17 09:01:31 +00:00
// Replacement will go into the current buffer
2025-04-05 14:21:11 +00:00
return data_ ;
}
return alloc_place ( calc_capacity ( newSize ) ) ;
}
// Вызывается после replace, когда меняли на более длинную замену, могли скопировать в новый буфер
2025-11-17 09:01:31 +00:00
// Called after replace, when they changed to a longer replacement, they could have copied it to a new buffer
2026-01-04 09:20:36 +00:00
constexpr void set_from_copy ( K * ptr , size_t newSize ) {
2025-04-05 14:21:11 +00:00
if ( ptr ! = data_ ) {
// Да, копировали в новый буфер
2025-11-17 09:01:31 +00:00
// Yes, copied to a new buffer
2025-04-05 14:21:11 +00:00
dealloc ( ) ;
data_ = ptr ;
capacity_ = calc_capacity ( newSize ) ;
}
size_ = newSize ;
data_ [ newSize ] = 0 ;
}
2026-02-12 16:47:32 +00:00
constexpr void copy_from_another ( K * buf , const K * src , size_t size ) {
// Реальный размер буфера всегда кратен sizeof(void*), поэтому копируя по sizeof(void*) байтов, мы не выйдем за пределы буфера
// The actual buffer size is always a multiple of sizeof(void*), so by copying sizeof(void*) bytes at a time, we won't go beyond the buffer's limits.
size_t need_copy_bytes = ( size + 1 ) * sizeof ( K ) ;
size_t cnt = ( need_copy_bytes + sizeof ( void * ) - 1 ) / sizeof ( void * ) * sizeof ( void * ) ;
traits : : copy ( buf , src , cnt / sizeof ( K ) ) ;
}
2025-04-05 14:21:11 +00:00
public :
2026-01-04 09:20:36 +00:00
/*!
* @ ru @ brief С о з д а т ь п у с т о й о б ъ е к т .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief Create an empty object .
* @ param . . . args - parameters for initializing the allocator .
*/
template < typename . . . Args >
requires ( std : : is_constructible_v < allocator_t , Args . . . > & & sizeof . . . ( Args ) > 0 )
constexpr lstring ( Args & & . . . args ) noexcept ( std : : is_nothrow_constructible_v < allocator_t , Args . . . > )
: base_storable ( std : : forward < Args > ( args ) . . . ) {
create_empty ( ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р и з д р у г о г о с т р о к о в о г о о б ъ е к т а .
* @ param other - д р у г о й с т р о к о в ы й о б ъ е к т , simple_str .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief A constructor from another string object .
* @ param other - another string object , simple_str .
* @ param . . . args - parameters for initializing the allocator .
*/
template < typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
constexpr lstring ( s_str other , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
base_storable : : init_from_str_other ( other ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р п о в т о р е н и я с т р о к и .
* @ param repeat - к о л и ч е с т в о п о в т о р о в .
* @ param pattern - с т р о к а , к о т о р у ю н а д о п о в т о р и т ь .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief String repetition constructor .
* @ param repeat - number of repetitions .
* @ param pattern - the line to be repeated .
* @ param . . . args - parameters for initializing the allocator .
*/
template < typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
constexpr lstring ( size_t repeat , s_str pattern , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
base_storable : : init_str_repeat ( repeat , pattern ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р п о в т о р е н и я с и м в о л а .
* @ param count - к о л и ч е с т в о п о в т о р о в .
* @ param pad - с и м в о л , к о т о р ы й н а д о п о в т о р и т ь .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief Character repetition constructor .
* @ param count - number of repetitions .
* @ param pad - the character to be repeated .
* @ param . . . args - parameters for initializing the allocator .
*/
template < typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
constexpr lstring ( size_t count , K pad , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
base_storable : : init_symb_repeat ( count , pad ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р и з с т р о к о в о г о в ы р а ж е н и я .
* @ param expr - с т р о к о в о е в ы р а ж е н и е .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ details К о н с т р у к т о р з а п р а ш и в а е т у с т р о к о в о г о в ы р а ж е н и я ` length ( ) ` ,
* в ы д е л я е т п а м я т ь н у ж н о г о р а з м е р а , и в ы з ы в а е т м е т о д ` place ( ) ` д л я р а з м е щ е н и я
* р е з у л ь т а т а в б у ф е р е .
* @ en @ brief Constructor from a string expression .
* @ param expr - string expression .
* @ param . . . args - parameters for initializing the allocator .
* @ details The constructor queries the string expression ` length ( ) ` ,
* allocates memory of the required size , and calls the ` place ( ) ` method to allocate
* result in buffer .
*/
template < typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
constexpr lstring ( const StrExprForType < K > auto & expr , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
base_storable : : init_str_expr ( expr ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р и з с т р о к о в о г о и с т о ч н и к а с з а м е н о й .
* @ param f - с т р о к о в ы й о б ъ е к т , и з к о т о р о г о б е р ё т с я и с х о д н а я с т р о к а .
* @ param pattern - п о д с т р о к а , к о т о р у ю н а д о з а м е н и т ь .
* @ param repl - с т р о к а , н а к о т о р у ю н а д о з а м е н и т ь .
* @ param offset - н а ч а л ь н а я п о з и ц и я д л я п о и с к а п о д с т р о к .
* @ param maxCount - м а к с и м а л ь н о е к о л и ч е с т в о з а м е н , 0 - б е з о г р а н и ч е н и й .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ 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 .
* @ param . . . args - parameters for initializing the allocator .
*/
template < StrType < K > From , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
constexpr lstring ( const From & f , s_str pattern , s_str repl , size_t offset = 0 , size_t maxCount = 0 , Args & & . . . args )
: base_storable ( std : : forward < Args > ( args ) . . . ) {
base_storable : : init_replaced ( f , pattern , repl , offset , maxCount ) ;
}
constexpr lstring ( ) {
create_empty ( ) ;
}
2025-04-05 14:21:11 +00:00
2026-01-04 09:20:36 +00:00
constexpr ~ lstring ( ) {
2025-04-05 14:21:11 +00:00
dealloc ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о п и р о в а н и е и з д р у г о й с т р о к и т а к о г о ж е т и п а .
* @ param other - д р у г а я с т р о к а .
* @ en @ brief Copy from another string of the same type .
* @ param other - another string .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr lstring ( const my_type & other ) : base_storable ( other . allocator ( ) ) {
2026-02-12 16:47:32 +00:00
struct copy { uint64_t p [ 2 ] ; } ;
constexpr size_t short_str = sizeof ( copy ) / sizeof ( K ) ;
if constexpr ( LocalCapacity > = short_str - 1 ) {
if ( other . size_ < short_str ) {
data_ = local_ ;
size_ = other . size_ ;
* ( copy * ) local_ = * ( const copy * ) other . local_ ;
return ;
2026-02-10 20:35:02 +00:00
}
2025-04-05 14:21:11 +00:00
}
2026-02-12 16:47:32 +00:00
if ( size_t size = other . size_ ) {
copy_from_another ( init ( size ) , other . symbols ( ) , size ) ;
} else {
create_empty ( ) ;
}
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о п и р о в а н и е и з д р у г о й с т р о к и т а к о г о ж е т и п а , н о с д р у г и м а л л о к а т о р о м .
* @ param other - д р у г а я с т р о к а .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief Copy from another string of the same type , but with a different allocator .
* @ param other - another string .
* @ param . . . args - parameters for initializing the allocator .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . Args >
requires ( sizeof . . . ( Args ) > 0 & & std : : is_convertible_v < allocator_t , Args . . . > )
2026-01-04 09:20:36 +00:00
constexpr lstring ( const my_type & other , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
2025-04-05 14:21:11 +00:00
if ( other . size_ ) {
2026-02-12 16:47:32 +00:00
copy_from_another ( init ( other . size_ ) , other . symbols ( ) , other . size_ ) ;
} else {
create_empty ( ) ;
2025-04-05 14:21:11 +00:00
}
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н с т р у к т о р и з с т р о к о в о г о л и т е р а л а .
* @ param value - с т р о к о в ы й л и т е р а л .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief String literal constructor .
* @ param value - string literal .
* @ param . . . args - parameter for initialization allocator .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t I = const_lit_for < K , T > : : Count , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
constexpr lstring ( T & & value , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
if constexpr ( I > 1 ) {
K * ptr = init ( I - 1 ) ;
2026-02-10 20:35:02 +00:00
traits : : copy ( ptr , ( const K * ) value , I - 1 ) ;
2026-02-12 16:47:32 +00:00
ptr [ I - 1 ] = K { } ;
} else {
2025-04-05 14:21:11 +00:00
create_empty ( ) ;
2026-02-12 16:47:32 +00:00
}
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н с т р у к т о р п е р е м е щ е н и я и з с т р о к и т а к о г о ж е т и п а .
* @ param other - д р у г а я с т р о к а .
* @ en @ brief Constructor for moving from a string of the same type .
* @ param other - another string .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr lstring ( my_type & & other ) noexcept : base_storable ( std : : move ( other . allocator ( ) ) ) {
2025-04-05 14:21:11 +00:00
if ( other . size_ ) {
size_ = other . size_ ;
if ( other . is_alloced ( ) ) {
data_ = other . data_ ;
2026-02-12 16:47:32 +00:00
other . data_ = other . local_ ;
2025-04-05 14:21:11 +00:00
capacity_ = other . capacity_ ;
} else {
data_ = local_ ;
2026-02-12 16:47:32 +00:00
copy_from_another ( data_ , other . local_ , size_ ) ;
2025-04-05 14:21:11 +00:00
}
other . size_ = 0 ;
other . local_ [ 0 ] = 0 ;
2026-02-12 16:47:32 +00:00
} else {
create_empty ( ) ;
2025-04-05 14:21:11 +00:00
}
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н с т р у к т о р з а п о л н е н и я с п о м о щ ь ю ф у н к т о р а ( с м . str_mutable : : fill ) .
* @ param op - ф у н к т о в з а п о л н е н и я .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief A fill constructor using a functor ( see str_mutable : : fill ) .
* @ param op - filling functions .
* @ param . . . args - parameters for initializing the allocator .
2025-04-05 14:21:11 +00:00
*/
template < typename Op , typename . . . Args >
requires ( std : : is_constructible_v < Allocator , Args . . . > & & ( std : : is_invocable_v < Op , my_type & > | | std : : is_invocable_v < Op , K * , size_t > ) )
lstring ( const Op & op , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
2026-01-04 09:20:36 +00:00
create_empty ( ) ;
2025-04-05 14:21:11 +00:00
this - > operator < < ( op ) ;
}
2026-01-30 14:30:09 +00:00
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 ( ) ) ;
}
2025-11-24 12:46:16 +00:00
2025-04-05 14:21:11 +00:00
// copy and swap для присваиваний здесь не очень применимо, так как для строк с большим локальным буфером лишняя копия даже перемещением будет дорого стоить
// Поэтому реализуем копирующее и перемещающее присваивание отдельно
2025-11-17 09:01:31 +00:00
// copy and swap for assignments is not very applicable here, since for strings with a large local buffer, an extra copy, even by moving, will be expensive
// Therefore, we implement the copy and move assignment separately
2025-11-24 12:46:16 +00:00
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р п р и с в а и в а н и я к о п и е й и з с т р о к и т а к о г о ж е т и п а .
* @ param other - д р у г а я с т р о к а .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ en @ brief Copy assignment operator from a string of the same type .
* @ param other - another string .
* @ return my_type & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
my_type & operator = ( const my_type & other ) {
// Так как между этими объектами не может быть косвенной зависимости, достаточно проверить только на равенство
2025-11-17 09:01:31 +00:00
// Since there cannot be an indirect dependency between these objects, it is enough to check only for equality
2025-04-05 14:21:11 +00:00
if ( & other ! = this ) {
traits : : copy ( reserve_no_preserve ( other . size_ ) , other . data_ , other . size_ + 1 ) ;
size_ = other . size_ ;
}
return * this ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р п р и с в а и в а н и я п е р е м е щ е н и е м и з с т р о к и т а к о г о ж е т и п а .
* @ param other - д р у г а я с т р о к а .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ en @ brief Assignment operator by moving from a string of the same type .
* @ param other - another string .
* @ return my_type & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
my_type & operator = ( my_type & & other ) noexcept {
// Так как между этими объектами не может быть косвенной зависимости, достаточно проверить только на равенство
2025-11-17 09:01:31 +00:00
// Since there cannot be an indirect dependency between these objects, it is enough to check only for equality
2025-04-05 14:21:11 +00:00
if ( & other ! = this ) {
dealloc ( ) ;
if ( other . is_alloced ( ) ) {
data_ = other . data_ ;
capacity_ = other . capacity_ ;
} else {
traits : : copy ( data_ , other . local_ , other . size_ + 1 ) ;
}
base_storable : : allocator ( ) = std : : move ( other . allocator ( ) ) ;
size_ = other . size_ ;
other . create_empty ( ) ;
}
return * this ;
}
my_type & assign ( const K * other , size_t len ) {
if ( len ) {
bool isIntersect = other > = data_ & & other + len < = data_ + size_ ;
if ( isIntersect ) {
// Особый случай, нам пытаются присвоить кусок нашей же строки.
// Просто переместим текст в буфере, и установим новый размер
2025-11-17 09:01:31 +00:00
// A special case, they are trying to assign us a piece of our own string.
// Just move the text in the buffer and set a new size
2025-04-05 14:21:11 +00:00
if ( other > data_ ) {
traits : : move ( data_ , other , len ) ;
}
} else {
traits : : copy ( reserve_no_preserve ( len ) , other , len ) ;
}
}
size_ = len ;
data_ [ size_ ] = 0 ;
return * this ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р п р и с в а и в а н и я и з simple_str .
* @ param other - д р у г а я с т р о к а .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ en @ brief Assignment operator from simple_str .
* @ param other - another string .
* @ return my_type & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
my_type & operator = ( simple_str < K > other ) {
return assign ( other . str , other . len ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р п р и с в а и в а н и я с т р о к о в о г о л и т е р а л а .
* @ param other - с т р о к о в ы й л и т е р а л , к о п и р у е т с я в б у ф е р с т р о к и .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ en @ brief String literal assignment operator .
* @ param other - string literal , copied to the string buffer .
* @ return my_type & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t S = const_lit_for < K , T > : : Count >
my_type & operator = ( T & & other ) {
2026-02-10 20:35:02 +00:00
return assign ( ( const K * ) other , S - 1 ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2026-01-30 14:30:09 +00:00
* @ ru @ brief О п е р а т о р п р и с в а и в а н и я с т р о к о в о г о в ы р а ж е н и я .
2025-11-17 09:01:31 +00:00
* @ param expr - с т р о к о в о е в ы р а ж е н и е , м а т е р и а л и з у е м о е в б у ф е р с т р о к и .
* @ return my_type & - с с ы л к у н а с е б я ж е .
2025-04-05 14:21:11 +00:00
* @ details Е с л и в с т р о к о в о м в ы р а ж е н и и ч т о - л и б о с с ы л а е т с я н а ч а с т и э т о й ж е с т р о к и , т о р е з у л ь т а т н е о п р е д е л ё н .
2025-11-17 09:01:31 +00:00
* @ en @ brief String expression appending operator .
* @ param expr - a string expression materialized into the string buffer .
* @ return my_type & - a reference to yourself .
* @ details If anything in a string expression refers to parts of the same string , then the result is undefined .
2025-04-05 14:21:11 +00:00
*/
my_type & operator = ( const StrExprForType < K > auto & expr ) {
size_t newLen = expr . length ( ) ;
if ( newLen ) {
expr . place ( reserve_no_preserve ( newLen ) ) ;
}
size_ = newLen ;
data_ [ size_ ] = 0 ;
return * this ;
}
2025-11-17 09:01:31 +00:00
/// @ru Длина строки. @en String length.
2026-01-04 09:20:36 +00:00
constexpr size_t length ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return size_ ;
}
2025-11-17 09:01:31 +00:00
/// @ru Указатель на константные символы. @en Pointer to constant characters.
2026-01-04 09:20:36 +00:00
constexpr const K * symbols ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return data_ ;
}
2025-11-17 09:01:31 +00:00
/// @ru Указатель на буфер строки. @en Pointer to a string buffer.
2026-01-04 09:20:36 +00:00
constexpr K * str ( ) noexcept {
2025-04-05 14:21:11 +00:00
return data_ ;
}
2025-11-17 09:01:31 +00:00
/// @ru Пустая ли строка. @en Is the string empty?
2026-01-04 09:20:36 +00:00
constexpr bool is_empty ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return size_ = = 0 ;
}
2025-11-17 09:01:31 +00:00
/// @ru Пустая ли строка, для совместимости с std::string. @en Whether the string is empty, for compatibility with std::string.
2026-01-04 09:20:36 +00:00
constexpr bool empty ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return size_ = = 0 ;
}
2025-11-17 09:01:31 +00:00
/// @ru Текущая ёмкость буфера строки. @en Current row buffer capacity.
2026-01-04 09:20:36 +00:00
constexpr size_t capacity ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return is_alloced ( ) ? capacity_ : LocalCapacity ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief В ы д е л и т ь б у ф е р , д о с т а т о ч н ы й д л я р а з м е щ е н и я newSize с и м в о л о в п л ю с з а в е р ш а ю щ и й н о л ь .
* @ param newSize - н о в ы й р а з м е р с т р о к и .
* @ return K * - у к а з а т е л ь н а б у ф е р .
2025-04-05 14:21:11 +00:00
* @ details С о д е р ж и м о е б у ф е р а н е о п р е д е л е н о , и н е г а р а н т и р у е т с я с о х р а н е н и е с т а р о г о с о д е р ж и м о г о .
* Р а з м е р с т р о к и у с т а н а в л и в а е т с я в newSize .
2025-11-17 09:01:31 +00:00
* @ en @ brief Allocate a buffer large enough to hold newSize characters plus a terminating null .
* @ param newSize - new string size .
* @ return K * - pointer to the buffer .
* @ details The contents of the buffer are undefined and the old contents are not guaranteed to be retained .
* The string size is set to newSize .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr K * reserve_no_preserve ( size_t newSize ) {
2025-04-05 14:21:11 +00:00
if ( newSize > capacity ( ) ) {
newSize = calc_capacity ( newSize ) ;
K * newData = alloc_place ( newSize ) ;
dealloc ( ) ;
data_ = newData ;
capacity_ = newSize ;
}
return data_ ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief В ы д е л и т ь б у ф е р , д о с т а т о ч н ы й д л я р а з м е щ е н и я newSize с и м в о л о в п л ю с з а в е р ш а ю щ и й н о л ь .
* @ param newSize - н о в ы й р а з м е р с т р о к и .
* @ return K * - у к а з а т е л ь н а б у ф е р .
2025-04-05 14:21:11 +00:00
* @ details С о д е р ж и м о е с т р о к и с о х р а н я е т с я . П р и у в е л и ч е н и и б у ф е р а р а з м е р в ы д е л я е т с я н е б о л ь ш е з а п р о ш е н н о г о .
* Р а з м е р с т р о к и у с т а н а в л и в а е т с я в newSize .
2025-11-17 09:01:31 +00:00
* @ en @ brief Allocate a buffer large enough to hold newSize characters plus a terminating null .
* @ param newSize - new string size .
* @ return K * - pointer to the buffer .
* @ details The contents of the string are preserved . When increasing the buffer , the size allocated is no larger than the requested one .
* The string size is set to newSize .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr K * reserve ( size_t newSize ) {
2025-04-05 14:21:11 +00:00
if ( newSize > capacity ( ) ) {
newSize = calc_capacity ( newSize ) ;
K * newData = alloc_place ( newSize ) ;
traits : : copy ( newData , data_ , size_ ) ;
dealloc ( ) ;
data_ = newData ;
capacity_ = newSize ;
}
return data_ ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У с т а н а в л и в а е т р а з м е р т е к у щ е й с т р о к и , п р и н е о б х о д и м о с т и в ы д е л я я м е с т о .
* @ param newSize - н о в ы й р а з м е р с т р о к и .
* @ return K * - у к а з а т е л ь н а б у ф е р .
2025-04-05 14:21:11 +00:00
* @ details С о д е р ж и м о е с т р о к и с о х р а н я е т с я . П р и у в е л и ч е н и и б у ф е р а р а з м е р в ы д е л я е т с я н е м е н е е ч е м 2 с т а р о г о р а з м е р а б у ф е р а .
* Р а з м е р с т р о к и у с т а н а в л и в а е т с я в newSize .
2025-11-17 09:01:31 +00:00
* @ en @ brief Sets the size of the current string , allocating space if necessary .
* @ param newSize - new string size .
* @ return K * - pointer to the buffer .
* @ details The contents of the string are preserved . When increasing the buffer size , at least 2 times the old buffer size are allocated .
* The string size is set to newSize .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr K * set_size ( size_t newSize ) {
2025-04-05 14:21:11 +00:00
size_t cap = capacity ( ) ;
if ( newSize > cap ) {
size_t needPlace = newSize ;
if ( needPlace < ( cap + 1 ) * 2 ) {
needPlace = ( cap + 1 ) * 2 - 1 ;
}
reserve ( needPlace ) ;
}
size_ = newSize ;
data_ [ newSize ] = 0 ;
return data_ ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У з н а т ь , л о к а л ь н ы й и л и в н е ш н и й б у ф е р и с п о л ь з у е т с я д л я с и м в о л о в .
* @ en @ brief Find out whether a local or external buffer is used for characters .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr bool is_local ( ) const noexcept {
2025-04-05 14:21:11 +00:00
return ! is_alloced ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п р е д е л и т ь д л и н у с т р о к и .
2025-04-05 14:21:11 +00:00
* И щ е т с и м в о л 0 в б у ф е р е с т р о к и д о е г о ё м к о с т и , п о с л е ч е г о у с т а н а л и в а е т д л и н у с т р о к и п о н а й д е н н о м у 0.
2025-11-17 09:01:31 +00:00
* @ en @ brief Determine the length of the string .
* Searches for the character 0 in the string buffer to its capacity , and then sets the length of the line to the found 0.
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr void define_size ( ) {
2025-04-05 14:21:11 +00:00
size_t cap = capacity ( ) ;
for ( size_t i = 0 ; i < cap ; i + + ) {
if ( data_ [ i ] = = 0 ) {
size_ = i ;
return ;
}
}
size_ = cap ;
data_ [ size_ ] = 0 ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief У м е н ь ш а е т р а з м е р в н е ш н е г о б у ф е р а д о м и н и м а л ь н о в о з м о ж н о г о д л я х р а н е н и я с т р о к и .
2025-04-05 14:21:11 +00:00
* Е с л и с т р о к а у м е с т и т с я в о в н у т р е н н и й б у ф е р - к о п и р у е т е ё в н е г о и о с в о б о ж д а е т в н е ш н и й б у ф е р .
2025-11-17 09:01:31 +00:00
* @ en @ brief Reduces the size of the external buffer to the smallest possible size to hold the string .
* If the string fits into the internal buffer , it copies it into it and frees the external buffer .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr void shrink_to_fit ( ) {
2025-04-05 14:21:11 +00:00
size_t need_capacity = calc_capacity ( size_ ) ;
if ( is_alloced ( ) & & capacity_ > need_capacity ) {
K * newData = size_ < = LocalCapacity ? local_ : alloc_place ( need_capacity ) ;
traits : : copy ( newData , data_ , size_ + 1 ) ;
base_storable : : allocator ( ) . deallocate ( to_real_address ( data_ ) ) ;
data_ = newData ;
if ( size_ > LocalCapacity ) {
capacity_ = need_capacity ;
}
}
}
2025-11-17 09:01:31 +00:00
/// @ru Делает строку пустой, не меняя буфер строки. @en Makes a string empty without changing the string buffer.
2026-01-04 09:20:36 +00:00
constexpr void clear ( ) {
2025-04-05 14:21:11 +00:00
set_size ( 0 ) ;
}
2025-11-17 09:01:31 +00:00
/// @ru Делает строку пустой и освобождает внешний буфер, если он был. @en Makes the string empty and frees the external buffer, if there was one.
2026-01-04 09:20:36 +00:00
constexpr void reset ( ) {
2025-04-05 14:21:11 +00:00
dealloc ( ) ;
local_ [ 0 ] = 0 ;
size_ = 0 ;
}
} ;
template < size_t N = 15 >
using lstringa = lstring < u8s , N > ;
template < size_t N = 15 >
2026-01-21 11:59:17 +00:00
using lstringb = lstring < ubs , N > ;
template < size_t N = 15 >
2025-04-05 14:21:11 +00:00
using lstringw = lstring < wchar_t , N > ;
template < size_t N = 15 >
using lstringu = lstring < u16s , N > ;
template < size_t N = 15 >
using lstringuu = lstring < u32s , N > ;
template < size_t N = 15 >
using lstringsa = lstring < u8s , N , true > ;
template < size_t N = 15 >
2026-01-21 11:59:17 +00:00
using lstringsb = lstring < ubs , N , true > ;
template < size_t N = 15 >
2025-04-05 14:21:11 +00:00
using lstringsw = lstring < wchar_t , N , true > ;
template < size_t N = 15 >
using lstringsu = lstring < u16s , N , true > ;
template < size_t N = 15 >
using lstringsuu = lstring < u32s , N , true > ;
template < typename T , typename K = typename const_lit < T > : : symb_type >
auto getLiteralType ( T & & ) {
return K { } ;
} ;
template < size_t Arch , size_t L >
inline constexpr const size_t _local_count = 0 ;
template < >
inline constexpr const size_t _local_count < 8 , 1 > = 23 ;
template < >
inline constexpr const size_t _local_count < 8 , 2 > = 15 ;
template < >
inline constexpr const size_t _local_count < 8 , 4 > = 7 ;
template < >
inline constexpr const size_t _local_count < 4 , 1 > = 15 ;
template < >
inline constexpr const size_t _local_count < 4 , 2 > = 11 ;
template < >
inline constexpr const size_t _local_count < 4 , 4 > = 5 ;
template < typename T >
constexpr const size_t local_count = _local_count < sizeof ( size_t ) , sizeof ( T ) > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К л а с с и м м у т а б е л ь н о й в л а д е ю щ е й с т р о к и .
* @ tparam K - т и п с и м в о л о в .
* @ tparam Allocator - т и п а л л о к а т о р а .
2025-04-05 14:21:11 +00:00
* @ details " shared " с т р о к а .
* К л а с с с small string optimization п л ю с р а з д е л я е м ы й и м м у т а б е л ь н ы й б у ф е р с т р о к и .
* Т а к к а к б у ф е р с т р о к и в э т о м к л а с с е и м м у т а б е л ь н ы й , т о :
* В о - п е р в ы х , н е т н у ж д ы х р а н и т ь р а з м е р в ы д е л е н н о г о б у ф е р а , м ы е г о в с ё - р а в н о н е б у д е м и з м е н я т ь .
* В о - в т о р ы х , п о я в л я е т с я е щ ё о д и н т и п с т р о к и - с т р о к а , и н и ц и а л и з и р о в а н н а я с т р о к о в ы м л и т е р а л о м .
* Д л я н е ё п р о с т о с о х р а н я е м у к а з а т е л ь н а с и м в о л ы , и н е с ч и т а е м с с ы л к и .
* Т а к и м о б р а з о м , и н и ц и а л и з а ц и я с т р о к о в о г о о б ъ е к т а в п р о г р а м м е л и т е р а л о м - н и ч е г о н и к у д а н е к о п и р у е т -
* н и в с е б я , н и в д и н а м и ч е с к у ю п а м я т ь , и н е с т о и т д о р о ж е п о с р а в н е н и ю с и н и ц и а л и з а ц и е й
* с ы р о г о у к а з а т е л я н а с т р о к у , и д а ж е е щ ё о п т и м а л ь н е е , т а к к а к е щ ё и с р а з у п о д с т а в л я е т р а з м е р ,
* а н е в ы ч и с л я е т е г о в р а н т а й м е .
* ` ` ` cpp
* stringa text = " text or very very very long text " ; // ничего не стоит!
* stringa copy = anotherString ; // Стоит только копирование байтов самого объекта плюс возможно один атомарный инкремент
* ` ` `
* В с л у ч а е р а з д е л я е м о г о б у ф е р а р а з м е р с т р о к и в с ё - р а в н о х р а н и м н е в о б щ е м б у ф е р е , а в к а ж д о м о б ъ е к т е .
* И з - з а SSO м е с т а в с ё - р а в н о х в а т а е т , а в п а м я т ь л е з т ь з а д л и н о й п р и д ё т с я м е н ь ш е .
* Н а п р и м е р , п о д с ч и т а т ь с у м м у д л и н с т р о к в в е к т о р е - п р о й д ё т с я т о л ь к о п о п а м я т и в в е к т о р е .
*
* Р а з м е р ы д л я x64 :
* - д л я u8s - 24 б а й т а , х р а н и т с т р о к и д о 23 с и м в о л о в + 0
* - д л я u16s - 32 б а й т а , х р а н и т с т р о к и д о 15 с и м в о л о в + 0
* - д л я u32s - 32 б а й т а , х р а н и т с т р о к и д о 7 с и м в о л о в + 0
2025-11-17 09:01:31 +00:00
* @ en @ brief Immutable owning string class .
* @ tparam K - character type .
* @ tparam Allocator - allocator type .
* @ details " shared " string .
* Class with small string optimization plus a shared immutable string buffer .
* Since the string buffer in this class is immutable , then :
* Firstly , there is no need to store the size of the allocated buffer ; we will not change it anyway .
* Secondly , another type of string appears - a string initialized with a string literal .
* For it , we simply save a pointer to symbols and do not count references .
* Thus , initializing a string object in a program with a literal does not copy anything anywhere -
* neither into itself nor into dynamic memory , and does not cost more than initialization
* a raw pointer to a string , and even more optimal , since it also immediately substitutes the size ,
* but does not calculate it at runtime .
* ` ` ` cpp
* stringa text = " text or very very very long text " ; // costs nothing!
* string copy = anotherString ; // All you need to do is copy the bytes of the object itself, plus possibly one atomic increment
* ` ` `
* In the case of a shared buffer , the size of the string is still stored not in the shared buffer , but in each object .
* Because of SSO , there is still enough space , and you will have to go to memory less for the length .
* For example , calculating the sum of the lengths of strings in a vector will only go through the memory in the vector .
*
* Sizes for x64 :
* - for u8s - 24 bytes , stores strings up to 23 characters + 0
* - for u16s - 32 bytes , stores strings of up to 15 characters + 0
* - for u32s - 32 bytes , stores strings of up to 7 characters + 0
2025-04-05 14:21:11 +00:00
*/
template < typename K , Allocatorable Allocator = allocator_string >
2025-11-13 14:57:42 +00:00
class decl_empty_bases sstring :
2025-04-05 14:21:11 +00:00
public str_algs < K , simple_str < K > , sstring < K , Allocator > , false > ,
public str_storable < K , sstring < K , Allocator > , Allocator > ,
2025-12-27 13:34:35 +00:00
public null_terminated < K , sstring < K , Allocator > > ,
public from_utf_convertible < K , sstring < K , Allocator > > {
2025-04-05 14:21:11 +00:00
public :
using symb_type = K ;
using uns_type = std : : make_unsigned_t < K > ;
using my_type = sstring < K , Allocator > ;
using allocator_t = Allocator ;
enum { LocalCount = local_count < K > } ;
protected :
using base_algs = str_algs < K , simple_str < K > , my_type , false > ;
using base_storable = str_storable < K , my_type , Allocator > ;
2025-12-27 13:34:35 +00:00
using base_utf = from_utf_convertible < K , my_type > ;
2025-04-05 14:21:11 +00:00
using traits = ch_traits < K > ;
using uni = unicode_traits < K > ;
2026-01-04 09:20:36 +00:00
using s_str = base_storable : : s_str ;
2025-04-05 14:21:11 +00:00
friend base_storable ;
friend base_utf ;
enum Types { Local , Constant , Shared } ;
union {
// Когда у нас короткая строка, она лежит в самом объекте, а в localRemain
// пишется, сколько символов ещё можно вписать. Когда строка занимает всё
// возможное место, то localRemain становится 0, type в этом случае тоже 0,
// и в итоге после символов строки получается 0, как и надо!
2025-11-17 09:01:31 +00:00
// When we have a short string, it lies in the object itself, and in localRemain
// writes how many more characters can be entered. When a line takes up everything
// possible location, then localRemain becomes 0, type in this case is also 0,
// and as a result, after the characters of the line we get 0, as it should!
2025-04-05 14:21:11 +00:00
struct {
2025-11-17 09:01:31 +00:00
K buf_ [ LocalCount ] ; // Локальный буфер строки | Local line buffer
2025-04-05 14:21:11 +00:00
uns_type localRemain_ : sizeof ( uns_type ) * CHAR_BIT - 2 ;
uns_type type_ : 2 ;
} ;
struct {
union {
2025-11-17 09:01:31 +00:00
// Указатель на ко нcта нтну ю строку | Pointer to a constant string
const K * cstr_ ;
// Указатель на строку, перед которой лежит SharedStringData
// Pointer to the string preceded by SharedStringData
const K * sstr_ ;
2025-04-05 14:21:11 +00:00
} ;
2025-11-17 09:01:31 +00:00
size_t bigLen_ ; // Длина не локальной строки | Non-local string length
2025-04-05 14:21:11 +00:00
} ;
} ;
2026-01-04 09:20:36 +00:00
constexpr void create_empty ( ) {
2025-04-05 14:21:11 +00:00
type_ = Local ;
localRemain_ = LocalCount ;
buf_ [ 0 ] = 0 ;
}
2026-01-29 14:56:15 +00:00
constexpr K * init ( size_t s ) {
2025-04-05 14:21:11 +00:00
if ( s > LocalCount ) {
type_ = Shared ;
localRemain_ = 0 ;
bigLen_ = s ;
sstr_ = SharedStringData < K > : : create ( s , base_storable : : allocator ( ) ) - > str ( ) ;
return ( K * ) sstr_ ;
} else {
type_ = Local ;
localRemain_ = LocalCount - s ;
return buf_ ;
}
}
K * set_size ( size_t newSize ) {
// Вызывается при создании строки при необходимости изменить размер.
// Других ссылок на shared buffer нет.
2025-11-17 09:01:31 +00:00
// Called when a string is created and needs to be resized.
// There are no other references to the shared buffer.
2025-04-05 14:21:11 +00:00
size_t size = length ( ) ;
if ( newSize ! = size ) {
if ( type_ = = Constant ) {
bigLen_ = newSize ;
} else {
if ( newSize < = LocalCount ) {
if ( type_ = = Shared ) {
SharedStringData < K > * str_buf = SharedStringData < K > : : from_str ( sstr_ ) ;
traits : : copy ( buf_ , sstr_ , newSize ) ;
str_buf - > decr ( base_storable : : allocator ( ) ) ;
}
type_ = Local ;
localRemain_ = LocalCount - newSize ;
} else {
if ( type_ = = Shared ) {
if ( newSize > size | | ( newSize > 64 & & newSize < = size * 3 / 4 ) ) {
K * newStr = SharedStringData < K > : : create ( newSize , base_storable : : allocator ( ) ) - > str ( ) ;
traits : : copy ( newStr , sstr_ , newSize ) ;
SharedStringData < K > : : from_str ( sstr_ ) - > decr ( base_storable : : allocator ( ) ) ;
sstr_ = newStr ;
}
} else if ( type_ = = Local ) {
K * newStr = SharedStringData < K > : : create ( newSize , base_storable : : allocator ( ) ) - > str ( ) ;
if ( size )
traits : : copy ( newStr , buf_ , size ) ;
sstr_ = newStr ;
type_ = Shared ;
localRemain_ = 0 ;
}
bigLen_ = newSize ;
}
}
}
K * str = type_ = = Local ? buf_ : ( K * ) sstr_ ;
str [ newSize ] = 0 ;
return str ;
}
public :
2026-01-04 09:20:36 +00:00
sstring ( ) {
create_empty ( ) ;
}
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н с т р у к т о р п у с т о й с т р о к и .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief Constructor for the empty string .
* @ param . . . args - parameters for initializing the allocator .
2025-04-05 14:21:11 +00:00
*/
template < typename . . . Args >
2026-01-04 09:20:36 +00:00
requires ( std : : is_constructible_v < allocator_t , Args . . . > & & sizeof . . . ( Args ) > 0 )
sstring ( Args & & . . . args ) noexcept ( std : : is_nothrow_constructible_v < allocator_t , Args . . . > )
: base_storable ( std : : forward < Args > ( args ) . . . ) {
create_empty ( ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р и з д р у г о г о с т р о к о в о г о о б ъ е к т а .
* @ param other - д р у г о й с т р о к о в ы й о б ъ е к т , simple_str .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief A constructor from another string object .
* @ param other - another string object , simple_str .
* @ param . . . args - parameters for initializing the allocator .
*/
template < typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
2026-01-29 14:56:15 +00:00
sstring ( s_str other , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
2026-01-04 09:20:36 +00:00
base_storable : : init_from_str_other ( other ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р п о в т о р е н и я с т р о к и .
* @ param repeat - к о л и ч е с т в о п о в т о р о в .
* @ param pattern - с т р о к а , к о т о р у ю н а д о п о в т о р и т ь .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief String repetition constructor .
* @ param repeat - number of repetitions .
* @ param pattern - the line to be repeated .
* @ param . . . args - parameters for initializing the allocator .
*/
template < typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
sstring ( size_t repeat , s_str pattern , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
base_storable : : init_str_repeat ( repeat , pattern ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р п о в т о р е н и я с и м в о л а .
* @ param count - к о л и ч е с т в о п о в т о р о в .
* @ param pad - с и м в о л , к о т о р ы й н а д о п о в т о р и т ь .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ en @ brief Character repetition constructor .
* @ param count - number of repetitions .
* @ param pad - the character to be repeated .
* @ param . . . args - parameters for initializing the allocator .
*/
template < typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
sstring ( size_t count , K pad , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
base_storable : : init_symb_repeat ( count , pad ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р и з с т р о к о в о г о в ы р а ж е н и я .
* @ param expr - с т р о к о в о е в ы р а ж е н и е .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ details К о н с т р у к т о р з а п р а ш и в а е т у с т р о к о в о г о в ы р а ж е н и я ` length ( ) ` ,
* в ы д е л я е т п а м я т ь н у ж н о г о р а з м е р а , и в ы з ы в а е т м е т о д ` place ( ) ` д л я р а з м е щ е н и я
* р е з у л ь т а т а в б у ф е р е .
* @ en @ brief Constructor from a string expression .
* @ param expr - string expression .
* @ param . . . args - parameters for initializing the allocator .
* @ details The constructor queries the string expression ` length ( ) ` ,
* allocates memory of the required size , and calls the ` place ( ) ` method to allocate
* result in buffer .
*/
template < typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
constexpr sstring ( const StrExprForType < K > auto & expr , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
base_storable : : init_str_expr ( expr ) ;
}
/*!
* @ ru @ brief К о н с т р у к т о р и з с т р о к о в о г о и с т о ч н и к а с з а м е н о й .
* @ param f - с т р о к о в ы й о б ъ е к т , и з к о т о р о г о б е р ё т с я и с х о д н а я с т р о к а .
* @ param pattern - п о д с т р о к а , к о т о р у ю н а д о з а м е н и т ь .
* @ param repl - с т р о к а , н а к о т о р у ю н а д о з а м е н и т ь .
* @ param offset - н а ч а л ь н а я п о з и ц и я д л я п о и с к а п о д с т р о к .
* @ param maxCount - м а к с и м а л ь н о е к о л и ч е с т в о з а м е н , 0 - б е з о г р а н и ч е н и й .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
* @ 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 .
* @ param . . . args - parameters for initializing the allocator .
*/
template < StrType < K > From , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
sstring ( const From & f , s_str pattern , s_str repl , size_t offset = 0 , size_t maxCount = 0 , Args & & . . . args )
: base_storable ( std : : forward < Args > ( args ) . . . ) {
base_storable : : init_replaced ( f , pattern , repl , offset , maxCount ) ;
}
2025-04-05 14:21:11 +00:00
static const sstring < K > empty_str ;
2025-11-17 09:01:31 +00:00
/// @ru Деструктор строки. @en String destructor.
2026-01-04 09:20:36 +00:00
constexpr ~ sstring ( ) {
2026-01-29 14:56:15 +00:00
if ( type_ = = Shared ) {
2025-04-05 14:21:11 +00:00
SharedStringData < K > : : from_str ( sstr_ ) - > decr ( base_storable : : allocator ( ) ) ;
}
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н с т р у к т о р к о п и р о в а н и я с т р о к и .
* @ param other - к о п и р у е м а я с т р о к а .
* @ en @ brief String copy constructor .
* @ param other - the string to be copied .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr sstring ( const my_type & other ) noexcept : base_storable ( other . allocator ( ) ) {
2025-04-05 14:21:11 +00:00
memcpy ( buf_ , other . buf_ , sizeof ( buf_ ) + sizeof ( K ) ) ;
if ( type_ = = Shared )
SharedStringData < K > : : from_str ( sstr_ ) - > incr ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н с т р у к т о р п е р е м е щ е н и я .
* @ param other - п е р е м е щ а е м а я с т р о к а .
* @ en @ brief Move constructor .
* @ param other - the string to be moved .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr sstring ( my_type & & other ) noexcept : base_storable ( std : : move ( other . allocator ( ) ) ) {
2025-04-05 14:21:11 +00:00
memcpy ( buf_ , other . buf_ , sizeof ( buf_ ) + sizeof ( K ) ) ;
other . create_empty ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н с т р у к т о р п е р е м е щ е н и я и з lstring с с о в м е с т и м ы м с sstring в н е ш н и м б у ф е р о м .
* @ param src - п е р е м е щ а е м а я с т р о к а .
2025-04-05 14:21:11 +00:00
* @ details В с л у ч а е , е с л и с и м в о л ы в lstring л е ж а т в о в н е ш н е м а л л о ц и р о в а н н о м б у ф е р е ,
* п р о с т о з а б и р а е м у к а з а т е л ь н а б у ф е р , о н н а м п о д о й д ё т .
2025-11-17 09:01:31 +00:00
* @ en @ brief A move constructor from lstring with an sstring - compatible external buffer .
* @ param src - the string to be moved .
* @ details If the characters in lstring are in an external allocated buffer ,
* we just take the pointer to the buffer , it will suit us .
2025-04-05 14:21:11 +00:00
*/
template < size_t N >
2026-01-04 09:20:36 +00:00
constexpr sstring ( lstring < K , N , true , Allocator > & & src ) : base_storable ( std : : move ( src . allocator ( ) ) ) {
2025-04-05 14:21:11 +00:00
size_t size = src . length ( ) ;
if ( size ) {
if ( src . is_alloced ( ) ) {
// Там динамический буфер, выделенный с запасом для SharedStringData.
2025-11-17 09:01:31 +00:00
// There is a dynamic buffer allocated with a reserve for SharedStringData.
2025-04-05 14:21:11 +00:00
K * str = src . str ( ) ;
if ( size > LocalCount ) {
// Просто присвоим е г о с е б е .
2025-11-17 09:01:31 +00:00
// Let's just assign it to ourselves.
2025-04-05 14:21:11 +00:00
sstr_ = str ;
bigLen_ = size ;
type_ = Shared ;
localRemain_ = 0 ;
new ( SharedStringData < K > : : from_str ( str ) ) SharedStringData < K > ( ) ;
} else {
// Скопируем локально
2025-11-17 09:01:31 +00:00
// Copy locally
2025-04-05 14:21:11 +00:00
type_ = Local ;
localRemain_ = LocalCount - size ;
traits : : copy ( buf_ , str , size + 1 ) ;
// Освободим тот буфер, у локальной строки буфер не разделяется с другими
2025-11-17 09:01:31 +00:00
// Let's free that buffer; a local string's buffer is not shared with others
2025-04-05 14:21:11 +00:00
src . dealloc ( ) ;
}
} else {
// Копируем из локального буфера
2025-11-17 09:01:31 +00:00
// Copy from local buffer
2025-04-05 14:21:11 +00:00
K * str = init ( src . size_ ) ;
traits : : copy ( str , src . symbols ( ) , size + 1 ) ;
}
src . create_empty ( ) ;
} else
create_empty ( ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief И н и ц и а л и з а ц и я и з с т р о к о в о г о л и т е р а л а .
* @ param s - с т р о к о в ы й л и т е р а л .
* @ param . . . args - п а р а м е т р ы д л я и н и ц и а л и з а ц и и а л л о к а т о р а .
2025-04-05 14:21:11 +00:00
* @ details В э т о м с л у ч а е п р о с т о з а п о м и н а е м у к а з а т е л ь н а с т р о к у и е ё д л и н у .
2025-11-17 09:01:31 +00:00
* @ en @ brief Initialize from a string literal .
* @ param s - string literal .
* @ param . . . args - parameters for initializing the allocator .
* @ details In this case , we simply remember the pointer to the string and its length .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t N = const_lit_for < K , T > : : Count , typename . . . Args >
requires std : : is_constructible_v < allocator_t , Args . . . >
2026-01-29 14:56:15 +00:00
sstring ( T & & s , Args & & . . . args ) : base_storable ( std : : forward < Args > ( args ) . . . ) {
type_ = Constant ;
localRemain_ = 0 ;
2026-02-10 20:35:02 +00:00
cstr_ = ( const K * ) s ;
2026-01-29 14:56:15 +00:00
bigLen_ = N - 1 ;
2025-04-05 14:21:11 +00:00
}
2026-01-30 14:30:09 +00:00
/*!
* @ 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 ( ) ) ;
}
2026-01-04 09:20:36 +00:00
constexpr void swap ( my_type & & other ) noexcept {
2025-04-05 14:21:11 +00:00
char buf [ sizeof ( buf_ ) + sizeof ( K ) ] ;
memcpy ( buf , buf_ , sizeof ( buf ) ) ;
memcpy ( buf_ , other . buf_ , sizeof ( buf ) ) ;
memcpy ( other . buf_ , buf , sizeof ( buf ) ) ;
std : : swap ( base_storable : : allocator ( ) , other . allocator ( ) ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р п р и с в о е н и я д р у г о й с т р о к и т о г о ж е т и п а .
* @ param other - д р у г а я с т р о к а .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ en @ brief Assignment operator to another string of the same type .
* @ param other - another string .
* @ return my_type & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr my_type & operator = ( my_type other ) noexcept {
2025-04-05 14:21:11 +00:00
swap ( std : : move ( other ) ) ;
return * this ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р п р и с в о е н и я д р у г о й с т р о к и д р у г о г о т и п а .
* @ param other - д р у г а я с т р о к а .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ en @ brief Assignment operator to another string of a different type .
* @ param other - another string .
* @ return my_type & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
2026-01-04 09:20:36 +00:00
constexpr my_type & operator = ( simple_str < K > other ) {
2025-04-05 14:21:11 +00:00
return operator = ( my_type { other , base_storable : : allocator ( ) } ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р п р и с в о е н и я с т р о к о в о г о л и т е р а л а .
* @ param other - с т р о к о в ы й л и т е р а .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ en @ brief String literal assignment operator .
* @ param other - string character .
* @ return my_type & - a reference to yourself .
2025-04-05 14:21:11 +00:00
*/
template < typename T , size_t N = const_lit_for < K , T > : : Count >
2026-01-04 09:20:36 +00:00
constexpr my_type & operator = ( T & & other ) {
2026-02-10 20:35:02 +00:00
return operator = ( my_type { std : : forward < T > ( other ) , base_storable : : allocator ( ) } ) ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р п р и с в о е н и я д р у г о й с т р о к и т и п а lstring .
2026-01-21 11:59:17 +00:00
* @ param other - д р у г а я с т р о к а .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ en @ brief Assignment operator to another string of type lstring .
* @ param other - another string .
* @ return my_type & - a reference to yourself .
*/
template < size_t N , bool forShared , typename A >
constexpr my_type & operator = ( const lstring < K , N , forShared , A > & other ) {
return operator = ( my_type { other . to_str ( ) , base_storable : : allocator ( ) } ) ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/*!
* @ ru @ brief О п е р а т о р п р и с в о е н и я п е р е м е щ а е м о й с т р о к и т и п а lstring с с о в м е с т и м ы м б у ф е р о м .
* @ param other - д р у г а я с т р о к а .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ en @ brief Assignment operator to a movable string of type lstring with a compatible buffer .
* @ param other - another string .
* @ return my_type & - a reference to yourself .
*/
template < size_t N >
constexpr my_type & operator = ( lstring < K , N , true , Allocator > & & other ) {
return operator = ( my_type { std : : move ( other ) } ) ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/*!
* @ ru @ brief О п е р а т о р п р и с в о е н и я с т р о к о в о г о в ы р а ж е н и я .
* @ param expr - с т р о к о в о е в ы р а ж е н и я .
* @ return my_type & - с с ы л к у н а с е б я ж е .
* @ details В с т р о к о в о м в ы р а ж е н и е д о п у с т и м о с с ы л а т ь с я н а ч а с т и э т о й ж е с т р о к и , т а к к а к с н а ч а л а с о з д а ё т с я к о п и я .
* @ en @ brief String expression assignment operator .
* @ param expr - string expression .
* @ return my_type & - a reference to yourself .
* @ details In a string expression , it is possible to refer to parts of the same string , since a copy is created first .
*/
constexpr my_type & operator = ( const StrExprForType < K > auto & expr ) {
return operator = ( my_type { expr , base_storable : : allocator ( ) } ) ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/*!
* @ ru @ brief С д е л а т ь с т р о к у п у с т о й .
* @ return my_type & - с с ы л к у н а с е б я ж е
* @ en @ brief Make the string empty .
* @ return my_type & - a reference to yourself .
*/
constexpr my_type & make_empty ( ) noexcept {
if ( type_ = = Shared )
SharedStringData < K > : : from_str ( sstr_ ) - > decr ( base_storable : : allocator ( ) ) ;
create_empty ( ) ;
return * this ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/// @ru Указатель на символы строки. @en Pointer to characters in the string.
constexpr const K * symbols ( ) const noexcept {
2026-01-29 14:56:15 +00:00
return type_ = = Local ? buf_ : cstr_ ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/// @ru Длина строки. @en Line length.
constexpr size_t length ( ) const noexcept {
2026-01-29 14:56:15 +00:00
return type_ = = Local ? LocalCount - localRemain_ : bigLen_ ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/// @ru Пустая ли строка. @en Is the string empty?
constexpr bool is_empty ( ) const noexcept {
return length ( ) = = 0 ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/// @ru Пустая ли строка, для совместимости с std::string. @en Whether the string is empty, for compatibility with std::string.
constexpr bool empty ( ) const noexcept {
return is_empty ( ) ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/*!
* @ ru @ brief П о л у ч и т ь с т р о к у , о т ф о р м а т и р о в а н н у ю с п о м о щ ь ю ` std : : sprintf ` .
* @ param pattern - ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я ` sprintf ` .
* @ return my_type .
* @ details Д л я Windows п о д д е р ж и в а ю т с я posix п о з и ц и о н н ы е а р г у м е н т ы , и с п о л ь з у е т с я ` _sprintf_p ` .
* @ en @ brief Get a string formatted with ` std : : sprintf ` .
* @ param pattern - format string .
* @ param . . . args - arguments for ` sprintf ` .
* @ return my_type .
* @ details On Windows , posix positional arguments are supported , using ` _sprintf_p ` .
*/
template < typename . . . T >
static my_type printf ( const K * pattern , T & & . . . args ) {
return my_type { lstring < K , 256 , true > { } . printf ( pattern , std : : forward < T > ( args ) . . . ) } ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/*!
* @ ru @ brief П о л у ч и т ь с т р о к у , о т ф о р м а т и р о в а н н у ю с п о м о щ ь ю ` std : : format ` .
* @ param fmtString - к о н с т а н т н а я ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я ` std : : format ` .
* @ return my_type .
* @ en @ brief Get a string formatted with ` std : : format ` .
* @ param fmtString - constant format string .
* @ param . . . args - arguments for ` std : : format ` .
* @ return my_type .
*/
template < typename . . . T >
2026-02-10 20:35:02 +00:00
static my_type format ( const FmtString < to_std_char_t < K > , T . . . > & fmtString , T & & . . . args ) {
2026-01-21 11:59:17 +00:00
return my_type { lstring < K , 256 , true , Allocator > { } . format ( fmtString , std : : forward < T > ( args ) . . . ) } ;
2025-04-05 14:21:11 +00:00
}
2026-01-21 11:59:17 +00:00
/*!
* @ ru @ brief П о л у ч и т ь с т р о к у , о т ф о р м а т и р о в а н н у ю с п о м о щ ь ю ` std : : vformat ` .
* @ param fmtString - ф о р м а т н а я с т р о к а .
* @ param . . . args - а р г у м е н т ы д л я ` std : : vformat ` .
* @ return my_type .
* @ en @ brief Get a string formatted with ` std : : vformat ` .
* @ param fmtString - format string .
* @ param . . . args - arguments for ` std : : vformat ` .
* @ return my_type .
*/
template < typename . . . T >
static my_type vformat ( simple_str < K > fmtString , T & & . . . args ) {
return my_type { lstring < K , 256 , true , Allocator > { } . vformat ( fmtString , std : : forward < T > ( args ) . . . ) } ;
2025-04-05 14:21:11 +00:00
}
} ;
2026-01-21 11:59:17 +00:00
template < typename K , Allocatorable Allocator >
inline const sstring < K > sstring < K , Allocator > : : empty_str { } ;
2026-01-30 14:30:09 +00:00
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>>
{
2026-02-03 07:38:21 +00:00
public :
2026-01-30 14:30:09 +00:00
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 >
2026-02-10 20:35:02 +00:00
constexpr cestring ( T & & s ) : base_storable ( ) , cstr_ ( ( const K * ) s ) , size_ ( M - 1 ) , is_cstr_ ( true ) , local_ { 0 } { }
2026-01-30 14:30:09 +00:00
} ;
2026-01-21 11:59:17 +00:00
template < typename K >
2026-01-29 14:56:15 +00:00
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 ) {
2026-01-21 11:59:17 +00:00
if constexpr ( std : : is_same_v < K , u8s > )
return s8 ;
2026-01-29 14:56:15 +00:00
if constexpr ( std : : is_same_v < K , ubs > )
return sb ;
2026-01-21 11:59:17 +00:00
if constexpr ( std : : is_same_v < K , uws > )
return sw ;
if constexpr ( std : : is_same_v < K , u16s > )
return s16 ;
if constexpr ( std : : is_same_v < K , u32s > )
return s32 ;
2025-04-05 14:21:11 +00:00
}
2026-01-29 14:56:15 +00:00
# define uni_string(K, p) select_str<K>(p, u8##p, L##p, u##p, U##p)
2026-01-21 11:59:17 +00:00
2025-11-12 12:08:55 +00:00
template < typename K , typename H >
2025-04-05 14:21:11 +00:00
struct StoreType {
simple_str < K > str ;
size_t hash ;
char node [ sizeof ( sstring < K > ) ] ;
const simple_str_nt < K > & to_nt ( ) const noexcept {
return static_cast < const simple_str_nt < K > & > ( str ) ;
}
const sstring < K > & to_str ( ) const noexcept {
return * reinterpret_cast < const sstring < K > * > ( node ) ;
}
} ;
template < bool Wide >
struct fnv_const {
static inline constexpr size_t basis = static_cast < size_t > ( 14695981039346656037ULL ) ;
static inline constexpr size_t prime = static_cast < size_t > ( 1099511628211ULL ) ;
} ;
template < >
struct fnv_const < false > {
static inline constexpr size_t basis = static_cast < size_t > ( 2166136261U ) ;
static inline constexpr size_t prime = static_cast < size_t > ( 16777619U ) ;
} ;
using fnv = fnv_const < sizeof ( size_t ) = = 8 > ;
template < typename K >
inline constexpr size_t fnv_hash ( const K * ptr , size_t l ) {
size_t h = fnv : : basis ;
for ( size_t i = 0 ; i < l ; i + + ) {
h = ( h ^ ( std : : make_unsigned_t < K > ) ptr [ i ] ) * fnv : : prime ;
}
return h ;
} ;
template < typename K >
inline constexpr size_t fnv_hash_ia ( const K * ptr , size_t l ) {
size_t h = fnv : : basis ;
for ( size_t i = 0 ; i < l ; i + + ) {
std : : make_unsigned_t < K > s = ( std : : make_unsigned_t < K > ) ptr [ i ] ;
h = ( h ^ ( s > = ' A ' & & s < = ' Z ' ? s | 0x20 : s ) ) * fnv : : prime ;
}
return h ;
} ;
template < typename T , typename K = typename const_lit < T > : : symb_type , size_t N = const_lit < T > : : Count >
inline constexpr size_t fnv_hash ( T & & value ) {
size_t h = fnv : : basis ;
for ( size_t i = 0 ; i < N - 1 ; i + + ) {
h = ( h ^ ( std : : make_unsigned_t < K > ) value [ i ] ) * fnv : : prime ;
}
return h ;
} ;
template < typename T , typename K = typename const_lit < T > : : symb_type , size_t N = const_lit < T > : : Count >
inline constexpr size_t fnv_hash_ia ( T & & value ) {
size_t h = fnv : : basis ;
for ( size_t i = 0 ; i < N - 1 ; i + + ) {
std : : make_unsigned_t < K > s = ( std : : make_unsigned_t < K > ) value [ i ] ;
h = ( h ^ ( s > = ' A ' & & s < = ' Z ' ? s | 0x20 : s ) ) * fnv : : prime ;
}
return h ;
} ;
template < typename K >
inline consteval size_t fnv_hash_compile ( const K * ptr , size_t l ) {
return fnv_hash ( ptr , l ) ;
} ;
template < typename K >
inline consteval size_t fnv_hash_ia_compile ( const K * ptr , size_t l ) {
return fnv_hash_ia ( ptr , l ) ;
} ;
2025-11-12 12:08:55 +00:00
static_assert ( std : : is_trivially_copyable_v < StoreType < u8s , int > > , " Store type must be trivially copyable " ) ;
2025-04-05 14:21:11 +00:00
template < typename K >
struct streql ;
template < typename K >
struct strhash ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief К о н т е й н е р д л я б о л е е э ф ф е к т и в н о г о п о и с к а п о с т р о к о в ы м к л ю ч а м .
2025-04-05 14:21:11 +00:00
* @ details И с п о л ь з у е т с я д л я х р а н е н и я и п о и с к а к л ю ч е й л ю б о г о с т р о к о в о г о т и п а .
* К а к unordered_map , н о ч у т ь л у ч ш е .
* В к а ч е с т в е к л ю ч е й х р а н и т simple_str в м е с т е с п о с ч и т а н н ы м х е ш е м и п у с т ы м м е с т о м д л я sstring .
* П о с л е в с т а в к и с о з д а е т в э т о м п у с т о м м е с т е sstring , ч т о б ы simple_str б ы л о н а ч т о с с ы л а т ь с я .
* П о з в о л я е т и с п о л ь з о в а т ь д л я в с т а в к и и п о и с к а л ю б ы е simstr с т р о к о в ы е о б ъ е к т ы , с о з д а в а я и з н и х о б ъ е к т
* sstring т о л ь к о п р и р е а л ь н о й в с т а в к е .
* Н а ч и н а я с С + + 20 в unordered_map п о я в и л а с ь в о з м о ж н о с т ь д л я г е т е р о г е н н о г о п о и с к а п о к л ю ч у с т и п о м ,
* о т л и ч н ы м о т т и п а х р а н я щ е г о с я к л ю ч а , н о э т о т р е б у е т о п р е д е л ё н н ы х т а н ц е в с т и п а м и х э ш а и с р а в н е н и я .
* П о и с к ж е с о в с т а в к о й ( try_emplace ) п о т и п у , о т л и ч н о м у о т т и п а к л ю ч а , п о я в л я е т с я в с т а н д а р т е т о л ь к о с C + + 26.
* И м е е т с я р е а л и з а ц и я х е ш и р о в а н и я и с р а в н е н и я д л я в а р и а н т о в :
* - с у ч ё т о м р е г и с т р а с и м в о л о в
* - б е з у ч ё т а р е г и с т р а с и м в о л о в , т о л ь к о ASCII
* - б е з у ч ё т а р е г и с т р а с и м в о л о в , у п р о щ ё н н ы й Unicode ( д о 0xFFFF ) .
* Х э ш и р о в а н и е в ы п о л н я е т с я а л г о р и т м о м FNV - 1 A .
* А в т о м а т и ч е с к а я к о н в е р т а ц и я simstr с т р о к о в ы х о б ъ е к т о в в т и п х р а н я щ е г о с я к л ю ч а ( т . е . с п о с ч и т а н н ы м х е ш е м ) ,
* а т а к ж е с о х р а н е н и е sstring в к л ю ч е п р и в с т а в к е - в ы п о л н я е т с я д л я м е т о д о в try_emplace , emplace , at ,
* find , operator [ ] , erase . П р и и с п о л ь з о в а н и и д р у г и х м е т о д о в п о и с к а в а м н у ж н о с а м и м о б е с п е ч и т ь п р а в и л ь н о
* п о с ч и т а н н ы й х э ш в к л ю ч е StoreType . М е т о д а м и в с т а в к и п о м и м о п е р е ч и с л е н н ы х н е п о л ь з о в а т ь с я , о н и н е
* с о х р а н я т sstring в к л ю ч е .
*
* О с н о в н о е , н а ч ё м х о т е л о с ь б ы з а о с т р и т ь в н и м а н и е - с а м о н а з н а ч е н и е strHashMap , д л я ч е г о о н о и з н а ч а л ь н о п р и д у м ы в а л о с ь .
* Ц е л ь б ы л а н е в т о м , ч т о б ы к а к - т о п о б и т ь п о п р о и з в о д и т е л ь н о с т и / п а м я т и unordered_map ( и н а ч е з а ч е м д е л а т ь strHashMap н а
* б а з е unordered_map ? ) О с н о в н а я п р о б л е м а , к о т о р а я р е ш а л а с ь - э т о т о , ч т о у н а с н е с к о л ь к о в а р и а н т о в с т р о к о в ы х о б ъ е к т о в ,
* и х о т е л о с ь б ы и м е т ь в о з м о ж н о с т ь и с п о л ь з о в а т ь д л я в с т а в к и и п о и с к а к л ю ч е й л ю б о й и з т и п о в с т р о к о в ы х о б ъ е к т о в .
* У н а с е с т ь simple_str , simple_str_nt , sstring , а lstring < N > в о о б щ е н а к а ж д о е N э т о н о в ы й т и п о б ъ е к т а .
* В std в с ё б ы л о п р о с т о - т а м т о л ь к о string , и с о о т в е т с т в е н н о , п о л ь з о в а л и с ь unordered_map < string , Ч т о - т о т а м > .
* И м е ж д у п р о ч и м , в std с т о л к н у л и с ь с т о й ж е п р о б л е м о й : к л ю ч и const char * , а с C + + 17 и string_view ( э т о к а к н а ш simple_str ) ,
* и с к а т ь в unordered_map < string , Type > - н е о ч е н ь х о р о ш о , п р и х о д и т с я к а ж д ы й р а з к л ю ч п р е о б р а з о в ы в а т ь в string , х о т я м о ж н о
* о б о й т и с ь и б е з э т о г о .
* П о э т о м у н а ч и н а я с С + + 20 в unordered_map т а к и д о б а в и л и в о з м о ж н о с т ь г е т е р о г е н н о г о п о и с к а - н а
* https : //en.cppreference.com/w/cpp/container/unordered_map/find это синтаксисы (3) и (4).
* П р а в д а , д л я э т о г о т р е б у ю т с я р и т у а л ь н ы е т а н ц ы с б у б н о м - т р е б у е т с я о с о б ы й т и п д л я х е ш и р о в а н и я ( к о т о р ы й , п о н я т н о , в
* с т а н д а р т у ж е н е в х о д и т и е г о н а д о р е а л и з о в ы в а т ь с а м о м у ) , к о т о р ы й у м е е т х е ш и р о в а т ь р а з н ы е т и п ы к л ю ч е й ,
* и с о д е р ж и т typename ` is_transparent ` . С о б с т в е н н о , н а т о й ж е с т р а н и ц е с н и м п р и м е р и п р и в е д ё н .
* Ч а с т ь п р о б л е м ы э т о з а к р ы л о - п о и с к а , н о п р о б л е м у в с т а в к и н е р е ш а л о - д л я в с т а в к и в unordered_map < string , Type >
* п о п р е ж н е м у т р е б у е т с я т о л ь к о string . И т о л ь к о в б у д у щ е м С + + 26 м ы ж д ё м в о з м о ж н о с т и г е т е р о г е н н о й в с т а в к и в в и д е
* try_emplace ( https : //en.cppreference.com/w/cpp/container/unordered_map/try_emplace) в синтаксисе (6), который
* п о з в о л и т п р и н и м а т ь к л ю ч и д р у г и х т и п о в и п р е о б р а з о в ы в а т ь и х в н у ж н ы й т и п т о л ь к о е с л и в с т а в к а р е а л ь н о о с у щ е с т в л я е т с я .
* В с в о е й с т р о к о в о й б и б л и о т е к е я с т о л к н у л с я с э т о й п р о б л е м о й е щ ё д о С + + 17 , и т а к я к а к н е н а с т о л ь к о к р у т , ч т о б ы
* в л и я т ь н а с т а н д а р т , п р о с т о с о з д а л с в о й к л а с с - н а с л е д н и к о т unordered_map , с о б ё р т к а м и в о к р у г м е т о д о в в с т а в к и / п о и с к а .
* Н у и д о п о л н и т е л ь н о д о б а в и л е щ ё д в а в а р и а н т а х е ш и р о в а н и я / с р а в н е н и я : б е з у ч ё т а р е г и с т р а ASCII , б е з у ч ё т а р е г и с т р а simple unicode .
* Т а к и м о б р а з о м , п о л у ч и л с я к л а с с , к о т о р ы й р а с ш и р я е т с т а н д а р т н ы й unordered_map в о з м о ж н о с т я м и п о р а б о т е с о с т р о к о в ы м и к л ю ч а м и р а з н ы х
* т и п о в , п о з в о л я ю щ и й и з б е ж а т ь л и ш н и х н е н у ж н ы х п р е о б р а з о в а н и й к л ю ч е й п р и п о и с к е и в с т а в к е .
* Т о , ч т о п р и э т о м м о ж е т у л у ч ш и т с я п р о и з в о д и т е л ь н о с т ь - н е ц е л ь , а п о б о ч н ы й э ф ф е к т - п р и я т н ы й , е с л и о н е с т ь ,
* н о и н е с м е р т е л ь н ы й , е с л и е г о н е т .
2025-11-17 09:01:31 +00:00
* @ en @ brief Container for more efficient searching by string keys .
* @ details Used to store and lookup keys of any string type .
* Like unordered_map , but a little better .
* Stores simple_str as keys along with the calculated hash and an empty space for sstring .
* After insertion , creates an sstring in this empty space so that simple_str has something to refer to .
* Allows you to use any simstr string objects for insertion and search , creating an object from them
* sstring only for real insertion .
* Since C + + 20 , unordered_map has the ability to perform heterogeneous search by key with type ,
* different from the type of the key being stored , but this requires some dancing with hash types and comparisons .
* Search with insertion ( try_emplace ) by a type other than the key type appears in the standard only with C + + 26.
* There is a hashing and comparison implementation for the options :
* - case sensitive
* - case insensitive , ASCII only
* - case insensitive , simplified Unicode ( up to 0xFFFF ) .
* Hashing is performed by the FNV - 1 A algorithm .
* Automatic conversion of simstr string objects to the type of the stored key ( i . e . with a calculated hash ) ,
* and also saving sstring in the key when inserting - performed for the try_emplace , emplace , at , methods
* find , operator [ ] , erase . When using other search methods , you need to provide the correct
* calculated hash in the StoreType key . Do not use insertion methods other than those listed ; they are not
* will save sstring in the key .
*
* The main thing I would like to focus on is the very purpose of strHashMap , for which it was originally invented .
* The goal was not to somehow beat unordered_map in terms of performance / memory ( otherwise why make strHashMap on
* unordered_map database ? ) The main problem that was solved is that we have several options for string objects ,
* and I would like to be able to use any type of string object to insert and search for keys .
* We have simple_str , simple_str_nt , sstring , and lstring < N > in general for every N is a new object type .
* In std everything was simple - there was only string , and accordingly , we used unordered_map < string , Something there > .
* And by the way , in std we encountered the same problem : the keys are const char * , and with C + + 17 and string_view ( this is like our simple_str ) ,
* searching in unordered_map < string , Type > is not very good , you have to convert the key to string every time , although you can
* do without this .
* Therefore , starting from C + + 20 , the possibility of heterogeneous search was added to unordered_map - on
* https : //en.cppreference.com/w/cpp/container/unordered_map/find these are syntaxes (3) and (4).
* True , this requires ritual dances with a tambourine - a special type is required for hashing ( which , of course , in
* the standard is no longer included and you need to implement it yourself ) , which can hash different types of keys ,
* and contains typename ` is_transparent ` . In fact , there is an example of it on the same page .
* This solved part of the problem - search , but did not solve the insertion problem - for inserting into unordered_map < string , Type >
* still only requires string . And only in the future C + + 26 we expect the possibility of heterogeneous insertion in the form
* try_emplace ( https : //en.cppreference.com/w/cpp/container/unordered_map/try_emplace) in syntax (6), which
* will allow you to accept keys of other types and convert them to the desired type only if the insertion is actually carried out .
* In my string library , I encountered this problem even before C + + 17 , and so I ’ m not so cool as to
* influence the standard , I simply created my own class - a descendant of unordered_map , with wrappers around the insertion / search methods .
* Well , I also added two more hashing / comparison options : case - insensitive ASCII , case - insensitive simple unicode .
* Thus , we have a class that extends the standard unordered_map with the ability to work with string keys of different
* types , allowing you to avoid unnecessary unnecessary key conversions when searching and inserting .
* The fact that performance may improve is not the goal , but a side effect - pleasant , if there is one ,
* but not fatal if it is not there .
2025-04-05 14:21:11 +00:00
*/
template < typename K , typename T , typename H = strhash < K > , typename E = streql < K > >
2025-11-12 12:08:55 +00:00
class hashStrMap : public std : : unordered_map < StoreType < K , H > , T , H , E > {
2025-04-05 14:21:11 +00:00
protected :
2025-11-12 12:08:55 +00:00
using InStore = StoreType < K , H > ;
2025-04-05 14:21:11 +00:00
public :
using my_type = hashStrMap < K , T , H , E > ;
using hash_t = std : : unordered_map < InStore , T , H , E > ;
using hasher = H ;
hashStrMap ( ) = default ;
hashStrMap ( const my_type & other ) : hash_t ( other ) {
for ( const auto & [ k , v ] : * this ) {
InStore & stored = const_cast < InStore & > ( k ) ;
sstring < K > tmp = * ( sstring < K > * ) stored . node ;
new ( stored . node ) sstring < K > ( std : : move ( tmp ) ) ;
stored . str . str = stored . to_str ( ) . symbols ( ) ;
}
}
~ hashStrMap ( ) {
for ( auto & k : * this )
( ( sstring < K > * ) k . first . node ) - > ~ sstring ( ) ;
}
hashStrMap ( my_type & & o ) = default ;
2025-11-24 12:46:16 +00:00
2025-04-05 14:21:11 +00:00
my_type & operator = ( const my_type & other ) {
hash_t : : operator = ( other ) ;
for ( const auto & [ k , v ] : * this ) {
InStore & stored = const_cast < InStore & > ( k ) ;
sstring < K > tmp = * ( sstring < K > * ) stored . node ;
new ( stored . node ) sstring < K > ( std : : move ( tmp ) ) ;
stored . str . str = stored . to_str ( ) . symbols ( ) ;
}
return * this ;
} ;
my_type & operator = ( my_type & & ) = default ;
2025-11-12 12:08:55 +00:00
hashStrMap ( std : : initializer_list < std : : pair < const InStore , T > > & & init ) {
2025-04-05 14:21:11 +00:00
for ( const auto & e : init )
emplace ( e . first , e . second ) ;
}
using init_str = std : : initializer_list < std : : pair < const sstring < K > , T > > ;
hashStrMap ( init_str & & init ) {
for ( const auto & e : init )
emplace ( e . first , e . second ) ;
}
// При входе хэш должен быть уже посчитан
2025-11-17 09:01:31 +00:00
// When entering, the hash must already be calculated
2025-04-05 14:21:11 +00:00
template < typename . . . ValArgs >
2025-11-12 12:08:55 +00:00
auto try_emplace ( const InStore & key , ValArgs & & . . . args ) {
2025-04-05 14:21:11 +00:00
auto it = hash_t : : try_emplace ( key , std : : forward < ValArgs > ( args ) . . . ) ;
if ( it . second ) {
InStore & stored = const_cast < InStore & > ( it . first - > first ) ;
new ( stored . node ) sstring < K > ( key . str ) ;
stored . str . str = stored . to_str ( ) . symbols ( ) ;
}
return it ;
}
2025-11-12 12:08:55 +00:00
static InStore toStoreType ( simple_str < K > key ) {
2025-04-05 14:21:11 +00:00
return { key , H { } ( key ) } ;
}
template < typename Key , typename . . . ValArgs >
requires ( std : : is_convertible_v < Key , simple_str < K > > )
auto try_emplace ( Key & & key , ValArgs & & . . . args ) {
auto it = hash_t : : try_emplace ( toStoreType ( key ) , std : : forward < ValArgs > ( args ) . . . ) ;
if ( it . second ) {
InStore & stored = const_cast < InStore & > ( it . first - > first ) ;
new ( stored . node ) sstring < K > ( std : : forward < Key > ( key ) ) ;
stored . str . str = stored . to_str ( ) . symbols ( ) ;
}
return it ;
}
template < typename . . . ValArgs >
2025-11-12 12:08:55 +00:00
auto emplace ( const InStore & key , ValArgs & & . . . args ) {
2025-04-05 14:21:11 +00:00
auto it = try_emplace ( key , std : : forward < ValArgs > ( args ) . . . ) ;
if ( ! it . second ) {
it . first - > second = T ( std : : forward < ValArgs > ( args ) . . . ) ;
}
return it ;
}
template < typename Key , typename . . . ValArgs >
requires ( std : : is_convertible_v < Key , simple_str < K > > )
auto emplace ( Key & & key , ValArgs & & . . . args ) {
auto it = try_emplace ( std : : forward < Key > ( key ) , std : : forward < ValArgs > ( args ) . . . ) ;
if ( ! it . second ) {
it . first - > second = T ( std : : forward < ValArgs > ( args ) . . . ) ;
}
return it ;
}
2025-11-12 12:08:55 +00:00
auto & operator [ ] ( const InStore & key ) {
2025-04-05 14:21:11 +00:00
return try_emplace ( key ) . first - > second ;
}
template < typename Key >
requires ( std : : is_convertible_v < Key , simple_str < K > > )
auto & operator [ ] ( Key & & key ) {
return try_emplace ( std : : forward < Key > ( key ) ) . first - > second ;
}
2025-11-12 12:08:55 +00:00
decltype ( auto ) at ( const InStore & key ) {
2025-04-05 14:21:11 +00:00
return hash_t : : at ( key ) ;
}
2025-11-12 12:08:55 +00:00
decltype ( auto ) at ( const InStore & key ) const {
2025-04-05 14:21:11 +00:00
return hash_t : : at ( key ) ;
}
2025-11-10 17:35:35 +00:00
decltype ( auto ) at ( simple_str < K > key ) {
2025-04-05 14:21:11 +00:00
return hash_t : : at ( toStoreType ( key ) ) ;
}
2025-11-10 17:35:35 +00:00
decltype ( auto ) at ( simple_str < K > key ) const {
2025-04-05 14:21:11 +00:00
return hash_t : : at ( toStoreType ( key ) ) ;
}
2025-11-12 12:08:55 +00:00
auto find ( const InStore & key ) const {
2025-04-05 14:21:11 +00:00
return hash_t : : find ( key ) ;
}
auto find ( simple_str < K > key ) const {
return find ( toStoreType ( key ) ) ;
}
2025-11-12 12:08:55 +00:00
auto find ( const InStore & key ) {
2025-04-05 14:21:11 +00:00
return hash_t : : find ( key ) ;
}
auto find ( simple_str < K > key ) {
return find ( toStoreType ( key ) ) ;
}
auto erase ( typename hash_t : : const_iterator it ) {
if ( it ! = hash_t : : end ( ) ) {
( ( sstring < K > * ) it - > first . node ) - > ~ sstring ( ) ;
}
return hash_t : : erase ( it ) ;
}
2025-11-12 12:08:55 +00:00
auto erase ( const InStore & key ) {
2025-04-05 14:21:11 +00:00
auto it = hash_t : : find ( key ) ;
if ( it ! = hash_t : : end ( ) ) {
( ( sstring < K > * ) it - > first . node ) - > ~ sstring ( ) ;
hash_t : : erase ( it ) ;
return 1 ;
}
return 0 ;
}
auto erase ( simple_str < K > key ) {
return erase ( toStoreType ( key ) ) ;
}
bool lookup ( simple_str < K > txt , T & val ) const {
auto it = find ( txt ) ;
if ( it ! = hash_t : : end ( ) ) {
val = it - > second ;
return true ;
}
return false ;
}
void clear ( ) {
for ( auto & k : * this )
( ( sstring < K > * ) k . first . node ) - > ~ sstring ( ) ;
hash_t : : clear ( ) ;
}
2025-11-12 12:08:55 +00:00
bool contains ( const InStore & key ) const {
2025-04-05 14:21:11 +00:00
return hash_t : : find ( key ) ! = this - > end ( ) ;
}
bool contains ( simple_str < K > key ) const {
return find ( toStoreType ( key ) ) ! = this - > end ( ) ;
}
} ;
template < typename K >
struct streql {
2025-11-12 12:08:55 +00:00
template < typename H >
bool operator ( ) ( const StoreType < K , H > & _Left , const StoreType < K , H > & _Right ) const {
2025-04-05 14:21:11 +00:00
return _Left . hash = = _Right . hash & & _Left . str = = _Right . str ;
}
} ;
template < typename K >
struct strhash { // hash functor for basic_string
size_t operator ( ) ( simple_str < K > _Keyval ) const {
return fnv_hash ( _Keyval . symbols ( ) , _Keyval . length ( ) ) ;
}
2025-11-13 08:16:20 +00:00
size_t operator ( ) ( const StoreType < K , strhash < K > > & _Keyval ) const {
2025-04-05 14:21:11 +00:00
return _Keyval . hash ;
}
} ;
template < typename K >
struct streqlia {
2025-11-12 12:08:55 +00:00
template < typename H >
bool operator ( ) ( const StoreType < K , H > & _Left , const StoreType < K , H > & _Right ) const {
2025-04-05 14:21:11 +00:00
return _Left . hash = = _Right . hash & & _Left . str . equal_ia ( _Right . str ) ;
}
} ;
template < typename K >
struct strhashia {
size_t operator ( ) ( simple_str < K > _Keyval ) const {
return fnv_hash_ia ( _Keyval . symbols ( ) , _Keyval . length ( ) ) ;
}
2025-11-13 08:16:20 +00:00
size_t operator ( ) ( const StoreType < K , strhashia < K > > & _Keyval ) const {
2025-04-05 14:21:11 +00:00
return _Keyval . hash ;
}
} ;
template < typename K >
struct streqliu {
2025-11-12 12:08:55 +00:00
template < typename H >
bool operator ( ) ( const StoreType < K , H > & _Left , const StoreType < K , H > & _Right ) const {
2025-04-05 14:21:11 +00:00
return _Left . hash = = _Right . hash & & _Left . str . equal_iu ( _Right . str ) ;
}
} ;
template < typename K >
struct strhashiu {
size_t operator ( ) ( simple_str < K > _Keyval ) const {
return unicode_traits < K > : : hashiu ( _Keyval . symbols ( ) , _Keyval . length ( ) ) ;
}
2025-11-13 08:16:20 +00:00
size_t operator ( ) ( const StoreType < K , strhashiu < K > > & _Keyval ) const {
2025-04-05 14:21:11 +00:00
return _Keyval . hash ;
}
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Д л я п о с т р о е н и я д л и н н ы х д и н а м и ч е с к и х с т р о к к о н к а т е н а ц и е й м е л к и х к у с о ч к о в .
2025-04-05 14:21:11 +00:00
* @ details В ы д е л я е т п о м е р е н а д о б н о с т и о т д е л ь н ы е б л о к и з а д а н н о г о р а з м е р а ( и л и к р а т н о г о е м у д л я б о л ь ш и х в с т а в о к ) ,
* ч т о б ы и з б е ж а т ь р е л о к а ц и и д л и н н ы х с т р о к . П о с л е п о с т р о е н и я м о ж н о с л и т ь в о д н у с т р о к у .
* К а к п о к а з а л и з а м е р ы , е с л и с л и в а т ь п о т о м в о д н у с т р о к у , р а б о т а е т м е д л е н н е е , ч е м lstring + = ,
* н о э к о н о м н е е п о п а м я т и . Е с л и н е с л и в а т ь в о д н у с т р о к у , а д а л ь ш е п е р е б и р а т ь б у ф е р а - б ы с т р е е .
* С а м я в л я е т с я с т р о к о в ы м в ы р а ж е н и е м .
2025-11-17 09:01:31 +00:00
* @ en @ brief For constructing long dynamic strings by concatenating small pieces .
* @ details Selects individual blocks of a given size ( or a multiple of it for large inserts ) as needed .
* to avoid relocation of long strings . After construction , you can merge it into one line .
* As measurements have shown , if you then merge it into one line , it works slower than lstring + = ,
* but more economical in memory . If you don ' t merge it into one line , and then iterate through buffers , it ' s faster .
* Itself is a string expression .
2025-04-05 14:21:11 +00:00
*/
template < typename K >
2026-01-21 11:59:17 +00:00
class chunked_string_builder : expr_to_std_string < chunked_string_builder < K > > {
2025-04-05 14:21:11 +00:00
using chunk_t = std : : pair < std : : unique_ptr < K [ ] > , size_t > ;
2025-11-17 09:01:31 +00:00
std : : vector < chunk_t > chunks ; // блоки и длина данных в них | blocks and data length in them
K * write { } ; // Текущая позиция записи | Current write position
size_t len { } ; // Общая длина | Total length
size_t remain { } ; // Сколько осталось места в текущем блоке | How much space is left in the current block
2025-04-05 14:21:11 +00:00
size_t align { 1024 } ;
public :
using my_type = chunked_string_builder < K > ;
using symb_type = K ;
chunked_string_builder ( ) = default ;
chunked_string_builder ( size_t a ) : align ( a ) { } ;
chunked_string_builder ( const my_type & ) = delete ;
chunked_string_builder ( my_type & & other ) noexcept
: chunks ( std : : move ( other . chunks ) ) , write ( other . write ) , len ( other . len ) , remain ( other . remain ) , align ( other . align ) {
other . len = other . remain = 0 ;
other . write = nullptr ;
}
my_type & operator = ( my_type other ) noexcept {
chunks . swap ( other . chunks ) ;
write = other . write ;
len = other . len ;
remain = other . remain ;
align = other . align ;
other . len = other . remain = 0 ;
other . write = nullptr ;
return * this ;
}
2025-11-17 09:01:31 +00:00
/// @ru Добавление порции данных. @en Adding a piece of data.
2025-04-05 14:21:11 +00:00
my_type & operator < < ( simple_str < K > data ) {
if ( data . len ) {
len + = data . len ;
if ( data . len < = remain ) {
// Добавляемые данные влезают в выделенный блок, просто скопируем их
2025-11-17 09:01:31 +00:00
// The added data fits into the selected block, just copy it
2025-04-05 14:21:11 +00:00
ch_traits < K > : : copy ( write , data . str , data . len ) ;
2025-11-17 09:01:31 +00:00
write + = data . len ; // Сдвинем позицию записи | Let's move the recording position
chunks . back ( ) . second + = data . len ; // Увеличим длину хранимых в блоке данных | Let's increase the length of the data stored in the block
remain - = data . len ; // Уменьшим остаток места в блоке | Reduce the remaining space in the block
2025-04-05 14:21:11 +00:00
} else {
2025-11-17 09:01:31 +00:00
// Н е влезают | They don't fit
2025-04-05 14:21:11 +00:00
if ( remain ) {
// Сначала запишем сколько влезет
2025-11-17 09:01:31 +00:00
// First, write down as much as we can
2025-04-05 14:21:11 +00:00
ch_traits < K > : : copy ( write , data . str , remain ) ;
data . len - = remain ;
data . str + = remain ;
2025-11-17 09:01:31 +00:00
chunks . back ( ) . second + = remain ; // Увеличим длину хранимых в блоке данных | Let's increase the length of the data stored in the block
2025-04-05 14:21:11 +00:00
}
// Выделим новый блок и впишем в него данные
2025-11-17 09:01:31 +00:00
// Рассчитаем размер блока, кратного заданному выравниванию
// Select a new block and write data into it
// Calculate the block size that is a multiple of the given alignment
size_t blockSize = ( data . len + align - 1 ) / align * align ;
2025-04-05 14:21:11 +00:00
chunks . emplace_back ( std : : make_unique < K [ ] > ( blockSize ) , data . len ) ;
write = chunks . back ( ) . first . get ( ) ;
ch_traits < K > : : copy ( write , data . str , data . len ) ;
write + = data . len ;
remain = blockSize - data . len ;
}
}
return * this ;
}
2025-11-17 09:01:31 +00:00
/// @ru Добавление строкового выражения. @en Adding a string expression.
2025-04-05 14:21:11 +00:00
my_type & operator < < ( const StrExprForType < K > auto & expr ) {
size_t l = expr . length ( ) ;
if ( l ) {
if ( l < remain ) {
write = expr . place ( write ) ;
chunks . back ( ) . second + = l ;
len + = l ;
remain - = l ;
} else if ( ! remain ) {
size_t blockSize = ( l + align - 1 ) / align * align ; // Рассчитаем размер блока, кратного заданному выравниванию
chunks . emplace_back ( std : : make_unique < K [ ] > ( blockSize ) , l ) ;
write = expr . place ( chunks . back ( ) . first . get ( ) ) ;
len + = l ;
remain = blockSize - l ;
} else {
auto store = std : : make_unique < K [ ] > ( l ) ;
expr . place ( store . get ( ) ) ;
return operator < < ( { store . get ( ) , l } ) ;
}
}
return * this ;
}
2025-11-17 09:01:31 +00:00
/// @ru Добавление символа. @en Adding a symbol.
2025-04-05 14:21:11 +00:00
template < typename T >
my_type & operator < < ( T data )
requires std : : is_same_v < T , K >
{
return operator < < ( expr_char < K > ( data ) ) ;
}
2025-11-17 09:01:31 +00:00
/// @ru Длина сохранённого текста. @en Length of the saved text.
2025-04-05 14:21:11 +00:00
constexpr size_t length ( ) const noexcept {
return len ;
}
2025-11-17 09:01:31 +00:00
/// @ru Сбрасывает содержимое, но при этом не удаляет первый буфер, чтобы потом избежать аллокации. @en Resets the contents, but does not delete the first buffer in order to avoid allocation later.
2025-04-05 14:21:11 +00:00
void reset ( ) {
if ( chunks . empty ( ) ) {
return ;
}
if ( chunks . size ( ) > 1 ) {
remain = 0 ;
chunks . resize ( 1 ) ;
}
remain + = chunks [ 0 ] . second ;
chunks [ 0 ] . second = 0 ;
len = 0 ;
write = chunks [ 0 ] . first . get ( ) ;
}
constexpr K * place ( K * p ) const noexcept {
for ( const auto & block : chunks ) {
ch_traits < K > : : copy ( p , block . first . get ( ) , block . second ) ;
p + = block . second ;
}
return p ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р и м е н я е т ф у н к т о р к к а ж д о м у с о х р а н ё н н о м у б у ф е р у .
* @ tparam Op - т и п ф у н к т о р а , ф у н к ц и я в и д а ( const K * ptr , size_t len ) .
* @ param o - ф у н к т о р .
* @ en @ brief Applies a functor to each stored buffer .
* @ tparam Op - type of the functor , function type ( const K * ptr , size_t len ) .
* @ param o is a functor .
2025-04-05 14:21:11 +00:00
*/
template < typename Op >
void out ( const Op & o ) const {
for ( const auto & block : chunks )
o ( block . first . get ( ) , block . second ) ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р о в е р я е т , р а с п о л о ж е н л и в е с ь т е к с т о д н и м н е п р е р ы в н ы м к у с к о м в п а м я т и .
* @ en @ brief Checks whether all text is located in one contiguous chunk in memory .
2025-04-05 14:21:11 +00:00
*/
bool is_continuous ( ) const {
if ( chunks . size ( ) ) {
const K * ptr = chunks . front ( ) . first . get ( ) ;
for ( const auto & chunk : chunks ) {
if ( chunk . first . get ( ) ! = ptr )
return false ;
ptr + = chunk . second ;
}
}
return true ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь у к а з а т е л ь н а н а ч а л о п е р в о г о б у ф е р а .
* И м е е т с м ы с л п р и м е н я т ь т о л ь к о е с л и is_continuous true .
* @ en @ brief Get a pointer to the beginning of the first buffer .
* It makes sense to apply only if is_continuous true .
2025-04-05 14:21:11 +00:00
*/
const K * begin ( ) const {
return chunks . size ( ) ? chunks . front ( ) . first . get ( ) : simple_str_nt < K > : : empty_str . str ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О ч и с т и т ь о б ъ е к т , о с в о б о д и в в с е в ы д е л е н н ы е б у ф е р а .
* @ en @ brief Clear the object , freeing all allocated buffers .
2025-04-05 14:21:11 +00:00
*/
void clear ( ) {
chunks . clear ( ) ;
write = nullptr ;
len = 0 ;
remain = 0 ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О б ъ е к т , п о з в о л я ю щ и й п о с л е д о в а т е л ь н о к о п и р о в а т ь с о д е р ж и м о е в б у ф е р з а д а н н о г о р а з м е р а .
* @ en @ brief An object that allows you to sequentially copy content into a buffer of a given size .
2025-04-05 14:21:11 +00:00
*/
struct portion_store {
typename decltype ( chunks ) : : const_iterator it , end ;
size_t writedFromCurrentChunk ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П р о в е р и т ь , ч т о д а н н ы е е щ ё н е к о н ч и л и с ь .
* @ en @ brief Check that the data has not yet run out .
2025-04-05 14:21:11 +00:00
*/
bool is_end ( ) {
return it = = end ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief С о х р а н и т ь о ч е р е д н у ю п о р ц и ю д а н н ы х в б у ф е р .
* @ param buffer - у к а з а т е л ь н а б у ф е р д л я с о х р а н е н и я д а н н ы х .
* @ param size - р а з м е р б у ф е р а .
2025-04-05 14:21:11 +00:00
* @ return size_t - к о л и ч е с т в о с к о п и р о в а н н ы х С И М В О Л О В ( н е б а й т о в ) .
2025-11-17 09:01:31 +00:00
* @ en @ brief Save the next portion of data to the buffer .
* @ param buffer - pointer to the buffer for storing data .
* @ param size - buffer size .
* @ return size_t - the number of CHARACTERS ( not bytes ) copied .
2025-04-05 14:21:11 +00:00
*/
size_t store ( K * buffer , size_t size ) {
size_t writed = 0 ;
while ( size & & ! is_end ( ) ) {
size_t remain = it - > second - writedFromCurrentChunk ;
size_t write = std : : min ( size , remain ) ;
ch_traits < K > : : copy ( buffer , it - > first . get ( ) + writedFromCurrentChunk , write ) ;
writed + = write ;
remain - = write ;
size - = write ;
if ( ! remain ) {
+ + it ;
writedFromCurrentChunk = 0 ;
} else
writedFromCurrentChunk + = write ;
}
return writed ;
}
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь portion_store , ч е р е з к о т о р ы й м о ж н о п о с л е д о в а т е л ь н о и з в л е к а т ь д а н н ы е в о в н е ш н и й б у ф е р .
* @ return portion_store .
* @ en @ brief Get a portion_store through which data can be sequentially retrieved into an external buffer .
* @ return portion_store .
2025-04-05 14:21:11 +00:00
*/
portion_store get_portion ( ) const {
return { chunks . begin ( ) , chunks . end ( ) , 0 } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief П о л у ч и т ь в н у т р е н н и е б у ф е р а с д а н н ы м и .
* @ return const auto & .
* @ en @ brief Get internal data buffers .
* @ return const auto & .
2025-04-05 14:21:11 +00:00
*/
const auto & data ( ) const {
return chunks ;
}
} ;
using stringa = sstring < u8s > ;
2026-01-21 11:59:17 +00:00
using stringb = sstring < ubs > ;
2025-04-05 14:21:11 +00:00
using stringw = sstring < wchar_t > ;
using stringu = sstring < u16s > ;
using stringuu = sstring < u32s > ;
2025-11-13 14:57:42 +00:00
static_assert ( sizeof ( stringa ) = = ( sizeof ( void * ) = = 8 ? 24 : 16 ) , " Bad size of sstring " ) ;
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я char с т р о к , р е г и с т р о з а в и с и м ы й п о и с к .
* @ en @ brief Type of hash dictionary for char strings , case sensitive search .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapA = hashStrMap < u8s , T , strhash < u8s > , streql < u8s > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я char с т р о к , р е г и с т р о н е з а в и с и м ы й п о и с к д л я ASCII с и м в о л о в .
* @ en @ brief Type of hash dictionary for char strings , case - insensitive lookup for ASCII characters .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapAIA = hashStrMap < u8s , T , strhashia < u8s > , streqlia < u8s > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я char с т р о к , р е г и с т р о н е з а в и с и м ы й п о и с к д л я Unicode с и м в о л о в д о 0xFFFF .
* @ en @ brief Hash dictionary type for char strings , case - insensitive search for Unicode characters up to 0xFFFF .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapAIU = hashStrMap < u8s , T , strhashiu < u8s > , streqliu < u8s > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я wchar_t с т р о к , р е г и с т р о з а в и с и м ы й п о и с к .
* @ en @ brief Hash dictionary type for wchar_t strings , case sensitive search .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapW = hashStrMap < wchar_t , T , strhash < wchar_t > , streql < wchar_t > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я wchar_t с т р о к , р е г и с т р о н е з а в и с и м ы й п о и с к д л я ASCII с и м в о л о в .
* @ en @ brief Hash dictionary type for wchar_t strings , case - insensitive lookup for ASCII characters .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapWIA = hashStrMap < wchar_t , T , strhashia < wchar_t > , streqlia < wchar_t > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я wchar_t с т р о к , р е г и с т р о н е з а в и с и м ы й п о и с к д л я Unicode с и м в о л о в д о 0xFFFF .
* @ en @ brief Hash dictionary type for wchar_t strings , case insensitive search for Unicode characters up to 0xFFFF .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapWIU = hashStrMap < wchar_t , T , strhashiu < wchar_t > , streqliu < wchar_t > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я char16_t с т р о к , р е г и с т р о з а в и с и м ы й п о и с к .
* @ en @ brief Hash dictionary type for char16_t strings , case sensitive search .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapU = hashStrMap < u16s , T , strhash < u16s > , streql < u16s > > ;
template < typename T >
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я char16_t с т р о к , р е г и с т р о н е з а в и с и м ы й п о и с к д л я ASCII с и м в о л о в .
* @ en @ brief Hash dictionary type for char16_t strings , case - insensitive lookup for ASCII characters .
2025-04-05 14:21:11 +00:00
*/
using hashStrMapUIA = hashStrMap < u16s , T , strhashia < u16s > , streqlia < u16s > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я char16_t с т р о к , р е г и с т р о н е з а в и с и м ы й п о и с к д л я Unicode с и м в о л о в д о 0xFFFF .
* @ en @ brief Hash dictionary type for char16_t strings , case insensitive search for Unicode characters up to 0xFFFF .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapUIU = hashStrMap < u16s , T , strhashiu < u16s > , streqliu < u16s > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я char32_t с т р о к , р е г и с т р о з а в и с и м ы й п о и с к .
* @ en @ brief Hash dictionary type for char32_t strings , case sensitive search .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapUU = hashStrMap < u32s , T , strhash < u32s > , streql < u32s > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я char32_t с т р о к , р е г и с т р о н е з а в и с и м ы й п о и с к д л я ASCII с и м в о л о в .
* @ en @ brief Hash dictionary type for char32_t strings , case - insensitive lookup for ASCII characters .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapUUIA = hashStrMap < u32s , T , strhashia < u32s > , streqlia < u32s > > ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Т и п х е ш - с л о в а р я д л я char32_t с т р о к , р е г и с т р о н е з а в и с и м ы й п о и с к д л я Unicode с и м в о л о в д о 0xFFFF .
* @ en @ brief Hash dictionary type for char32_t strings , case insensitive search for Unicode characters up to 0xFFFF .
2025-04-05 14:21:11 +00:00
*/
template < typename T >
using hashStrMapUUIU = hashStrMap < u32s , T , strhashiu < u32s > , streqliu < u32s > > ;
inline constexpr simple_str_nt < u8s > utf8_bom { " \xEF \xBB \xBF " , 3 } ; // NOLINT
inline namespace literals {
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в simple_str_nt .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return simple_str_nt .
* @ en @ brief Operator literal in simple_str_nt .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return simple_str_nt .
2025-04-05 14:21:11 +00:00
*/
2025-08-10 10:01:39 +00:00
SS_CONSTEVAL simple_str_nt < u8s > operator " " _ss ( const u8s * ptr , size_t l ) {
2025-04-05 14:21:11 +00:00
return simple_str_nt < u8s > { ptr , l } ;
}
2026-01-21 11:59:17 +00:00
/*!
* @ ru @ brief О п е р а т о р л и т е р а л в simple_str_nt .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return simple_str_nt .
* @ en @ brief Operator literal in simple_str_nt .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return simple_str_nt .
*/
SS_CONSTEVAL simple_str_nt < ubs > operator " " _ss ( const ubs * ptr , size_t l ) {
return simple_str_nt < ubs > { ptr , l } ;
}
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в simple_str_nt .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return simple_str_nt .
* @ en @ brief Operator literal in simple_str_nt .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return simple_str_nt .
2025-04-05 14:21:11 +00:00
*/
2025-08-10 10:01:39 +00:00
SS_CONSTEVAL simple_str_nt < uws > operator " " _ss ( const uws * ptr , size_t l ) {
2025-04-05 14:21:11 +00:00
return simple_str_nt < uws > { ptr , l } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в simple_str_nt .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return simple_str_nt .
* @ en @ brief Operator literal in simple_str_nt .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return simple_str_nt .
2025-04-05 14:21:11 +00:00
*/
2025-08-10 10:01:39 +00:00
SS_CONSTEVAL simple_str_nt < u16s > operator " " _ss ( const u16s * ptr , size_t l ) {
2025-04-05 14:21:11 +00:00
return simple_str_nt < u16s > { ptr , l } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в simple_str_nt .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return simple_str_nt .
* @ en @ brief Operator literal in simple_str_nt .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return simple_str_nt .
2025-04-05 14:21:11 +00:00
*/
2025-08-10 10:01:39 +00:00
SS_CONSTEVAL simple_str_nt < u32s > operator " " _ss ( const u32s * ptr , size_t l ) {
2025-04-05 14:21:11 +00:00
return simple_str_nt < u32s > { ptr , l } ;
}
2025-11-13 08:16:20 +00:00
template < typename K > using HashKey = StoreType < K , strhash < K > > ;
template < typename K > using HashKeyIA = StoreType < K , strhashia < K > > ;
template < typename K > using HashKeyIU = StoreType < K , strhashiu < K > > ;
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м с у ч ё т о м р е г и с т р а .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a case - sensitive hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-04-05 14:21:11 +00:00
*/
2025-11-13 08:16:20 +00:00
consteval HashKey < u8s > operator " " _h ( const u8s * ptr , size_t l ) {
return HashKey < u8s > { { ptr , l } , fnv_hash_compile ( ptr , l ) } ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м б е з у ч ё т а р е г и с т р а ASCII .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a case - insensitive ASCII hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-04-05 14:21:11 +00:00
*/
2025-11-13 08:16:20 +00:00
consteval HashKeyIA < u8s > operator " " _ia ( const u8s * ptr , size_t l ) {
return HashKeyIA < u8s > { { ptr , l } , fnv_hash_ia_compile ( ptr , l ) } ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м б е з у ч ё т а р е г и с т р а simple unicode .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a simple unicode case - insensitive hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-04-05 14:21:11 +00:00
*/
2025-11-13 08:16:20 +00:00
inline HashKeyIU < u8s > operator " " _iu ( const u8s * ptr , size_t l ) {
return HashKeyIU < u8s > { { ptr , l } , strhashiu < u8s > { } ( simple_str < u8s > { ptr , l } ) } ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м с у ч ё т о м р е г и с т р а .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a case - sensitive hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-04-05 14:21:11 +00:00
*/
2025-11-13 08:16:20 +00:00
consteval HashKey < u16s > operator " " _h ( const u16s * ptr , size_t l ) {
return HashKey < u16s > { { ptr , l } , fnv_hash_compile ( ptr , l ) } ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м б е з у ч ё т а р е г и с т р а ASCII .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a case - insensitive ASCII hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-04-05 14:21:11 +00:00
*/
2025-11-13 08:16:20 +00:00
consteval HashKeyIA < u16s > operator " " _ia ( const u16s * ptr , size_t l ) {
return HashKeyIA < u16s > { { ptr , l } , fnv_hash_ia_compile ( ptr , l ) } ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м б е з у ч ё т а р е г и с т р а simple unicode .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a simple unicode case - insensitive hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-04-05 14:21:11 +00:00
*/
2025-11-13 08:16:20 +00:00
inline HashKeyIU < u16s > operator " " _iu ( const u16s * ptr , size_t l ) {
return HashKeyIU < u16s > { { ptr , l } , strhashiu < u16s > { } ( simple_str < u16s > { ptr , l } ) } ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м с у ч ё т о м р е г и с т р а .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a case - sensitive hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-04-05 14:21:11 +00:00
*/
2025-11-13 08:16:20 +00:00
consteval HashKey < u32s > operator " " _h ( const u32s * ptr , size_t l ) {
return HashKey < u32s > { { ptr , l } , fnv_hash_compile ( ptr , l ) } ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м б е з у ч ё т а р е г и с т р а ASCII .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a case - insensitive ASCII hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-04-05 14:21:11 +00:00
*/
2025-11-13 08:16:20 +00:00
consteval HashKeyIA < u32s > operator " " _ia ( const u32s * ptr , size_t l ) {
return HashKeyIA < u32s > { { ptr , l } , fnv_hash_ia_compile ( ptr , l ) } ;
2025-04-05 14:21:11 +00:00
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м б е з у ч ё т а р е г и с т р а simple unicode .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a simple unicode case - insensitive hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-04-05 14:21:11 +00:00
*/
2025-11-13 08:16:20 +00:00
inline HashKeyIU < u32s > operator " " _iu ( const u32s * ptr , size_t l ) {
return HashKeyIU < u32s > { { ptr , l } , strhashiu < u32s > { } ( simple_str < u32s > { ptr , l } ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м с у ч ё т о м р е г и с т р а .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a case - sensitive hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-11-13 08:16:20 +00:00
*/
consteval HashKey < uws > operator " " _h ( const uws * ptr , size_t l ) {
return HashKey < uws > { { ptr , l } , fnv_hash_compile ( ptr , l ) } ;
2025-04-05 14:21:11 +00:00
}
2025-11-13 08:16:20 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м б е з у ч ё т а р е г и с т р а ASCII .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a case - insensitive ASCII hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-11-13 08:16:20 +00:00
*/
consteval HashKeyIA < uws > operator " " _ia ( const uws * ptr , size_t l ) {
return HashKeyIA < uws > { { ptr , l } , fnv_hash_ia_compile ( ptr , l ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р л и т е р а л в к л ю ч д л я hashStrMap с п о с ч и т а н н ы м в compile time х е ш е м б е з у ч ё т а р е г и с т р а simple unicode .
* @ param ptr - у к а з а т е л ь н а с т р о к у .
* @ param l - д л и н а с т р о к и .
* @ return StoreType .
* @ en @ brief Key literal operator for hashStrMap with a simple unicode case - insensitive hash calculated at compile time .
* @ param ptr - pointer to a string .
* @ param l - string length .
* @ return StoreType .
2025-11-13 08:16:20 +00:00
*/
inline HashKeyIU < uws > operator " " _iu ( const uws * ptr , size_t l ) {
return HashKeyIU < uws > { { ptr , l } , strhashiu < uws > { } ( simple_str < uws > { ptr , l } ) } ;
}
2025-04-05 14:21:11 +00:00
} // namespace literals
2026-02-15 14:13:54 +00:00
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 > > ;
2025-04-05 14:21:11 +00:00
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р в ы в о д а в п о т о к simple_str .
* @ param stream - п о т о к в ы в о д а .
* @ param text - т е к с т .
2025-11-24 12:46:16 +00:00
* @ return std : : ostream & .
2025-11-17 09:01:31 +00:00
* @ en @ brief Stream output operator simple_str .
* @ param stream - output stream .
* @ param text - text .
* @ return std : : ostream & .
2025-04-05 14:21:11 +00:00
*/
inline std : : ostream & operator < < ( std : : ostream & stream , ssa text ) {
return stream < < std : : string_view { text . symbols ( ) , text . length ( ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р в ы в о д а в п о т о к simple_str .
* @ param stream - п о т о к в ы в о д а .
* @ param text - т е к с т .
* @ return std : : ostream & .
* @ en @ brief Stream output operator simple_str .
* @ param stream - output stream .
* @ param text - text .
* @ return std : : ostream & .
2025-04-05 14:21:11 +00:00
*/
inline std : : wostream & operator < < ( std : : wostream & stream , ssw text ) {
return stream < < std : : wstring_view { text . symbols ( ) , text . length ( ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р в ы в о д а в п о т о к simple_str .
* @ param stream - п о т о к в ы в о д а .
* @ param text - т е к с т .
* @ return std : : ostream & .
* @ en @ brief Stream output operator simple_str .
* @ param stream - output stream .
* @ param text - text .
* @ return std : : ostream & .
2025-04-05 14:21:11 +00:00
*/
inline std : : wostream & operator < < ( std : : wostream & stream , simple_str < wchar_type > text ) {
return stream < < std : : wstring_view { from_w ( text . symbols ( ) ) , text . length ( ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р в ы в о д а в п о т о к sstring .
* @ param stream - п о т о к в ы в о д а .
* @ param text - т е к с т .
* @ return std : : ostream & .
* @ en @ brief Operator for outputting sstring to stream .
* @ param stream - output stream .
* @ param text - text .
* @ return std : : ostream & .
2025-04-05 14:21:11 +00:00
*/
inline std : : ostream & operator < < ( std : : ostream & stream , const stringa & text ) {
return stream < < std : : string_view { text . symbols ( ) , text . length ( ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р в ы в о д а в п о т о к sstring .
* @ param stream - п о т о к в ы в о д а .
* @ param text - т е к с т .
* @ return std : : ostream & .
* @ en @ brief Operator for outputting sstring to stream .
* @ param stream - output stream .
* @ param text - text .
* @ return std : : ostream & .
2025-04-05 14:21:11 +00:00
*/
inline std : : wostream & operator < < ( std : : wostream & stream , const stringw & text ) {
return stream < < std : : wstring_view { text . symbols ( ) , text . length ( ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р в ы в о д а в п о т о к sstring .
* @ param stream - п о т о к в ы в о д а .
* @ param text - т е к с т .
* @ return std : : ostream & .
* @ en @ brief Operator for outputting sstring to stream .
* @ param stream - output stream .
* @ param text - text .
* @ return std : : ostream & .
2025-04-05 14:21:11 +00:00
*/
inline std : : wostream & operator < < ( std : : wostream & stream , const sstring < wchar_type > & text ) {
return stream < < std : : wstring_view { from_w ( text . symbols ( ) ) , text . length ( ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р в ы в о д а в п о т о к lstring .
* @ param stream - п о т о к в ы в о д а .
* @ param text - т е к с т .
* @ return std : : ostream & .
* @ en @ brief Operator to output lstring to stream .
* @ param stream - output stream .
* @ param text - text .
* @ return std : : ostream & .
2025-04-05 14:21:11 +00:00
*/
template < size_t N , bool S , simstr : : Allocatorable A >
inline std : : ostream & operator < < ( std : : ostream & stream , const lstring < u8s , N , S , A > & text ) {
return stream < < std : : string_view { text . symbols ( ) , text . length ( ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р в ы в о д а в п о т о к lstring .
* @ param stream - п о т о к в ы в о д а .
* @ param text - т е к с т .
* @ return std : : ostream & .
* @ en @ brief Operator to output lstring to stream .
* @ param stream - output stream .
* @ param text - text .
* @ return std : : ostream & .
2025-04-05 14:21:11 +00:00
*/
template < size_t N , bool S , simstr : : Allocatorable A >
inline std : : wostream & operator < < ( std : : wostream & stream , const lstring < uws , N , S , A > & text ) {
return stream < < std : : wstring_view { text . symbols ( ) , text . length ( ) } ;
}
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief О п е р а т о р в ы в о д а в п о т о к lstring .
* @ param stream - п о т о к в ы в о д а .
* @ param text - т е к с т .
* @ return std : : ostream & .
* @ en @ brief Operator to output lstring to stream .
* @ param stream - output stream .
* @ param text - text .
* @ return std : : ostream & .
2025-04-05 14:21:11 +00:00
*/
template < size_t N , bool S , simstr : : Allocatorable A >
inline std : : wostream & operator < < ( std : : wostream & stream , const lstring < wchar_type , N , S , A > & text ) {
return stream < < std : : wstring_view { from_w ( text . symbols ( ) ) , text . length ( ) } ;
}
} // namespace simstr
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а simple_str .
* @ en @ brief Formatter to use in std : : format for values of type simple_str .
2025-04-05 14:21:11 +00:00
*/
template < typename K >
struct std : : formatter < simstr : : simple_str < K > , K > : std : : formatter < std : : basic_string_view < K > , K > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( simstr : : simple_str < K > t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < K > , K > : : format ( { t . str , t . len } , fc ) ;
}
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а simple_str_nt .
* @ en @ brief Formatter to use in std : : format for values of type simple_str_nt .
2025-04-05 14:21:11 +00:00
*/
template < typename K >
struct std : : formatter < simstr : : simple_str_nt < K > , K > : std : : formatter < std : : basic_string_view < K > , K > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( simstr : : simple_str_nt < K > t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < K > , K > : : format ( { t . str , t . len } , fc ) ;
}
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а sstring .
* @ en @ brief Formatter to use in std : : format for values of type string .
2025-04-05 14:21:11 +00:00
*/
template < typename K >
struct std : : formatter < simstr : : sstring < K > , K > : std : : formatter < std : : basic_string_view < K > , K > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( const simstr : : sstring < K > & t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < K > , K > : : format ( { t . symbols ( ) , t . length ( ) } , fc ) ;
}
} ;
/*!
2025-11-17 09:01:31 +00:00
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а lstring .
* @ en @ brief Formatter to use in std : : format for values of type lstring .
2025-04-05 14:21:11 +00:00
*/
template < typename K , size_t N , bool S , typename A >
struct std : : formatter < simstr : : lstring < K , N , S , A > , K > : std : : formatter < std : : basic_string_view < K > , K > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( const simstr : : lstring < K , N , S , A > & t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < K > , K > : : format ( { t . symbols ( ) , t . length ( ) } , fc ) ;
}
} ;
2026-01-21 11:59:17 +00:00
/*!
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а simple_str < char8_t > .
* @ en @ brief Formatter to use in std : : format for values of type simple_str < char8_t > .
*/
template < >
struct std : : formatter < simstr : : simple_str < char8_t > , char > : std : : formatter < std : : basic_string_view < char > , char > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( simstr : : simple_str < char8_t > t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < char > , char > : : format ( { ( const char * ) t . str , t . len } , fc ) ;
}
} ;
/*!
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а simple_str_nt < char8_t > .
* @ en @ brief Formatter to use in std : : format for values of type simple_str_nt < char8_t > .
*/
template < >
struct std : : formatter < simstr : : simple_str_nt < char8_t > , char > : std : : formatter < std : : basic_string_view < char > , char > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( simstr : : simple_str_nt < char8_t > t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < char > , char > : : format ( { ( const char * ) t . str , t . len } , fc ) ;
}
} ;
/*!
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а sstring < char8_t > .
* @ en @ brief Formatter to use in std : : format for values of type string < char8_t > .
*/
template < >
struct std : : formatter < simstr : : sstring < char8_t > , char > : std : : formatter < std : : basic_string_view < char > , char > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( const simstr : : sstring < char8_t > & t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < char > , char > : : format ( { ( const char * ) t . symbols ( ) , t . length ( ) } , fc ) ;
}
} ;
/*!
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а lstring < char8_t > .
* @ en @ brief Formatter to use in std : : format for values of type lstring < char8_t > .
*/
template < size_t N , bool S , typename A >
struct std : : formatter < simstr : : lstring < char8_t , N , S , A > , char > : std : : formatter < std : : basic_string_view < char > , char > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( const simstr : : lstring < char8_t , N , S , A > & t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < char > , char > : : format ( { ( const char * ) t . symbols ( ) , t . length ( ) } , fc ) ;
}
} ;
/*!
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а simple_str < char16_t / char32_t > .
* @ en @ brief Formatter to use in std : : format for values of type simple_str < char16_t / char32_t > .
*/
template < >
struct std : : formatter < simstr : : simple_str < simstr : : wchar_type > , wchar_t > : std : : formatter < std : : basic_string_view < wchar_t > , wchar_t > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( simstr : : simple_str < simstr : : wchar_type > t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < wchar_t > , wchar_t > : : format ( { ( const wchar_t * ) t . str , t . len } , fc ) ;
}
} ;
/*!
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а simple_str_nt < char16_t / char32_t > .
* @ en @ brief Formatter to use in std : : format for values of type simple_str_nt < char16_t / char32_t > .
*/
template < >
struct std : : formatter < simstr : : simple_str_nt < simstr : : wchar_type > , wchar_t > : std : : formatter < std : : basic_string_view < wchar_t > , wchar_t > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( simstr : : simple_str_nt < simstr : : wchar_type > t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < wchar_t > , wchar_t > : : format ( { ( const wchar_t * ) t . str , t . len } , fc ) ;
}
} ;
/*!
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а sstring < char16_t / char32_t > .
* @ en @ brief Formatter to use in std : : format for values of type string < char16_t / char32_t > .
*/
template < >
struct std : : formatter < simstr : : sstring < simstr : : wchar_type > , wchar_t > : std : : formatter < std : : basic_string_view < wchar_t > , wchar_t > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( const simstr : : sstring < simstr : : wchar_type > & t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < wchar_t > , wchar_t > : : format ( { ( const wchar_t * ) t . symbols ( ) , t . length ( ) } , fc ) ;
}
} ;
/*!
* @ ru @ brief Ф о р м а т т е р д л я и с п о л ь з о в а н и я в std : : format з н а ч е н и й т и п а lstring < char16_t / char32_t > .
* @ en @ brief Formatter to use in std : : format for values of type lstring < char16_t / char32_t > .
*/
template < size_t N , bool S , typename A >
struct std : : formatter < simstr : : lstring < simstr : : wchar_type , N , S , A > , wchar_t > : std : : formatter < std : : basic_string_view < wchar_t > , wchar_t > {
// Define format() by calling the base class implementation with the wrapped value
template < typename FormatContext >
auto format ( const simstr : : lstring < simstr : : wchar_type , N , S , A > & t , FormatContext & fc ) const {
return std : : formatter < std : : basic_string_view < wchar_t > , wchar_t > : : format ( { ( const wchar_t * ) t . symbols ( ) , t . length ( ) } , fc ) ;
}
} ;