Skip to content

Commit ccac0ac

Browse files
committed
compiler/eccss: Initial take at LIKE comparison function
- Co-authored With Patrick
1 parent bdb3f9e commit ccac0ac

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

compiler/eccss/eccss.ec

+83-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ enum ECCSSFunctionIndex : int
1111
strlwr,
1212
subst,
1313
format,
14-
pow
14+
pow,
15+
like
1516
};
1617

1718
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 *
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
239305
public 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;

compiler/eccss/expressions.ec

+2-1
Original file line numberDiff line numberDiff line change
@@ -1261,7 +1261,8 @@ public:
12611261
}
12621262
if(nonResolved) flags.resolved = false;
12631263
}
1264-
if(evaluator != null && computeType != preprocessing && flags.resolved)
1264+
// We need to evaluate the function if resolved is true (should not yet be set if e.g., featureID / geometry is needed)
1265+
if(evaluator != null && flags.resolved)
12651266
expType = evaluator.evaluatorClass.computeFunction(evaluator, value, expValue, args, numArgs, &flags);
12661267
}
12671268
return flags;

0 commit comments

Comments
 (0)