ALib C++ Library
Library Version: 2412 R0
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 !DOXYGEN
15#endif // !DOXYGEN
16
17
18//! @cond NO_DOX
19
20#define ARG0 (*args)
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)
30
31#define FUNC( name,...) Box name( Scope& scope, \
32 ArgIterator args, \
33 ArgIterator end ) \
34 { (void) scope; (void) args; (void) end; __VA_ARGS__ }
35#if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
36# define TOINT(arg) arg
37#else
38# define TOINT(arg) static_cast<integer>(arg)
39#endif
40
41
42namespace alib { namespace expressions { namespace plugins {
43
44// #################################################################################################
45// ### ToString (not in anonymous namespace)
46// #################################################################################################
47Box CBToString( Scope& scope, ArgIterator args, ArgIterator end)
48{
49 String256 tmp;
50 tmp.DbgDisableBufferReplacementWarning();
51 while( args < end )
52 {
53 Box& arg= *args;
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);
56 else tmp << arg;
57
58 ++args;
59 }
60
61 return String(scope.Allocator, tmp);
62}
63
64// #################################################################################################
65// ### Format (not in anonymous namespace)
66// #################################################################################################
67Box CBFormat( Scope& scope, ArgIterator args, ArgIterator end)
68{
69 String1K buf;
70 buf.DbgDisableBufferReplacementWarning();
71
72 BoxesMA& formatterArgs= scope.Formatter->GetArgContainer();
73 while( args != end)
74 formatterArgs.Add( *args++ );
75
76 try
77 {
78 scope.Formatter->FormatArgs( buf );
79 }
80 catch( Exception& )
81 {
82 throw;
83 }
84
85 return String( scope.Allocator, buf );
86}
87
88
89namespace {
90
91
92// #################################################################################################
93// ### String - constants
94// #################################################################################################
95Box constTAB;
96Box constNL;
97
98// #################################################################################################
99// ### String functions
100// #################################################################################################
101
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 ); )
116
117FUNC(trim , return Substring(STR(ARG0)).Trim ( ); )
118FUNC(trim2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).Trim (ws); )
119FUNC(trimStart , return Substring(STR(ARG0)).TrimStart( ); )
120FUNC(trimStart2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).TrimStart(ws); )
121FUNC(trimEnd , return Substring(STR(ARG0)).TrimEnd ( ); )
122FUNC(trimEnd2 , String256 ws(STR(ARG1)); return Substring(STR(ARG0)).TrimEnd (ws); )
123
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; )
126
127FUNC(token , Tokenizer tknzr( STR(ARG0), STR(ARG1).CharAtStart() );
128 for( auto i= INT(ARG2) ; i >= 0 ; --i )
129 tknzr.Next( lang::Whitespaces::Keep );
130 return tknzr.Actual; )
131
132FUNC(hex , String128 buf;
133 buf << Format::Hex( static_cast<uint64_t>(INT(ARG0)),
134 args + 1 != end ? static_cast<int>(INT(ARG1)) : 0,
135 &scope.Formatter->DefaultNumberFormat );
136 return ALLOCS(buf); )
137FUNC(oct , String128 buf;
138 buf << Format::Oct( static_cast<uint64_t>(INT(ARG0)),
139 args + 1 != end ? static_cast<int>(INT(ARG1)) : 0,
140 &scope.Formatter->DefaultNumberFormat );
141 return ALLOCS(buf); )
142FUNC(bin , String128 buf;
143 buf << Format::Bin( static_cast<uint64_t>(INT(ARG0)),
144 args + 1 != end ? static_cast<int>(INT(ARG1)) : 0,
145 &scope.Formatter->DefaultNumberFormat );
146 return ALLOCS(buf); )
147
148
149Box replace( Scope& scope, ArgIterator args, ArgIterator )
150{
151 String src = STR(ARG0);
152 String needle = STR(ARG1);
153 String replacement= STR(ARG2);
154
155 // replace char with char?
156 if( needle.Length() == 1 && replacement.Length() == 1 )
157 {
158 String2K result(src);
159 result.SearchAndReplace( needle[0], replacement[0], 0 );
160 return ALLOCS(result);
161 }
162
163 // replace string with char or string
164 String256 buf;
165 buf.DbgDisableBufferReplacementWarning();
166 buf << src;
167 buf.SearchAndReplace( needle, replacement, 0 );
168 return ALLOCS(buf);
169}
170
171Box repeat( Scope& scope, ArgIterator args, ArgIterator )
172{
173 String src = STR(ARG0);
174 String256 buf;
175 buf.DbgDisableBufferReplacementWarning();
176 for( auto i= INT(ARG1) ; i > 0 ; --i )
177 buf << src;
178 return ALLOCS(buf);
179}
180
181// #################################################################################################
182// ### Strings - Unary operators
183// #################################################################################################
184FUNC(boolNot, return LEN(ARG0) == 0; )
185
186
187// #################################################################################################
188// ### Strings - Binary operators
189// #################################################################################################
190
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 )); )
193
194
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)); )
200
201
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) ); )
208
209FUNC( arr, return STR(ARG0).Substring( INT(ARG1), 1); )
210
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) ) ); )
214
215// #################################################################################################
216// ### Strings - Wildcard matching
217// #################################################################################################
218DOX_MARKER([DOX_EXPR_CTRES_1])
219struct ScopeWildcardMatcher : public ScopeResource
220{
221 // the matcher object
222 WildcardMatcher matcher;
223
224 // virtual destructor, implicitly deletes the matcher.
225 virtual ~ScopeWildcardMatcher() override {}
226};
227DOX_MARKER([DOX_EXPR_CTRES_1])
228
229DOX_MARKER([DOX_EXPR_CTRES_6])
230Box wldcrd( Scope& scope, ArgIterator args, ArgIterator end )
231{
232 String haystack= STR(ARG0);
233 String pattern = STR(ARG1);
234 lang::Case sensitivity= ( end-args > 2 && BOL(ARG2) ) ? lang::Case::Ignore
235 : lang::Case::Sensitive;
236
237 if( !scope.IsCompileTime() )
238 {
239 // Search for resource named "_wc"+ pattern.
240 NString128 keyString("_wc");
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 );
247 }
248DOX_MARKER([DOX_EXPR_CTRES_6])
249
250DOX_MARKER([DOX_EXPR_CTRES_7])
251 // This is either compile-time (with both arguments being constant) or it is
252 // evaluation time and the pattern string is not constant.
253 {
254 WildcardMatcher matcher( pattern );
255 return matcher.Match( haystack, sensitivity );
256 }
257}
258DOX_MARKER([DOX_EXPR_CTRES_7])
259
260// #################################################################################################
261// ### Strings - Regex matching
262// #################################################################################################
263#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
264struct ScopeRegexMatcher : public ScopeResource
265{
266 // the matcher object
267 RegexMatcher matcher;
268
269 // virtual destructor, implicitly deletes the matcher.
270 virtual ~ScopeRegexMatcher() override {}
271};
272
273Box regex( Scope& scope, ArgIterator args, ArgIterator )
274{
275 String haystack= STR(ARG0);
276 String pattern = STR(ARG1);
277
278 if( !scope.IsCompileTime() )
279 {
280 // Search for resource named "_wc"+ pattern.
281 NString128 keyString( "_re" );
282 keyString.DbgDisableBufferReplacementWarning();
283 keyString << pattern;
284 auto storedMatcher= scope.vmMembers->CTScope->NamedResources->Find( keyString );
285 if( storedMatcher != scope.vmMembers->CTScope->NamedResources->end() )
286 {
287 ScopeRegexMatcher* matcher= dynamic_cast<ScopeRegexMatcher*>( storedMatcher->second );
288 return matcher->matcher.Match( haystack );
289 }
290 }
291
292 // This is either compile-time or the pattern string is not constant
293 {
294 RegexMatcher matcher( pattern );
295 return matcher.Match( haystack );
296 }
297}
298#endif
299
300// #################################################################################################
301// ### Strings - Tables
302// #################################################################################################
303constexpr Calculus::OperatorTableEntry operatorTableStrings[] =
304{
305 // unary operators
309
310 // binary operators
323 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
325 #endif
327};
328
329
330} // anonymous namespace
331
332// #################################################################################################
333// ### Strings - Constructor. Creates the hash map
334// #################################################################################################
335Strings::Strings( Compiler& compiler )
336: Calculus( "ALib Strings", compiler, CompilePriorities::Strings )
337{
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 Token::LoadResourcedTokens( EXPRESSIONS, "CPS", functionNames
352 ALIB_DBG(,tableSize) );
354 Token* descriptor= functionNames;
355
356 // Constant identifiers
357 ConstantIdentifiers=
358 {
359 { *descriptor++, constNL },
360 { *descriptor++, constTAB },
361 };
362
363 Functions=
364 {
365 { *descriptor++, CALCULUS_SIGNATURE(Signatures::Var ), CALCULUS_CALLBACK(CBToString ), &Types::String , CTI },
366 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(wldcrd ), &Types::Boolean, CTI },
367 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(wldcrd ), &Types::Boolean, CTI },
368 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SVar), CALCULUS_CALLBACK(CBFormat ), &Types::String , CTI },
369 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(toUpper ), &Types::String , CTI },
370 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(toLower ), &Types::String , CTI },
371 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(compSS ), &Types::Integer, CTI },
372 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(compSSB ), &Types::Integer, CTI },
373 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(startsWith ), &Types::Boolean, CTI },
374 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK(startsWithC), &Types::Boolean, CTI },
375 { *descriptor , CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK( endsWith ), &Types::Boolean, CTI },
376 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSB ), CALCULUS_CALLBACK( endsWithC), &Types::Boolean, CTI },
377 { *descriptor , CALCULUS_SIGNATURE(Signatures::SI ), CALCULUS_CALLBACK(substr ), &Types::String , CTI },
378 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SII ), CALCULUS_CALLBACK(substr2 ), &Types::String , CTI },
379 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(idxof ), &Types::Integer, CTI },
380 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(count ), &Types::Integer, CTI },
381 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trim ), &Types::String , CTI },
382 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trim2 ), &Types::String , CTI },
383 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trimStart ), &Types::String , CTI },
384 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trimStart2 ), &Types::String , CTI },
385 { *descriptor , CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(trimEnd ), &Types::String , CTI },
386 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(trimEnd2 ), &Types::String , CTI },
387 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(parsei ), &Types::Integer, CTI },
388 { *descriptor++, CALCULUS_SIGNATURE(Signatures::S ), CALCULUS_CALLBACK(parsef ), &Types::Float , CTI },
389 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSI ), CALCULUS_CALLBACK(token ), &Types::String , CTI },
390 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(hex ), &Types::String , CTI },
391 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(hex ), &Types::String , CTI },
392 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(oct ), &Types::String , CTI },
393 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(oct ), &Types::String , CTI },
394 { *descriptor , CALCULUS_SIGNATURE(Signatures::I ), CALCULUS_CALLBACK(bin ), &Types::String , CTI },
395 { *descriptor++, CALCULUS_SIGNATURE(Signatures::II ), CALCULUS_CALLBACK(bin ), &Types::String , CTI },
396 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SSS ), CALCULUS_CALLBACK(replace ), &Types::String , CTI },
397 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SI ), CALCULUS_CALLBACK(repeat ), &Types::String , CTI },
398
399 #if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
400 { *descriptor++, CALCULUS_SIGNATURE(Signatures::SS ), CALCULUS_CALLBACK(regex ), &Types::Boolean, CTI },
401 #endif
402 };
403
404 ALIB_ASSERT_ERROR( descriptor - functionNames == tableSize, "EXPR",
405 "Descriptor table size mismatch: Consumed {} descriptors, {} available.",
406 descriptor - functionNames, tableSize )
408}
409
410namespace {
411bool genericConcatenation( Type type )
412{
413 return !(
414 type.IsType<integer>()
415 || type.IsType<double >()
416 || type.IsType<String >() );
417
418}
419}
420
421DOX_MARKER([DOX_EXPR_CTRES_2])
422bool Strings::TryCompilation( CIFunction& ciFunction )
423{
424 // invoke parent
425 if( !Calculus::TryCompilation( ciFunction ) )
426 return false;
427DOX_MARKER([DOX_EXPR_CTRES_2])
428
429#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
430 if( ciFunction.Callback == regex && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
431 {
432 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
433 NString128 keyString("_re");
434 keyString.DbgDisableBufferReplacementWarning();
435 keyString << pattern;
436 auto storedMatcher= ciFunction.CompileTimeScope.NamedResources->Find( keyString );
437 if( storedMatcher == ciFunction.CompileTimeScope.NamedResources->end() )
438 {
439 auto& alloc= ciFunction.CompileTimeScope.Allocator;
440 ScopeRegexMatcher* matcher= alloc().New<ScopeRegexMatcher>();
441 matcher->matcher.Compile( pattern );
442 ciFunction.CompileTimeScope.NamedResources->EmplaceOrAssign(
443 NString( alloc, keyString ),
444 matcher );
445 }
446 }
447#endif
448
449DOX_MARKER([DOX_EXPR_CTRES_3])
450 if( ciFunction.Callback == wldcrd && (ciFunction.ArgsBegin + 1)->UnboxLength() > 0)
451 {
452DOX_MARKER([DOX_EXPR_CTRES_3])
453DOX_MARKER([DOX_EXPR_CTRES_4])
454 String pattern= (ciFunction.ArgsBegin + 1)->Unbox<String>();
455 NString128 keyString(A_CHAR("_wc"));
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() )
463 {
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),
469 hashCode);
470 }
471 }
472 return true;
473DOX_MARKER([DOX_EXPR_CTRES_5])
474}
475
476
477bool Strings::TryCompilation( CIBinaryOp& ciBinaryOp )
478{
479 Box& lhs= * ciBinaryOp.ArgsBegin;
480 Box& rhs= *(ciBinaryOp.ArgsBegin + 1);
481
482 // fetch string concatenation operator '+'
483 if( ciBinaryOp.Operator == A_CHAR("+") )
484 {
485 bool argsAreConst= ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst;
486
487 if( lhs.IsType<String>() && genericConcatenation(rhs) )
488 {
489 // optimize out?
490 if( argsAreConst )
491 {
492 ciBinaryOp.TypeOrValue = add_SX( ciBinaryOp.CompileTimeScope,
493 ciBinaryOp.ArgsBegin,
494 ciBinaryOp.ArgsEnd );
495 ALIB_DBG( ciBinaryOp.DbgCallbackName = "add_SX"; )
496 return true;
497 }
498
499 ciBinaryOp.Callback = add_SX;
500 ciBinaryOp.TypeOrValue = Types::String;
501 return true;
502 }
503
504 if( genericConcatenation(lhs) && rhs.IsType<String>() )
505 {
506 if( argsAreConst )
507 {
508 ciBinaryOp.TypeOrValue = add_XS( ciBinaryOp.CompileTimeScope,
509 ciBinaryOp.ArgsBegin,
510 ciBinaryOp.ArgsEnd );
511 ALIB_DBG( ciBinaryOp.DbgCallbackName = "add_XS"; )
512 return true;
513 }
514
515 ciBinaryOp.Callback = add_XS;
516 ciBinaryOp.TypeOrValue = Types::String;
517 return true;
518 }
519 }
520
521 // invoke parent
522 if( !Calculus::TryCompilation( ciBinaryOp ) )
523 return false;
524
525 // Perform the same mechanics as with TryCompilation("regex") above:
526 // check for regex match operator '*'
527#if ALIB_FEAT_BOOST_REGEX && (!ALIB_CHARACTERS_WIDE || ALIB_CHARACTERS_NATIVE_WCHAR)
528 if( ciBinaryOp.Operator == A_CHAR("%") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
529 {
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();
535
536 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources->Find( keyString, hashCode );
537 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources->end() )
538 {
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 ),
544 matcher,
545 hashCode );
546 }
547 }
548#endif
549
550 // check for wildcard match operator '*'
551 if( ciBinaryOp.Operator == A_CHAR("*") && !ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
552 {
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();
558
559 auto storedMatcher= ciBinaryOp.CompileTimeScope.NamedResources->Find( keyString, hashCode );
560 if( storedMatcher == ciBinaryOp.CompileTimeScope.NamedResources->end() )
561 {
562 auto& alloc= ciBinaryOp.CompileTimeScope.Allocator;
563 ScopeWildcardMatcher* matcher= alloc().New<ScopeWildcardMatcher>();
564 matcher->matcher.Compile( pattern );
565
566 NString keyCopy(alloc, keyString);
567 ciBinaryOp.CompileTimeScope.NamedResources->InsertUnique( std::make_pair(keyCopy, matcher),
568 hashCode );
569 }
570 }
571 return true;
572}
573
574}}} // namespace [alib::expressions::detail]
575
576
577#undef BOL
578#undef INT
579#undef FLT
580#undef STR
581#undef LEN
582#undef CPY
583#undef EMP
584#undef FUNC_UNARY
585#undef FUNC
586#undef UN_MAP_ENTRY
587#undef BIN_MAP_ENTRY
588#undef BIN_ALIAS_ENTRY
589
590//! @endcond
TBoxes & Add()
Definition boxes.inl:74
constexpr integer Length() const
Definition string.hpp:326
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())
Definition substring.hpp:89
bool ConsumeInt(TIntegral &result, TNumberFormat< TChar > *numberFormat=nullptr)
TSubstring & Trim(const TCString< TChar > &whiteSpaces=TT_CStringConstants< TChar >::DefaultWhitespaces())
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:849
#define CALCULUS_CALLBACK(func)
Definition calculus.hpp:29
#define CALCULUS_SIGNATURE(BoxPointerArray)
Definition calculus.hpp:36
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:760
#define ALIB_DBG(...)
Definition alib.hpp:390
#define ALIB_COMMA
Definition alib.hpp:982
TChar ToUpper(TChar c)
TChar ToLower(TChar c)
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
Definition integers.hpp:43
@ Keep
Keep whitespaces in string.
Case
Denotes upper and lower case character treatment.
Definition alib.cpp:69
expressions::plugins::Calculus Calculus
Type alias in namespace alib.
Definition calculus.hpp:851
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.
Definition cstring.hpp:580
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.
Definition token.hpp:551
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.
Definition compiler.hpp:553
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:273
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
Definition calculus.hpp:473
static constexpr CTInvokable CTI
Definition calculus.hpp:249
ALIB_API Strings(Compiler &compiler)