ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
strings.cpp
1//##################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6//##################################################################################################
7#include "alib_precompile.hpp"
8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
10#endif
11#if ALIB_C20_MODULES
12 module;
13#endif
14//========================================= Global Fragment ========================================
17
18//============================================== Module ============================================
19#if ALIB_C20_MODULES
20 module ALib.Expressions.Impl;
21 import ALib.Characters.Functions;
22 import ALib.Strings;
23 import ALib.Strings.Search;
24 import ALib.Strings.Tokenizer;
25#else
27# include "ALib.Strings.H"
28# include "ALib.Strings.Search.H"
31#endif
32//========================================== Implementation ========================================
33//! @cond NO_DOX
34
35#define ARG0 (*args)
36#define ARG1 (*(args+1))
37#define ARG2 (*(args+2))
38#define BOL(box) (box).Unbox<bool >()
39#define INT(box) (box).Unbox<integer>()
40#define FLT(box) (box).Unbox<double >()
41#define STR(box) (box).Unbox<String >()
42#define LEN(box) (box).UnboxLength()
43#define STR1K(str) String1K(STR(str))
44#define ALLOCS(str) String(scope.Allocator, str)
45
46#define FUNC( name,...) Box name( Scope& scope, \
47 ArgIterator args, \
48 ArgIterator end ) \
49 { (void) scope; (void) args; (void) end; __VA_ARGS__ }
50#if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
51# define TOINT(arg) arg
52#else
53# define TOINT(arg) integer(arg)
54#endif
55
56
57namespace alib { namespace expressions { namespace plugins {
58
59//##################################################################################################
60// ### ToString (not in anonymous namespace)
61//##################################################################################################
62Box CBToString( Scope& scope, ArgIterator args, ArgIterator end) {
63 String256 tmp;
64 tmp.DbgDisableBufferReplacementWarning();
65 while( args < end ) {
66 Box& arg= *args;
67 if( arg.IsType<integer>() ) tmp << Dec( INT(arg), &scope.Formatter->DefaultNumberFormat);
68 else if( arg.IsType<double >() ) tmp << Dec( FLT(arg), &scope.Formatter->DefaultNumberFormat);
69 else tmp << arg;
70
71 ++args;
72 }
73
74 return String(scope.Allocator, tmp);
75}
76
77//##################################################################################################
78// ### Format (not in anonymous namespace)
79//##################################################################################################
80Box CBFormat( Scope& scope, ArgIterator args, ArgIterator end) {
81 String1K buf;
82 buf.DbgDisableBufferReplacementWarning();
83
84 BoxesMA& formatterArgs= scope.Formatter->GetArgContainer();
85 while( args != end)
86 formatterArgs.Add( *args++ );
87
88 try
89 {
90 scope.Formatter->FormatArgs( buf );
91 }
92 catch( Exception& )
93 {
94 throw;
95 }
96
97 return String( scope.Allocator, buf );
98}
99
100
101namespace {
102
103
104//##################################################################################################
105// ### String - constants
106//##################################################################################################
107Box constTAB;
108Box constNL;
109
110//##################################################################################################
111// ### String functions
112//##################################################################################################
113
114FUNC(toUpper , return ALLOCS(STR1K(ARG0).ToUpper()); )
115FUNC(toLower , return ALLOCS(STR1K(ARG0).ToLower()); )
116FUNC(startsWith , return STR(ARG0).StartsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
117FUNC(startsWithC, return BOL(ARG2) ? STR(ARG0).StartsWith<CHK,lang::Case::Ignore >( STR(ARG1) )
118 : STR(ARG0).StartsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
119FUNC(endsWith , return STR(ARG0). EndsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
120FUNC(endsWithC , return BOL(ARG2) ? STR(ARG0). EndsWith<CHK,lang::Case::Ignore >( STR(ARG1) )
121 : STR(ARG0). EndsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
122FUNC(substr , return STR(ARG0).Substring( INT(ARG1) ); )
123FUNC(substr2 , return STR(ARG0).Substring( INT(ARG1), INT(ARG2) ); )
124FUNC(idxof , String needle= STR(ARG1); return needle.Length() == 1 ? STR(ARG0).IndexOf ( needle[0], 0 )
125 : STR(ARG0).IndexOf( needle , 0 ); )
126FUNC(count , String needle= STR(ARG1); return needle.Length() == 1 ? STR(ARG0).CountChar ( needle[0] )
127 : STR(ARG0).Count ( needle , 0 ); )
128
129FUNC(trim , return Substring(STR(ARG0)).Trim ( ); )
130FUNC(trim2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).Trim (ws); )
131FUNC(trimStart , return Substring(STR(ARG0)).TrimStart( ); )
132FUNC(trimStart2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).TrimStart(ws); )
133FUNC(trimEnd , return Substring(STR(ARG0)).TrimEnd ( ); )
134FUNC(trimEnd2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).TrimEnd (ws); )
135
136FUNC(parsei , integer result; Substring(STR(ARG0)).ConsumeInt (result, &scope.Formatter->DefaultNumberFormat); return result; )
137FUNC(parsef , double result; Substring(STR(ARG0)).ConsumeFloat(result, &scope.Formatter->DefaultNumberFormat); return result; )
138
139FUNC(token , Tokenizer tknzr( STR(ARG0), STR(ARG1).CharAtStart() );
140 for( integer i= INT(ARG2) ; i >= 0 ; --i )
142 return tknzr.Actual; )
143
144FUNC(hex , String128 buf;
145 buf << Hex( uint64_t(INT(ARG0)),
146 args + 1 != end ? int(INT(ARG1)) : 0,
147 &scope.Formatter->DefaultNumberFormat );
148 return ALLOCS(buf); )
149FUNC(oct , String128 buf;
150 buf << Oct( uint64_t(INT(ARG0)),
151 args + 1 != end ? int(INT(ARG1)) : 0,
152 &scope.Formatter->DefaultNumberFormat );
153 return ALLOCS(buf); )
154FUNC(bin , String128 buf;
155 buf << Bin( uint64_t(INT(ARG0)),
156 args + 1 != end ? int(INT(ARG1)) : 0,
157 &scope.Formatter->DefaultNumberFormat );
158 return ALLOCS(buf); )
159
160
161Box replace( Scope& scope, ArgIterator args, ArgIterator ) {
162 String src = STR(ARG0);
163 String needle = STR(ARG1);
164 String replacement= STR(ARG2);
165
166 // replace char with char?
167 if( needle.Length() == 1 && replacement.Length() == 1 ) {
168 String2K result(src);
169 result.SearchAndReplace( needle[0], replacement[0], 0 );
170 return ALLOCS(result);
171 }
172
173 // replace string with char or string
174 String256 buf;
175 buf.DbgDisableBufferReplacementWarning();
176 buf << src;
177 buf.SearchAndReplace( needle, replacement, 0 );
178 return ALLOCS(buf);
179}
180
181Box repeat( Scope& scope, ArgIterator args, ArgIterator ) {
182 String src = STR(ARG0);
183 String256 buf;
184 buf.DbgDisableBufferReplacementWarning();
185 for( integer i= INT(ARG1) ; i > 0 ; --i )
186 buf << src;
187 return ALLOCS(buf);
188}
189
190//##################################################################################################
191// ### Strings - Unary operators
192//##################################################################################################
193FUNC(boolNot, return LEN(ARG0) == 0; )
194
195
196//##################################################################################################
197// ### Strings - Binary operators
198//##################################################################################################
199
200FUNC(add_SI, return ALLOCS(STR1K(ARG0) << Dec( INT(ARG1), &scope.Formatter->DefaultNumberFormat )); )
201FUNC(add_SF, return ALLOCS(STR1K(ARG0) << Dec( FLT(ARG1), &scope.Formatter->DefaultNumberFormat )); )
202
203
204FUNC(add_IS, return ALLOCS(String1K() << Dec( INT(ARG0), &scope.Formatter->DefaultNumberFormat) << STR(ARG1)); )
205FUNC(add_FS, return ALLOCS(String1K() << Dec( FLT(ARG0), &scope.Formatter->DefaultNumberFormat) << STR(ARG1)); )
206FUNC(add_SS, return ALLOCS(String1K(STR(ARG0)) << STR(ARG1)); )
207FUNC(add_SX, return ALLOCS(String1K(STR(ARG0)) << ARG1); )
208FUNC(add_XS, return ALLOCS(String1K( ARG0) << STR(ARG1)); )
209
210
211FUNC( sm, return STR(ARG0) < ( STR(ARG1) ); )
212FUNC( smEq, return STR(ARG0) <= ( STR(ARG1) ); )
213FUNC( gt, return STR(ARG0) > ( STR(ARG1) ); )
214FUNC( gtEq, return STR(ARG0) >= ( STR(ARG1) ); )
215FUNC( eq, return STR(ARG0).Equals( STR(ARG1) ); )
216FUNC( neq, return !STR(ARG0).Equals( STR(ARG1) ); )
217
218FUNC( arr, return STR(ARG0).Substring( INT(ARG1), 1); )
219
220FUNC( compSS, return TOINT( STR(ARG0).CompareTo<CHK ALIB_COMMA lang::Case::Sensitive>( STR(ARG1) ) ); )
221FUNC(compSSB, return TOINT( BOL(ARG2) ? STR(ARG0).CompareTo<CHK ALIB_COMMA lang::Case::Ignore >( STR(ARG1) )
222 : STR(ARG0).CompareTo<CHK ALIB_COMMA lang::Case::Sensitive>( STR(ARG1) ) ); )
223
224//##################################################################################################
225// ### Strings - Wildcard matching
226//##################################################################################################
227DOX_MARKER([DOX_EXPR_CTRES_1])
228struct ScopeWildcardMatcher : public ScopeResource
229{
230 // the matcher object
231 WildcardMatcher matcher;
232
233 // virtual destructor, implicitly deletes the matcher.
234 virtual ~ScopeWildcardMatcher() override {}
235};
236DOX_MARKER([DOX_EXPR_CTRES_1])
237
238DOX_MARKER([DOX_EXPR_CTRES_6])
239Box wldcrd( Scope& scope, ArgIterator args, ArgIterator end ) {
240 String haystack= STR(ARG0);
241 String pattern = STR(ARG1);
242 lang::Case sensitivity= ( end-args > 2 && BOL(ARG2) ) ? lang::Case::Ignore
243 : lang::Case::Sensitive;
244
245 if( !scope.IsCompileTime() ) {
246 // Search for resource named "_wc"+ pattern.
247 NString128 keyString("_wc");
248 keyString.DbgDisableBufferReplacementWarning();
249 keyString << pattern;
250 auto storedMatcher= scope.EvalScopeVMMembers->CTScope->NamedResources->Find( keyString );
251 if( storedMatcher != scope.EvalScopeVMMembers->CTScope->NamedResources->end() )
252 return dynamic_cast<ScopeWildcardMatcher*>( storedMatcher.Mapped() )
253 ->matcher.Match( haystack, sensitivity );
254 }
255DOX_MARKER([DOX_EXPR_CTRES_6])
256
257DOX_MARKER([DOX_EXPR_CTRES_7])
258 // This is either compile-time (with both arguments being constant) or it is
259 // evaluation time and the pattern string is not constant.
260 {
261 WildcardMatcher matcher( pattern );
262 return matcher.Match( haystack, sensitivity );
263} }
264DOX_MARKER([DOX_EXPR_CTRES_7])
265
266//##################################################################################################
267// ### Strings - Regex matching
268//##################################################################################################
269#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
270struct ScopeRegexMatcher : public ScopeResource
271{
272 // the matcher object
273 RegexMatcher matcher;
274
275 // virtual destructor, implicitly deletes the matcher.
276 virtual ~ScopeRegexMatcher() override {}
277};
278
279Box regex( Scope& scope, ArgIterator args, ArgIterator ) {
280 String haystack= STR(ARG0);
281 String pattern = STR(ARG1);
282
283 if( !scope.IsCompileTime() ) {
284 // Search for resource named "_wc"+ pattern.
285 NString128 keyString( "_re" );
286 keyString.DbgDisableBufferReplacementWarning();
287 keyString << pattern;
288 auto storedMatcher= scope.EvalScopeVMMembers->CTScope->NamedResources->Find( keyString );
289 if( storedMatcher != scope.EvalScopeVMMembers->CTScope->NamedResources->end() ) {
290 ScopeRegexMatcher* matcher= dynamic_cast<ScopeRegexMatcher*>( storedMatcher->second );
291 return matcher->matcher.Match( haystack );
292 } }
293
294 // This is either compile-time or the pattern string is not constant
295 {
296 RegexMatcher matcher( pattern );
297 return matcher.Match( haystack );
298} }
299#endif
300
301//##################################################################################################
302// ### Strings - Tables
303//##################################################################################################
304constexpr Calculus::OperatorTableEntry operatorTableStrings[] =
305{
306 // unary operators
310
311 // binary operators
324 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
326 #endif
328};
329
330
331} // anonymous namespace
332
333//##################################################################################################
334// ### Strings - Constructor. Creates the hash map
335//##################################################################################################
336Strings::Strings( Compiler& compiler )
337: Calculus( "ALib Strings", compiler, CompilePriorities::Strings ) {
338 constTAB= A_CHAR("\t"); // Initialize constant static boxes. This must not be done
339 constNL = NEW_LINE; // in the C++ bootstrap code.
340
341 AddOperators( operatorTableStrings );
342
343 // load identifier/function names from resources
344 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
345 constexpr int tableSize= 25;
346 #else
347 constexpr int tableSize= 24;
348 #endif
349
350 Token functionNames[tableSize];
351 strings::util::LoadResourcedTokens( EXPRESSIONS, "CPS", functionNames
352 ALIB_DBG(,tableSize) );
353 Token* descriptor= functionNames;
354
355 // Constant identifiers
356 ConstantIdentifiers=
357 {
358 { *descriptor++, constNL },
359 { *descriptor++, constTAB },
360 };
361
362 Functions=
363 {
364 { *descriptor++, CALCULUS_SIGNATURE(Signatures::Var ), CALCULUS_CALLBACK(CBToString ), &Types::String , CTI },
365 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(wldcrd ), &Types::Boolean, CTI },
366 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(wldcrd ), &Types::Boolean, CTI },
367 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SVar), CALCULUS_CALLBACK(CBFormat ), &Types::String , CTI },
368 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(toUpper ), &Types::String , CTI },
369 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(toLower ), &Types::String , CTI },
370 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(compSS ), &Types::Integer, CTI },
371 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(compSSB ), &Types::Integer, CTI },
372 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(startsWith ), &Types::Boolean, CTI },
373 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(startsWithC), &Types::Boolean, CTI },
374 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK( endsWith ), &Types::Boolean, CTI },
375 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK( endsWithC), &Types::Boolean, CTI },
376 { *descriptor , CALCULUS_SIGNATURE(Signatures::SI ), CALCULUS_CALLBACK(substr ), &Types::String , CTI },
377 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SII ), CALCULUS_CALLBACK(substr2 ), &Types::String , CTI },
378 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(idxof ), &Types::Integer, CTI },
379 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(count ), &Types::Integer, CTI },
380 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trim ), &Types::String , CTI },
381 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trim2 ), &Types::String , CTI },
382 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trimStart ), &Types::String , CTI },
383 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trimStart2 ), &Types::String , CTI },
384 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trimEnd ), &Types::String , CTI },
385 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trimEnd2 ), &Types::String , CTI },
386 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(parsei ), &Types::Integer, CTI },
387 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(parsef ), &Types::Float , CTI },
388 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSI ), CALCULUS_CALLBACK(token ), &Types::String , CTI },
389 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(hex ), &Types::String , CTI },
390 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(hex ), &Types::String , CTI },
391 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(oct ), &Types::String , CTI },
392 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(oct ), &Types::String , CTI },
393 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(bin ), &Types::String , CTI },
394 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(bin ), &Types::String , CTI },
395 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSS ), CALCULUS_CALLBACK(replace ), &Types::String , CTI },
396 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SI ), CALCULUS_CALLBACK(repeat ), &Types::String , CTI },
397
398 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
399 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(regex ), &Types::Boolean, CTI },
400 #endif
401 };
402
403 ALIB_ASSERT_ERROR( descriptor - functionNames == tableSize, "EXPR",
404 "Descriptor table size mismatch: Consumed {} descriptors, {} available.",
405 descriptor - functionNames, tableSize )
406}
407
408namespace {
409bool genericConcatenation( Type type ) {
410 return !(
411 type.IsType<integer>()
412 || type.IsType<double >()
413 || type.IsType<String >() );
414
415}
416}
417
418DOX_MARKER([DOX_EXPR_CTRES_2])
419bool Strings::TryCompilation( CIFunction& ciFunction ) {
420 // invoke parent
421 if( !Calculus::TryCompilation( ciFunction ) )
422 return false;
423DOX_MARKER([DOX_EXPR_CTRES_2])
424
425#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
426 if( ciFunction.Callback == regex && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0) {
427 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
428 NString128 keyString("_re");
429 keyString.DbgDisableBufferReplacementWarning();
430 keyString << pattern;
431 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources->Find( keyString );
432 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources->end() ) {
433 auto& alloc= ciFunction.CompileTimeScope.Allocator;
434 ScopeRegexMatcher* matcher= alloc().New<ScopeRegexMatcher>();
435 matcher->matcher.Compile( pattern );
436 ciFunction.CompileTimeScope.NamedResources->EmplaceOrAssign(
437 NString( alloc, keyString ),
438 matcher );
439 } }
440#endif
441
442DOX_MARKER([DOX_EXPR_CTRES_3])
443 if( ciFunction.Callback == wldcrd && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0) {
444DOX_MARKER([DOX_EXPR_CTRES_3])
445DOX_MARKER([DOX_EXPR_CTRES_4])
446 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
447 NString128 keyString(A_CHAR("_wc"));
448 keyString.DbgDisableBufferReplacementWarning();
449 keyString << pattern;
450DOX_MARKER([DOX_EXPR_CTRES_4])
451DOX_MARKER([DOX_EXPR_CTRES_5])
452 auto hashCode = keyString.Hashcode();
453 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources->Find( keyString, hashCode );
454 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources->end() ) {
455 auto& alloc= ciFunction.CompileTimeScope.Allocator;
456 ScopeWildcardMatcher* matcher= alloc().New<ScopeWildcardMatcher>();
457 matcher->matcher.Compile( pattern );
458 NString keyCopy( ciFunction.CompileTimeScope.Allocator, keyString );
459 ciFunction.CompileTimeScope.NamedResources->InsertUnique( std::make_pair(keyCopy, matcher),
460 hashCode);
461 } }
462 return true;
463DOX_MARKER([DOX_EXPR_CTRES_5])
464}
465
466
467bool Strings::TryCompilation( CIBinaryOp& ciBinaryOp ) {
468 Box& lhs= * ciBinaryOp.ArgsBegin;
469 Box& rhs= *(ciBinaryOp.ArgsBegin + 1);
470
471 // fetch string concatenation operator '+'
472 if( ciBinaryOp.Operator == A_CHAR("+") ) {
473 bool argsAreConst= ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst;
474
475 if( lhs.IsType<String>() && genericConcatenation(rhs) ) {
476 // optimize out?
477 if( argsAreConst ) {
478 ciBinaryOp.TypeOrValue = add_SX( ciBinaryOp.CompileTimeScope,
479 ciBinaryOp.ArgsBegin,
480 ciBinaryOp.ArgsEnd );
481 ALIB_DBG( ciBinaryOp.DbgCallbackName = "add_SX"; )
482 return true;
483 }
484
485 ciBinaryOp.Callback = add_SX;
486 ciBinaryOp.TypeOrValue = Types::String;
487 return true;
488 }
489
490 if( genericConcatenation(lhs) && rhs.IsType<String>() ) {
491 if( argsAreConst ) {
492 ciBinaryOp.TypeOrValue = add_XS( ciBinaryOp.CompileTimeScope,
493 ciBinaryOp.ArgsBegin,
494 ciBinaryOp.ArgsEnd );
495 ALIB_DBG( ciBinaryOp.DbgCallbackName = "add_XS"; )
496 return true;
497 }
498
499 ciBinaryOp.Callback = add_XS;
500 ciBinaryOp.TypeOrValue = Types::String;
501 return true;
502 } }
503
504 // invoke parent
505 if( !Calculus::TryCompilation( ciBinaryOp ) )
506 return false;
507
508 // Perform the same mechanics as with TryCompilation("regex") above:
509 // check for regex match operator '*'
510#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
511 if( ciBinaryOp.Operator == A_CHAR("%") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst ) {
512 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
513 NString128 keyString(A_CHAR("_re"));
514 keyString.DbgDisableBufferReplacementWarning();
515 keyString << pattern;
516 auto hashCode = keyString.Hashcode();
517
518 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources->Find( keyString, hashCode );
519 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources->end() ) {
520 auto& alloc= ciBinaryOp.CompileTimeScope.Allocator;
521 ScopeRegexMatcher* matcher= alloc().New<ScopeRegexMatcher>();
522 matcher->matcher.Compile( pattern );
523 ciBinaryOp.CompileTimeScope.NamedResources->InsertOrAssign(
524 NString(alloc, keyString ),
525 matcher,
526 hashCode );
527 } }
528#endif
529
530 // check for wildcard match operator '*'
531 if( ciBinaryOp.Operator == A_CHAR("*") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst ) {
532 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
533 NString128 keyString(A_CHAR("_wc"));
534 keyString.DbgDisableBufferReplacementWarning();
535 keyString << pattern;
536 auto hashCode = keyString.Hashcode();
537
538 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources->Find( keyString, hashCode );
539 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources->end() ) {
540 auto& alloc= ciBinaryOp.CompileTimeScope.Allocator;
541 ScopeWildcardMatcher* matcher= alloc().New<ScopeWildcardMatcher>();
542 matcher->matcher.Compile( pattern );
543
544 NString keyCopy(alloc, keyString);
545 ciBinaryOp.CompileTimeScope.NamedResources->InsertUnique( std::make_pair(keyCopy, matcher),
546 hashCode );
547 } }
548 return true;
549}
550
551}}} // namespace [alib::expressions::detail]
552
553
554#undef BOL
555#undef INT
556#undef FLT
557#undef STR
558#undef LEN
559#undef CPY
560#undef EMP
561#undef FUNC_UNARY
562#undef FUNC
563#undef UN_MAP_ENTRY
564#undef BIN_MAP_ENTRY
565#undef BIN_ALIAS_ENTRY
566
567//! @endcond
TBoxes & Add()
Definition boxes.inl:55
constexpr integer Length() const
Definition string.inl:316
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
Definition substring.inl:70
ALIB_DLL bool ConsumeFloat(double &result, TNumberFormat< TChar > *numberFormat=nullptr)
bool ConsumeInt(std::integral auto &result, TNumberFormat< TChar > *numberFormat=nullptr)
TSubstring & Trim(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
TSubstring & TrimEnd(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
Definition substring.inl:90
ALIB_DLL TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:26
#define A_CHAR(STR)
#define CALCULUS_CALLBACK(func)
#define CALCULUS_SIGNATURE(BoxPointerArray)
#define ALIB_DBG(...)
Definition alib.inl:853
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
#define ALIB_COMMA
Definition alib.inl:963
TChar ToUpper(TChar c)
TChar ToLower(TChar c)
ALIB_DLL Box CBFormat(Scope &scope, ArgIterator args, ArgIterator)
ALIB_DLL Box CBToString(Scope &scope, ArgIterator args, ArgIterator)
StdVectorMA< Box >::iterator ArgIterator
platform_specific integer
Definition integers.inl:32
Case
Denotes upper and lower case character treatment.
@ Keep
Keep whitespaces in string.
strings::TDec< character > Dec
Type alias in namespace alib.
Definition format.inl:541
NLocalString< 128 > NString128
Type alias name for TLocalString<nchar,128>.
strings::util::Token Token
Type alias in namespace alib.
Definition token.inl:398
LocalString< 256 > String256
Type alias name for TLocalString<character,256>.
strings::util::TTokenizer< character > Tokenizer
Type alias in namespace alib.
lox::Scope Scope
Type alias in namespace alib.
LocalString< 128 > String128
Type alias name for TLocalString<character,128>.
constexpr CString NEW_LINE
A zero-terminated string containing the new-line character sequence.
Definition cstring.inl:616
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2198
strings::TOct< character > Oct
Type alias in namespace alib.
Definition format.inl:559
strings::util::TWildcardMatcher< character > WildcardMatcher
Type alias in namespace alib.
strings::THex< character > Hex
Type alias in namespace alib.
Definition format.inl:550
format::Formatter Formatter
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1149
LocalString< 1024 > String1K
Type alias name for TLocalString<character,1024>.
strings::util::RegexMatcher RegexMatcher
Type alias in namespace alib.
exceptions::Exception Exception
Type alias in namespace alib.
boxing::TBoxes< MonoAllocator > BoxesMA
Type alias in namespace alib.
Definition boxes.inl:193
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2189
expressions::Compiler Compiler
Type alias in namespace alib.
Definition compiler.inl:540
strings::TBin< character > Bin
Type alias in namespace alib.
Definition format.inl:568
LocalString< 2048 > String2K
Type alias name for TLocalString<character,2048>.
strings::TSubstring< character > Substring
Type alias in namespace alib.
static ALIB_DLL Box Integer
Sample type-box for integer types. (Precisely for type integer.)
static ALIB_DLL Box Boolean
Sample type-box for C++ type bool.
static ALIB_DLL Box Void
Sample type-box for C++ type void.
static ALIB_DLL Box Float
Sample type-box for C++ type double.
static ALIB_DLL Box String
static constexpr CTInvokable CTI
Definition calculus.inl:234
const std::tuple< String, Type, Type, CallbackDecl, Type, CTInvokable > OperatorTableEntry
Definition calculus.inl:449
ALIB_DLL Strings(Compiler &compiler)