/* * 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 #include #include // #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() { }