2 ******************************************************************************
3 * Copyright (C) 2014, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 ******************************************************************************
6 * simplepatternformatter.cpp
8 #include "simplepatternformatter.h"
12 #define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0]))
16 typedef enum SimplePatternFormatterCompileState
{
20 } SimplePatternFormatterCompileState
;
22 class SimplePatternFormatterIdBuilder
{
24 SimplePatternFormatterIdBuilder() : id(0), idLen(0) { }
25 ~SimplePatternFormatterIdBuilder() { }
26 void reset() { id
= 0; idLen
= 0; }
27 int32_t getId() const { return id
; }
28 void appendTo(UChar
*buffer
, int32_t *len
) const;
29 UBool
isValid() const { return (idLen
> 0); }
34 SimplePatternFormatterIdBuilder(
35 const SimplePatternFormatterIdBuilder
&other
);
36 SimplePatternFormatterIdBuilder
&operator=(
37 const SimplePatternFormatterIdBuilder
&other
);
40 void SimplePatternFormatterIdBuilder::appendTo(
41 UChar
*buffer
, int32_t *len
) const {
42 int32_t origLen
= *len
;
44 for (int32_t i
= origLen
+ idLen
- 1; i
>= origLen
; i
--) {
45 int32_t digit
= kId
% 10;
46 buffer
[i
] = digit
+ 0x30;
49 *len
= origLen
+ idLen
;
52 void SimplePatternFormatterIdBuilder::add(UChar ch
) {
53 id
= id
* 10 + (ch
- 0x30);
57 SimplePatternFormatter::SimplePatternFormatter() :
59 placeholdersByOffset(placeholderBuffer
),
61 placeholderCapacity(EXPECTED_PLACEHOLDER_COUNT
),
65 SimplePatternFormatter::SimplePatternFormatter(const UnicodeString
&pattern
) :
67 placeholdersByOffset(placeholderBuffer
),
69 placeholderCapacity(EXPECTED_PLACEHOLDER_COUNT
),
71 UErrorCode status
= U_ZERO_ERROR
;
72 compile(pattern
, status
);
75 SimplePatternFormatter::SimplePatternFormatter(
76 const SimplePatternFormatter
&other
) :
77 noPlaceholders(other
.noPlaceholders
),
78 placeholdersByOffset(placeholderBuffer
),
80 placeholderCapacity(EXPECTED_PLACEHOLDER_COUNT
),
81 placeholderCount(other
.placeholderCount
) {
82 placeholderSize
= ensureCapacity(other
.placeholderSize
);
85 other
.placeholdersByOffset
,
86 placeholderSize
* 2 * sizeof(int32_t));
89 SimplePatternFormatter
&SimplePatternFormatter::operator=(
90 const SimplePatternFormatter
& other
) {
94 noPlaceholders
= other
.noPlaceholders
;
95 placeholderCount
= other
.placeholderCount
;
96 placeholderSize
= ensureCapacity(other
.placeholderSize
);
99 other
.placeholdersByOffset
,
100 placeholderSize
* 2 * sizeof(int32_t));
104 SimplePatternFormatter::~SimplePatternFormatter() {
105 if (placeholdersByOffset
!= placeholderBuffer
) {
106 uprv_free(placeholdersByOffset
);
110 UBool
SimplePatternFormatter::compile(
111 const UnicodeString
&pattern
, UErrorCode
&status
) {
112 if (U_FAILURE(status
)) {
115 const UChar
*patternBuffer
= pattern
.getBuffer();
116 int32_t patternLength
= pattern
.length();
117 UChar
*buffer
= noPlaceholders
.getBuffer(patternLength
);
120 placeholderCount
= 0;
121 SimplePatternFormatterCompileState state
= INIT
;
122 SimplePatternFormatterIdBuilder idBuilder
;
123 for (int32_t i
= 0; i
< patternLength
; ++i
) {
124 UChar ch
= patternBuffer
[i
];
129 } else if (ch
== 0x7B) {
138 buffer
[len
++] = 0x27;
139 } else if (ch
== 0x7B) {
140 buffer
[len
++] = 0x7B;
142 buffer
[len
++] = 0x27;
148 if (ch
>= 0x30 && ch
<= 0x39) {
150 } else if (ch
== 0x7D && idBuilder
.isValid()) {
151 if (!addPlaceholder(idBuilder
.getId(), len
)) {
152 status
= U_MEMORY_ALLOCATION_ERROR
;
157 buffer
[len
++] = 0x7B;
158 idBuilder
.appendTo(buffer
, &len
);
172 buffer
[len
++] = 0x27;
175 buffer
[len
++] = 0X7B;
176 idBuilder
.appendTo(buffer
, &len
);
182 noPlaceholders
.releaseBuffer(len
);
186 UnicodeString
& SimplePatternFormatter::format(
187 const UnicodeString
&arg0
,
188 UnicodeString
&appendTo
,
189 UErrorCode
&status
) const {
190 const UnicodeString
*params
[] = {&arg0
};
200 UnicodeString
& SimplePatternFormatter::format(
201 const UnicodeString
&arg0
,
202 const UnicodeString
&arg1
,
203 UnicodeString
&appendTo
,
204 UErrorCode
&status
) const {
205 const UnicodeString
*params
[] = {&arg0
, &arg1
};
215 UnicodeString
& SimplePatternFormatter::format(
216 const UnicodeString
&arg0
,
217 const UnicodeString
&arg1
,
218 const UnicodeString
&arg2
,
219 UnicodeString
&appendTo
,
220 UErrorCode
&status
) const {
221 const UnicodeString
*params
[] = {&arg0
, &arg1
, &arg2
};
231 static void updatePlaceholderOffset(
232 int32_t placeholderId
,
233 int32_t placeholderOffset
,
234 int32_t *offsetArray
,
235 int32_t offsetArrayLength
) {
236 if (placeholderId
< offsetArrayLength
) {
237 offsetArray
[placeholderId
] = placeholderOffset
;
241 static void appendRange(
242 const UnicodeString
&src
,
245 UnicodeString
&dest
) {
246 dest
.append(src
, start
, end
- start
);
249 UnicodeString
& SimplePatternFormatter::format(
250 const UnicodeString
* const *placeholderValues
,
251 int32_t placeholderValueCount
,
252 UnicodeString
&appendTo
,
253 int32_t *offsetArray
,
254 int32_t offsetArrayLength
,
255 UErrorCode
&status
) const {
256 if (U_FAILURE(status
)) {
259 if (placeholderValueCount
< placeholderCount
) {
260 status
= U_ILLEGAL_ARGUMENT_ERROR
;
263 for (int32_t i
= 0; i
< offsetArrayLength
; ++i
) {
266 if (placeholderSize
== 0) {
267 appendTo
.append(noPlaceholders
);
273 placeholdersByOffset
[0],
275 updatePlaceholderOffset(
276 placeholdersByOffset
[1],
280 appendTo
.append(*placeholderValues
[placeholdersByOffset
[1]]);
281 for (int32_t i
= 1; i
< placeholderSize
; ++i
) {
284 placeholdersByOffset
[2 * i
- 2],
285 placeholdersByOffset
[2 * i
],
287 updatePlaceholderOffset(
288 placeholdersByOffset
[2 * i
+ 1],
292 appendTo
.append(*placeholderValues
[placeholdersByOffset
[2 * i
+ 1]]);
296 placeholdersByOffset
[2 * placeholderSize
- 2],
297 noPlaceholders
.length(),
302 int32_t SimplePatternFormatter::ensureCapacity(int32_t atLeast
) {
303 if (atLeast
<= placeholderCapacity
) {
306 // aim to double capacity each time
307 int32_t newCapacity
= 2*atLeast
- 2;
309 // allocate new buffer
310 int32_t *newBuffer
= (int32_t *) uprv_malloc(2 * newCapacity
* sizeof(int32_t));
311 if (newBuffer
== NULL
) {
312 return placeholderCapacity
;
315 // Copy contents of old buffer to new buffer
316 uprv_memcpy(newBuffer
, placeholdersByOffset
, 2 * placeholderSize
* sizeof(int32_t));
319 if (placeholdersByOffset
!= placeholderBuffer
) {
320 uprv_free(placeholdersByOffset
);
324 placeholdersByOffset
= newBuffer
;
325 placeholderCapacity
= newCapacity
;
329 UBool
SimplePatternFormatter::addPlaceholder(int32_t id
, int32_t offset
) {
330 if (ensureCapacity(placeholderSize
+ 1) < placeholderSize
+ 1) {
334 placeholdersByOffset
[2 * placeholderSize
- 2] = offset
;
335 placeholdersByOffset
[2 * placeholderSize
- 1] = id
;
336 if (id
>= placeholderCount
) {
337 placeholderCount
= id
+ 1;