Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: source/common/listformatter.cpp

Issue 845603002: Update ICU to 54.1 step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@master
Patch Set: remove unusued directories Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/common/icuplug.cpp ('k') | source/common/loadednormalizer2impl.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ******************************************************************************* 2 *******************************************************************************
3 * 3 *
4 * Copyright (C) 2013, International Business Machines 4 * Copyright (C) 2013-2014, International Business Machines
5 * Corporation and others. All Rights Reserved. 5 * Corporation and others. All Rights Reserved.
6 * 6 *
7 ******************************************************************************* 7 *******************************************************************************
8 * file name: listformatter.cpp 8 * file name: listformatter.cpp
9 * encoding: US-ASCII 9 * encoding: US-ASCII
10 * tab size: 8 (not used) 10 * tab size: 8 (not used)
11 * indentation:4 11 * indentation:4
12 * 12 *
13 * created on: 2012aug27 13 * created on: 2012aug27
14 * created by: Umesh P. Nair 14 * created by: Umesh P. Nair
15 */ 15 */
16 16
17 #include "unicode/listformatter.h" 17 #include "unicode/listformatter.h"
18 #include "simplepatternformatter.h"
18 #include "mutex.h" 19 #include "mutex.h"
19 #include "hash.h" 20 #include "hash.h"
20 #include "cstring.h" 21 #include "cstring.h"
21 #include "ulocimp.h" 22 #include "ulocimp.h"
22 #include "charstr.h" 23 #include "charstr.h"
23 #include "ucln_cmn.h" 24 #include "ucln_cmn.h"
24 #include "uresimp.h" 25 #include "uresimp.h"
25 26
26 U_NAMESPACE_BEGIN 27 U_NAMESPACE_BEGIN
27 28
29 struct ListFormatInternal : public UMemory {
30 SimplePatternFormatter twoPattern;
31 SimplePatternFormatter startPattern;
32 SimplePatternFormatter middlePattern;
33 SimplePatternFormatter endPattern;
34
35 ListFormatInternal(
36 const UnicodeString& two,
37 const UnicodeString& start,
38 const UnicodeString& middle,
39 const UnicodeString& end) :
40 twoPattern(two),
41 startPattern(start),
42 middlePattern(middle),
43 endPattern(end) {}
44
45 ListFormatInternal(const ListFormatData &data) :
46 twoPattern(data.twoPattern),
47 startPattern(data.startPattern),
48 middlePattern(data.middlePattern),
49 endPattern(data.endPattern) { }
50
51 ListFormatInternal(const ListFormatInternal &other) :
52 twoPattern(other.twoPattern),
53 startPattern(other.startPattern),
54 middlePattern(other.middlePattern),
55 endPattern(other.endPattern) { }
56 };
57
58
59
28 static Hashtable* listPatternHash = NULL; 60 static Hashtable* listPatternHash = NULL;
29 static UMutex listFormatterMutex = U_MUTEX_INITIALIZER; 61 static UMutex listFormatterMutex = U_MUTEX_INITIALIZER;
30 static UChar FIRST_PARAMETER[] = { 0x7b, 0x30, 0x7d }; // "{0}"
31 static UChar SECOND_PARAMETER[] = { 0x7b, 0x31, 0x7d }; // "{0}"
32 static const char *STANDARD_STYLE = "standard"; 62 static const char *STANDARD_STYLE = "standard";
33 63
34 U_CDECL_BEGIN 64 U_CDECL_BEGIN
35 static UBool U_CALLCONV uprv_listformatter_cleanup() { 65 static UBool U_CALLCONV uprv_listformatter_cleanup() {
36 delete listPatternHash; 66 delete listPatternHash;
37 listPatternHash = NULL; 67 listPatternHash = NULL;
38 return TRUE; 68 return TRUE;
39 } 69 }
40 70
41 static void U_CALLCONV 71 static void U_CALLCONV
42 uprv_deleteListFormatData(void *obj) { 72 uprv_deleteListFormatInternal(void *obj) {
43 delete static_cast<ListFormatData *>(obj); 73 delete static_cast<ListFormatInternal *>(obj);
44 } 74 }
45 75
46 U_CDECL_END 76 U_CDECL_END
47 77
48 static ListFormatData* loadListFormatData(const Locale& locale, const char* styl e, UErrorCode& errorCode); 78 static ListFormatInternal* loadListFormatInternal(
49 static void getStringByKey(const UResourceBundle* rb, const char* key, UnicodeSt ring& result, UErrorCode& errorCode); 79 const Locale& locale,
80 const char* style,
81 UErrorCode& errorCode);
50 82
51 ListFormatter::ListFormatter(const ListFormatter& other) : data(other.data) { 83 static void getStringByKey(
84 const UResourceBundle* rb,
85 const char* key,
86 UnicodeString& result,
87 UErrorCode& errorCode);
88
89 ListFormatter::ListFormatter(const ListFormatter& other) :
90 owned(other.owned), data(other.data) {
91 if (other.owned != NULL) {
92 owned = new ListFormatInternal(*other.owned);
93 data = owned;
94 }
52 } 95 }
53 96
54 ListFormatter& ListFormatter::operator=(const ListFormatter& other) { 97 ListFormatter& ListFormatter::operator=(const ListFormatter& other) {
55 data = other.data; 98 if (this == &other) {
99 return *this;
100 }
101 delete owned;
102 if (other.owned) {
103 owned = new ListFormatInternal(*other.owned);
104 data = owned;
105 } else {
106 owned = NULL;
107 data = other.data;
108 }
56 return *this; 109 return *this;
57 } 110 }
58 111
59 void ListFormatter::initializeHash(UErrorCode& errorCode) { 112 void ListFormatter::initializeHash(UErrorCode& errorCode) {
60 if (U_FAILURE(errorCode)) { 113 if (U_FAILURE(errorCode)) {
61 return; 114 return;
62 } 115 }
63 116
64 listPatternHash = new Hashtable(); 117 listPatternHash = new Hashtable();
65 if (listPatternHash == NULL) { 118 if (listPatternHash == NULL) {
66 errorCode = U_MEMORY_ALLOCATION_ERROR; 119 errorCode = U_MEMORY_ALLOCATION_ERROR;
67 return; 120 return;
68 } 121 }
69 122
70 listPatternHash->setValueDeleter(uprv_deleteListFormatData); 123 listPatternHash->setValueDeleter(uprv_deleteListFormatInternal);
71 ucln_common_registerCleanup(UCLN_COMMON_LIST_FORMATTER, uprv_listformatter_c leanup); 124 ucln_common_registerCleanup(UCLN_COMMON_LIST_FORMATTER, uprv_listformatter_c leanup);
72 125
73 } 126 }
74 127
75 const ListFormatData* ListFormatter::getListFormatData( 128 const ListFormatInternal* ListFormatter::getListFormatInternal(
76 const Locale& locale, const char *style, UErrorCode& errorCode) { 129 const Locale& locale, const char *style, UErrorCode& errorCode) {
77 if (U_FAILURE(errorCode)) { 130 if (U_FAILURE(errorCode)) {
78 return NULL; 131 return NULL;
79 } 132 }
80 CharString keyBuffer(locale.getName(), errorCode); 133 CharString keyBuffer(locale.getName(), errorCode);
81 keyBuffer.append(':', errorCode).append(style, errorCode); 134 keyBuffer.append(':', errorCode).append(style, errorCode);
82 UnicodeString key(keyBuffer.data(), -1, US_INV); 135 UnicodeString key(keyBuffer.data(), -1, US_INV);
83 ListFormatData* result = NULL; 136 ListFormatInternal* result = NULL;
84 { 137 {
85 Mutex m(&listFormatterMutex); 138 Mutex m(&listFormatterMutex);
86 if (listPatternHash == NULL) { 139 if (listPatternHash == NULL) {
87 initializeHash(errorCode); 140 initializeHash(errorCode);
88 if (U_FAILURE(errorCode)) { 141 if (U_FAILURE(errorCode)) {
89 return NULL; 142 return NULL;
90 } 143 }
91 } 144 }
92 result = static_cast<ListFormatData*>(listPatternHash->get(key)); 145 result = static_cast<ListFormatInternal*>(listPatternHash->get(key));
93 } 146 }
94 if (result != NULL) { 147 if (result != NULL) {
95 return result; 148 return result;
96 } 149 }
97 result = loadListFormatData(locale, style, errorCode); 150 result = loadListFormatInternal(locale, style, errorCode);
98 if (U_FAILURE(errorCode)) { 151 if (U_FAILURE(errorCode)) {
99 return NULL; 152 return NULL;
100 } 153 }
101 154
102 { 155 {
103 Mutex m(&listFormatterMutex); 156 Mutex m(&listFormatterMutex);
104 ListFormatData* temp = static_cast<ListFormatData*>(listPatternHash->get (key)); 157 ListFormatInternal* temp = static_cast<ListFormatInternal*>(listPatternH ash->get(key));
105 if (temp != NULL) { 158 if (temp != NULL) {
106 delete result; 159 delete result;
107 result = temp; 160 result = temp;
108 } else { 161 } else {
109 listPatternHash->put(key, result, errorCode); 162 listPatternHash->put(key, result, errorCode);
110 if (U_FAILURE(errorCode)) { 163 if (U_FAILURE(errorCode)) {
111 return NULL; 164 return NULL;
112 } 165 }
113 } 166 }
114 } 167 }
115 return result; 168 return result;
116 } 169 }
117 170
118 static ListFormatData* loadListFormatData( 171 static ListFormatInternal* loadListFormatInternal(
119 const Locale& locale, const char * style, UErrorCode& errorCode) { 172 const Locale& locale, const char * style, UErrorCode& errorCode) {
120 UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode); 173 UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode);
121 if (U_FAILURE(errorCode)) { 174 if (U_FAILURE(errorCode)) {
122 ures_close(rb); 175 ures_close(rb);
123 return NULL; 176 return NULL;
124 } 177 }
125 rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode); 178 rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode);
126 rb = ures_getByKeyWithFallback(rb, style, rb, &errorCode); 179 rb = ures_getByKeyWithFallback(rb, style, rb, &errorCode);
127 180
128 // TODO(Travis Keep): This is a hack until fallbacks can be added for 181 // TODO(Travis Keep): This is a hack until fallbacks can be added for
129 // listPattern/duration and listPattern/duration-narrow in CLDR. 182 // listPattern/duration and listPattern/duration-narrow in CLDR.
130 if (errorCode == U_MISSING_RESOURCE_ERROR) { 183 if (errorCode == U_MISSING_RESOURCE_ERROR) {
131 errorCode = U_ZERO_ERROR; 184 errorCode = U_ZERO_ERROR;
132 rb = ures_getByKeyWithFallback(rb, "standard", rb, &errorCode); 185 rb = ures_getByKeyWithFallback(rb, "standard", rb, &errorCode);
133 } 186 }
134 if (U_FAILURE(errorCode)) { 187 if (U_FAILURE(errorCode)) {
135 ures_close(rb); 188 ures_close(rb);
136 return NULL; 189 return NULL;
137 } 190 }
138 UnicodeString two, start, middle, end; 191 UnicodeString two, start, middle, end;
139 getStringByKey(rb, "2", two, errorCode); 192 getStringByKey(rb, "2", two, errorCode);
140 getStringByKey(rb, "start", start, errorCode); 193 getStringByKey(rb, "start", start, errorCode);
141 getStringByKey(rb, "middle", middle, errorCode); 194 getStringByKey(rb, "middle", middle, errorCode);
142 getStringByKey(rb, "end", end, errorCode); 195 getStringByKey(rb, "end", end, errorCode);
143 ures_close(rb); 196 ures_close(rb);
144 if (U_FAILURE(errorCode)) { 197 if (U_FAILURE(errorCode)) {
145 return NULL; 198 return NULL;
146 } 199 }
147 ListFormatData* result = new ListFormatData(two, start, middle, end); 200 ListFormatInternal* result = new ListFormatInternal(two, start, middle, end) ;
148 if (result == NULL) { 201 if (result == NULL) {
149 errorCode = U_MEMORY_ALLOCATION_ERROR; 202 errorCode = U_MEMORY_ALLOCATION_ERROR;
150 return NULL; 203 return NULL;
151 } 204 }
152 return result; 205 return result;
153 } 206 }
154 207
155 static void getStringByKey(const UResourceBundle* rb, const char* key, UnicodeSt ring& result, UErrorCode& errorCode) { 208 static void getStringByKey(const UResourceBundle* rb, const char* key, UnicodeSt ring& result, UErrorCode& errorCode) {
156 int32_t len; 209 int32_t len;
157 const UChar* ustr = ures_getStringByKeyWithFallback(rb, key, &len, &errorCod e); 210 const UChar* ustr = ures_getStringByKeyWithFallback(rb, key, &len, &errorCod e);
158 if (U_FAILURE(errorCode)) { 211 if (U_FAILURE(errorCode)) {
159 return; 212 return;
160 } 213 }
161 result.setTo(ustr, len); 214 result.setTo(ustr, len);
162 } 215 }
163 216
164 ListFormatter* ListFormatter::createInstance(UErrorCode& errorCode) { 217 ListFormatter* ListFormatter::createInstance(UErrorCode& errorCode) {
165 Locale locale; // The default locale. 218 Locale locale; // The default locale.
166 return createInstance(locale, errorCode); 219 return createInstance(locale, errorCode);
167 } 220 }
168 221
169 ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& e rrorCode) { 222 ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& e rrorCode) {
170 return createInstance(locale, STANDARD_STYLE, errorCode); 223 return createInstance(locale, STANDARD_STYLE, errorCode);
171 } 224 }
172 225
173 ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *s tyle, UErrorCode& errorCode) { 226 ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *s tyle, UErrorCode& errorCode) {
174 Locale tempLocale = locale; 227 Locale tempLocale = locale;
175 const ListFormatData* listFormatData = getListFormatData(tempLocale, style, errorCode); 228 const ListFormatInternal* listFormatInternal = getListFormatInternal(tempLoc ale, style, errorCode);
176 if (U_FAILURE(errorCode)) { 229 if (U_FAILURE(errorCode)) {
177 return NULL; 230 return NULL;
178 } 231 }
179 ListFormatter* p = new ListFormatter(listFormatData); 232 ListFormatter* p = new ListFormatter(listFormatInternal);
180 if (p == NULL) { 233 if (p == NULL) {
181 errorCode = U_MEMORY_ALLOCATION_ERROR; 234 errorCode = U_MEMORY_ALLOCATION_ERROR;
182 return NULL; 235 return NULL;
183 } 236 }
184 return p; 237 return p;
185 } 238 }
186 239
187 240 ListFormatter::ListFormatter(const ListFormatData& listFormatData) {
188 ListFormatter::ListFormatter(const ListFormatData* listFormatterData) : data(lis tFormatterData) { 241 owned = new ListFormatInternal(listFormatData);
242 data = owned;
189 } 243 }
190 244
191 ListFormatter::~ListFormatter() {} 245 ListFormatter::ListFormatter(const ListFormatInternal* listFormatterInternal) : owned(NULL), data(listFormatterInternal) {
246 }
192 247
193 UnicodeString& ListFormatter::format(const UnicodeString items[], int32_t nItems , 248 ListFormatter::~ListFormatter() {
194 UnicodeString& appendTo, UErrorCode& errorCode) const { 249 delete owned;
250 }
251
252 /**
253 * Joins first and second using the pattern pat.
254 * On entry offset is an offset into first or -1 if offset unspecified.
255 * On exit offset is offset of second in result if recordOffset was set
256 * Otherwise if it was >=0 it is set to point into result where it used
257 * to point into first.
258 */
259 static void joinStrings(
260 const SimplePatternFormatter& pat,
261 const UnicodeString& first,
262 const UnicodeString& second,
263 UnicodeString &result,
264 UBool recordOffset,
265 int32_t &offset,
266 UErrorCode& errorCode) {
267 if (U_FAILURE(errorCode)) {
268 return;
269 }
270 const UnicodeString *params[2] = {&first, &second};
271 int32_t offsets[2];
272 pat.format(
273 params,
274 UPRV_LENGTHOF(params),
275 result,
276 offsets,
277 UPRV_LENGTHOF(offsets),
278 errorCode);
279 if (U_FAILURE(errorCode)) {
280 return;
281 }
282 if (offsets[0] == -1 || offsets[1] == -1) {
283 errorCode = U_INVALID_FORMAT_ERROR;
284 return;
285 }
286 if (recordOffset) {
287 offset = offsets[1];
288 } else if (offset >= 0) {
289 offset += offsets[0];
290 }
291 }
292
293 UnicodeString& ListFormatter::format(
294 const UnicodeString items[],
295 int32_t nItems,
296 UnicodeString& appendTo,
297 UErrorCode& errorCode) const {
298 int32_t offset;
299 return format(items, nItems, appendTo, -1, offset, errorCode);
300 }
301
302 UnicodeString& ListFormatter::format(
303 const UnicodeString items[],
304 int32_t nItems,
305 UnicodeString& appendTo,
306 int32_t index,
307 int32_t &offset,
308 UErrorCode& errorCode) const {
309 offset = -1;
195 if (U_FAILURE(errorCode)) { 310 if (U_FAILURE(errorCode)) {
196 return appendTo; 311 return appendTo;
197 } 312 }
198 if (data == NULL) { 313 if (data == NULL) {
199 errorCode = U_INVALID_STATE_ERROR; 314 errorCode = U_INVALID_STATE_ERROR;
200 return appendTo; 315 return appendTo;
201 } 316 }
202 317
203 if (nItems > 0) { 318 if (nItems <= 0) {
204 UnicodeString newString = items[0]; 319 return appendTo;
205 if (nItems == 2) { 320 }
206 addNewString(data->twoPattern, newString, items[1], errorCode); 321 if (nItems == 1) {
207 } else if (nItems > 2) { 322 if (index == 0) {
208 addNewString(data->startPattern, newString, items[1], errorCode); 323 offset = appendTo.length();
209 int32_t i;
210 for (i = 2; i < nItems - 1; ++i) {
211 addNewString(data->middlePattern, newString, items[i], errorCode );
212 }
213 addNewString(data->endPattern, newString, items[nItems - 1], errorCo de);
214 } 324 }
215 if (U_SUCCESS(errorCode)) { 325 appendTo.append(items[0]);
216 appendTo += newString; 326 return appendTo;
327 }
328 if (nItems == 2) {
329 if (index == 0) {
330 offset = 0;
217 } 331 }
332 joinStrings(
333 data->twoPattern,
334 items[0],
335 items[1],
336 appendTo,
337 index == 1,
338 offset,
339 errorCode);
340 return appendTo;
341 }
342 UnicodeString temp[2];
343 if (index == 0) {
344 offset = 0;
345 }
346 joinStrings(
347 data->startPattern,
348 items[0],
349 items[1],
350 temp[0],
351 index == 1,
352 offset,
353 errorCode);
354 int32_t i;
355 int32_t pos = 0;
356 int32_t npos = 0;
357 UBool startsWithZeroPlaceholder =
358 data->middlePattern.startsWithPlaceholder(0);
359 for (i = 2; i < nItems - 1; ++i) {
360 if (!startsWithZeroPlaceholder) {
361 npos = (pos + 1) & 1;
362 temp[npos].remove();
363 }
364 joinStrings(
365 data->middlePattern,
366 temp[pos],
367 items[i],
368 temp[npos],
369 index == i,
370 offset,
371 errorCode);
372 pos = npos;
373 }
374 if (!data->endPattern.startsWithPlaceholder(0)) {
375 npos = (pos + 1) & 1;
376 temp[npos].remove();
377 }
378 joinStrings(
379 data->endPattern,
380 temp[pos],
381 items[nItems - 1],
382 temp[npos],
383 index == nItems - 1,
384 offset,
385 errorCode);
386 if (U_SUCCESS(errorCode)) {
387 if (offset >= 0) {
388 offset += appendTo.length();
389 }
390 appendTo += temp[npos];
218 } 391 }
219 return appendTo; 392 return appendTo;
220 } 393 }
221 394
222 /**
223 * Joins originalString and nextString using the pattern pat and puts the result in
224 * originalString.
225 */
226 void ListFormatter::addNewString(const UnicodeString& pat, UnicodeString& origin alString,
227 const UnicodeString& nextString, UErrorCode& er rorCode) const {
228 if (U_FAILURE(errorCode)) {
229 return;
230 }
231
232 int32_t p0Offset = pat.indexOf(FIRST_PARAMETER, 3, 0);
233 if (p0Offset < 0) {
234 errorCode = U_ILLEGAL_ARGUMENT_ERROR;
235 return;
236 }
237 int32_t p1Offset = pat.indexOf(SECOND_PARAMETER, 3, 0);
238 if (p1Offset < 0) {
239 errorCode = U_ILLEGAL_ARGUMENT_ERROR;
240 return;
241 }
242
243 int32_t i, j;
244
245 const UnicodeString* firstString;
246 const UnicodeString* secondString;
247 if (p0Offset < p1Offset) {
248 i = p0Offset;
249 j = p1Offset;
250 firstString = &originalString;
251 secondString = &nextString;
252 } else {
253 i = p1Offset;
254 j = p0Offset;
255 firstString = &nextString;
256 secondString = &originalString;
257 }
258
259 UnicodeString result = UnicodeString(pat, 0, i) + *firstString;
260 result += UnicodeString(pat, i+3, j-i-3);
261 result += *secondString;
262 result += UnicodeString(pat, j+3);
263 originalString = result;
264 }
265
266 U_NAMESPACE_END 395 U_NAMESPACE_END
OLDNEW
« no previous file with comments | « source/common/icuplug.cpp ('k') | source/common/loadednormalizer2impl.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698