10# if !defined (HPP_ALIB_EXPRESSIONS_PLUGINS_STRINGS)
14# if !defined (HPP_ALIB_MONOMEM_MASTRING)
18# if !defined (HPP_ALIB_STRINGS_UTIL_WILDCARDMATCHER)
22# if !defined (HPP_ALIB_STRINGS_UTIL_REGEXMATCHER)
26# if !defined (HPP_ALIB_STRINGS_FORMAT)
29# if !defined (HPP_ALIB_STRINGS_UTIL_TOKENIZER)
38#define ARG1 (*(args+1))
39#define ARG2 (*(args+2))
40#define BOL(box) (box).Unbox<bool >()
41#define INT(box) (box).Unbox<integer>()
42#define FLT(box) (box).Unbox<double >()
43#define STR(box) (box).Unbox<String >()
44#define LEN(box) (box).UnboxLength()
45#define CPY(str,size) MAString( scope.Allocator, STR(str), size)
46#define WRT(box,size) MAString( scope.Allocator, box, size)
47#define EMP(size ) MAString( scope.Allocator, size)
49#define FUNC( name,...) Box name( Scope& scope, \
52 { (void) scope; (void) args; (void) end; __VA_ARGS__ }
53#if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
54# define TOINT(arg) arg
56# define TOINT(arg) static_cast<integer>(arg)
60namespace alib {
namespace expressions {
namespace plugins {
68 tmp.DbgDisableBufferReplacementWarning();
72 if( arg.IsType<
integer>() ) tmp <<
Format( INT(arg), &scope.Formatter->DefaultNumberFormat);
73 else if( arg.IsType<
double >() ) tmp <<
Format( FLT(arg), &scope.Formatter->DefaultNumberFormat);
79 return MAString( scope.Allocator, tmp, 0 );
88 buf.DbgDisableBufferReplacementWarning();
92 formatterArgs.
Add( *args++ );
96 scope.Formatter->FormatArgs( buf );
100 scope.Formatter->Release();
104 scope.Formatter->Release();
106 return MAString( scope.Allocator, buf, 0 );
123FUNC(toUpper ,
return CPY(ARG0, 0).ToUpper(); )
124FUNC(toLower ,
return CPY(ARG0, 0).ToLower(); )
125FUNC(startsWith ,
return STR(ARG0).StartsWith<true,lang::Case::Sensitive>( STR(ARG1) ); )
126FUNC(startsWithC,
return BOL(ARG2) ? STR(ARG0).StartsWith<true,lang::Case::Ignore >( STR(ARG1) )
127 : STR(ARG0).StartsWith<true,lang::
Case::
Sensitive>( STR(ARG1) ); )
128FUNC(endsWith ,
return STR(ARG0). EndsWith<true,lang::Case::Sensitive>( STR(ARG1) ); )
129FUNC(endsWithC ,
return BOL(ARG2) ? STR(ARG0). EndsWith<true,lang::Case::Ignore >( STR(ARG1) )
130 : STR(ARG0). EndsWith<true,lang::
Case::
Sensitive>( STR(ARG1) ); )
131FUNC(substr ,
return STR(ARG0).Substring( INT(ARG1) ); )
132FUNC(substr2 ,
return STR(ARG0).Substring( INT(ARG1), INT(ARG2) ); )
133FUNC(idxof ,
String needle= STR(ARG1);
return needle.Length() == 1 ? STR(ARG0).IndexOf ( needle[0], 0 )
134 : STR(ARG0).IndexOf( needle , 0 ); )
135FUNC(count ,
String needle= STR(ARG1);
return needle.Length() == 1 ? STR(ARG0).CountChar ( needle[0] )
136 : STR(ARG0).Count ( needle , 0 ); )
145FUNC(parsei ,
integer result;
Substring(STR(ARG0)).
ConsumeInt (result, &scope.Formatter->DefaultNumberFormat);
return result; )
146FUNC(parsef ,
double result;
Substring(STR(ARG0)).
ConsumeFloat(result, &scope.Formatter->DefaultNumberFormat);
return result; )
148FUNC(token ,
Tokenizer tknzr( STR(ARG0), STR(ARG1).CharAtStart() );
149 for(
auto i= INT(ARG2) ; i >= 0 ; --i )
151 return tknzr.Actual; )
154 buf << Format::Hex( static_cast<uint64_t>(INT(ARG0)),
155 args + 1 != end ?
static_cast<int>(INT(ARG1)) : 0,
157 return MAString(scope.Allocator, buf,0); )
159 buf << Format::Oct( static_cast<uint64_t>(INT(ARG0)),
160 args + 1 != end ?
static_cast<int>(INT(ARG1)) : 0,
162 return MAString(scope.Allocator, buf,0); )
164 buf << Format::Bin( static_cast<uint64_t>(INT(ARG0)),
165 args + 1 != end ?
static_cast<int>(INT(ARG1)) : 0,
167 return MAString(scope.Allocator, buf,0); )
173 String needle = STR(ARG1);
174 String replacement= STR(ARG2);
177 if( needle.Length() == 1 && replacement.Length() == 1 )
179 MAString result(scope.Allocator, src, 0 );
180 result.SearchAndReplace( needle[0], replacement[0], 0 );
186 buf.DbgDisableBufferReplacementWarning();
188 buf.SearchAndReplace( needle, replacement, 0 );
189 return MAString( scope.Allocator, buf, 0 );
196 buf.DbgDisableBufferReplacementWarning();
197 for(
auto i= INT(ARG1) ; i > 0 ; --i )
199 return MAString( scope.Allocator, buf, 0 );
205FUNC(boolNot,
return LEN(ARG0) == 0; )
212FUNC(add_SI,
return CPY(ARG0, 28 ) <<
Format( INT(ARG1), &scope.Formatter->DefaultNumberFormat ); )
213FUNC(add_SF,
return CPY(ARG0, 48 ) <<
Format( FLT(ARG1), &scope.Formatter->DefaultNumberFormat ); )
216FUNC(add_IS,
return EMP(LEN(ARG1) + 28 ) <<
Format( INT(ARG0), &scope.Formatter->DefaultNumberFormat) << STR(ARG1); )
217FUNC(add_FS,
return EMP(LEN(ARG1) + 48 ) <<
Format( FLT(ARG0), &scope.Formatter->DefaultNumberFormat) << STR(ARG1); )
218FUNC(add_SS,
return CPY(ARG0, LEN(ARG1)) << STR(ARG1); )
221 tmp.DbgDisableBufferReplacementWarning();
223 return CPY(ARG0, tmp.Length() ) << tmp;
226FUNC(add_XS,
return WRT( ARG0, ARG1.UnboxLength() ) << ARG1; )
229FUNC( sm,
return STR(ARG0) < ( STR(ARG1) ); )
230FUNC( smEq,
return STR(ARG0) <= ( STR(ARG1) ); )
231FUNC( gt,
return STR(ARG0) > ( STR(ARG1) ); )
232FUNC( gtEq,
return STR(ARG0) >= ( STR(ARG1) ); )
233FUNC( eq,
return STR(ARG0).Equals( STR(ARG1) ); )
234FUNC( neq,
return !STR(ARG0).Equals( STR(ARG1) ); )
236FUNC( arr,
return STR(ARG0).Substring( INT(ARG1), 1); )
239FUNC(compSSB,
return TOINT( BOL(ARG2) ? STR(ARG0).CompareTo<true ALIB_COMMA lang::Case::Ignore >( STR(ARG1) )
245DOX_MARKER([DOX_ALIB_EXPR_CTRES_1])
246struct ScopeWildcardMatcher :
public ScopeResource
252 virtual ~ScopeWildcardMatcher()
override {}
254DOX_MARKER([DOX_ALIB_EXPR_CTRES_1])
256DOX_MARKER([DOX_ALIB_EXPR_CTRES_6])
259 String haystack= STR(ARG0);
260 String pattern = STR(ARG1);
264 if( !scope.IsCompileTime() )
268 keyString.DbgDisableBufferReplacementWarning();
269 keyString << pattern;
270 auto storedMatcher= scope.CTScope->NamedResources.Find( keyString );
271 if( storedMatcher != scope.CTScope->NamedResources.end() )
272 return dynamic_cast<ScopeWildcardMatcher*
>( storedMatcher.Mapped() )
273 ->matcher.Match( haystack, sensitivity );
275DOX_MARKER([DOX_ALIB_EXPR_CTRES_6])
277DOX_MARKER([DOX_ALIB_EXPR_CTRES_7])
281 return matcher.Match( haystack, sensitivity );
284DOX_MARKER([DOX_ALIB_EXPR_CTRES_7])
289#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
290struct ScopeRegexMatcher :
public ScopeResource
296 virtual ~ScopeRegexMatcher()
override {}
301 String haystack= STR(ARG0);
302 String pattern = STR(ARG1);
304 if( !scope.IsCompileTime() )
308 keyString.DbgDisableBufferReplacementWarning();
309 keyString << pattern;
310 auto storedMatcher= scope.CTScope->NamedResources.Find( keyString );
311 if( storedMatcher != scope.CTScope->NamedResources.end() )
313 ScopeRegexMatcher* matcher=
dynamic_cast<ScopeRegexMatcher*
>( storedMatcher->second );
314 return matcher->matcher.Match( haystack );
321 return matcher.Match( haystack );
349 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
362:
Calculus(
"ALib Strings", compiler )
367 AddOperators( operatorTableStrings );
370 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
371 constexpr int tableSize= 25;
373 constexpr int tableSize= 24;
376 Token functionNames[tableSize];
377 Token::LoadResourcedTokens( EXPRESSIONS,
"CPS", functionNames
380 Token* descriptor= functionNames;
385 { *descriptor++, constNL },
386 { *descriptor++, constTAB },
425 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
431 "Descriptor table size mismatch: Consumed {} descriptors, {} available.",
432 descriptor - functionNames, tableSize )
437bool genericConcatenation( Type type )
441 || type.IsType<
double >()
442 || type.IsType<
String >() );
447DOX_MARKER([DOX_ALIB_EXPR_CTRES_2])
448bool Strings::TryCompilation( CIFunction& ciFunction )
451 if( !Calculus::TryCompilation( ciFunction ) )
453DOX_MARKER([DOX_ALIB_EXPR_CTRES_2])
455#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
456 if( ciFunction.Callback == regex && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
458 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
460 keyString.DbgDisableBufferReplacementWarning();
461 keyString << pattern;
462 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources.Find( keyString );
463 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources.end() )
465 ScopeRegexMatcher* matcher=
new ScopeRegexMatcher();
466 matcher->matcher.Compile( pattern );
467 ciFunction.CompileTimeScope.NamedResources.EmplaceOrAssign(
468 NMAString( ciFunction.CompileTimeScope.Allocator, keyString, 0 ),
474DOX_MARKER([DOX_ALIB_EXPR_CTRES_3])
475 if( ciFunction.Callback == wldcrd && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
477DOX_MARKER([DOX_ALIB_EXPR_CTRES_3])
478DOX_MARKER([DOX_ALIB_EXPR_CTRES_4])
479 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
481 keyString.DbgDisableBufferReplacementWarning();
482 keyString << pattern;
483DOX_MARKER([DOX_ALIB_EXPR_CTRES_4])
484DOX_MARKER([DOX_ALIB_EXPR_CTRES_5])
485 auto hashCode = keyString.Hashcode();
486 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources.Find( keyString, hashCode );
487 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources.end() )
489 ScopeWildcardMatcher* matcher=
new ScopeWildcardMatcher();
490 matcher->matcher.Compile( pattern );
491 NString keyCopy= ciFunction.CompileTimeScope.Allocator.EmplaceString( keyString );
492 ciFunction.CompileTimeScope.NamedResources.InsertUnique( std::make_pair(keyCopy, matcher),
497DOX_MARKER([DOX_ALIB_EXPR_CTRES_5])
501bool Strings::TryCompilation( CIBinaryOp& ciBinaryOp )
503 Box& lhs= * ciBinaryOp.ArgsBegin;
504 Box& rhs= *(ciBinaryOp.ArgsBegin + 1);
507 if( ciBinaryOp.Operator ==
A_CHAR(
"+") )
509 bool argsAreConst= ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst;
511 if( lhs.IsType<String>() && genericConcatenation(rhs) )
516 ciBinaryOp.TypeOrValue = add_SX( ciBinaryOp.CompileTimeScope,
517 ciBinaryOp.ArgsBegin,
518 ciBinaryOp.ArgsEnd );
519 ALIB_DBG( ciBinaryOp.DbgCallbackName =
"add_SX"; )
523 ciBinaryOp.Callback = add_SX;
524 ciBinaryOp.TypeOrValue = Types::String;
528 if( genericConcatenation(lhs) && rhs.IsType<
String>() )
532 ciBinaryOp.TypeOrValue = add_XS( ciBinaryOp.CompileTimeScope,
533 ciBinaryOp.ArgsBegin,
534 ciBinaryOp.ArgsEnd );
535 ALIB_DBG( ciBinaryOp.DbgCallbackName =
"add_XS"; )
539 ciBinaryOp.Callback = add_XS;
540 ciBinaryOp.TypeOrValue = Types::String;
546 if( !Calculus::TryCompilation( ciBinaryOp ) )
551#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
552 if( ciBinaryOp.Operator ==
A_CHAR(
"%") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
554 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
556 keyString.DbgDisableBufferReplacementWarning();
557 keyString << pattern;
558 auto hashCode = keyString.Hashcode();
560 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources.Find( keyString, hashCode );
561 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources.end() )
563 ScopeRegexMatcher* matcher=
new ScopeRegexMatcher();
564 matcher->matcher.Compile( pattern );
565 ciBinaryOp.CompileTimeScope.NamedResources.InsertOrAssign(
566 NMAString( ciBinaryOp.CompileTimeScope.Allocator, keyString, 0 ),
574 if( ciBinaryOp.Operator ==
A_CHAR(
"*") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
576 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
578 keyString.DbgDisableBufferReplacementWarning();
579 keyString << pattern;
580 auto hashCode = keyString.Hashcode();
582 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources.Find( keyString, hashCode );
583 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources.end() )
585 ScopeWildcardMatcher* matcher=
new ScopeWildcardMatcher();
586 matcher->matcher.Compile( pattern );
588 NString keyCopy= ciBinaryOp.CompileTimeScope.Allocator.EmplaceString( keyString );
589 ciBinaryOp.CompileTimeScope.NamedResources.InsertUnique( std::make_pair(keyCopy, matcher),
610#undef BIN_ALIAS_ENTRY
TSubstring & Trim(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
TSubstring & TrimEnd(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
ALIB_API bool ConsumeFloat(double &result, TNumberFormat< TChar > *numberFormat=nullptr)
bool ConsumeInt(TIntegral &result, TNumberFormat< TChar > *numberFormat=nullptr)
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
#define ALIB_WARNINGS_RESTORE
#define CALCULUS_CALLBACK(func)
#define CALCULUS_SIGNATURE(BoxPointerArray)
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
#define ALIB_CALLER_PRUNED
ALIB_API Box CBFormat(Scope &scope, ArgIterator args, ArgIterator)
ALIB_API Box CBToString(Scope &scope, ArgIterator args, ArgIterator)
std::vector< Box >::iterator ArgIterator
platform_specific integer
@ Keep
Keep whitespaces in string.
expressions::plugins::Calculus Calculus
Type alias in namespace alib.
NLocalString< 128 > NString128
Type alias name for TLocalString<nchar,128> .
lang::Exception Exception
Type alias in namespace alib.
constexpr CString NewLine()
strings::util::TWildcardMatcher< character > WildcardMatcher
Type alias in namespace alib.
strings::util::TTokenizer< character > Tokenizer
Type alias in namespace alib.
lox::Scope Scope
Type alias in namespace alib.
strings::TString< nchar > NString
Type alias in namespace alib.
strings::TSubstring< character > Substring
Type alias in namespace alib.
monomem::TMAString< nchar > NMAString
Type alias in namespace alib.
strings::TFormat< character > Format
Type alias in namespace alib.
boxing::Boxes Boxes
Type alias in namespace alib.
LocalString< 256 > String256
Type alias name for TLocalString<character,256> .
strings::util::Token Token
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
monomem::TMAString< character > MAString
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
expressions::Compiler Compiler
Type alias in namespace alib.
lang::format::Formatter Formatter
Type alias in namespace alib.
LocalString< 128 > String128
Type alias name for TLocalString<character,128> .
strings::util::RegexMatcher RegexMatcher
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
static ALIB_API Box Integer
static ALIB_API Box Boolean
static ALIB_API Box String
static ALIB_API Box Float
const std::tuple< String, Type, Type, CallbackDecl, Type, CTInvokable > OperatorTableEntry
static constexpr CTInvokable CTI
ALIB_API Strings(Compiler &compiler)