ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
strings.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !defined(ALIB_DOX)
10# if !defined (HPP_ALIB_EXPRESSIONS_PLUGINS_STRINGS)
12# endif
13
14# if !defined (HPP_ALIB_MONOMEM_MASTRING)
16# endif
17
18# if !defined (HPP_ALIB_STRINGS_UTIL_WILDCARDMATCHER)
20# endif
21
22# if !defined (HPP_ALIB_STRINGS_UTIL_REGEXMATCHER)
24# endif
25
26# if !defined (HPP_ALIB_STRINGS_FORMAT)
28# endif
29# if !defined (HPP_ALIB_STRINGS_UTIL_TOKENIZER)
31# endif
32#endif // !defined(ALIB_DOX)
33
34
35//! @cond NO_DOX
36
37#define ARG0 (*args)
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)
48
49#define FUNC( name,...) Box name( Scope& scope, \
50 ArgIterator args, \
51 ArgIterator end ) \
52 { (void) scope; (void) args; (void) end; __VA_ARGS__ }
53#if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
54# define TOINT(arg) arg
55#else
56# define TOINT(arg) static_cast<integer>(arg)
57#endif
58
59
60namespace alib { namespace expressions { namespace plugins {
61
62// #################################################################################################
63// ### ToString (not in anonymous namespace)
64// #################################################################################################
65Box CBToString( Scope& scope, ArgIterator args, ArgIterator end)
66{
67 String256 tmp;
68 tmp.DbgDisableBufferReplacementWarning();
69 while( args < end )
70 {
71 Box& arg= *args;
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);
74 else tmp << arg;
75
76 ++args;
77 }
78
79 return MAString( scope.Allocator, tmp, 0 );
80}
81
82// #################################################################################################
83// ### Format (not in anonymous namespace)
84// #################################################################################################
85Box CBFormat( Scope& scope, ArgIterator args, ArgIterator end)
86{
87 String256 buf;
88 buf.DbgDisableBufferReplacementWarning();
89
90 Boxes& formatterArgs= scope.Formatter->Acquire(ALIB_CALLER_PRUNED);
91 while( args != end)
92 formatterArgs.Add( *args++ );
93
94 try
95 {
96 scope.Formatter->FormatArgs( buf );
97 }
98 catch( Exception& )
99 {
100 scope.Formatter->Release();
101 throw;
102 }
103
104 scope.Formatter->Release();
105
106 return MAString( scope.Allocator, buf, 0 );
107}
108
109
110namespace {
111
112
113// #################################################################################################
114// ### String - constants
115// #################################################################################################
116Box constTAB;
117Box constNL;
118
119// #################################################################################################
120// ### String functions
121// #################################################################################################
122
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 ); )
137
138FUNC(trim , return Substring(STR(ARG0)).Trim ( ); )
139FUNC(trim2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).Trim (ws); )
140FUNC(trimStart , return Substring(STR(ARG0)).TrimStart( ); )
141FUNC(trimStart2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).TrimStart(ws); )
142FUNC(trimEnd , return Substring(STR(ARG0)).TrimEnd ( ); )
143FUNC(trimEnd2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).TrimEnd (ws); )
144
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; )
147
148FUNC(token , Tokenizer tknzr( STR(ARG0), STR(ARG1).CharAtStart() );
149 for( auto i= INT(ARG2) ; i >= 0 ; --i )
150 tknzr.Next( lang::Whitespaces::Keep );
151 return tknzr.Actual; )
152
153FUNC(hex , String128 buf;
154 buf << Format::Hex( static_cast<uint64_t>(INT(ARG0)),
155 args + 1 != end ? static_cast<int>(INT(ARG1)) : 0,
156 &scope.Formatter->DefaultNumberFormat );
157 return MAString(scope.Allocator, buf,0); )
158FUNC(oct , String128 buf;
159 buf << Format::Oct( static_cast<uint64_t>(INT(ARG0)),
160 args + 1 != end ? static_cast<int>(INT(ARG1)) : 0,
161 &scope.Formatter->DefaultNumberFormat );
162 return MAString(scope.Allocator, buf,0); )
163FUNC(bin , String128 buf;
164 buf << Format::Bin( static_cast<uint64_t>(INT(ARG0)),
165 args + 1 != end ? static_cast<int>(INT(ARG1)) : 0,
166 &scope.Formatter->DefaultNumberFormat );
167 return MAString(scope.Allocator, buf,0); )
168
169
170Box replace( Scope& scope, ArgIterator args, ArgIterator )
171{
172 String src = STR(ARG0);
173 String needle = STR(ARG1);
174 String replacement= STR(ARG2);
175
176 // replace char with char?
177 if( needle.Length() == 1 && replacement.Length() == 1 )
178 {
179 MAString result(scope.Allocator, src, 0 );
180 result.SearchAndReplace( needle[0], replacement[0], 0 );
181 return result;
182 }
183
184 // replace string with char or string
185 String256 buf;
186 buf.DbgDisableBufferReplacementWarning();
187 buf << src;
188 buf.SearchAndReplace( needle, replacement, 0 );
189 return MAString( scope.Allocator, buf, 0 );
190}
191
192Box repeat( Scope& scope, ArgIterator args, ArgIterator )
193{
194 String src = STR(ARG0);
195 String256 buf;
196 buf.DbgDisableBufferReplacementWarning();
197 for( auto i= INT(ARG1) ; i > 0 ; --i )
198 buf << src;
199 return MAString( scope.Allocator, buf, 0 );
200}
201
202// #################################################################################################
203// ### Strings - Unary operators
204// #################################################################################################
205FUNC(boolNot, return LEN(ARG0) == 0; )
206
207
208// #################################################################################################
209// ### Strings - Binary operators
210// #################################################################################################
211
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 ); )
214
215
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); )
219FUNC(add_SX,
220 String256 tmp;
221 tmp.DbgDisableBufferReplacementWarning();
222 tmp << ARG1;
223 return CPY(ARG0, tmp.Length() ) << tmp;
224)
225
226FUNC(add_XS, return WRT( ARG0, ARG1.UnboxLength() ) << ARG1; )
227
228
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) ); )
235
236FUNC( arr, return STR(ARG0).Substring( INT(ARG1), 1); )
237
238FUNC( compSS, return TOINT( STR(ARG0).CompareTo<true ALIB_COMMA lang::Case::Sensitive>( STR(ARG1) ) ); )
239FUNC(compSSB, return TOINT( BOL(ARG2) ? STR(ARG0).CompareTo<true ALIB_COMMA lang::Case::Ignore >( STR(ARG1) )
240 : STR(ARG0).CompareTo<true ALIB_COMMA lang::Case::Sensitive>( STR(ARG1) ) ); )
241
242// #################################################################################################
243// ### Strings - Wildcard matching
244// #################################################################################################
245DOX_MARKER([DOX_ALIB_EXPR_CTRES_1])
246struct ScopeWildcardMatcher : public ScopeResource
247{
248 // the matcher object
249 WildcardMatcher matcher;
250
251 // virtual destructor, implicitly deletes the matcher.
252 virtual ~ScopeWildcardMatcher() override {}
253};
254DOX_MARKER([DOX_ALIB_EXPR_CTRES_1])
255
256DOX_MARKER([DOX_ALIB_EXPR_CTRES_6])
257Box wldcrd( Scope& scope, ArgIterator args, ArgIterator end )
258{
259 String haystack= STR(ARG0);
260 String pattern = STR(ARG1);
261 lang::Case sensitivity= ( end-args > 2 && BOL(ARG2) ) ? lang::Case::Ignore
262 : lang::Case::Sensitive;
263
264 if( !scope.IsCompileTime() )
265 {
266 // Search for resource named "_wc"+ pattern.
267 NString128 keyString("_wc");
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 );
274 }
275DOX_MARKER([DOX_ALIB_EXPR_CTRES_6])
276
277DOX_MARKER([DOX_ALIB_EXPR_CTRES_7])
278 // This is either compile-time or the pattern string is not constant
279 {
280 WildcardMatcher matcher( pattern );
281 return matcher.Match( haystack, sensitivity );
282 }
283}
284DOX_MARKER([DOX_ALIB_EXPR_CTRES_7])
285
286// #################################################################################################
287// ### Strings - Regex matching
288// #################################################################################################
289#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
290struct ScopeRegexMatcher : public ScopeResource
291{
292 // the matcher object
293 RegexMatcher matcher;
294
295 // virtual destructor, implicitly deletes the matcher.
296 virtual ~ScopeRegexMatcher() override {}
297};
298
299Box regex( Scope& scope, ArgIterator args, ArgIterator )
300{
301 String haystack= STR(ARG0);
302 String pattern = STR(ARG1);
303
304 if( !scope.IsCompileTime() )
305 {
306 // Search for resource named "_wc"+ pattern.
307 NString128 keyString( "_re" );
308 keyString.DbgDisableBufferReplacementWarning();
309 keyString << pattern;
310 auto storedMatcher= scope.CTScope->NamedResources.Find( keyString );
311 if( storedMatcher != scope.CTScope->NamedResources.end() )
312 {
313 ScopeRegexMatcher* matcher= dynamic_cast<ScopeRegexMatcher*>( storedMatcher->second );
314 return matcher->matcher.Match( haystack );
315 }
316 }
317
318 // This is either compile-time or the pattern string is not constant
319 {
320 RegexMatcher matcher( pattern );
321 return matcher.Match( haystack );
322 }
323}
324#endif
325
326// #################################################################################################
327// ### Strings - Tables
328// #################################################################################################
329constexpr Calculus::OperatorTableEntry operatorTableStrings[] =
330{
331 // unary operators
335
336 // binary operators
349 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
351 #endif
353};
354
355
356} // anonymous namespace
357
358// #################################################################################################
359// ### Strings - Constructor. Creates the hash map
360// #################################################################################################
361Strings::Strings( Compiler& compiler )
362: Calculus( "ALib Strings", compiler )
363{
364 constTAB= A_CHAR("\t"); // Initialize constant static boxes. This must not be done
365 constNL = NewLine(); // in the C++ bootstrap code.
366
367 AddOperators( operatorTableStrings );
368
369 // load identifier/function names from resources
370 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
371 constexpr int tableSize= 25;
372 #else
373 constexpr int tableSize= 24;
374 #endif
375
376 Token functionNames[tableSize];
377 Token::LoadResourcedTokens( EXPRESSIONS, "CPS", functionNames
378 ALIB_DBG(,tableSize) );
380 Token* descriptor= functionNames;
381
382 // Constant identifiers
383 ConstantIdentifiers=
384 {
385 { *descriptor++, constNL },
386 { *descriptor++, constTAB },
387 };
388
389 Functions=
390 {
391 { *descriptor++, CALCULUS_SIGNATURE(Signatures::Var ), CALCULUS_CALLBACK(CBToString ), &Types::String , CTI },
392 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(wldcrd ), &Types::Boolean, CTI },
393 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(wldcrd ), &Types::Boolean, CTI },
394 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SVar), CALCULUS_CALLBACK(CBFormat ), &Types::String , CTI },
395 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(toUpper ), &Types::String , CTI },
396 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(toLower ), &Types::String , CTI },
397 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(compSS ), &Types::Integer, CTI },
398 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(compSSB ), &Types::Integer, CTI },
399 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(startsWith ), &Types::Boolean, CTI },
400 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(startsWithC), &Types::Boolean, CTI },
401 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK( endsWith ), &Types::Boolean, CTI },
402 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK( endsWithC), &Types::Boolean, CTI },
403 { *descriptor , CALCULUS_SIGNATURE(Signatures::SI ), CALCULUS_CALLBACK(substr ), &Types::String , CTI },
404 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SII ), CALCULUS_CALLBACK(substr2 ), &Types::String , CTI },
405 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(idxof ), &Types::Integer, CTI },
406 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(count ), &Types::Integer, CTI },
407 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trim ), &Types::String , CTI },
408 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trim2 ), &Types::String , CTI },
409 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trimStart ), &Types::String , CTI },
410 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trimStart2 ), &Types::String , CTI },
411 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trimEnd ), &Types::String , CTI },
412 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trimEnd2 ), &Types::String , CTI },
413 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(parsei ), &Types::Integer, CTI },
414 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(parsef ), &Types::Float , CTI },
415 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSI ), CALCULUS_CALLBACK(token ), &Types::String , CTI },
416 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(hex ), &Types::String , CTI },
417 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(hex ), &Types::String , CTI },
418 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(oct ), &Types::String , CTI },
419 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(oct ), &Types::String , CTI },
420 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(bin ), &Types::String , CTI },
421 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(bin ), &Types::String , CTI },
422 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSS ), CALCULUS_CALLBACK(replace ), &Types::String , CTI },
423 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SI ), CALCULUS_CALLBACK(repeat ), &Types::String , CTI },
424
425 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
426 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(regex ), &Types::Boolean, CTI },
427 #endif
428 };
429
430 ALIB_ASSERT_ERROR( descriptor - functionNames == tableSize, "EXPR",
431 "Descriptor table size mismatch: Consumed {} descriptors, {} available.",
432 descriptor - functionNames, tableSize )
434}
435
436namespace {
437bool genericConcatenation( Type type )
438{
439 return !(
440 type.IsType<integer>()
441 || type.IsType<double >()
442 || type.IsType<String >() );
443
444}
445}
446
447DOX_MARKER([DOX_ALIB_EXPR_CTRES_2])
448bool Strings::TryCompilation( CIFunction& ciFunction )
449{
450 // invoke parent
451 if( !Calculus::TryCompilation( ciFunction ) )
452 return false;
453DOX_MARKER([DOX_ALIB_EXPR_CTRES_2])
454
455#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
456 if( ciFunction.Callback == regex && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
457 {
458 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
459 NString128 keyString("_re");
460 keyString.DbgDisableBufferReplacementWarning();
461 keyString << pattern;
462 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources.Find( keyString );
463 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources.end() )
464 {
465 ScopeRegexMatcher* matcher= new ScopeRegexMatcher();
466 matcher->matcher.Compile( pattern );
467 ciFunction.CompileTimeScope.NamedResources.EmplaceOrAssign(
468 NMAString( ciFunction.CompileTimeScope.Allocator, keyString, 0 ),
469 matcher );
470 }
471 }
472#endif
473
474DOX_MARKER([DOX_ALIB_EXPR_CTRES_3])
475 if( ciFunction.Callback == wldcrd && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
476 {
477DOX_MARKER([DOX_ALIB_EXPR_CTRES_3])
478DOX_MARKER([DOX_ALIB_EXPR_CTRES_4])
479 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
480 NString128 keyString(A_CHAR("_wc"));
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() )
488 {
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),
493 hashCode);
494 }
495 }
496 return true;
497DOX_MARKER([DOX_ALIB_EXPR_CTRES_5])
498}
499
500
501bool Strings::TryCompilation( CIBinaryOp& ciBinaryOp )
502{
503 Box& lhs= * ciBinaryOp.ArgsBegin;
504 Box& rhs= *(ciBinaryOp.ArgsBegin + 1);
505
506 // fetch string concatenation operator '+'
507 if( ciBinaryOp.Operator == A_CHAR("+") )
508 {
509 bool argsAreConst= ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst;
510
511 if( lhs.IsType<String>() && genericConcatenation(rhs) )
512 {
513 // optimize out?
514 if( argsAreConst )
515 {
516 ciBinaryOp.TypeOrValue = add_SX( ciBinaryOp.CompileTimeScope,
517 ciBinaryOp.ArgsBegin,
518 ciBinaryOp.ArgsEnd );
519 ALIB_DBG( ciBinaryOp.DbgCallbackName = "add_SX"; )
520 return true;
521 }
522
523 ciBinaryOp.Callback = add_SX;
524 ciBinaryOp.TypeOrValue = Types::String;
525 return true;
526 }
527
528 if( genericConcatenation(lhs) && rhs.IsType<String>() )
529 {
530 if( argsAreConst )
531 {
532 ciBinaryOp.TypeOrValue = add_XS( ciBinaryOp.CompileTimeScope,
533 ciBinaryOp.ArgsBegin,
534 ciBinaryOp.ArgsEnd );
535 ALIB_DBG( ciBinaryOp.DbgCallbackName = "add_XS"; )
536 return true;
537 }
538
539 ciBinaryOp.Callback = add_XS;
540 ciBinaryOp.TypeOrValue = Types::String;
541 return true;
542 }
543 }
544
545 // invoke parent
546 if( !Calculus::TryCompilation( ciBinaryOp ) )
547 return false;
548
549 // Perform the same mechanics as with TryCompilation("regex") above:
550 // check for regex match operator '*'
551#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
552 if( ciBinaryOp.Operator == A_CHAR("%") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
553 {
554 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
555 NString128 keyString(A_CHAR("_re"));
556 keyString.DbgDisableBufferReplacementWarning();
557 keyString << pattern;
558 auto hashCode = keyString.Hashcode();
559
560 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources.Find( keyString, hashCode );
561 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources.end() )
562 {
563 ScopeRegexMatcher* matcher= new ScopeRegexMatcher();
564 matcher->matcher.Compile( pattern );
565 ciBinaryOp.CompileTimeScope.NamedResources.InsertOrAssign(
566 NMAString( ciBinaryOp.CompileTimeScope.Allocator, keyString, 0 ),
567 matcher,
568 hashCode );
569 }
570 }
571#endif
572
573 // check for wildcard match operator '*'
574 if( ciBinaryOp.Operator == A_CHAR("*") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
575 {
576 String pattern= (ciBinaryOp.ArgsBegin + 1)->Unbox<String>();
577 NString128 keyString(A_CHAR("_wc"));
578 keyString.DbgDisableBufferReplacementWarning();
579 keyString << pattern;
580 auto hashCode = keyString.Hashcode();
581
582 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources.Find( keyString, hashCode );
583 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources.end() )
584 {
585 ScopeWildcardMatcher* matcher= new ScopeWildcardMatcher();
586 matcher->matcher.Compile( pattern );
587
588 NString keyCopy= ciBinaryOp.CompileTimeScope.Allocator.EmplaceString( keyString );
589 ciBinaryOp.CompileTimeScope.NamedResources.InsertUnique( std::make_pair(keyCopy, matcher),
590 hashCode );
591 }
592 }
593 return true;
594}
595
596}}} // namespace [alib::expressions::detail]
597
598
599#undef BOL
600#undef INT
601#undef FLT
602#undef STR
603#undef LEN
604#undef CPY
605#undef EMP
606#undef FUNC_UNARY
607#undef FUNC
608#undef UN_MAP_ENTRY
609#undef BIN_MAP_ENTRY
610#undef BIN_ALIAS_ENTRY
611
612//! @endcond
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())
Definition substring.hpp:89
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define CALCULUS_CALLBACK(func)
Definition calculus.hpp:34
#define CALCULUS_SIGNATURE(BoxPointerArray)
Definition calculus.hpp:41
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
#define ALIB_DBG(...)
Definition alib.hpp:457
#define ALIB_CALLER_PRUNED
Definition alib.hpp:845
#define ALIB_COMMA
Definition alib.hpp:825
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
Definition integers.hpp:50
@ Keep
Keep whitespaces in string.
Definition alib.cpp:57
expressions::plugins::Calculus Calculus
Type alias in namespace alib.
Definition calculus.hpp:903
NLocalString< 128 > NString128
Type alias name for TLocalString<nchar,128> .
lang::Exception Exception
Type alias in namespace alib.
constexpr CString NewLine()
Definition cstring.hpp:528
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.
Definition mastring.hpp:114
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.
Definition token.hpp:537
strings::TString< character > String
Type alias in namespace alib.
monomem::TMAString< character > MAString
Type alias in namespace alib.
Definition mastring.hpp:105
boxing::Box Box
Type alias in namespace alib.
expressions::Compiler Compiler
Type alias in namespace alib.
Definition compiler.hpp:596
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.
Definition integers.hpp:286
static ALIB_API Box Void
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
Definition calculus.hpp:506
static constexpr CTInvokable CTI
Definition calculus.hpp:258
ALIB_API Strings(Compiler &compiler)