Line data Source code
1 : // © 2016 and later: Unicode, Inc. and others.
2 : // License & terms of use: http://www.unicode.org/copyright.html
3 : /*
4 : * Copyright (C) 2015, International Business Machines
5 : * Corporation and others. All Rights Reserved.
6 : *
7 : * file name: affixpatternparser.cpp
8 : */
9 :
10 : #include "unicode/utypes.h"
11 :
12 : #if !UCONFIG_NO_FORMATTING
13 :
14 : #include "unicode/dcfmtsym.h"
15 : #include "unicode/plurrule.h"
16 : #include "unicode/strenum.h"
17 : #include "unicode/ucurr.h"
18 : #include "unicode/ustring.h"
19 : #include "affixpatternparser.h"
20 : #include "charstr.h"
21 : #include "precision.h"
22 : #include "uassert.h"
23 : #include "unistrappender.h"
24 :
25 : static UChar gDefaultSymbols[] = {0xa4, 0xa4, 0xa4};
26 :
27 : static UChar gPercent = 0x25;
28 : static UChar gPerMill = 0x2030;
29 : static UChar gNegative = 0x2D;
30 : static UChar gPositive = 0x2B;
31 :
32 : #define PACK_TOKEN_AND_LENGTH(t, l) ((UChar) (((t) << 8) | (l & 0xFF)))
33 :
34 : #define UNPACK_TOKEN(c) ((AffixPattern::ETokenType) (((c) >> 8) & 0x7F))
35 :
36 : #define UNPACK_LONG(c) (((c) >> 8) & 0x80)
37 :
38 : #define UNPACK_LENGTH(c) ((c) & 0xFF)
39 :
40 : U_NAMESPACE_BEGIN
41 :
42 : static int32_t
43 0 : nextToken(const UChar *buffer, int32_t idx, int32_t len, UChar *token) {
44 0 : if (buffer[idx] != 0x27 || idx + 1 == len) {
45 0 : *token = buffer[idx];
46 0 : return 1;
47 : }
48 0 : *token = buffer[idx + 1];
49 0 : if (buffer[idx + 1] == 0xA4) {
50 0 : int32_t i = 2;
51 0 : for (; idx + i < len && i < 4 && buffer[idx + i] == buffer[idx + 1]; ++i)
52 : ;
53 0 : return i;
54 : }
55 0 : return 2;
56 : }
57 :
58 : static int32_t
59 0 : nextUserToken(const UChar *buffer, int32_t idx, int32_t len, UChar *token) {
60 0 : *token = buffer[idx];
61 : int32_t max;
62 0 : switch (buffer[idx]) {
63 : case 0x27:
64 0 : max = 2;
65 0 : break;
66 : case 0xA4:
67 0 : max = 3;
68 0 : break;
69 : default:
70 0 : max = 1;
71 0 : break;
72 : }
73 0 : int32_t i = 1;
74 0 : for (; idx + i < len && i < max && buffer[idx + i] == buffer[idx]; ++i)
75 : ;
76 0 : return i;
77 : }
78 :
79 0 : CurrencyAffixInfo::CurrencyAffixInfo()
80 : : fSymbol(gDefaultSymbols, 1),
81 : fISO(gDefaultSymbols, 2),
82 0 : fLong(DigitAffix(gDefaultSymbols, 3)),
83 0 : fIsDefault(TRUE) {
84 0 : }
85 :
86 : void
87 0 : CurrencyAffixInfo::set(
88 : const char *locale,
89 : const PluralRules *rules,
90 : const UChar *currency,
91 : UErrorCode &status) {
92 0 : if (U_FAILURE(status)) {
93 0 : return;
94 : }
95 0 : fIsDefault = FALSE;
96 0 : if (currency == NULL) {
97 0 : fSymbol.setTo(gDefaultSymbols, 1);
98 0 : fISO.setTo(gDefaultSymbols, 2);
99 0 : fLong.remove();
100 0 : fLong.append(gDefaultSymbols, 3);
101 0 : fIsDefault = TRUE;
102 0 : return;
103 : }
104 : int32_t len;
105 : UBool unusedIsChoice;
106 : const UChar *symbol = ucurr_getName(
107 : currency, locale, UCURR_SYMBOL_NAME, &unusedIsChoice,
108 0 : &len, &status);
109 0 : if (U_FAILURE(status)) {
110 0 : return;
111 : }
112 0 : fSymbol.setTo(symbol, len);
113 0 : fISO.setTo(currency, u_strlen(currency));
114 0 : fLong.remove();
115 0 : StringEnumeration* keywords = rules->getKeywords(status);
116 0 : if (U_FAILURE(status)) {
117 0 : return;
118 : }
119 : const UnicodeString* pluralCount;
120 0 : while ((pluralCount = keywords->snext(status)) != NULL) {
121 0 : CharString pCount;
122 0 : pCount.appendInvariantChars(*pluralCount, status);
123 : const UChar *pluralName = ucurr_getPluralName(
124 0 : currency, locale, &unusedIsChoice, pCount.data(),
125 0 : &len, &status);
126 0 : fLong.setVariant(pCount.data(), UnicodeString(pluralName, len), status);
127 : }
128 0 : delete keywords;
129 : }
130 :
131 : void
132 0 : CurrencyAffixInfo::adjustPrecision(
133 : const UChar *currency, const UCurrencyUsage usage,
134 : FixedPrecision &precision, UErrorCode &status) {
135 0 : if (U_FAILURE(status)) {
136 0 : return;
137 : }
138 :
139 : int32_t digitCount = ucurr_getDefaultFractionDigitsForUsage(
140 0 : currency, usage, &status);
141 0 : precision.fMin.setFracDigitCount(digitCount);
142 0 : precision.fMax.setFracDigitCount(digitCount);
143 : double increment = ucurr_getRoundingIncrementForUsage(
144 0 : currency, usage, &status);
145 0 : if (increment == 0.0) {
146 0 : precision.fRoundingIncrement.clear();
147 : } else {
148 0 : precision.fRoundingIncrement.set(increment);
149 : // guard against round-off error
150 0 : precision.fRoundingIncrement.round(6);
151 : }
152 : }
153 :
154 : void
155 0 : AffixPattern::addLiteral(
156 : const UChar *literal, int32_t start, int32_t len) {
157 0 : char32Count += u_countChar32(literal + start, len);
158 0 : literals.append(literal, start, len);
159 0 : int32_t tlen = tokens.length();
160 : // Takes 4 UChars to encode maximum literal length.
161 0 : UChar *tokenChars = tokens.getBuffer(tlen + 4);
162 :
163 : // find start of literal size. May be tlen if there is no literal.
164 : // While finding start of literal size, compute literal length
165 0 : int32_t literalLength = 0;
166 0 : int32_t tLiteralStart = tlen;
167 0 : while (tLiteralStart > 0 && UNPACK_TOKEN(tokenChars[tLiteralStart - 1]) == kLiteral) {
168 0 : tLiteralStart--;
169 0 : literalLength <<= 8;
170 0 : literalLength |= UNPACK_LENGTH(tokenChars[tLiteralStart]);
171 : }
172 : // Add number of chars we just added to literal
173 0 : literalLength += len;
174 :
175 : // Now encode the new length starting at tLiteralStart
176 0 : tlen = tLiteralStart;
177 0 : tokenChars[tlen++] = PACK_TOKEN_AND_LENGTH(kLiteral, literalLength & 0xFF);
178 0 : literalLength >>= 8;
179 0 : while (literalLength) {
180 0 : tokenChars[tlen++] = PACK_TOKEN_AND_LENGTH(kLiteral | 0x80, literalLength & 0xFF);
181 0 : literalLength >>= 8;
182 : }
183 0 : tokens.releaseBuffer(tlen);
184 0 : }
185 :
186 : void
187 0 : AffixPattern::add(ETokenType t) {
188 0 : add(t, 1);
189 0 : }
190 :
191 : void
192 0 : AffixPattern::addCurrency(uint8_t count) {
193 0 : add(kCurrency, count);
194 0 : }
195 :
196 : void
197 0 : AffixPattern::add(ETokenType t, uint8_t count) {
198 0 : U_ASSERT(t != kLiteral);
199 0 : char32Count += count;
200 0 : switch (t) {
201 : case kCurrency:
202 0 : hasCurrencyToken = TRUE;
203 0 : break;
204 : case kPercent:
205 0 : hasPercentToken = TRUE;
206 0 : break;
207 : case kPerMill:
208 0 : hasPermillToken = TRUE;
209 0 : break;
210 : default:
211 : // Do nothing
212 0 : break;
213 : }
214 0 : tokens.append(PACK_TOKEN_AND_LENGTH(t, count));
215 0 : }
216 :
217 : AffixPattern &
218 0 : AffixPattern::append(const AffixPattern &other) {
219 0 : AffixPatternIterator iter;
220 0 : other.iterator(iter);
221 0 : UnicodeString literal;
222 0 : while (iter.nextToken()) {
223 0 : switch (iter.getTokenType()) {
224 : case kLiteral:
225 0 : iter.getLiteral(literal);
226 0 : addLiteral(literal.getBuffer(), 0, literal.length());
227 0 : break;
228 : case kCurrency:
229 0 : addCurrency(iter.getTokenLength());
230 0 : break;
231 : default:
232 0 : add(iter.getTokenType());
233 0 : break;
234 : }
235 : }
236 0 : return *this;
237 : }
238 :
239 : void
240 0 : AffixPattern::remove() {
241 0 : tokens.remove();
242 0 : literals.remove();
243 0 : hasCurrencyToken = FALSE;
244 0 : hasPercentToken = FALSE;
245 0 : hasPermillToken = FALSE;
246 0 : char32Count = 0;
247 0 : }
248 :
249 : // escapes literals for strings where special characters are NOT escaped
250 : // except for apostrophe.
251 0 : static void escapeApostropheInLiteral(
252 : const UnicodeString &literal, UnicodeStringAppender &appender) {
253 0 : int32_t len = literal.length();
254 0 : const UChar *buffer = literal.getBuffer();
255 0 : for (int32_t i = 0; i < len; ++i) {
256 0 : UChar ch = buffer[i];
257 0 : switch (ch) {
258 : case 0x27:
259 0 : appender.append((UChar) 0x27);
260 0 : appender.append((UChar) 0x27);
261 0 : break;
262 : default:
263 0 : appender.append(ch);
264 0 : break;
265 : }
266 : }
267 0 : }
268 :
269 :
270 : // escapes literals for user strings where special characters in literals
271 : // are escaped with apostrophe.
272 0 : static void escapeLiteral(
273 : const UnicodeString &literal, UnicodeStringAppender &appender) {
274 0 : int32_t len = literal.length();
275 0 : const UChar *buffer = literal.getBuffer();
276 0 : for (int32_t i = 0; i < len; ++i) {
277 0 : UChar ch = buffer[i];
278 0 : switch (ch) {
279 : case 0x27:
280 0 : appender.append((UChar) 0x27);
281 0 : appender.append((UChar) 0x27);
282 0 : break;
283 : case 0x25:
284 0 : appender.append((UChar) 0x27);
285 0 : appender.append((UChar) 0x25);
286 0 : appender.append((UChar) 0x27);
287 0 : break;
288 : case 0x2030:
289 0 : appender.append((UChar) 0x27);
290 0 : appender.append((UChar) 0x2030);
291 0 : appender.append((UChar) 0x27);
292 0 : break;
293 : case 0xA4:
294 0 : appender.append((UChar) 0x27);
295 0 : appender.append((UChar) 0xA4);
296 0 : appender.append((UChar) 0x27);
297 0 : break;
298 : case 0x2D:
299 0 : appender.append((UChar) 0x27);
300 0 : appender.append((UChar) 0x2D);
301 0 : appender.append((UChar) 0x27);
302 0 : break;
303 : case 0x2B:
304 0 : appender.append((UChar) 0x27);
305 0 : appender.append((UChar) 0x2B);
306 0 : appender.append((UChar) 0x27);
307 0 : break;
308 : default:
309 0 : appender.append(ch);
310 0 : break;
311 : }
312 : }
313 0 : }
314 :
315 : UnicodeString &
316 0 : AffixPattern::toString(UnicodeString &appendTo) const {
317 0 : AffixPatternIterator iter;
318 0 : iterator(iter);
319 0 : UnicodeStringAppender appender(appendTo);
320 0 : UnicodeString literal;
321 0 : while (iter.nextToken()) {
322 0 : switch (iter.getTokenType()) {
323 : case kLiteral:
324 0 : escapeApostropheInLiteral(iter.getLiteral(literal), appender);
325 0 : break;
326 : case kPercent:
327 0 : appender.append((UChar) 0x27);
328 0 : appender.append((UChar) 0x25);
329 0 : break;
330 : case kPerMill:
331 0 : appender.append((UChar) 0x27);
332 0 : appender.append((UChar) 0x2030);
333 0 : break;
334 : case kCurrency:
335 : {
336 0 : appender.append((UChar) 0x27);
337 0 : int32_t cl = iter.getTokenLength();
338 0 : for (int32_t i = 0; i < cl; ++i) {
339 0 : appender.append((UChar) 0xA4);
340 : }
341 : }
342 0 : break;
343 : case kNegative:
344 0 : appender.append((UChar) 0x27);
345 0 : appender.append((UChar) 0x2D);
346 0 : break;
347 : case kPositive:
348 0 : appender.append((UChar) 0x27);
349 0 : appender.append((UChar) 0x2B);
350 0 : break;
351 : default:
352 0 : U_ASSERT(FALSE);
353 : break;
354 : }
355 : }
356 0 : return appendTo;
357 : }
358 :
359 : UnicodeString &
360 0 : AffixPattern::toUserString(UnicodeString &appendTo) const {
361 0 : AffixPatternIterator iter;
362 0 : iterator(iter);
363 0 : UnicodeStringAppender appender(appendTo);
364 0 : UnicodeString literal;
365 0 : while (iter.nextToken()) {
366 0 : switch (iter.getTokenType()) {
367 : case kLiteral:
368 0 : escapeLiteral(iter.getLiteral(literal), appender);
369 0 : break;
370 : case kPercent:
371 0 : appender.append((UChar) 0x25);
372 0 : break;
373 : case kPerMill:
374 0 : appender.append((UChar) 0x2030);
375 0 : break;
376 : case kCurrency:
377 : {
378 0 : int32_t cl = iter.getTokenLength();
379 0 : for (int32_t i = 0; i < cl; ++i) {
380 0 : appender.append((UChar) 0xA4);
381 : }
382 : }
383 0 : break;
384 : case kNegative:
385 0 : appender.append((UChar) 0x2D);
386 0 : break;
387 : case kPositive:
388 0 : appender.append((UChar) 0x2B);
389 0 : break;
390 : default:
391 0 : U_ASSERT(FALSE);
392 : break;
393 : }
394 : }
395 0 : return appendTo;
396 : }
397 :
398 : class AffixPatternAppender : public UMemory {
399 : public:
400 0 : AffixPatternAppender(AffixPattern &dest) : fDest(&dest), fIdx(0) { }
401 :
402 0 : inline void append(UChar x) {
403 0 : if (fIdx == UPRV_LENGTHOF(fBuffer)) {
404 0 : fDest->addLiteral(fBuffer, 0, fIdx);
405 0 : fIdx = 0;
406 : }
407 0 : fBuffer[fIdx++] = x;
408 0 : }
409 :
410 : inline void append(UChar32 x) {
411 : if (fIdx >= UPRV_LENGTHOF(fBuffer) - 1) {
412 : fDest->addLiteral(fBuffer, 0, fIdx);
413 : fIdx = 0;
414 : }
415 : U16_APPEND_UNSAFE(fBuffer, fIdx, x);
416 : }
417 :
418 0 : inline void flush() {
419 0 : if (fIdx) {
420 0 : fDest->addLiteral(fBuffer, 0, fIdx);
421 : }
422 0 : fIdx = 0;
423 0 : }
424 :
425 : /**
426 : * flush the buffer when we go out of scope.
427 : */
428 0 : ~AffixPatternAppender() {
429 0 : flush();
430 0 : }
431 : private:
432 : AffixPattern *fDest;
433 : int32_t fIdx;
434 : UChar fBuffer[32];
435 : AffixPatternAppender(const AffixPatternAppender &other);
436 : AffixPatternAppender &operator=(const AffixPatternAppender &other);
437 : };
438 :
439 :
440 : AffixPattern &
441 0 : AffixPattern::parseUserAffixString(
442 : const UnicodeString &affixStr,
443 : AffixPattern &appendTo,
444 : UErrorCode &status) {
445 0 : if (U_FAILURE(status)) {
446 0 : return appendTo;
447 : }
448 0 : int32_t len = affixStr.length();
449 0 : const UChar *buffer = affixStr.getBuffer();
450 : // 0 = not quoted; 1 = quoted.
451 0 : int32_t state = 0;
452 0 : AffixPatternAppender appender(appendTo);
453 0 : for (int32_t i = 0; i < len; ) {
454 : UChar token;
455 0 : int32_t tokenSize = nextUserToken(buffer, i, len, &token);
456 0 : i += tokenSize;
457 0 : if (token == 0x27 && tokenSize == 1) { // quote
458 0 : state = 1 - state;
459 0 : continue;
460 : }
461 0 : if (state == 0) {
462 0 : switch (token) {
463 : case 0x25:
464 0 : appender.flush();
465 0 : appendTo.add(kPercent, 1);
466 0 : break;
467 : case 0x27: // double quote
468 0 : appender.append((UChar) 0x27);
469 0 : break;
470 : case 0x2030:
471 0 : appender.flush();
472 0 : appendTo.add(kPerMill, 1);
473 0 : break;
474 : case 0x2D:
475 0 : appender.flush();
476 0 : appendTo.add(kNegative, 1);
477 0 : break;
478 : case 0x2B:
479 0 : appender.flush();
480 0 : appendTo.add(kPositive, 1);
481 0 : break;
482 : case 0xA4:
483 0 : appender.flush();
484 0 : appendTo.add(kCurrency, tokenSize);
485 0 : break;
486 : default:
487 0 : appender.append(token);
488 0 : break;
489 : }
490 : } else {
491 0 : switch (token) {
492 : case 0x27: // double quote
493 0 : appender.append((UChar) 0x27);
494 0 : break;
495 : case 0xA4: // included b/c tokenSize can be > 1
496 0 : for (int32_t j = 0; j < tokenSize; ++j) {
497 0 : appender.append((UChar) 0xA4);
498 : }
499 0 : break;
500 : default:
501 0 : appender.append(token);
502 0 : break;
503 : }
504 : }
505 : }
506 0 : return appendTo;
507 : }
508 :
509 : AffixPattern &
510 0 : AffixPattern::parseAffixString(
511 : const UnicodeString &affixStr,
512 : AffixPattern &appendTo,
513 : UErrorCode &status) {
514 0 : if (U_FAILURE(status)) {
515 0 : return appendTo;
516 : }
517 0 : int32_t len = affixStr.length();
518 0 : const UChar *buffer = affixStr.getBuffer();
519 0 : for (int32_t i = 0; i < len; ) {
520 : UChar token;
521 0 : int32_t tokenSize = nextToken(buffer, i, len, &token);
522 0 : if (tokenSize == 1) {
523 0 : int32_t literalStart = i;
524 0 : ++i;
525 0 : while (i < len && (tokenSize = nextToken(buffer, i, len, &token)) == 1) {
526 0 : ++i;
527 : }
528 0 : appendTo.addLiteral(buffer, literalStart, i - literalStart);
529 :
530 : // If we reached end of string, we are done
531 0 : if (i == len) {
532 0 : return appendTo;
533 : }
534 : }
535 0 : i += tokenSize;
536 0 : switch (token) {
537 : case 0x25:
538 0 : appendTo.add(kPercent, 1);
539 0 : break;
540 : case 0x2030:
541 0 : appendTo.add(kPerMill, 1);
542 0 : break;
543 : case 0x2D:
544 0 : appendTo.add(kNegative, 1);
545 0 : break;
546 : case 0x2B:
547 0 : appendTo.add(kPositive, 1);
548 0 : break;
549 : case 0xA4:
550 : {
551 0 : if (tokenSize - 1 > 3) {
552 0 : status = U_PARSE_ERROR;
553 0 : return appendTo;
554 : }
555 0 : appendTo.add(kCurrency, tokenSize - 1);
556 : }
557 0 : break;
558 : default:
559 0 : appendTo.addLiteral(&token, 0, 1);
560 0 : break;
561 : }
562 : }
563 0 : return appendTo;
564 : }
565 :
566 : AffixPatternIterator &
567 0 : AffixPattern::iterator(AffixPatternIterator &result) const {
568 0 : result.nextLiteralIndex = 0;
569 0 : result.lastLiteralLength = 0;
570 0 : result.nextTokenIndex = 0;
571 0 : result.tokens = &tokens;
572 0 : result.literals = &literals;
573 0 : return result;
574 : }
575 :
576 : UBool
577 0 : AffixPatternIterator::nextToken() {
578 0 : int32_t tlen = tokens->length();
579 0 : if (nextTokenIndex == tlen) {
580 0 : return FALSE;
581 : }
582 0 : ++nextTokenIndex;
583 0 : const UChar *tokenBuffer = tokens->getBuffer();
584 0 : if (UNPACK_TOKEN(tokenBuffer[nextTokenIndex - 1]) ==
585 : AffixPattern::kLiteral) {
586 0 : while (nextTokenIndex < tlen &&
587 0 : UNPACK_LONG(tokenBuffer[nextTokenIndex])) {
588 0 : ++nextTokenIndex;
589 : }
590 0 : lastLiteralLength = 0;
591 0 : int32_t i = nextTokenIndex - 1;
592 0 : for (; UNPACK_LONG(tokenBuffer[i]); --i) {
593 0 : lastLiteralLength <<= 8;
594 0 : lastLiteralLength |= UNPACK_LENGTH(tokenBuffer[i]);
595 : }
596 0 : lastLiteralLength <<= 8;
597 0 : lastLiteralLength |= UNPACK_LENGTH(tokenBuffer[i]);
598 0 : nextLiteralIndex += lastLiteralLength;
599 : }
600 0 : return TRUE;
601 : }
602 :
603 : AffixPattern::ETokenType
604 0 : AffixPatternIterator::getTokenType() const {
605 0 : return UNPACK_TOKEN(tokens->charAt(nextTokenIndex - 1));
606 : }
607 :
608 : UnicodeString &
609 0 : AffixPatternIterator::getLiteral(UnicodeString &result) const {
610 0 : const UChar *buffer = literals->getBuffer();
611 0 : result.setTo(buffer + (nextLiteralIndex - lastLiteralLength), lastLiteralLength);
612 0 : return result;
613 : }
614 :
615 : int32_t
616 0 : AffixPatternIterator::getTokenLength() const {
617 0 : const UChar *tokenBuffer = tokens->getBuffer();
618 0 : AffixPattern::ETokenType type = UNPACK_TOKEN(tokenBuffer[nextTokenIndex - 1]);
619 0 : return type == AffixPattern::kLiteral ? lastLiteralLength : UNPACK_LENGTH(tokenBuffer[nextTokenIndex - 1]);
620 : }
621 :
622 0 : AffixPatternParser::AffixPatternParser()
623 0 : : fPercent(gPercent), fPermill(gPerMill), fNegative(gNegative), fPositive(gPositive) {
624 0 : }
625 :
626 0 : AffixPatternParser::AffixPatternParser(
627 0 : const DecimalFormatSymbols &symbols) {
628 0 : setDecimalFormatSymbols(symbols);
629 0 : }
630 :
631 : void
632 0 : AffixPatternParser::setDecimalFormatSymbols(
633 : const DecimalFormatSymbols &symbols) {
634 0 : fPercent = symbols.getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
635 0 : fPermill = symbols.getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
636 0 : fNegative = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
637 0 : fPositive = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
638 0 : }
639 :
640 : PluralAffix &
641 0 : AffixPatternParser::parse(
642 : const AffixPattern &affixPattern,
643 : const CurrencyAffixInfo ¤cyAffixInfo,
644 : PluralAffix &appendTo,
645 : UErrorCode &status) const {
646 0 : if (U_FAILURE(status)) {
647 0 : return appendTo;
648 : }
649 0 : AffixPatternIterator iter;
650 0 : affixPattern.iterator(iter);
651 0 : UnicodeString literal;
652 0 : while (iter.nextToken()) {
653 0 : switch (iter.getTokenType()) {
654 : case AffixPattern::kPercent:
655 0 : appendTo.append(fPercent, UNUM_PERCENT_FIELD);
656 0 : break;
657 : case AffixPattern::kPerMill:
658 0 : appendTo.append(fPermill, UNUM_PERMILL_FIELD);
659 0 : break;
660 : case AffixPattern::kNegative:
661 0 : appendTo.append(fNegative, UNUM_SIGN_FIELD);
662 0 : break;
663 : case AffixPattern::kPositive:
664 0 : appendTo.append(fPositive, UNUM_SIGN_FIELD);
665 0 : break;
666 : case AffixPattern::kCurrency:
667 0 : switch (iter.getTokenLength()) {
668 : case 1:
669 0 : appendTo.append(
670 0 : currencyAffixInfo.getSymbol(), UNUM_CURRENCY_FIELD);
671 0 : break;
672 : case 2:
673 0 : appendTo.append(
674 0 : currencyAffixInfo.getISO(), UNUM_CURRENCY_FIELD);
675 0 : break;
676 : case 3:
677 0 : appendTo.append(
678 0 : currencyAffixInfo.getLong(), UNUM_CURRENCY_FIELD, status);
679 0 : break;
680 : default:
681 0 : U_ASSERT(FALSE);
682 : break;
683 : }
684 0 : break;
685 : case AffixPattern::kLiteral:
686 0 : appendTo.append(iter.getLiteral(literal));
687 0 : break;
688 : default:
689 0 : U_ASSERT(FALSE);
690 : break;
691 : }
692 : }
693 0 : return appendTo;
694 : }
695 :
696 :
697 : U_NAMESPACE_END
698 : #endif /* #if !UCONFIG_NO_FORMATTING */
|