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