@@ -11,7 +11,8 @@ enum ECCSSFunctionIndex : int
11
11
strlwr,
12
12
subst,
13
13
format,
14
- pow
14
+ pow ,
15
+ like
15
16
};
16
17
17
18
static 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 *
235
236
return CopyString (output);
236
237
}
237
238
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
+
238
304
// For extending ECCSS with custom identifiers and styling properties
239
305
public struct ECCSSEvaluator
240
306
{
@@ -307,6 +373,13 @@ public struct ECCSSEvaluator
307
373
expType = class (double );
308
374
break ;
309
375
}
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
+ }
310
383
}
311
384
}
312
385
return expType;
@@ -380,6 +453,15 @@ public struct ECCSSEvaluator
380
453
}
381
454
break ;
382
455
}
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
+ }
383
465
}
384
466
}
385
467
return expType;
0 commit comments