21#define ARG1 (*(args+1))
22#define ARG2 (*(args+2))
23#define BOL(box) (box).Unbox<bool >()
24#define INT(box) (box).Unbox<integer>()
25#define FLT(box) (box).Unbox<double >()
26#define STR(box) (box).Unbox<String >()
27#define LEN(box) (box).UnboxLength()
28#define STR1K(str) String1K(STR(str))
29#define ALLOCS(str) String(scope.Allocator, str)
31#define FUNC( name,...) Box name( Scope& scope, \
34 { (void) scope; (void) args; (void) end; __VA_ARGS__ }
35#if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
36# define TOINT(arg) arg
38# define TOINT(arg) static_cast<integer>(arg)
42namespace alib {
namespace expressions {
namespace plugins {
50 tmp.DbgDisableBufferReplacementWarning();
54 if( arg.IsType<
integer>() ) tmp <<
Format( INT(arg), &scope.Formatter->DefaultNumberFormat);
55 else if( arg.IsType<
double >() ) tmp <<
Format( FLT(arg), &scope.Formatter->DefaultNumberFormat);
61 return String(scope.Allocator, tmp);
70 buf.DbgDisableBufferReplacementWarning();
72 BoxesMA& formatterArgs= scope.Formatter->GetArgContainer();
74 formatterArgs.
Add( *args++ );
78 scope.Formatter->FormatArgs( buf );
85 return String( scope.Allocator, buf );
102FUNC(toUpper ,
return ALLOCS(STR1K(ARG0).
ToUpper()); )
103FUNC(toLower ,
return ALLOCS(STR1K(ARG0).
ToLower()); )
104FUNC(startsWith ,
return STR(ARG0).StartsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
105FUNC(startsWithC,
return BOL(ARG2) ? STR(ARG0).StartsWith<CHK,lang::Case::Ignore >( STR(ARG1) )
106 : STR(ARG0).StartsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
107FUNC(endsWith ,
return STR(ARG0). EndsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
108FUNC(endsWithC ,
return BOL(ARG2) ? STR(ARG0). EndsWith<CHK,lang::Case::Ignore >( STR(ARG1) )
109 : STR(ARG0). EndsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
110FUNC(substr ,
return STR(ARG0).
Substring( INT(ARG1) ); )
111FUNC(substr2 ,
return STR(ARG0).
Substring( INT(ARG1), INT(ARG2) ); )
112FUNC(idxof ,
String needle= STR(ARG1);
return needle.
Length() == 1 ? STR(ARG0).IndexOf ( needle[0], 0 )
113 : STR(ARG0).IndexOf( needle , 0 ); )
114FUNC(count ,
String needle= STR(ARG1);
return needle.
Length() == 1 ? STR(ARG0).CountChar ( needle[0] )
115 : STR(ARG0).Count ( needle , 0 ); )
117FUNC(trim ,
return Substring(STR(ARG0)).Trim ( ); )
119FUNC(trimStart ,
return Substring(STR(ARG0)).TrimStart( ); )
121FUNC(trimEnd ,
return Substring(STR(ARG0)).TrimEnd ( ); )
124FUNC(parsei ,
integer result;
Substring(STR(ARG0)).
ConsumeInt (result, &scope.Formatter->DefaultNumberFormat);
return result; )
125FUNC(parsef ,
double result;
Substring(STR(ARG0)).
ConsumeFloat(result, &scope.Formatter->DefaultNumberFormat);
return result; )
127FUNC(token ,
Tokenizer tknzr( STR(ARG0), STR(ARG1).CharAtStart() );
128 for(
auto i= INT(ARG2) ; i >= 0 ; --i )
130 return tknzr.Actual; )
133 buf << Format::Hex( static_cast<uint64_t>(INT(ARG0)),
134 args + 1 != end ?
static_cast<int>(INT(ARG1)) : 0,
136 return ALLOCS(buf); )
138 buf << Format::Oct( static_cast<uint64_t>(INT(ARG0)),
139 args + 1 != end ?
static_cast<int>(INT(ARG1)) : 0,
141 return ALLOCS(buf); )
143 buf << Format::Bin( static_cast<uint64_t>(INT(ARG0)),
144 args + 1 != end ?
static_cast<int>(INT(ARG1)) : 0,
146 return ALLOCS(buf); )
152 String needle = STR(ARG1);
153 String replacement= STR(ARG2);
156 if( needle.Length() == 1 && replacement.Length() == 1 )
159 result.SearchAndReplace( needle[0], replacement[0], 0 );
160 return ALLOCS(result);
165 buf.DbgDisableBufferReplacementWarning();
167 buf.SearchAndReplace( needle, replacement, 0 );
175 buf.DbgDisableBufferReplacementWarning();
176 for(
auto i= INT(ARG1) ; i > 0 ; --i )
184FUNC(boolNot,
return LEN(ARG0) == 0; )
191FUNC(add_SI,
return ALLOCS(STR1K(ARG0) <<
Format( INT(ARG1), &scope.Formatter->DefaultNumberFormat )); )
192FUNC(add_SF, return ALLOCS(STR1K(ARG0) <<
Format( FLT(ARG1), &scope.
Formatter->DefaultNumberFormat )); )
195FUNC(add_IS, return ALLOCS(
String1K() <<
Format( INT(ARG0), &scope.
Formatter->DefaultNumberFormat) << STR(ARG1)); )
196FUNC(add_FS, return ALLOCS(
String1K() <<
Format( FLT(ARG0), &scope.
Formatter->DefaultNumberFormat) << STR(ARG1)); )
197FUNC(add_SS, return ALLOCS(
String1K(STR(ARG0)) << STR(ARG1)); )
198FUNC(add_SX, return ALLOCS(
String1K(STR(ARG0)) << ARG1); )
199FUNC(add_XS, return ALLOCS(
String1K( ARG0) << STR(ARG1)); )
202FUNC( sm, return STR(ARG0) < ( STR(ARG1) ); )
203FUNC( smEq, return STR(ARG0) <= ( STR(ARG1) ); )
204FUNC( gt, return STR(ARG0) > ( STR(ARG1) ); )
205FUNC( gtEq, return STR(ARG0) >= ( STR(ARG1) ); )
206FUNC( eq, return STR(ARG0).
Equals( STR(ARG1) ); )
207FUNC( neq, return !STR(ARG0).
Equals( STR(ARG1) ); )
209FUNC( arr, return STR(ARG0).
Substring( INT(ARG1), 1); )
211FUNC( compSS, return TOINT( STR(ARG0).CompareTo<CHK
ALIB_COMMA lang::Case::Sensitive>( STR(ARG1) ) ); )
212FUNC(compSSB, return TOINT( BOL(ARG2) ? STR(ARG0).CompareTo<CHK
ALIB_COMMA lang::Case::Ignore >( STR(ARG1) )
213 : STR(ARG0).CompareTo<CHK
ALIB_COMMA lang::Case::Sensitive>( STR(ARG1) ) ); )
218DOX_MARKER([DOX_EXPR_CTRES_1])
219struct ScopeWildcardMatcher : public ScopeResource
225 virtual ~ScopeWildcardMatcher()
override {}
227DOX_MARKER([DOX_EXPR_CTRES_1])
229DOX_MARKER([DOX_EXPR_CTRES_6])
232 String haystack= STR(ARG0);
233 String pattern = STR(ARG1);
237 if( !scope.IsCompileTime() )
241 keyString.DbgDisableBufferReplacementWarning();
242 keyString << pattern;
243 auto storedMatcher= scope.vmMembers->CTScope->NamedResources->Find( keyString );
244 if( storedMatcher != scope.vmMembers->CTScope->NamedResources->end() )
245 return dynamic_cast<ScopeWildcardMatcher*
>( storedMatcher.Mapped() )
246 ->matcher.Match( haystack, sensitivity );
248DOX_MARKER([DOX_EXPR_CTRES_6])
250DOX_MARKER([DOX_EXPR_CTRES_7])
255 return matcher.Match( haystack, sensitivity );
258DOX_MARKER([DOX_EXPR_CTRES_7])
263#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
264struct ScopeRegexMatcher :
public ScopeResource
270 virtual ~ScopeRegexMatcher()
override {}
275 String haystack= STR(ARG0);
276 String pattern = STR(ARG1);
278 if( !scope.IsCompileTime() )
282 keyString.DbgDisableBufferReplacementWarning();
283 keyString << pattern;
284 auto storedMatcher= scope.vmMembers->CTScope->NamedResources->Find( keyString );
285 if( storedMatcher != scope.vmMembers->CTScope->NamedResources->end() )
287 ScopeRegexMatcher* matcher=
dynamic_cast<ScopeRegexMatcher*
>( storedMatcher->second );
288 return matcher->matcher.Match( haystack );
295 return matcher.Match( haystack );
323 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
341 AddOperators( operatorTableStrings );
344 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
345 constexpr int tableSize= 25;
347 constexpr int tableSize= 24;
350 Token functionNames[tableSize];
351 Token::LoadResourcedTokens( EXPRESSIONS,
"CPS", functionNames
354 Token* descriptor= functionNames;
359 { *descriptor++, constNL },
360 { *descriptor++, constTAB },
399 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
405 "Descriptor table size mismatch: Consumed {} descriptors, {} available.",
406 descriptor - functionNames, tableSize )
411bool genericConcatenation( Type type )
415 || type.IsType<
double >()
416 || type.IsType<
String >() );
421DOX_MARKER([DOX_EXPR_CTRES_2])
422bool Strings::TryCompilation( CIFunction& ciFunction )
425 if( !Calculus::TryCompilation( ciFunction ) )
427DOX_MARKER([DOX_EXPR_CTRES_2])
429#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
430 if( ciFunction.Callback == regex && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
432 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
434 keyString.DbgDisableBufferReplacementWarning();
435 keyString << pattern;
436 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources->Find( keyString );
437 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources->end() )
439 auto& alloc= ciFunction.CompileTimeScope.Allocator;
440 ScopeRegexMatcher* matcher= alloc().New<ScopeRegexMatcher>();
441 matcher->matcher.Compile( pattern );
442 ciFunction.CompileTimeScope.NamedResources->EmplaceOrAssign(
449DOX_MARKER([DOX_EXPR_CTRES_3])
450 if( ciFunction.Callback == wldcrd && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
452DOX_MARKER([DOX_EXPR_CTRES_3])
453DOX_MARKER([DOX_EXPR_CTRES_4])
454 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
456 keyString.DbgDisableBufferReplacementWarning();
457 keyString << pattern;
458DOX_MARKER([DOX_EXPR_CTRES_4])
459DOX_MARKER([DOX_EXPR_CTRES_5])
460 auto hashCode = keyString.Hashcode();
461 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources->Find( keyString, hashCode );
462 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources->end() )
464 auto& alloc= ciFunction.CompileTimeScope.Allocator;
465 ScopeWildcardMatcher* matcher= alloc().New<ScopeWildcardMatcher>();
466 matcher->matcher.Compile( pattern );
467 NString keyCopy( ciFunction.CompileTimeScope.Allocator, keyString );
468 ciFunction.CompileTimeScope.NamedResources->InsertUnique( std::make_pair(keyCopy, matcher),
473DOX_MARKER([DOX_EXPR_CTRES_5])
477bool Strings::TryCompilation( CIBinaryOp& ciBinaryOp )
479 Box& lhs= * ciBinaryOp.ArgsBegin;
480 Box& rhs= *(ciBinaryOp.ArgsBegin + 1);
483 if( ciBinaryOp.Operator ==
A_CHAR(
"+") )
485 bool argsAreConst= ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst;
487 if( lhs.IsType<String>() && genericConcatenation(rhs) )
492 ciBinaryOp.TypeOrValue = add_SX( ciBinaryOp.CompileTimeScope,
493 ciBinaryOp.ArgsBegin,
494 ciBinaryOp.ArgsEnd );
495 ALIB_DBG( ciBinaryOp.DbgCallbackName =
"add_SX"; )
499 ciBinaryOp.Callback = add_SX;
500 ciBinaryOp.TypeOrValue = Types::String;
504 if( genericConcatenation(lhs) && rhs.IsType<String>() )
508 ciBinaryOp.TypeOrValue = add_XS( ciBinaryOp.CompileTimeScope,
509 ciBinaryOp.ArgsBegin,
510 ciBinaryOp.ArgsEnd );
511 ALIB_DBG( ciBinaryOp.DbgCallbackName =
"add_XS"; )
515 ciBinaryOp.Callback = add_XS;
516 ciBinaryOp.TypeOrValue = Types::String;
522 if( !Calculus::TryCompilation( ciBinaryOp ) )
527#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
528 if( ciBinaryOp.Operator ==
A_CHAR(
"%") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
530 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
531 NString128 keyString(A_CHAR(
"_re"));
532 keyString.DbgDisableBufferReplacementWarning();
533 keyString << pattern;
534 auto hashCode = keyString.Hashcode();
536 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources->Find( keyString, hashCode );
537 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources->end() )
539 auto& alloc= ciBinaryOp.CompileTimeScope.Allocator;
540 ScopeRegexMatcher* matcher= alloc().New<ScopeRegexMatcher>();
541 matcher->matcher.Compile( pattern );
542 ciBinaryOp.CompileTimeScope.NamedResources->InsertOrAssign(
543 NString(alloc, keyString ),
551 if( ciBinaryOp.Operator ==
A_CHAR(
"*") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
553 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
554 NString128 keyString(A_CHAR(
"_wc"));
555 keyString.DbgDisableBufferReplacementWarning();
556 keyString << pattern;
557 auto hashCode = keyString.Hashcode();
559 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources->Find( keyString, hashCode );
560 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources->end() )
562 auto& alloc= ciBinaryOp.CompileTimeScope.Allocator;
563 ScopeWildcardMatcher* matcher= alloc().New<ScopeWildcardMatcher>();
564 matcher->matcher.Compile( pattern );
566 NString keyCopy(alloc, keyString);
567 ciBinaryOp.CompileTimeScope.NamedResources->InsertUnique( std::make_pair(keyCopy, matcher),
588#undef BIN_ALIAS_ENTRY
constexpr integer Length() const
TSubstring & TrimEnd(const TCString< TChar > &whiteSpaces=TT_CStringConstants< TChar >::DefaultWhitespaces())
ALIB_API bool ConsumeFloat(double &result, TNumberFormat< TChar > *numberFormat=nullptr)
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=TT_CStringConstants< TChar >::DefaultWhitespaces())
bool ConsumeInt(TIntegral &result, TNumberFormat< TChar > *numberFormat=nullptr)
TSubstring & Trim(const TCString< TChar > &whiteSpaces=TT_CStringConstants< 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
ALIB_API Box CBFormat(Scope &scope, ArgIterator args, ArgIterator)
ALIB_API Box CBToString(Scope &scope, ArgIterator args, ArgIterator)
StdVectorMono< Box >::iterator ArgIterator
@ Equals
Verbal alias "Equals" to operator '=='.
@ Strings
Built-in String comparison and manipulation.
platform_specific integer
@ Keep
Keep whitespaces in string.
Case
Denotes upper and lower case character treatment.
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.
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.
boxing::TBoxes< MonoAllocator > BoxesMA
Type alias in namespace alib.
strings::TString< nchar > NString
Type alias in namespace alib.
strings::TSubstring< character > Substring
Type alias in namespace alib.
LocalString< 2048 > String2K
Type alias name for TLocalString<character,2048>.
constexpr CString NEW_LINE
A zero-terminated string containing the new-line character sequence.
strings::TFormat< character > Format
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.
LocalString< 1024 > String1K
Type alias name for TLocalString<character,1024>.
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 Void
Sample type-box for C++ type void.
static ALIB_API Box Integer
Sample type-box for integer types. (Precisely for type integer.)
static ALIB_API Box Boolean
Sample type-box for C++ type bool.
static ALIB_API Box String
static ALIB_API Box Float
Sample type-box for C++ type double.
const std::tuple< String, Type, Type, CallbackDecl, Type, CTInvokable > OperatorTableEntry
static constexpr CTInvokable CTI
ALIB_API Strings(Compiler &compiler)