@@ -11,7 +11,8 @@ enum ECCSSFunctionIndex : int
1111 strlwr,
1212 subst,
1313 format,
14- pow
14+ pow,
15+ like
1516};
1617
1718static int strncpymax (String output, const String input, int count, int max)
@@ -235,6 +236,71 @@ static String formatValues(const String format, int numArgs, const FieldValue *
235236 return CopyString (output);
236237}
237238
239+ #define MAX_WILDCARD 300
240+
241+ /* static */ bool like (const String string, const String pattern)
242+ {
243+ bool result = true ;
244+ int wildcardPosition[MAX_WILDCARD], stringPosition[MAX_WILDCARD], currentWildcard = 0 ;
245+ int i, j;
246+ char chp;
247+ bool lastWasWildcard = false ;
248+
249+ for (i = 0 , j = 0 ; (chp = pattern[i]); i++, j++)
250+ {
251+ char chs = string[j];
252+
253+ lastWasWildcard = false ;
254+ if (chs && chp == ' _' )
255+ {
256+ // Match any single char (but it might be multiple bytes for unicode chars)
257+ int nb;
258+ UTF8GetChar (string + j, &nb);
259+ j += nb - 1 ;
260+ }
261+ else
262+ {
263+ if (chp == ' %' )
264+ {
265+ if (pattern[i+1 ] == ' %' )
266+ i++; // Escaped (%%) actual % to match
267+ else
268+ {
269+ lastWasWildcard = true ;
270+ // Wildcard
271+ if (chs && currentWildcard < MAX_WILDCARD)
272+ {
273+ wildcardPosition[currentWildcard] = i;
274+ stringPosition[currentWildcard] = j;
275+ currentWildcard++;
276+ }
277+ j--; // Start trying at j
278+ continue ;
279+ }
280+ }
281+ if (chs != chp)
282+ {
283+ // Mismatch, abort or continue trying to match wildcard
284+ if (currentWildcard)
285+ {
286+ currentWildcard--;
287+ i = wildcardPosition[currentWildcard]-1 ;
288+ j = stringPosition[currentWildcard];
289+ }
290+ else
291+ {
292+ if (!lastWasWildcard || pattern[i + 1 ])
293+ result = false ;
294+ break ;
295+ }
296+ }
297+ }
298+ }
299+ // Mismatch if we have any character left in the string and are not still in a wildcard
300+ if (!lastWasWildcard && string[j]) result = false ;
301+ return result;
302+ }
303+
238304// For extending ECCSS with custom identifiers and styling properties
239305public struct ECCSSEvaluator
240306{
@@ -307,6 +373,13 @@ public struct ECCSSEvaluator
307373 expType = class (double );
308374 break ;
309375 }
376+ case like:
377+ {
378+ if (args.list .count >= 1 ) args[0 ].destType = class (String);
379+ if (args.list .count >= 2 ) args[1 ].destType = class (String);
380+ expType = class (bool );
381+ break ;
382+ }
310383 }
311384 }
312385 return expType;
@@ -380,6 +453,15 @@ public struct ECCSSEvaluator
380453 }
381454 break ;
382455 }
456+ case like:
457+ {
458+ if (numArgs >= 2 && args[0 ].type .type == text && args[1 ].type .type == text)
459+ {
460+ value .type = { type = integer/* , format = boolean*/ };
461+ value .i = like (args[0 ].s , args[1 ].s );
462+ }
463+ break ;
464+ }
383465 }
384466 }
385467 return expType;
0 commit comments