1fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/* 2fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius****************************************************************************** 3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 2014, International Business Machines 4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Corporation and others. All Rights Reserved. 5fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius****************************************************************************** 6fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* simplepatternformatter.cpp 7fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*/ 8fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "simplepatternformatter.h" 9fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "cstring.h" 10fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "uassert.h" 11fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 12fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0])) 13fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 14fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_BEGIN 15fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 16fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliustypedef enum SimplePatternFormatterCompileState { 17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius INIT, 18fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius APOSTROPHE, 19fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius PLACEHOLDER 20fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} SimplePatternFormatterCompileState; 21fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusclass SimplePatternFormatterIdBuilder { 23fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliuspublic: 24fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SimplePatternFormatterIdBuilder() : id(0), idLen(0) { } 25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ~SimplePatternFormatterIdBuilder() { } 26fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void reset() { id = 0; idLen = 0; } 27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t getId() const { return id; } 28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void appendTo(UChar *buffer, int32_t *len) const; 29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UBool isValid() const { return (idLen > 0); } 30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void add(UChar ch); 31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusprivate: 32fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t id; 33fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t idLen; 34fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SimplePatternFormatterIdBuilder( 35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const SimplePatternFormatterIdBuilder &other); 36fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SimplePatternFormatterIdBuilder &operator=( 37fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const SimplePatternFormatterIdBuilder &other); 38fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}; 39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid SimplePatternFormatterIdBuilder::appendTo( 41fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UChar *buffer, int32_t *len) const { 42fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t origLen = *len; 43fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t kId = id; 44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = origLen + idLen - 1; i >= origLen; i--) { 45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t digit = kId % 10; 46fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[i] = digit + 0x30; 47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius kId /= 10; 48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius *len = origLen + idLen; 50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 51fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid SimplePatternFormatterIdBuilder::add(UChar ch) { 53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius id = id * 10 + (ch - 0x30); 54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius idLen++; 55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusSimplePatternFormatter::SimplePatternFormatter() : 58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius noPlaceholders(), 59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset(placeholderBuffer), 60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderSize(0), 61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCapacity(EXPECTED_PLACEHOLDER_COUNT), 62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCount(0) { 63fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 64fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 65fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusSimplePatternFormatter::SimplePatternFormatter(const UnicodeString &pattern) : 66fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius noPlaceholders(), 67fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset(placeholderBuffer), 68fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderSize(0), 69fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCapacity(EXPECTED_PLACEHOLDER_COUNT), 70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCount(0) { 71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode status = U_ZERO_ERROR; 72fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius compile(pattern, status); 73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 74fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 75fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusSimplePatternFormatter::SimplePatternFormatter( 76fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const SimplePatternFormatter &other) : 77fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius noPlaceholders(other.noPlaceholders), 78fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset(placeholderBuffer), 79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderSize(0), 80fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCapacity(EXPECTED_PLACEHOLDER_COUNT), 81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCount(other.placeholderCount) { 82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderSize = ensureCapacity(other.placeholderSize); 83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memcpy( 84fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset, 85fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius other.placeholdersByOffset, 86fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderSize * 2 * sizeof(int32_t)); 87fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 88fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 89fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusSimplePatternFormatter &SimplePatternFormatter::operator=( 90fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const SimplePatternFormatter& other) { 91fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (this == &other) { 92fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return *this; 93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius noPlaceholders = other.noPlaceholders; 95fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCount = other.placeholderCount; 96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderSize = ensureCapacity(other.placeholderSize); 97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memcpy( 98fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset, 99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius other.placeholdersByOffset, 100fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderSize * 2 * sizeof(int32_t)); 101fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return *this; 102fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 103fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 104fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusSimplePatternFormatter::~SimplePatternFormatter() { 105fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (placeholdersByOffset != placeholderBuffer) { 106fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_free(placeholdersByOffset); 107fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 108fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 109fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 110fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool SimplePatternFormatter::compile( 111fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &pattern, UErrorCode &status) { 112fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 113fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 114fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 115fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UChar *patternBuffer = pattern.getBuffer(); 116fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t patternLength = pattern.length(); 117fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UChar *buffer = noPlaceholders.getBuffer(patternLength); 118fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t len = 0; 119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderSize = 0; 120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCount = 0; 121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SimplePatternFormatterCompileState state = INIT; 122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SimplePatternFormatterIdBuilder idBuilder; 123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 0; i < patternLength; ++i) { 124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UChar ch = patternBuffer[i]; 125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch (state) { 126fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case INIT: 127fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (ch == 0x27) { 128fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius state = APOSTROPHE; 129fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else if (ch == 0x7B) { 130fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius state = PLACEHOLDER; 131fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius idBuilder.reset(); 132fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 133fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[len++] = ch; 134fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 135fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 136fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case APOSTROPHE: 137fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (ch == 0x27) { 138fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[len++] = 0x27; 139fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else if (ch == 0x7B) { 140fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[len++] = 0x7B; 141fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 142fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[len++] = 0x27; 143fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[len++] = ch; 144fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 145fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius state = INIT; 146fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 147fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case PLACEHOLDER: 148fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (ch >= 0x30 && ch <= 0x39) { 149fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius idBuilder.add(ch); 150fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else if (ch == 0x7D && idBuilder.isValid()) { 151fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (!addPlaceholder(idBuilder.getId(), len)) { 152fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_MEMORY_ALLOCATION_ERROR; 153fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 154fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 155fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius state = INIT; 156fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 157fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[len++] = 0x7B; 158fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius idBuilder.appendTo(buffer, &len); 159fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[len++] = ch; 160fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius state = INIT; 161fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 162fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 163fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 164fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT(FALSE); 165fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 166fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 167fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 168fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch (state) { 169fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case INIT: 170fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 171fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case APOSTROPHE: 172fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[len++] = 0x27; 173fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 174fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case PLACEHOLDER: 175fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[len++] = 0X7B; 176fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius idBuilder.appendTo(buffer, &len); 177fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 178fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT(false); 180fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 181fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 182fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius noPlaceholders.releaseBuffer(len); 183fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return TRUE; 184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 185fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 186fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString& SimplePatternFormatter::format( 187fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &arg0, 188fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 189fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 190fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString *params[] = {&arg0}; 191fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return format( 192fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius params, 193fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LENGTHOF(params), 194fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo, 195fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NULL, 196fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 0, 197fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 198fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 199fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 200fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString& SimplePatternFormatter::format( 201fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &arg0, 202fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &arg1, 203fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 205fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString *params[] = {&arg0, &arg1}; 206fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return format( 207fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius params, 208fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LENGTHOF(params), 209fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo, 210fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NULL, 211fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 0, 212fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 213fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 214fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 215fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString& SimplePatternFormatter::format( 216fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &arg0, 217fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &arg1, 218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &arg2, 219fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 221fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString *params[] = {&arg0, &arg1, &arg2}; 222fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return format( 223fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius params, 224fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LENGTHOF(params), 225fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo, 226fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NULL, 227fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 0, 228fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 229fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 230fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 231fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic void updatePlaceholderOffset( 232fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t placeholderId, 233fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t placeholderOffset, 234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t *offsetArray, 235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t offsetArrayLength) { 236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (placeholderId < offsetArrayLength) { 237fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offsetArray[placeholderId] = placeholderOffset; 238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 239fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 241fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic void appendRange( 242fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &src, 243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t start, 244fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t end, 245fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &dest) { 246fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius dest.append(src, start, end - start); 247fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 248fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 249fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString& SimplePatternFormatter::format( 250fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString * const *placeholderValues, 251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t placeholderValueCount, 252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 253fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t *offsetArray, 254fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t offsetArrayLength, 255fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 256fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 257fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 258fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 259fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (placeholderValueCount < placeholderCount) { 260fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_ILLEGAL_ARGUMENT_ERROR; 261fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 262fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 263fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 0; i < offsetArrayLength; ++i) { 264fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offsetArray[i] = -1; 265fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 266fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (placeholderSize == 0) { 267fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo.append(noPlaceholders); 268fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 269fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 270fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendRange( 271fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius noPlaceholders, 272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 0, 273fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset[0], 274fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo); 275fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius updatePlaceholderOffset( 276fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset[1], 277fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo.length(), 278fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offsetArray, 279fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offsetArrayLength); 280fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo.append(*placeholderValues[placeholdersByOffset[1]]); 281fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 1; i < placeholderSize; ++i) { 282fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendRange( 283fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius noPlaceholders, 284fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset[2 * i - 2], 285fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset[2 * i], 286fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo); 287fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius updatePlaceholderOffset( 288fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset[2 * i + 1], 289fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo.length(), 290fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offsetArray, 291fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offsetArrayLength); 292fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo.append(*placeholderValues[placeholdersByOffset[2 * i + 1]]); 293fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 294fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendRange( 295fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius noPlaceholders, 296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset[2 * placeholderSize - 2], 297fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius noPlaceholders.length(), 298fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo); 299fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 300fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 301fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 302fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusint32_t SimplePatternFormatter::ensureCapacity(int32_t atLeast) { 303fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (atLeast <= placeholderCapacity) { 304fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return atLeast; 305fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 306fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // aim to double capacity each time 307fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t newCapacity = 2*atLeast - 2; 308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 309fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // allocate new buffer 310fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t *newBuffer = (int32_t *) uprv_malloc(2 * newCapacity * sizeof(int32_t)); 311fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (newBuffer == NULL) { 312fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return placeholderCapacity; 313fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 314fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 315fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Copy contents of old buffer to new buffer 316fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memcpy(newBuffer, placeholdersByOffset, 2 * placeholderSize * sizeof(int32_t)); 317fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 318fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // free old buffer 319fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (placeholdersByOffset != placeholderBuffer) { 320fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_free(placeholdersByOffset); 321fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 322fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 323fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Use new buffer 324fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset = newBuffer; 325fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCapacity = newCapacity; 326fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return atLeast; 327fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 328fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool SimplePatternFormatter::addPlaceholder(int32_t id, int32_t offset) { 330fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (ensureCapacity(placeholderSize + 1) < placeholderSize + 1) { 331fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 332fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 333fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ++placeholderSize; 334fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset[2 * placeholderSize - 2] = offset; 335fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholdersByOffset[2 * placeholderSize - 1] = id; 336fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (id >= placeholderCount) { 337fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius placeholderCount = id + 1; 338fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 339fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return TRUE; 340fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 341fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 342fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END 343