| Index: source/common/simplepatternformatter.cpp
|
| diff --git a/source/common/simplepatternformatter.cpp b/source/common/simplepatternformatter.cpp
|
| deleted file mode 100644
|
| index abaaea9dcd51f9c19feddee5124cbafb5b7b06c5..0000000000000000000000000000000000000000
|
| --- a/source/common/simplepatternformatter.cpp
|
| +++ /dev/null
|
| @@ -1,538 +0,0 @@
|
| -/*
|
| -******************************************************************************
|
| -* Copyright (C) 2014-2015, International Business Machines
|
| -* Corporation and others. All Rights Reserved.
|
| -******************************************************************************
|
| -* simplepatternformatter.cpp
|
| -*/
|
| -#include "simplepatternformatter.h"
|
| -#include "cstring.h"
|
| -#include "uassert.h"
|
| -
|
| -U_NAMESPACE_BEGIN
|
| -
|
| -static UBool isInvalidArray(const void *array, int32_t size) {
|
| - return (size < 0 || (size > 0 && array == NULL));
|
| -}
|
| -
|
| -typedef enum SimplePatternFormatterCompileState {
|
| - INIT,
|
| - APOSTROPHE,
|
| - PLACEHOLDER
|
| -} SimplePatternFormatterCompileState;
|
| -
|
| -// Handles parsing placeholders in the pattern string, e.g {4} or {35}
|
| -class SimplePatternFormatterIdBuilder {
|
| -public:
|
| - SimplePatternFormatterIdBuilder() : id(0), idLen(0) { }
|
| - ~SimplePatternFormatterIdBuilder() { }
|
| -
|
| - // Resets so that this object has seen no placeholder ID.
|
| - void reset() { id = 0; idLen = 0; }
|
| -
|
| - // Returns the numeric placeholder ID parsed so far
|
| - int32_t getId() const { return id; }
|
| -
|
| - // Appends the numeric placeholder ID parsed so far back to a
|
| - // UChar buffer. Used to recover if parser using this object finds
|
| - // no closing curly brace.
|
| - void appendTo(UChar *buffer, int32_t *len) const;
|
| -
|
| - // Returns true if this object has seen a placeholder ID.
|
| - UBool isValid() const { return (idLen > 0); }
|
| -
|
| - // Processes a single digit character. Pattern string parser calls this
|
| - // as it processes digits after an opening curly brace.
|
| - void add(UChar ch);
|
| -private:
|
| - int32_t id;
|
| - int32_t idLen;
|
| - SimplePatternFormatterIdBuilder(
|
| - const SimplePatternFormatterIdBuilder &other);
|
| - SimplePatternFormatterIdBuilder &operator=(
|
| - const SimplePatternFormatterIdBuilder &other);
|
| -};
|
| -
|
| -void SimplePatternFormatterIdBuilder::appendTo(
|
| - UChar *buffer, int32_t *len) const {
|
| - int32_t origLen = *len;
|
| - int32_t kId = id;
|
| - for (int32_t i = origLen + idLen - 1; i >= origLen; i--) {
|
| - int32_t digit = kId % 10;
|
| - buffer[i] = digit + 0x30;
|
| - kId /= 10;
|
| - }
|
| - *len = origLen + idLen;
|
| -}
|
| -
|
| -void SimplePatternFormatterIdBuilder::add(UChar ch) {
|
| - id = id * 10 + (ch - 0x30);
|
| - idLen++;
|
| -}
|
| -
|
| -// Represents placeholder values.
|
| -class SimplePatternFormatterPlaceholderValues : public UMemory {
|
| -public:
|
| - SimplePatternFormatterPlaceholderValues(
|
| - const UnicodeString * const *values,
|
| - int32_t valuesCount);
|
| -
|
| - // Returns TRUE if appendTo value is at any index besides exceptIndex.
|
| - UBool isAppendToInAnyIndexExcept(
|
| - const UnicodeString &appendTo, int32_t exceptIndex) const;
|
| -
|
| - // For each appendTo value, stores the snapshot of it in its place.
|
| - void snapshotAppendTo(const UnicodeString &appendTo);
|
| -
|
| - // Returns the placeholder value at index. No range checking performed.
|
| - // Returned reference is valid for as long as this object exists.
|
| - const UnicodeString &get(int32_t index) const;
|
| -private:
|
| - const UnicodeString * const *fValues;
|
| - int32_t fValuesCount;
|
| - const UnicodeString *fAppendTo;
|
| - UnicodeString fAppendToCopy;
|
| - SimplePatternFormatterPlaceholderValues(
|
| - const SimplePatternFormatterPlaceholderValues &);
|
| - SimplePatternFormatterPlaceholderValues &operator=(
|
| - const SimplePatternFormatterPlaceholderValues &);
|
| -};
|
| -
|
| -SimplePatternFormatterPlaceholderValues::SimplePatternFormatterPlaceholderValues(
|
| - const UnicodeString * const *values,
|
| - int32_t valuesCount)
|
| - : fValues(values),
|
| - fValuesCount(valuesCount),
|
| - fAppendTo(NULL),
|
| - fAppendToCopy() {
|
| -}
|
| -
|
| -UBool SimplePatternFormatterPlaceholderValues::isAppendToInAnyIndexExcept(
|
| - const UnicodeString &appendTo, int32_t exceptIndex) const {
|
| - for (int32_t i = 0; i < fValuesCount; ++i) {
|
| - if (i != exceptIndex && fValues[i] == &appendTo) {
|
| - return TRUE;
|
| - }
|
| - }
|
| - return FALSE;
|
| -}
|
| -
|
| -void SimplePatternFormatterPlaceholderValues::snapshotAppendTo(
|
| - const UnicodeString &appendTo) {
|
| - fAppendTo = &appendTo;
|
| - fAppendToCopy = appendTo;
|
| -}
|
| -
|
| -const UnicodeString &SimplePatternFormatterPlaceholderValues::get(
|
| - int32_t index) const {
|
| - if (fAppendTo == NULL || fAppendTo != fValues[index]) {
|
| - return *fValues[index];
|
| - }
|
| - return fAppendToCopy;
|
| -}
|
| -
|
| -SimplePatternFormatter::SimplePatternFormatter() :
|
| - noPlaceholders(),
|
| - placeholders(),
|
| - placeholderSize(0),
|
| - placeholderCount(0),
|
| - firstPlaceholderReused(FALSE) {
|
| -}
|
| -
|
| -SimplePatternFormatter::SimplePatternFormatter(const UnicodeString &pattern) :
|
| - noPlaceholders(),
|
| - placeholders(),
|
| - placeholderSize(0),
|
| - placeholderCount(0),
|
| - firstPlaceholderReused(FALSE) {
|
| - UErrorCode status = U_ZERO_ERROR;
|
| - compile(pattern, status);
|
| -}
|
| -
|
| -SimplePatternFormatter::SimplePatternFormatter(const UnicodeString &pattern,
|
| - int32_t min, int32_t max,
|
| - UErrorCode &errorCode)
|
| - : noPlaceholders(),
|
| - placeholders(),
|
| - placeholderSize(0),
|
| - placeholderCount(0),
|
| - firstPlaceholderReused(FALSE) {
|
| - compileMinMaxPlaceholders(pattern, min, max, errorCode);
|
| -}
|
| -
|
| -SimplePatternFormatter::SimplePatternFormatter(
|
| - const SimplePatternFormatter &other) :
|
| - noPlaceholders(other.noPlaceholders),
|
| - placeholders(),
|
| - placeholderSize(0),
|
| - placeholderCount(other.placeholderCount),
|
| - firstPlaceholderReused(other.firstPlaceholderReused) {
|
| - placeholderSize = ensureCapacity(other.placeholderSize);
|
| - uprv_memcpy(
|
| - placeholders.getAlias(),
|
| - other.placeholders.getAlias(),
|
| - placeholderSize * sizeof(PlaceholderInfo));
|
| -}
|
| -
|
| -SimplePatternFormatter &SimplePatternFormatter::operator=(
|
| - const SimplePatternFormatter& other) {
|
| - if (this == &other) {
|
| - return *this;
|
| - }
|
| - noPlaceholders = other.noPlaceholders;
|
| - placeholderSize = ensureCapacity(other.placeholderSize);
|
| - placeholderCount = other.placeholderCount;
|
| - firstPlaceholderReused = other.firstPlaceholderReused;
|
| - uprv_memcpy(
|
| - placeholders.getAlias(),
|
| - other.placeholders.getAlias(),
|
| - placeholderSize * sizeof(PlaceholderInfo));
|
| - return *this;
|
| -}
|
| -
|
| -SimplePatternFormatter::~SimplePatternFormatter() {
|
| -}
|
| -
|
| -UBool SimplePatternFormatter::compileMinMaxPlaceholders(
|
| - const UnicodeString &pattern,
|
| - int32_t min, int32_t max,
|
| - UErrorCode &status) {
|
| - if (U_FAILURE(status)) {
|
| - return FALSE;
|
| - }
|
| - const UChar *patternBuffer = pattern.getBuffer();
|
| - int32_t patternLength = pattern.length();
|
| - UChar *buffer = noPlaceholders.getBuffer(patternLength);
|
| - int32_t len = 0;
|
| - placeholderSize = 0;
|
| - placeholderCount = 0;
|
| - SimplePatternFormatterCompileState state = INIT;
|
| - SimplePatternFormatterIdBuilder idBuilder;
|
| - for (int32_t i = 0; i < patternLength; ++i) {
|
| - UChar ch = patternBuffer[i];
|
| - switch (state) {
|
| - case INIT:
|
| - if (ch == 0x27) {
|
| - state = APOSTROPHE;
|
| - } else if (ch == 0x7B) {
|
| - state = PLACEHOLDER;
|
| - idBuilder.reset();
|
| - } else {
|
| - buffer[len++] = ch;
|
| - }
|
| - break;
|
| - case APOSTROPHE:
|
| - if (ch == 0x27) {
|
| - buffer[len++] = 0x27;
|
| - } else if (ch == 0x7B) {
|
| - buffer[len++] = 0x7B;
|
| - } else {
|
| - buffer[len++] = 0x27;
|
| - buffer[len++] = ch;
|
| - }
|
| - state = INIT;
|
| - break;
|
| - case PLACEHOLDER:
|
| - if (ch >= 0x30 && ch <= 0x39) {
|
| - idBuilder.add(ch);
|
| - } else if (ch == 0x7D && idBuilder.isValid()) {
|
| - if (!addPlaceholder(idBuilder.getId(), len)) {
|
| - noPlaceholders.releaseBuffer(0);
|
| - status = U_MEMORY_ALLOCATION_ERROR;
|
| - return FALSE;
|
| - }
|
| - state = INIT;
|
| - } else {
|
| - buffer[len++] = 0x7B;
|
| - idBuilder.appendTo(buffer, &len);
|
| - buffer[len++] = ch;
|
| - state = INIT;
|
| - }
|
| - break;
|
| - default:
|
| - U_ASSERT(FALSE);
|
| - break;
|
| - }
|
| - }
|
| - switch (state) {
|
| - case INIT:
|
| - break;
|
| - case APOSTROPHE:
|
| - buffer[len++] = 0x27;
|
| - break;
|
| - case PLACEHOLDER:
|
| - buffer[len++] = 0X7B;
|
| - idBuilder.appendTo(buffer, &len);
|
| - break;
|
| - default:
|
| - U_ASSERT(false);
|
| - break;
|
| - }
|
| - noPlaceholders.releaseBuffer(len);
|
| - if (placeholderCount < min || max < placeholderCount) {
|
| - status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - return FALSE;
|
| - }
|
| - return TRUE;
|
| -}
|
| -
|
| -UnicodeString& SimplePatternFormatter::format(
|
| - const UnicodeString &arg0,
|
| - UnicodeString &appendTo,
|
| - UErrorCode &status) const {
|
| - const UnicodeString *params[] = {&arg0};
|
| - return formatAndAppend(
|
| - params,
|
| - UPRV_LENGTHOF(params),
|
| - appendTo,
|
| - NULL,
|
| - 0,
|
| - status);
|
| -}
|
| -
|
| -UnicodeString& SimplePatternFormatter::format(
|
| - const UnicodeString &arg0,
|
| - const UnicodeString &arg1,
|
| - UnicodeString &appendTo,
|
| - UErrorCode &status) const {
|
| - const UnicodeString *params[] = {&arg0, &arg1};
|
| - return formatAndAppend(
|
| - params,
|
| - UPRV_LENGTHOF(params),
|
| - appendTo,
|
| - NULL,
|
| - 0,
|
| - status);
|
| -}
|
| -
|
| -UnicodeString& SimplePatternFormatter::format(
|
| - const UnicodeString &arg0,
|
| - const UnicodeString &arg1,
|
| - const UnicodeString &arg2,
|
| - UnicodeString &appendTo,
|
| - UErrorCode &status) const {
|
| - const UnicodeString *params[] = {&arg0, &arg1, &arg2};
|
| - return formatAndAppend(
|
| - params,
|
| - UPRV_LENGTHOF(params),
|
| - appendTo,
|
| - NULL,
|
| - 0,
|
| - status);
|
| -}
|
| -
|
| -static void updatePlaceholderOffset(
|
| - int32_t placeholderId,
|
| - int32_t placeholderOffset,
|
| - int32_t *offsetArray,
|
| - int32_t offsetArrayLength) {
|
| - if (placeholderId < offsetArrayLength) {
|
| - offsetArray[placeholderId] = placeholderOffset;
|
| - }
|
| -}
|
| -
|
| -static void appendRange(
|
| - const UnicodeString &src,
|
| - int32_t start,
|
| - int32_t end,
|
| - UnicodeString &dest) {
|
| - // This check improves performance significantly.
|
| - if (start == end) {
|
| - return;
|
| - }
|
| - dest.append(src, start, end - start);
|
| -}
|
| -
|
| -UnicodeString& SimplePatternFormatter::formatAndAppend(
|
| - const UnicodeString * const *placeholderValues,
|
| - int32_t placeholderValueCount,
|
| - UnicodeString &appendTo,
|
| - int32_t *offsetArray,
|
| - int32_t offsetArrayLength,
|
| - UErrorCode &status) const {
|
| - if (U_FAILURE(status)) {
|
| - return appendTo;
|
| - }
|
| - if (isInvalidArray(placeholderValues, placeholderValueCount)
|
| - || isInvalidArray(offsetArray, offsetArrayLength)) {
|
| - status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - return appendTo;
|
| - }
|
| - if (placeholderValueCount < placeholderCount) {
|
| - status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - return appendTo;
|
| - }
|
| -
|
| - // Since we are disallowing parameter values that are the same as
|
| - // appendTo, we have to check all placeholderValues as opposed to
|
| - // the first placeholderCount placeholder values.
|
| - SimplePatternFormatterPlaceholderValues values(
|
| - placeholderValues, placeholderValueCount);
|
| - if (values.isAppendToInAnyIndexExcept(appendTo, -1)) {
|
| - status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - return appendTo;
|
| - }
|
| - return formatAndAppend(
|
| - values,
|
| - appendTo,
|
| - offsetArray,
|
| - offsetArrayLength);
|
| -}
|
| -
|
| -UnicodeString& SimplePatternFormatter::formatAndReplace(
|
| - const UnicodeString * const *placeholderValues,
|
| - int32_t placeholderValueCount,
|
| - UnicodeString &result,
|
| - int32_t *offsetArray,
|
| - int32_t offsetArrayLength,
|
| - UErrorCode &status) const {
|
| - if (U_FAILURE(status)) {
|
| - return result;
|
| - }
|
| - if (isInvalidArray(placeholderValues, placeholderValueCount)
|
| - || isInvalidArray(offsetArray, offsetArrayLength)) {
|
| - status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - return result;
|
| - }
|
| - if (placeholderValueCount < placeholderCount) {
|
| - status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - return result;
|
| - }
|
| - SimplePatternFormatterPlaceholderValues values(
|
| - placeholderValues, placeholderCount);
|
| - int32_t placeholderAtStart = getUniquePlaceholderAtStart();
|
| -
|
| - // If pattern starts with a unique placeholder and that placeholder
|
| - // value is result, we may be able to optimize by just appending to result.
|
| - if (placeholderAtStart >= 0
|
| - && placeholderValues[placeholderAtStart] == &result) {
|
| -
|
| - // If result is the value for other placeholders, call off optimization.
|
| - if (values.isAppendToInAnyIndexExcept(result, placeholderAtStart)) {
|
| - values.snapshotAppendTo(result);
|
| - result.remove();
|
| - return formatAndAppend(
|
| - values,
|
| - result,
|
| - offsetArray,
|
| - offsetArrayLength);
|
| - }
|
| -
|
| - // Otherwise we can optimize
|
| - formatAndAppend(
|
| - values,
|
| - result,
|
| - offsetArray,
|
| - offsetArrayLength);
|
| -
|
| - // We have to make the offset for the placeholderAtStart
|
| - // placeholder be 0. Otherwise it would be the length of the
|
| - // previous value of result.
|
| - if (offsetArrayLength > placeholderAtStart) {
|
| - offsetArray[placeholderAtStart] = 0;
|
| - }
|
| - return result;
|
| - }
|
| - if (values.isAppendToInAnyIndexExcept(result, -1)) {
|
| - values.snapshotAppendTo(result);
|
| - }
|
| - result.remove();
|
| - return formatAndAppend(
|
| - values,
|
| - result,
|
| - offsetArray,
|
| - offsetArrayLength);
|
| -}
|
| -
|
| -UnicodeString& SimplePatternFormatter::formatAndAppend(
|
| - const SimplePatternFormatterPlaceholderValues &values,
|
| - UnicodeString &appendTo,
|
| - int32_t *offsetArray,
|
| - int32_t offsetArrayLength) const {
|
| - for (int32_t i = 0; i < offsetArrayLength; ++i) {
|
| - offsetArray[i] = -1;
|
| - }
|
| - if (placeholderSize == 0) {
|
| - appendTo.append(noPlaceholders);
|
| - return appendTo;
|
| - }
|
| - appendRange(
|
| - noPlaceholders,
|
| - 0,
|
| - placeholders[0].offset,
|
| - appendTo);
|
| - updatePlaceholderOffset(
|
| - placeholders[0].id,
|
| - appendTo.length(),
|
| - offsetArray,
|
| - offsetArrayLength);
|
| - const UnicodeString *placeholderValue = &values.get(placeholders[0].id);
|
| - if (placeholderValue != &appendTo) {
|
| - appendTo.append(*placeholderValue);
|
| - }
|
| - for (int32_t i = 1; i < placeholderSize; ++i) {
|
| - appendRange(
|
| - noPlaceholders,
|
| - placeholders[i - 1].offset,
|
| - placeholders[i].offset,
|
| - appendTo);
|
| - updatePlaceholderOffset(
|
| - placeholders[i].id,
|
| - appendTo.length(),
|
| - offsetArray,
|
| - offsetArrayLength);
|
| - placeholderValue = &values.get(placeholders[i].id);
|
| - if (placeholderValue != &appendTo) {
|
| - appendTo.append(*placeholderValue);
|
| - }
|
| - }
|
| - appendRange(
|
| - noPlaceholders,
|
| - placeholders[placeholderSize - 1].offset,
|
| - noPlaceholders.length(),
|
| - appendTo);
|
| - return appendTo;
|
| -}
|
| -
|
| -int32_t SimplePatternFormatter::getUniquePlaceholderAtStart() const {
|
| - if (placeholderSize == 0
|
| - || firstPlaceholderReused || placeholders[0].offset != 0) {
|
| - return -1;
|
| - }
|
| - return placeholders[0].id;
|
| -}
|
| -
|
| -int32_t SimplePatternFormatter::ensureCapacity(
|
| - int32_t desiredCapacity, int32_t allocationSize) {
|
| - if (allocationSize < desiredCapacity) {
|
| - allocationSize = desiredCapacity;
|
| - }
|
| - if (desiredCapacity <= placeholders.getCapacity()) {
|
| - return desiredCapacity;
|
| - }
|
| - // allocate new buffer
|
| - if (placeholders.resize(allocationSize, placeholderSize) == NULL) {
|
| - return placeholders.getCapacity();
|
| - }
|
| - return desiredCapacity;
|
| -}
|
| -
|
| -UBool SimplePatternFormatter::addPlaceholder(int32_t id, int32_t offset) {
|
| - if (ensureCapacity(placeholderSize + 1, 2 * placeholderSize) < placeholderSize + 1) {
|
| - return FALSE;
|
| - }
|
| - ++placeholderSize;
|
| - PlaceholderInfo *placeholderEnd = &placeholders[placeholderSize - 1];
|
| - placeholderEnd->offset = offset;
|
| - placeholderEnd->id = id;
|
| - if (id >= placeholderCount) {
|
| - placeholderCount = id + 1;
|
| - }
|
| - if (placeholderSize > 1
|
| - && placeholders[placeholderSize - 1].id == placeholders[0].id) {
|
| - firstPlaceholderReused = TRUE;
|
| - }
|
| - return TRUE;
|
| -}
|
| -
|
| -U_NAMESPACE_END
|
|
|