128 lines
2.6 KiB
C++
128 lines
2.6 KiB
C++
/*
|
|
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
|
* Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
|
|
#include "PatternEvaluator.h"
|
|
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
|
|
// #pragma mark - PatternEvaluator
|
|
|
|
|
|
/*static*/ BString
|
|
PatternEvaluator::Evaluate(const char* pattern, PlaceholderMapper& mapper)
|
|
{
|
|
BString result;
|
|
BString before;
|
|
bool isBefore = false;
|
|
bool isAfter = false;
|
|
bool hadResult = false;
|
|
bool began = false;
|
|
|
|
while (*pattern != '\0') {
|
|
// find next placeholder
|
|
const char* placeholder = strchr(pattern, '%');
|
|
size_t length = 0;
|
|
if (placeholder != NULL)
|
|
length = placeholder - pattern;
|
|
else
|
|
length = INT_MAX;
|
|
|
|
// append skipped chars
|
|
if (placeholder != pattern) {
|
|
if (isBefore) {
|
|
before.SetTo(pattern, length);
|
|
isBefore = false;
|
|
} else if (!isAfter || hadResult) {
|
|
result.Append(pattern, length);
|
|
isBefore = false;
|
|
before.SetTo(NULL);
|
|
isAfter = false;
|
|
}
|
|
}
|
|
if (placeholder == NULL)
|
|
return result;
|
|
|
|
pattern = placeholder + 1;
|
|
|
|
// check for special placeholders
|
|
switch (pattern[0]) {
|
|
case '%':
|
|
// An escaped '%'
|
|
result += '%';
|
|
pattern++;
|
|
continue;
|
|
case '<':
|
|
// An optional before string
|
|
isBefore = began = true;
|
|
hadResult = false;
|
|
pattern++;
|
|
continue;
|
|
case '>':
|
|
// An optional after string
|
|
isAfter = true;
|
|
began = false;
|
|
before.SetTo(NULL);
|
|
pattern++;
|
|
continue;
|
|
case '-':
|
|
// End of any other section; ignore
|
|
pattern++;
|
|
isBefore = false;
|
|
isAfter = false;
|
|
continue;
|
|
}
|
|
// Count non alpha numeric characters to the before section
|
|
while (pattern[0] != '\0' && !isalnum(pattern[0])) {
|
|
before.Append(pattern[0], 1);
|
|
pattern++;
|
|
}
|
|
|
|
// parse a number, if there is one
|
|
int64 number = 0;
|
|
bool hasNumber = false;
|
|
if (isdigit(*pattern)) {
|
|
char* numberEnd;
|
|
number = strtoll(pattern, &numberEnd, 10);
|
|
pattern = numberEnd;
|
|
hasNumber = true;
|
|
}
|
|
|
|
BString mappedValue;
|
|
if (*pattern != '\0' && mapper.MapPlaceholder(*pattern,
|
|
number, hasNumber, mappedValue)) {
|
|
// mapped successfully -- append the replacement string
|
|
if (began && !mappedValue.IsEmpty())
|
|
hadResult = true;
|
|
if (!before.IsEmpty() && !mappedValue.IsEmpty()) {
|
|
result += before;
|
|
before.SetTo(NULL);
|
|
}
|
|
|
|
result += mappedValue;
|
|
pattern++;
|
|
} else {
|
|
// something went wrong -- just append the literal part of the
|
|
// pattern
|
|
result.Append(placeholder, length);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
// #pragma mark - PlaceholderMapper
|
|
|
|
|
|
PatternEvaluator::PlaceholderMapper::~PlaceholderMapper()
|
|
{
|
|
}
|