Skip to content

Commit

Permalink
compiler/ecsss: Initial take at LIKE comparison function
Browse files Browse the repository at this point in the history
- Co-authored With Patrick
  • Loading branch information
jerstlouis committed Jul 12, 2023
1 parent bdb3f9e commit 43fc1b2
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
84 changes: 83 additions & 1 deletion compiler/eccss/eccss.ec
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ enum ECCSSFunctionIndex : int
strlwr,
subst,
format,
pow
pow,
like
};

static int strncpymax(String output, const String input, int count, int max)
Expand Down Expand Up @@ -235,6 +236,71 @@ static String formatValues(const String format, int numArgs, const FieldValue *
return CopyString(output);
}

#define MAX_WILDCARD 300

/*static */bool like(const String string, const String pattern)
{
bool result = true;
int wildcardPosition[MAX_WILDCARD], stringPosition[MAX_WILDCARD], currentWildcard = 0;
int i, j;
char chp;
bool lastWasWildcard = false;

for(i = 0, j = 0; (chp = pattern[i]); i++, j++)
{
char chs = string[j];

lastWasWildcard = false;
if(chs && chp == '_')
{
// Match any single char (but it might be multiple bytes for unicode chars)
int nb;
UTF8GetChar(string + j, &nb);
j += nb - 1;
}
else
{
if(chp == '%')
{
if(pattern[i+1] == '%')
i++; // Escaped (%%) actual % to match
else
{
lastWasWildcard = true;
// Wildcard
if(chs && currentWildcard < MAX_WILDCARD)
{
wildcardPosition[currentWildcard] = i;
stringPosition[currentWildcard] = j;
currentWildcard++;
}
j--; // Start trying at j
continue;
}
}
if(chs != chp)
{
// Mismatch, abort or continue trying to match wildcard
if(currentWildcard)
{
currentWildcard--;
i = wildcardPosition[currentWildcard]-1;
j = stringPosition[currentWildcard];
}
else
{
if(!lastWasWildcard || pattern[i + 1])
result = false;
break;
}
}
}
}
// Mismatch if we have any character left in the string and are not still in a wildcard
if(!lastWasWildcard && string[j]) result = false;
return result;
}

// For extending ECCSS with custom identifiers and styling properties
public struct ECCSSEvaluator
{
Expand Down Expand Up @@ -307,6 +373,13 @@ public struct ECCSSEvaluator
expType = class(double);
break;
}
case like:
{
if(args.list.count >= 1) args[0].destType = class(String);
if(args.list.count >= 2) args[1].destType = class(String);
expType = class(bool);
break;
}
}
}
return expType;
Expand Down Expand Up @@ -380,6 +453,15 @@ public struct ECCSSEvaluator
}
break;
}
case like:
{
if(numArgs >= 2 && args[0].type.type == text && args[1].type.type == text)
{
value.type = { type = integer/*, format = boolean*/ };
value.i = like(args[0].s, args[1].s);
}
break;
}
}
}
return expType;
Expand Down
3 changes: 2 additions & 1 deletion compiler/eccss/expressions.ec
Original file line number Diff line number Diff line change
Expand Up @@ -1261,7 +1261,8 @@ public:
}
if(nonResolved) flags.resolved = false;
}
if(evaluator != null && computeType != preprocessing && flags.resolved)
// We need to evaluate the function if resolved is true (should not yet be set if e.g., featureID / geometry is needed)
if(evaluator != null && flags.resolved)
expType = evaluator.evaluatorClass.computeFunction(evaluator, value, expValue, args, numArgs, &flags);
}
return flags;
Expand Down

0 comments on commit 43fc1b2

Please sign in to comment.