ALib C++ Library
Library Version: 2510 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
22 import ALib.Strings;
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{
64 String256 tmp;
65 tmp.DbgDisableBufferReplacementWarning();
66 while( args < end )
67 {
68 Box& arg= *args;
69 if( arg.IsType<integer>() ) tmp << Dec( INT(arg), &scope.Formatter->DefaultNumberFormat);
70 else if( arg.IsType<double >() ) tmp << Dec( FLT(arg), &scope.Formatter->DefaultNumberFormat);
71 else tmp << arg;
72
73 ++args;
74 }
75
76 return String(scope.Allocator, tmp);
77}
78
79// #################################################################################################
80// ### Format (not in anonymous namespace)
81// #################################################################################################
82Box CBFormat( Scope& scope, ArgIterator args, ArgIterator end)
83{
84 String1K buf;
85 buf.DbgDisableBufferReplacementWarning();
86
87 BoxesMA& formatterArgs= scope.Formatter->GetArgContainer();
88 while( args != end)
89 formatterArgs.Add( *args++ );
90
91 try
92 {
93 scope.Formatter->FormatArgs( buf );
94 }
95 catch( Exception& )
96 {
97 throw;
98 }
99
100 return String( scope.Allocator, buf );
101}
102
103
104namespace {
105
106
107// #################################################################################################
108// ### String - constants
109// #################################################################################################
110Box constTAB;
111Box constNL;
112
113// #################################################################################################
114// ### String functions
115// #################################################################################################
116
117FUNC(toUpper , return ALLOCS(STR1K(ARG0).ToUpper()); )
118FUNC(toLower , return ALLOCS(STR1K(ARG0).ToLower()); )
119FUNC(startsWith , return STR(ARG0).StartsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
120FUNC(startsWithC, return BOL(ARG2) ? STR(ARG0).StartsWith<CHK,lang::Case::Ignore >( STR(ARG1) )
121 : STR(ARG0).StartsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
122FUNC(endsWith , return STR(ARG0). EndsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
123FUNC(endsWithC , return BOL(ARG2) ? STR(ARG0). EndsWith<CHK,lang::Case::Ignore >( STR(ARG1) )
124 : STR(ARG0). EndsWith<CHK,lang::Case::Sensitive>( STR(ARG1) ); )
125FUNC(substr , return STR(ARG0).Substring( INT(ARG1) ); )
126FUNC(substr2 , return STR(ARG0).Substring( INT(ARG1), INT(ARG2) ); )
127FUNC(idxof , String needle= STR(ARG1); return needle.Length() == 1 ? STR(ARG0).IndexOf ( needle[0], 0 )
128 : STR(ARG0).IndexOf( needle , 0 ); )
129FUNC(count , String needle= STR(ARG1); return needle.Length() == 1 ? STR(ARG0).CountChar ( needle[0] )
130 : STR(ARG0).Count ( needle , 0 ); )
131
132FUNC(trim , return Substring(STR(ARG0)).Trim ( ); )
133FUNC(trim2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).Trim (ws); )
134FUNC(trimStart , return Substring(STR(ARG0)).TrimStart( ); )
135FUNC(trimStart2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).TrimStart(ws); )
136FUNC(trimEnd , return Substring(STR(ARG0)).TrimEnd ( ); )
137FUNC(trimEnd2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).TrimEnd (ws); )
138
139FUNC(parsei , integer result; Substring(STR(ARG0)).ConsumeInt (result, &scope.Formatter->DefaultNumberFormat); return result; )
140FUNC(parsef , double result; Substring(STR(ARG0)).ConsumeFloat(result, &scope.Formatter->DefaultNumberFormat); return result; )
141
142FUNC(token , Tokenizer tknzr( STR(ARG0), STR(ARG1).CharAtStart() );
143 for( integer i= INT(ARG2) ; i >= 0 ; --i )
145 return tknzr.Actual; )
146
147FUNC(hex , String128 buf;
148 buf << Hex( uint64_t(INT(ARG0)),
149 args + 1 != end ? int(INT(ARG1)) : 0,
150 &scope.Formatter->DefaultNumberFormat );
151 return ALLOCS(buf); )
152FUNC(oct , String128 buf;
153 buf << Oct( uint64_t(INT(ARG0)),
154 args + 1 != end ? int(INT(ARG1)) : 0,
155 &scope.Formatter->DefaultNumberFormat );
156 return ALLOCS(buf); )
157FUNC(bin , String128 buf;
158 buf << Bin( uint64_t(INT(ARG0)),
159 args + 1 != end ? int(INT(ARG1)) : 0,
160 &scope.Formatter->DefaultNumberFormat );
161 return ALLOCS(buf); )
162
163
164Box replace( Scope& scope, ArgIterator args, ArgIterator )
165{
166 String src = STR(ARG0);
167 String needle = STR(ARG1);
168 String replacement= STR(ARG2);
169
170 // replace char with char?
171 if( needle.Length() == 1 && replacement.Length() == 1 )
172 {
173 String2K result(src);
174 result.SearchAndReplace( needle[0], replacement[0], 0 );
175 return ALLOCS(result);
176 }
177
178 // replace string with char or string
179 String256 buf;
180 buf.DbgDisableBufferReplacementWarning();
181 buf << src;
182 buf.SearchAndReplace( needle, replacement, 0 );
183 return ALLOCS(buf);
184}
185
186Box repeat( Scope& scope, ArgIterator args, ArgIterator )
187{
188 String src = STR(ARG0);
189 String256 buf;
190 buf.DbgDisableBufferReplacementWarning();
191 for( integer i= INT(ARG1) ; i > 0 ; --i )
192 buf << src;
193 return ALLOCS(buf);
194}
195
196// #################################################################################################
197// ### Strings - Unary operators
198// #################################################################################################
199FUNC(boolNot, return LEN(ARG0) == 0; )
200
201
202// #################################################################################################
203// ### Strings - Binary operators
204// #################################################################################################
205
206FUNC(add_SI, return ALLOCS(STR1K(ARG0) << Dec( INT(ARG1), &scope.Formatter->DefaultNumberFormat )); )
207FUNC(add_SF, return ALLOCS(STR1K(ARG0) << Dec( FLT(ARG1), &scope.Formatter->DefaultNumberFormat )); )
208
209
210FUNC(add_IS, return ALLOCS(String1K() << Dec( INT(ARG0), &scope.Formatter->DefaultNumberFormat) << STR(ARG1)); )
211FUNC(add_FS, return ALLOCS(String1K() << Dec( FLT(ARG0), &scope.Formatter->DefaultNumberFormat) << STR(ARG1)); )
212FUNC(add_SS, return ALLOCS(String1K(STR(ARG0)) << STR(ARG1)); )
213FUNC(add_SX, return ALLOCS(String1K(STR(ARG0)) << ARG1); )
214FUNC(add_XS, return ALLOCS(String1K( ARG0) << STR(ARG1)); )
215
216
217FUNC( sm, return STR(ARG0) < ( STR(ARG1) ); )
218FUNC( smEq, return STR(ARG0) <= ( STR(ARG1) ); )
219FUNC( gt, return STR(ARG0) > ( STR(ARG1) ); )
220FUNC( gtEq, return STR(ARG0) >= ( STR(ARG1) ); )
221FUNC( eq, return STR(ARG0).Equals( STR(ARG1) ); )
222FUNC( neq, return !STR(ARG0).Equals( STR(ARG1) ); )
223
224FUNC( arr, return STR(ARG0).Substring( INT(ARG1), 1); )
225
226FUNC( compSS, return TOINT( STR(ARG0).CompareTo<CHK ALIB_COMMA lang::Case::Sensitive>( STR(ARG1) ) ); )
227FUNC(compSSB, return TOINT( BOL(ARG2) ? STR(ARG0).CompareTo<CHK ALIB_COMMA lang::Case::Ignore >( STR(ARG1) )
228 : STR(ARG0).CompareTo<CHK ALIB_COMMA lang::Case::Sensitive>( STR(ARG1) ) ); )
229
230// #################################################################################################
231// ### Strings - Wildcard matching
232// #################################################################################################
233DOX_MARKER([DOX_EXPR_CTRES_1])
234struct ScopeWildcardMatcher : public ScopeResource
235{
236 // the matcher object
237 WildcardMatcher matcher;
238
239 // virtual destructor, implicitly deletes the matcher.
240 virtual ~ScopeWildcardMatcher() override {}
241};
242DOX_MARKER([DOX_EXPR_CTRES_1])
243
244DOX_MARKER([DOX_EXPR_CTRES_6])
245Box wldcrd( Scope& scope, ArgIterator args, ArgIterator end )
246{
247 String haystack= STR(ARG0);
248 String pattern = STR(ARG1);
249 lang::Case sensitivity= ( end-args > 2 && BOL(ARG2) ) ? lang::Case::Ignore
250 : lang::Case::Sensitive;
251
252 if( !scope.IsCompileTime() )
253 {
254 // Search for resource named "_wc"+ pattern.
255 NString128 keyString("_wc");
256 keyString.DbgDisableBufferReplacementWarning();
257 keyString << pattern;
258 auto storedMatcher= scope.EvalScopeVMMembers->CTScope->NamedResources->Find( keyString );
259 if( storedMatcher != scope.EvalScopeVMMembers->CTScope->NamedResources->end() )
260 return dynamic_cast<ScopeWildcardMatcher*>( storedMatcher.Mapped() )
261 ->matcher.Match( haystack, sensitivity );
262 }
263DOX_MARKER([DOX_EXPR_CTRES_6])
264
265DOX_MARKER([DOX_EXPR_CTRES_7])
266 // This is either compile-time (with both arguments being constant) or it is
267 // evaluation time and the pattern string is not constant.
268 {
269 WildcardMatcher matcher( pattern );
270 return matcher.Match( haystack, sensitivity );
271 }
272}
273DOX_MARKER([DOX_EXPR_CTRES_7])
274
275// #################################################################################################
276// ### Strings - Regex matching
277// #################################################################################################
278#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
279struct ScopeRegexMatcher : public ScopeResource
280{
281 // the matcher object
282 RegexMatcher matcher;
283
284 // virtual destructor, implicitly deletes the matcher.
285 virtual ~ScopeRegexMatcher() override {}
286};
287
288Box regex( Scope& scope, ArgIterator args, ArgIterator )
289{
290 String haystack= STR(ARG0);
291 String pattern = STR(ARG1);
292
293 if( !scope.IsCompileTime() )
294 {
295 // Search for resource named "_wc"+ pattern.
296 NString128 keyString( "_re" );
297 keyString.DbgDisableBufferReplacementWarning();
298 keyString << pattern;
299 auto storedMatcher= scope.EvalScopeVMMembers->CTScope->NamedResources->Find( keyString );
300 if( storedMatcher != scope.EvalScopeVMMembers->CTScope->NamedResources->end() )
301 {
302 ScopeRegexMatcher* matcher= dynamic_cast<ScopeRegexMatcher*>( storedMatcher->second );
303 return matcher->matcher.Match( haystack );
304 }
305 }
306
307 // This is either compile-time or the pattern string is not constant
308 {
309 RegexMatcher matcher( pattern );
310 return matcher.Match( haystack );
311 }
312}
313#endif
314
315// #################################################################################################
316// ### Strings - Tables
317// #################################################################################################
318constexpr Calculus::OperatorTableEntry operatorTableStrings[] =
319{
320 // unary operators
324
325 // binary operators
338 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
340 #endif
342};
343
344
345} // anonymous namespace
346
347// #################################################################################################
348// ### Strings - Constructor. Creates the hash map
349// #################################################################################################
350Strings::Strings( Compiler& compiler )
351: Calculus( "ALib Strings", compiler, CompilePriorities::Strings )
352{
353 constTAB= A_CHAR("\t"); // Initialize constant static boxes. This must not be done
354 constNL = NEW_LINE; // in the C++ bootstrap code.
355
356 AddOperators( operatorTableStrings );
357
358 // load identifier/function names from resources
359 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
360 constexpr int tableSize= 25;
361 #else
362 constexpr int tableSize= 24;
363 #endif
364
365 Token functionNames[tableSize];
366 strings::util::LoadResourcedTokens( EXPRESSIONS, "CPS", functionNames
367 ALIB_DBG(,tableSize) );
368 Token* descriptor= functionNames;
369
370 // Constant identifiers
371 ConstantIdentifiers=
372 {
373 { *descriptor++, constNL },
374 { *descriptor++, constTAB },
375 };
376
377 Functions=
378 {
379 { *descriptor++, CALCULUS_SIGNATURE(Signatures::Var ), CALCULUS_CALLBACK(CBToString ), &Types::String , CTI },
380 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(wldcrd ), &Types::Boolean, CTI },
381 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(wldcrd ), &Types::Boolean, CTI },
382 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SVar), CALCULUS_CALLBACK(CBFormat ), &Types::String , CTI },
383 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(toUpper ), &Types::String , CTI },
384 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(toLower ), &Types::String , CTI },
385 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(compSS ), &Types::Integer, CTI },
386 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(compSSB ), &Types::Integer, CTI },
387 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(startsWith ), &Types::Boolean, CTI },
388 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(startsWithC), &Types::Boolean, CTI },
389 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK( endsWith ), &Types::Boolean, CTI },
390 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK( endsWithC), &Types::Boolean, CTI },
391 { *descriptor , CALCULUS_SIGNATURE(Signatures::SI ), CALCULUS_CALLBACK(substr ), &Types::String , CTI },
392 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SII ), CALCULUS_CALLBACK(substr2 ), &Types::String , CTI },
393 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(idxof ), &Types::Integer, CTI },
394 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(count ), &Types::Integer, CTI },
395 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trim ), &Types::String , CTI },
396 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trim2 ), &Types::String , CTI },
397 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trimStart ), &Types::String , CTI },
398 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trimStart2 ), &Types::String , CTI },
399 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trimEnd ), &Types::String , CTI },
400 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trimEnd2 ), &Types::String , CTI },
401 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(parsei ), &Types::Integer, CTI },
402 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(parsef ), &Types::Float , CTI },
403 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSI ), CALCULUS_CALLBACK(token ), &Types::String , CTI },
404 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(hex ), &Types::String , CTI },
405 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(hex ), &Types::String , CTI },
406 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(oct ), &Types::String , CTI },
407 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(oct ), &Types::String , CTI },
408 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(bin ), &Types::String , CTI },
409 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(bin ), &Types::String , CTI },
410 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSS ), CALCULUS_CALLBACK(replace ), &Types::String , CTI },
411 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SI ), CALCULUS_CALLBACK(repeat ), &Types::String , CTI },
412
413 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
414 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(regex ), &Types::Boolean, CTI },
415 #endif
416 };
417
418 ALIB_ASSERT_ERROR( descriptor - functionNames == tableSize, "EXPR",
419 "Descriptor table size mismatch: Consumed {} descriptors, {} available.",
420 descriptor - functionNames, tableSize )
421}
422
423namespace {
424bool genericConcatenation( Type type )
425{
426 return !(
427 type.IsType<integer>()
428 || type.IsType<double >()
429 || type.IsType<String >() );
430
431}
432}
433
434DOX_MARKER([DOX_EXPR_CTRES_2])
435bool Strings::TryCompilation( CIFunction& ciFunction )
436{
437 // invoke parent
438 if( !Calculus::TryCompilation( ciFunction ) )
439 return false;
440DOX_MARKER([DOX_EXPR_CTRES_2])
441
442#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
443 if( ciFunction.Callback == regex && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
444 {
445 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
446 NString128 keyString("_re");
447 keyString.DbgDisableBufferReplacementWarning();
448 keyString << pattern;
449 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources->Find( keyString );
450 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources->end() )
451 {
452 auto& alloc= ciFunction.CompileTimeScope.Allocator;
453 ScopeRegexMatcher* matcher= alloc().New<ScopeRegexMatcher>();
454 matcher->matcher.Compile( pattern );
455 ciFunction.CompileTimeScope.NamedResources->EmplaceOrAssign(
456 NString( alloc, keyString ),
457 matcher );
458 }
459 }
460#endif
461
462DOX_MARKER([DOX_EXPR_CTRES_3])
463 if( ciFunction.Callback == wldcrd && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
464 {
465DOX_MARKER([DOX_EXPR_CTRES_3])
466DOX_MARKER([DOX_EXPR_CTRES_4])
467 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
468 NString128 keyString(A_CHAR("_wc"));
469 keyString.DbgDisableBufferReplacementWarning();
470 keyString << pattern;
471DOX_MARKER([DOX_EXPR_CTRES_4])
472DOX_MARKER([DOX_EXPR_CTRES_5])
473 auto hashCode = keyString.Hashcode();
474 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources->Find( keyString, hashCode );
475 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources->end() )
476 {
477 auto& alloc= ciFunction.CompileTimeScope.Allocator;
478 ScopeWildcardMatcher* matcher= alloc().New<ScopeWildcardMatcher>();
479 matcher->matcher.Compile( pattern );
480 NString keyCopy( ciFunction.CompileTimeScope.Allocator, keyString );
481 ciFunction.CompileTimeScope.NamedResources->InsertUnique( std::make_pair(keyCopy, matcher),
482 hashCode);
483 }
484 }
485 return true;
486DOX_MARKER([DOX_EXPR_CTRES_5])
487}
488
489
490bool Strings::TryCompilation( CIBinaryOp& ciBinaryOp )
491{
492 Box& lhs= * ciBinaryOp.ArgsBegin;
493 Box& rhs= *(ciBinaryOp.ArgsBegin + 1);
494
495 // fetch string concatenation operator '+'
496 if( ciBinaryOp.Operator == A_CHAR("+") )
497 {
498 bool argsAreConst= ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst;
499
500 if( lhs.IsType<String>() && genericConcatenation(rhs) )
501 {
502 // optimize out?
503 if( argsAreConst )
504 {
505 ciBinaryOp.TypeOrValue = add_SX( ciBinaryOp.CompileTimeScope,
506 ciBinaryOp.ArgsBegin,
507 ciBinaryOp.ArgsEnd );
508 ALIB_DBG( ciBinaryOp.DbgCallbackName = "add_SX"; )
509 return true;
510 }
511
512 ciBinaryOp.Callback = add_SX;
513 ciBinaryOp.TypeOrValue = Types::String;
514 return true;
515 }
516
517 if( genericConcatenation(lhs) && rhs.IsType<String>() )
518 {
519 if( argsAreConst )
520 {
521 ciBinaryOp.TypeOrValue = add_XS( ciBinaryOp.CompileTimeScope,
522 ciBinaryOp.ArgsBegin,
523 ciBinaryOp.ArgsEnd );
524 ALIB_DBG( ciBinaryOp.DbgCallbackName = "add_XS"; )
525 return true;
526 }
527
528 ciBinaryOp.Callback = add_XS;
529 ciBinaryOp.TypeOrValue = Types::String;
530 return true;
531 }
532 }
533
534 // invoke parent
535 if( !Calculus::TryCompilation( ciBinaryOp ) )
536 return false;
537
538 // Perform the same mechanics as with TryCompilation("regex") above:
539 // check for regex match operator '*'
540#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
541 if( ciBinaryOp.Operator == A_CHAR("%") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
542 {
543 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
544 NString128 keyString(A_CHAR("_re"));
545 keyString.DbgDisableBufferReplacementWarning();
546 keyString << pattern;
547 auto hashCode = keyString.Hashcode();
548
549 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources->Find( keyString, hashCode );
550 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources->end() )
551 {
552 auto& alloc= ciBinaryOp.CompileTimeScope.Allocator;
553 ScopeRegexMatcher* matcher= alloc().New<ScopeRegexMatcher>();
554 matcher->matcher.Compile( pattern );
555 ciBinaryOp.CompileTimeScope.NamedResources->InsertOrAssign(
556 NString(alloc, keyString ),
557 matcher,
558 hashCode );
559 }
560 }
561#endif
562
563 // check for wildcard match operator '*'
564 if( ciBinaryOp.Operator == A_CHAR("*") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
565 {
566 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
567 NString128 keyString(A_CHAR("_wc"));
568 keyString.DbgDisableBufferReplacementWarning();
569 keyString << pattern;
570 auto hashCode = keyString.Hashcode();
571
572 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources->Find( keyString, hashCode );
573 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources->end() )
574 {
575 auto& alloc= ciBinaryOp.CompileTimeScope.Allocator;
576 ScopeWildcardMatcher* matcher= alloc().New<ScopeWildcardMatcher>();
577 matcher->matcher.Compile( pattern );
578
579 NString keyCopy(alloc, keyString);
580 ciBinaryOp.CompileTimeScope.NamedResources->InsertUnique( std::make_pair(keyCopy, matcher),
581 hashCode );
582 }
583 }
584 return true;
585}
586
587}}} // namespace [alib::expressions::detail]
588
589
590#undef BOL
591#undef INT
592#undef FLT
593#undef STR
594#undef LEN
595#undef CPY
596#undef EMP
597#undef FUNC_UNARY
598#undef FUNC
599#undef UN_MAP_ENTRY
600#undef BIN_MAP_ENTRY
601#undef BIN_ALIAS_ENTRY
602
603//! @endcond
TBoxes & Add()
Definition boxes.inl:61
constexpr integer Length() const
Definition string.inl:318
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
Definition substring.inl:76
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:98
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:836
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1049
#define ALIB_COMMA
Definition alib.inl:946
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)
StdVectorMono< 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:545
NLocalString< 128 > NString128
Type alias name for TLocalString<nchar,128>.
strings::util::Token Token
Type alias in namespace alib.
Definition token.inl:401
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:644
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2390
strings::TOct< character > Oct
Type alias in namespace alib.
Definition format.inl:563
strings::util::TWildcardMatcher< character > WildcardMatcher
Type alias in namespace alib.
strings::THex< character > Hex
Type alias in namespace alib.
Definition format.inl:554
format::Formatter Formatter
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1216
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:245
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2381
expressions::Compiler Compiler
Type alias in namespace alib.
Definition compiler.inl:574
strings::TBin< character > Bin
Type alias in namespace alib.
Definition format.inl:572
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:458
ALIB_DLL Strings(Compiler &compiler)