]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/fmtable.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / fmtable.cpp
CommitLineData
f3c0d7a5
A
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
b75a7d8f
A
3/*
4*******************************************************************************
2ca993e8
A
5* Copyright (C) 1997-2016, International Business Machines Corporation and
6* others. All Rights Reserved.
b75a7d8f
A
7*******************************************************************************
8*
9* File FMTABLE.CPP
10*
11* Modification History:
12*
13* Date Name Description
14* 03/25/97 clhuang Initial Implementation.
15********************************************************************************
16*/
17
18#include "unicode/utypes.h"
19
20#if !UCONFIG_NO_FORMATTING
21
729e4ab9 22#include <math.h>
b75a7d8f 23#include "unicode/fmtable.h"
374ca955
A
24#include "unicode/ustring.h"
25#include "unicode/measure.h"
26#include "unicode/curramt.h"
57a6839d 27#include "unicode/uformattable.h"
729e4ab9 28#include "charstr.h"
b75a7d8f 29#include "cmemory.h"
729e4ab9
A
30#include "cstring.h"
31#include "decNumber.h"
32#include "digitlst.h"
b331163b 33#include "fmtableimp.h"
0f5d89e8 34#include "number_decimalquantity.h"
b75a7d8f
A
35
36// *****************************************************************************
37// class Formattable
38// *****************************************************************************
39
40U_NAMESPACE_BEGIN
41
374ca955
A
42UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
43
0f5d89e8
A
44using number::impl::DecimalQuantity;
45
51004dcb 46
374ca955
A
47//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
48
49// NOTE: As of 3.0, there are limitations to the UObject API. It does
729e4ab9 50// not (yet) support cloning, operator=, nor operator==. To
374ca955
A
51// work around this, I implement some simple inlines here. Later
52// these can be modified or removed. [alan]
53
54// NOTE: These inlines assume that all fObjects are in fact instances
55// of the Measure class, which is true as of 3.0. [alan]
56
57// Return TRUE if *a == *b.
73c04bcf 58static inline UBool objectEquals(const UObject* a, const UObject* b) {
374ca955
A
59 // LATER: return *a == *b;
60 return *((const Measure*) a) == *((const Measure*) b);
61}
62
63// Return a clone of *a.
73c04bcf 64static inline UObject* objectClone(const UObject* a) {
374ca955
A
65 // LATER: return a->clone();
66 return ((const Measure*) a)->clone();
67}
68
69// Return TRUE if *a is an instance of Measure.
73c04bcf 70static inline UBool instanceOfMeasure(const UObject* a) {
729e4ab9 71 return dynamic_cast<const Measure*>(a) != NULL;
374ca955
A
72}
73
73c04bcf
A
74/**
75 * Creates a new Formattable array and copies the values from the specified
76 * original.
77 * @param array the original array
78 * @param count the original array count
79 * @return the new Formattable array.
80 */
729e4ab9 81static Formattable* createArrayCopy(const Formattable* array, int32_t count) {
73c04bcf 82 Formattable *result = new Formattable[count];
46f4442e
A
83 if (result != NULL) {
84 for (int32_t i=0; i<count; ++i)
85 result[i] = array[i]; // Don't memcpy!
86 }
73c04bcf
A
87 return result;
88}
89
374ca955
A
90//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
91
92/**
93 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
94 */
729e4ab9 95static void setError(UErrorCode& ec, UErrorCode err) {
374ca955
A
96 if (U_SUCCESS(ec)) {
97 ec = err;
98 }
99}
b75a7d8f 100
729e4ab9
A
101//
102// Common initialization code, shared by constructors.
103// Put everything into a known state.
104//
105void Formattable::init() {
106 fValue.fInt64 = 0;
107 fType = kLong;
108 fDecimalStr = NULL;
109 fDecimalNum = NULL;
0f5d89e8 110 fDecimalQuantity = NULL;
729e4ab9
A
111 fBogus.setToBogus();
112}
113
b75a7d8f
A
114// -------------------------------------
115// default constructor.
116// Creates a formattable object with a long value 0.
117
729e4ab9
A
118Formattable::Formattable() {
119 init();
b75a7d8f
A
120}
121
122// -------------------------------------
123// Creates a formattable object with a Date instance.
124
125Formattable::Formattable(UDate date, ISDATE /*isDate*/)
b75a7d8f 126{
729e4ab9
A
127 init();
128 fType = kDate;
b75a7d8f
A
129 fValue.fDate = date;
130}
131
132// -------------------------------------
133// Creates a formattable object with a double value.
134
135Formattable::Formattable(double value)
b75a7d8f 136{
729e4ab9
A
137 init();
138 fType = kDouble;
b75a7d8f
A
139 fValue.fDouble = value;
140}
141
142// -------------------------------------
729e4ab9 143// Creates a formattable object with an int32_t value.
b75a7d8f
A
144
145Formattable::Formattable(int32_t value)
b75a7d8f 146{
729e4ab9 147 init();
374ca955
A
148 fValue.fInt64 = value;
149}
150
151// -------------------------------------
729e4ab9 152// Creates a formattable object with an int64_t value.
374ca955
A
153
154Formattable::Formattable(int64_t value)
374ca955 155{
729e4ab9
A
156 init();
157 fType = kInt64;
374ca955 158 fValue.fInt64 = value;
b75a7d8f
A
159}
160
729e4ab9
A
161// -------------------------------------
162// Creates a formattable object with a decimal number value from a string.
163
f3c0d7a5 164Formattable::Formattable(StringPiece number, UErrorCode &status) {
729e4ab9
A
165 init();
166 setDecimalNumber(number, status);
167}
168
169
b75a7d8f
A
170// -------------------------------------
171// Creates a formattable object with a UnicodeString instance.
172
173Formattable::Formattable(const UnicodeString& stringToCopy)
b75a7d8f 174{
729e4ab9
A
175 init();
176 fType = kString;
b75a7d8f
A
177 fValue.fString = new UnicodeString(stringToCopy);
178}
179
180// -------------------------------------
181// Creates a formattable object with a UnicodeString* value.
182// (adopting symantics)
183
184Formattable::Formattable(UnicodeString* stringToAdopt)
b75a7d8f 185{
729e4ab9
A
186 init();
187 fType = kString;
b75a7d8f
A
188 fValue.fString = stringToAdopt;
189}
190
374ca955 191Formattable::Formattable(UObject* objectToAdopt)
374ca955 192{
729e4ab9
A
193 init();
194 fType = kObject;
374ca955
A
195 fValue.fObject = objectToAdopt;
196}
197
b75a7d8f
A
198// -------------------------------------
199
200Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
201 : UObject(), fType(kArray)
202{
729e4ab9
A
203 init();
204 fType = kArray;
b75a7d8f
A
205 fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
206 fValue.fArrayAndCount.fCount = count;
207}
208
209// -------------------------------------
210// copy constructor
211
729e4ab9 212
b75a7d8f 213Formattable::Formattable(const Formattable &source)
729e4ab9 214 : UObject(*this)
b75a7d8f 215{
729e4ab9 216 init();
b75a7d8f
A
217 *this = source;
218}
219
220// -------------------------------------
221// assignment operator
222
223Formattable&
224Formattable::operator=(const Formattable& source)
225{
226 if (this != &source)
227 {
228 // Disposes the current formattable value/setting.
229 dispose();
230
231 // Sets the correct data type for this value.
232 fType = source.fType;
233 switch (fType)
234 {
235 case kArray:
236 // Sets each element in the array one by one and records the array count.
237 fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount;
238 fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray,
239 source.fValue.fArrayAndCount.fCount);
240 break;
241 case kString:
242 // Sets the string value.
243 fValue.fString = new UnicodeString(*source.fValue.fString);
244 break;
245 case kDouble:
246 // Sets the double value.
247 fValue.fDouble = source.fValue.fDouble;
248 break;
249 case kLong:
374ca955 250 case kInt64:
b75a7d8f 251 // Sets the long value.
374ca955 252 fValue.fInt64 = source.fValue.fInt64;
b75a7d8f
A
253 break;
254 case kDate:
255 // Sets the Date value.
256 fValue.fDate = source.fValue.fDate;
257 break;
374ca955
A
258 case kObject:
259 fValue.fObject = objectClone(source.fValue.fObject);
260 break;
b75a7d8f 261 }
729e4ab9
A
262
263 UErrorCode status = U_ZERO_ERROR;
264 if (source.fDecimalNum != NULL) {
51004dcb 265 fDecimalNum = new DigitList(*source.fDecimalNum); // TODO: use internal digit list
729e4ab9 266 }
0f5d89e8
A
267 if (source.fDecimalQuantity != NULL) {
268 fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity);
269 }
729e4ab9
A
270 if (source.fDecimalStr != NULL) {
271 fDecimalStr = new CharString(*source.fDecimalStr, status);
272 if (U_FAILURE(status)) {
273 delete fDecimalStr;
274 fDecimalStr = NULL;
275 }
276 }
b75a7d8f
A
277 }
278 return *this;
279}
280
281// -------------------------------------
282
283UBool
284Formattable::operator==(const Formattable& that) const
285{
374ca955
A
286 int32_t i;
287
b75a7d8f
A
288 if (this == &that) return TRUE;
289
290 // Returns FALSE if the data types are different.
291 if (fType != that.fType) return FALSE;
292
293 // Compares the actual data values.
374ca955 294 UBool equal = TRUE;
b75a7d8f
A
295 switch (fType) {
296 case kDate:
374ca955
A
297 equal = (fValue.fDate == that.fValue.fDate);
298 break;
b75a7d8f 299 case kDouble:
374ca955
A
300 equal = (fValue.fDouble == that.fValue.fDouble);
301 break;
b75a7d8f 302 case kLong:
374ca955
A
303 case kInt64:
304 equal = (fValue.fInt64 == that.fValue.fInt64);
305 break;
b75a7d8f 306 case kString:
374ca955
A
307 equal = (*(fValue.fString) == *(that.fValue.fString));
308 break;
b75a7d8f 309 case kArray:
374ca955
A
310 if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
311 equal = FALSE;
312 break;
313 }
b75a7d8f 314 // Checks each element for equality.
374ca955
A
315 for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
316 if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
317 equal = FALSE;
318 break;
319 }
320 }
321 break;
322 case kObject:
46f4442e
A
323 if (fValue.fObject == NULL || that.fValue.fObject == NULL) {
324 equal = FALSE;
325 } else {
326 equal = objectEquals(fValue.fObject, that.fValue.fObject);
327 }
b75a7d8f
A
328 break;
329 }
374ca955 330
729e4ab9 331 // TODO: compare digit lists if numeric.
374ca955 332 return equal;
b75a7d8f
A
333}
334
335// -------------------------------------
336
337Formattable::~Formattable()
338{
339 dispose();
340}
341
342// -------------------------------------
343
344void Formattable::dispose()
345{
346 // Deletes the data value if necessary.
347 switch (fType) {
348 case kString:
349 delete fValue.fString;
350 break;
351 case kArray:
352 delete[] fValue.fArrayAndCount.fArray;
353 break;
374ca955
A
354 case kObject:
355 delete fValue.fObject;
356 break;
357 default:
b75a7d8f
A
358 break;
359 }
729e4ab9
A
360
361 fType = kLong;
362 fValue.fInt64 = 0;
51004dcb 363
729e4ab9
A
364 delete fDecimalStr;
365 fDecimalStr = NULL;
51004dcb
A
366
367 FmtStackData *stackData = (FmtStackData*)fStackData;
368 if(fDecimalNum != &(stackData->stackDecimalNum)) {
369 delete fDecimalNum;
370 } else {
371 fDecimalNum->~DigitList(); // destruct, don't deallocate
372 }
729e4ab9 373 fDecimalNum = NULL;
0f5d89e8
A
374
375 delete fDecimalQuantity;
376 fDecimalQuantity = NULL;
b75a7d8f
A
377}
378
374ca955
A
379Formattable *
380Formattable::clone() const {
381 return new Formattable(*this);
382}
383
b75a7d8f
A
384// -------------------------------------
385// Gets the data type of this Formattable object.
386Formattable::Type
387Formattable::getType() const
388{
389 return fType;
390}
391
374ca955
A
392UBool
393Formattable::isNumeric() const {
394 switch (fType) {
395 case kDouble:
396 case kLong:
397 case kInt64:
398 return TRUE;
399 default:
400 return FALSE;
401 }
402}
403
404// -------------------------------------
405int32_t
406//Formattable::getLong(UErrorCode* status) const
407Formattable::getLong(UErrorCode& status) const
408{
409 if (U_FAILURE(status)) {
410 return 0;
411 }
412
413 switch (fType) {
414 case Formattable::kLong:
415 return (int32_t)fValue.fInt64;
57a6839d 416 case Formattable::kInt64:
374ca955
A
417 if (fValue.fInt64 > INT32_MAX) {
418 status = U_INVALID_FORMAT_ERROR;
419 return INT32_MAX;
420 } else if (fValue.fInt64 < INT32_MIN) {
421 status = U_INVALID_FORMAT_ERROR;
422 return INT32_MIN;
423 } else {
424 return (int32_t)fValue.fInt64;
425 }
426 case Formattable::kDouble:
427 if (fValue.fDouble > INT32_MAX) {
428 status = U_INVALID_FORMAT_ERROR;
429 return INT32_MAX;
430 } else if (fValue.fDouble < INT32_MIN) {
431 status = U_INVALID_FORMAT_ERROR;
432 return INT32_MIN;
433 } else {
434 return (int32_t)fValue.fDouble; // loses fraction
435 }
436 case Formattable::kObject:
46f4442e
A
437 if (fValue.fObject == NULL) {
438 status = U_MEMORY_ALLOCATION_ERROR;
439 return 0;
440 }
374ca955
A
441 // TODO Later replace this with instanceof call
442 if (instanceOfMeasure(fValue.fObject)) {
443 return ((const Measure*) fValue.fObject)->
444 getNumber().getLong(status);
445 }
2ca993e8
A
446 U_FALLTHROUGH;
447 default:
374ca955
A
448 status = U_INVALID_FORMAT_ERROR;
449 return 0;
450 }
451}
452
453// -------------------------------------
729e4ab9
A
454// Maximum int that can be represented exactly in a double. (53 bits)
455// Larger ints may be rounded to a near-by value as not all are representable.
456// TODO: move this constant elsewhere, possibly configure it for different
457// floating point formats, if any non-standard ones are still in use.
458static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
459
374ca955
A
460int64_t
461Formattable::getInt64(UErrorCode& status) const
462{
463 if (U_FAILURE(status)) {
464 return 0;
465 }
466
467 switch (fType) {
468 case Formattable::kLong:
469 case Formattable::kInt64:
470 return fValue.fInt64;
471 case Formattable::kDouble:
729e4ab9 472 if (fValue.fDouble > (double)U_INT64_MAX) {
374ca955
A
473 status = U_INVALID_FORMAT_ERROR;
474 return U_INT64_MAX;
729e4ab9 475 } else if (fValue.fDouble < (double)U_INT64_MIN) {
374ca955
A
476 status = U_INVALID_FORMAT_ERROR;
477 return U_INT64_MIN;
729e4ab9
A
478 } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalNum != NULL) {
479 int64_t val = fDecimalNum->getInt64();
480 if (val != 0) {
481 return val;
482 } else {
483 status = U_INVALID_FORMAT_ERROR;
484 return fValue.fDouble > 0 ? U_INT64_MAX : U_INT64_MIN;
485 }
374ca955
A
486 } else {
487 return (int64_t)fValue.fDouble;
729e4ab9 488 }
374ca955 489 case Formattable::kObject:
46f4442e
A
490 if (fValue.fObject == NULL) {
491 status = U_MEMORY_ALLOCATION_ERROR;
492 return 0;
493 }
374ca955
A
494 if (instanceOfMeasure(fValue.fObject)) {
495 return ((const Measure*) fValue.fObject)->
496 getNumber().getInt64(status);
497 }
2ca993e8
A
498 U_FALLTHROUGH;
499 default:
374ca955
A
500 status = U_INVALID_FORMAT_ERROR;
501 return 0;
502 }
503}
504
505// -------------------------------------
506double
507Formattable::getDouble(UErrorCode& status) const
508{
509 if (U_FAILURE(status)) {
510 return 0;
511 }
512
513 switch (fType) {
514 case Formattable::kLong:
515 case Formattable::kInt64: // loses precision
516 return (double)fValue.fInt64;
517 case Formattable::kDouble:
518 return fValue.fDouble;
519 case Formattable::kObject:
46f4442e
A
520 if (fValue.fObject == NULL) {
521 status = U_MEMORY_ALLOCATION_ERROR;
522 return 0;
523 }
374ca955
A
524 // TODO Later replace this with instanceof call
525 if (instanceOfMeasure(fValue.fObject)) {
526 return ((const Measure*) fValue.fObject)->
527 getNumber().getDouble(status);
528 }
2ca993e8
A
529 U_FALLTHROUGH;
530 default:
374ca955
A
531 status = U_INVALID_FORMAT_ERROR;
532 return 0;
533 }
534}
535
536const UObject*
537Formattable::getObject() const {
538 return (fType == kObject) ? fValue.fObject : NULL;
539}
540
b75a7d8f
A
541// -------------------------------------
542// Sets the value to a double value d.
543
544void
545Formattable::setDouble(double d)
546{
547 dispose();
548 fType = kDouble;
549 fValue.fDouble = d;
550}
551
552// -------------------------------------
553// Sets the value to a long value l.
554
555void
556Formattable::setLong(int32_t l)
557{
558 dispose();
559 fType = kLong;
374ca955
A
560 fValue.fInt64 = l;
561}
562
563// -------------------------------------
564// Sets the value to an int64 value ll.
565
566void
567Formattable::setInt64(int64_t ll)
568{
569 dispose();
570 fType = kInt64;
571 fValue.fInt64 = ll;
b75a7d8f
A
572}
573
574// -------------------------------------
575// Sets the value to a Date instance d.
576
577void
578Formattable::setDate(UDate d)
579{
580 dispose();
581 fType = kDate;
582 fValue.fDate = d;
583}
584
585// -------------------------------------
586// Sets the value to a string value stringToCopy.
587
588void
589Formattable::setString(const UnicodeString& stringToCopy)
590{
591 dispose();
592 fType = kString;
593 fValue.fString = new UnicodeString(stringToCopy);
594}
595
596// -------------------------------------
597// Sets the value to an array of Formattable objects.
598
599void
600Formattable::setArray(const Formattable* array, int32_t count)
601{
602 dispose();
603 fType = kArray;
604 fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
605 fValue.fArrayAndCount.fCount = count;
606}
607
608// -------------------------------------
609// Adopts the stringToAdopt value.
610
611void
612Formattable::adoptString(UnicodeString* stringToAdopt)
613{
614 dispose();
615 fType = kString;
616 fValue.fString = stringToAdopt;
617}
618
619// -------------------------------------
620// Adopts the array value and its count.
621
622void
623Formattable::adoptArray(Formattable* array, int32_t count)
624{
625 dispose();
626 fType = kArray;
627 fValue.fArrayAndCount.fArray = array;
628 fValue.fArrayAndCount.fCount = count;
629}
630
374ca955
A
631void
632Formattable::adoptObject(UObject* objectToAdopt) {
633 dispose();
634 fType = kObject;
635 fValue.fObject = objectToAdopt;
636}
637
638// -------------------------------------
639UnicodeString&
640Formattable::getString(UnicodeString& result, UErrorCode& status) const
641{
642 if (fType != kString) {
643 setError(status, U_INVALID_FORMAT_ERROR);
644 result.setToBogus();
645 } else {
46f4442e
A
646 if (fValue.fString == NULL) {
647 setError(status, U_MEMORY_ALLOCATION_ERROR);
648 } else {
649 result = *fValue.fString;
650 }
374ca955
A
651 }
652 return result;
653}
654
655// -------------------------------------
656const UnicodeString&
657Formattable::getString(UErrorCode& status) const
658{
659 if (fType != kString) {
660 setError(status, U_INVALID_FORMAT_ERROR);
661 return *getBogus();
662 }
46f4442e
A
663 if (fValue.fString == NULL) {
664 setError(status, U_MEMORY_ALLOCATION_ERROR);
665 return *getBogus();
666 }
374ca955
A
667 return *fValue.fString;
668}
669
670// -------------------------------------
671UnicodeString&
672Formattable::getString(UErrorCode& status)
673{
674 if (fType != kString) {
675 setError(status, U_INVALID_FORMAT_ERROR);
676 return *getBogus();
677 }
46f4442e
A
678 if (fValue.fString == NULL) {
679 setError(status, U_MEMORY_ALLOCATION_ERROR);
680 return *getBogus();
681 }
374ca955
A
682 return *fValue.fString;
683}
684
685// -------------------------------------
686const Formattable*
687Formattable::getArray(int32_t& count, UErrorCode& status) const
688{
689 if (fType != kArray) {
690 setError(status, U_INVALID_FORMAT_ERROR);
691 count = 0;
692 return NULL;
693 }
694 count = fValue.fArrayAndCount.fCount;
695 return fValue.fArrayAndCount.fArray;
696}
697
698// -------------------------------------
699// Gets the bogus string, ensures mondo bogosity.
700
701UnicodeString*
702Formattable::getBogus() const
703{
704 return (UnicodeString*)&fBogus; /* cast away const :-( */
705}
706
729e4ab9
A
707
708// --------------------------------------
709StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
710 if (U_FAILURE(status)) {
711 return "";
712 }
713 if (fDecimalStr != NULL) {
57a6839d 714 return fDecimalStr->toStringPiece();
729e4ab9
A
715 }
716
57a6839d
A
717 CharString *decimalStr = internalGetCharString(status);
718 if(decimalStr == NULL) {
719 return ""; // getDecimalNumber returns "" for error cases
720 } else {
721 return decimalStr->toStringPiece();
722 }
723}
724
725CharString *Formattable::internalGetCharString(UErrorCode &status) {
726 if(fDecimalStr == NULL) {
727 if (fDecimalNum == NULL) {
729e4ab9
A
728 // No decimal number for the formattable yet. Which means the value was
729 // set directly by the user as an int, int64 or double. If the value came
730 // from parsing, or from the user setting a decimal number, fDecimalNum
731 // would already be set.
732 //
57a6839d 733 fDecimalNum = new DigitList; // TODO: use internal digit list
729e4ab9 734 if (fDecimalNum == NULL) {
57a6839d
A
735 status = U_MEMORY_ALLOCATION_ERROR;
736 return NULL;
729e4ab9
A
737 }
738
739 switch (fType) {
740 case kDouble:
57a6839d
A
741 fDecimalNum->set(this->getDouble());
742 break;
729e4ab9 743 case kLong:
57a6839d
A
744 fDecimalNum->set(this->getLong());
745 break;
729e4ab9 746 case kInt64:
57a6839d
A
747 fDecimalNum->set(this->getInt64());
748 break;
729e4ab9 749 default:
57a6839d
A
750 // The formattable's value is not a numeric type.
751 status = U_INVALID_STATE_ERROR;
752 return NULL;
729e4ab9 753 }
57a6839d 754 }
729e4ab9 755
0f5d89e8
A
756 if (fDecimalQuantity == NULL) {
757 // No decimal number for the formattable yet...
758 LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status);
759 if (U_FAILURE(status)) { return nullptr; }
760 populateDecimalQuantity(*dq, status);
761 if (U_FAILURE(status)) { return nullptr; }
762 fDecimalQuantity = dq.orphan();
763 }
764
57a6839d
A
765 fDecimalStr = new CharString;
766 if (fDecimalStr == NULL) {
729e4ab9 767 status = U_MEMORY_ALLOCATION_ERROR;
57a6839d
A
768 return NULL;
769 }
770 fDecimalNum->getDecimal(*fDecimalStr, status);
729e4ab9 771 }
57a6839d 772 return fDecimalStr;
729e4ab9
A
773}
774
0f5d89e8
A
775void
776Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const {
777 if (fDecimalQuantity != nullptr) {
778 output = *fDecimalQuantity;
779 return;
780 }
781
782 switch (fType) {
783 case kDouble:
784 output.setToDouble(this->getDouble());
785 output.roundToInfinity();
786 break;
787 case kLong:
788 output.setToInt(this->getLong());
789 break;
790 case kInt64:
791 output.setToLong(this->getInt64());
792 break;
793 default:
794 // The formattable's value is not a numeric type.
795 status = U_INVALID_STATE_ERROR;
796 }
797}
729e4ab9 798
51004dcb
A
799DigitList *
800Formattable::getInternalDigitList() {
801 FmtStackData *stackData = (FmtStackData*)fStackData;
802 if(fDecimalNum != &(stackData->stackDecimalNum)) {
803 delete fDecimalNum;
804 fDecimalNum = new (&(stackData->stackDecimalNum), kOnStack) DigitList();
805 } else {
806 fDecimalNum->clear();
807 }
808 return fDecimalNum;
809}
729e4ab9
A
810
811// ---------------------------------------
812void
813Formattable::adoptDigitList(DigitList *dl) {
51004dcb
A
814 if(fDecimalNum==dl) {
815 fDecimalNum = NULL; // don't delete
816 }
817 dispose();
818
819 fDecimalNum = dl;
729e4ab9 820
51004dcb
A
821 if(dl==NULL) { // allow adoptDigitList(NULL) to clear
822 return;
823 }
729e4ab9
A
824
825 // Set the value into the Union of simple type values.
826 // Cannot use the set() functions because they would delete the fDecimalNum value,
827
828 if (fDecimalNum->fitsIntoLong(FALSE)) {
829 fType = kLong;
830 fValue.fInt64 = fDecimalNum->getLong();
831 } else if (fDecimalNum->fitsIntoInt64(FALSE)) {
832 fType = kInt64;
833 fValue.fInt64 = fDecimalNum->getInt64();
834 } else {
835 fType = kDouble;
836 fValue.fDouble = fDecimalNum->getDouble();
837 }
838}
839
0f5d89e8
A
840// ---------------------------------------
841void
842Formattable::adoptDecimalQuantity(DecimalQuantity *dq) {
843 if (fDecimalQuantity != NULL) {
844 delete fDecimalQuantity;
845 }
846 fDecimalQuantity = dq;
847 if (dq == NULL) { // allow adoptDigitList(NULL) to clear
848 return;
849 }
850
851 // Set the value into the Union of simple type values.
852 // Cannot use the set() functions because they would delete the fDecimalNum value.
853 if (fDecimalQuantity->fitsInLong()) {
854 fValue.fInt64 = fDecimalQuantity->toLong();
855 if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) {
856 fType = kLong;
857 } else {
858 fType = kInt64;
859 }
860 } else {
861 fType = kDouble;
862 fValue.fDouble = fDecimalQuantity->toDouble();
863 }
864}
865
729e4ab9
A
866
867// ---------------------------------------
868void
f3c0d7a5 869Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) {
729e4ab9
A
870 if (U_FAILURE(status)) {
871 return;
872 }
873 dispose();
874
875 // Copy the input string and nul-terminate it.
876 // The decNumber library requires nul-terminated input. StringPiece input
877 // is not guaranteed nul-terminated. Too bad.
878 // CharString automatically adds the nul.
51004dcb 879 DigitList *dnum = new DigitList(); // TODO: use getInternalDigitList
729e4ab9
A
880 if (dnum == NULL) {
881 status = U_MEMORY_ALLOCATION_ERROR;
882 return;
883 }
884 dnum->set(CharString(numberString, status).toStringPiece(), status);
885 if (U_FAILURE(status)) {
886 delete dnum;
887 return; // String didn't contain a decimal number.
888 }
889 adoptDigitList(dnum);
890
0f5d89e8
A
891 auto* dq = new DecimalQuantity();
892 dq->setToDecNumber(numberString, status);
893 adoptDecimalQuantity(dq);
894
729e4ab9
A
895 // Note that we do not hang on to the caller's input string.
896 // If we are asked for the string, we will regenerate one from fDecimalNum.
897}
898
b75a7d8f
A
899#if 0
900//----------------------------------------------------
901// console I/O
902//----------------------------------------------------
903#ifdef _DEBUG
904
b75a7d8f
A
905#include <iostream>
906using namespace std;
b75a7d8f
A
907
908#include "unicode/datefmt.h"
909#include "unistrm.h"
910
911class FormattableStreamer /* not : public UObject because all methods are static */ {
912public:
913 static void streamOut(ostream& stream, const Formattable& obj);
914
915private:
916 FormattableStreamer() {} // private - forbid instantiation
917};
918
919// This is for debugging purposes only. This will send a displayable
920// form of the Formattable object to the output stream.
921
922void
923FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
924{
925 static DateFormat *defDateFormat = 0;
926
927 UnicodeString buffer;
928 switch(obj.getType()) {
929 case Formattable::kDate :
930 // Creates a DateFormat instance for formatting the
931 // Date instance.
932 if (defDateFormat == 0) {
933 defDateFormat = DateFormat::createInstance();
934 }
935 defDateFormat->format(obj.getDate(), buffer);
936 stream << buffer;
937 break;
938 case Formattable::kDouble :
939 // Output the double as is.
940 stream << obj.getDouble() << 'D';
941 break;
942 case Formattable::kLong :
943 // Output the double as is.
944 stream << obj.getLong() << 'L';
945 break;
946 case Formattable::kString:
947 // Output the double as is. Please see UnicodeString console
948 // I/O routine for more details.
949 stream << '"' << obj.getString(buffer) << '"';
950 break;
951 case Formattable::kArray:
952 int32_t i, count;
953 const Formattable* array;
954 array = obj.getArray(count);
955 stream << '[';
956 // Recursively calling the console I/O routine for each element in the array.
957 for (i=0; i<count; ++i) {
958 FormattableStreamer::streamOut(stream, array[i]);
959 stream << ( (i==(count-1)) ? "" : ", " );
960 }
961 stream << ']';
962 break;
963 default:
964 // Not a recognizable Formattable object.
965 stream << "INVALID_Formattable";
966 }
967 stream.flush();
968}
969#endif
970
971#endif
972
973U_NAMESPACE_END
974
57a6839d
A
975/* ---- UFormattable implementation ---- */
976
977U_NAMESPACE_USE
978
979U_DRAFT UFormattable* U_EXPORT2
980ufmt_open(UErrorCode *status) {
981 if( U_FAILURE(*status) ) {
982 return NULL;
983 }
984 UFormattable *fmt = (new Formattable())->toUFormattable();
985
986 if( fmt == NULL ) {
987 *status = U_MEMORY_ALLOCATION_ERROR;
988 }
989 return fmt;
990}
991
992U_DRAFT void U_EXPORT2
993ufmt_close(UFormattable *fmt) {
994 Formattable *obj = Formattable::fromUFormattable(fmt);
995
996 delete obj;
997}
998
999U_INTERNAL UFormattableType U_EXPORT2
1000ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
1001 if(U_FAILURE(*status)) {
1002 return (UFormattableType)UFMT_COUNT;
1003 }
1004 const Formattable *obj = Formattable::fromUFormattable(fmt);
1005 return (UFormattableType)obj->getType();
1006}
1007
1008
1009U_INTERNAL UBool U_EXPORT2
1010ufmt_isNumeric(const UFormattable *fmt) {
1011 const Formattable *obj = Formattable::fromUFormattable(fmt);
1012 return obj->isNumeric();
1013}
1014
1015U_DRAFT UDate U_EXPORT2
1016ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
1017 const Formattable *obj = Formattable::fromUFormattable(fmt);
1018
1019 return obj->getDate(*status);
1020}
1021
1022U_DRAFT double U_EXPORT2
1023ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
1024 Formattable *obj = Formattable::fromUFormattable(fmt);
1025
1026 return obj->getDouble(*status);
1027}
1028
1029U_DRAFT int32_t U_EXPORT2
1030ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
1031 Formattable *obj = Formattable::fromUFormattable(fmt);
1032
1033 return obj->getLong(*status);
1034}
1035
1036
1037U_DRAFT const void *U_EXPORT2
1038ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
1039 const Formattable *obj = Formattable::fromUFormattable(fmt);
1040
1041 const void *ret = obj->getObject();
1042 if( ret==NULL &&
1043 (obj->getType() != Formattable::kObject) &&
1044 U_SUCCESS( *status )) {
1045 *status = U_INVALID_FORMAT_ERROR;
1046 }
1047 return ret;
1048}
1049
1050U_DRAFT const UChar* U_EXPORT2
1051ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
1052 Formattable *obj = Formattable::fromUFormattable(fmt);
1053
1054 // avoid bogosity by checking the type first.
1055 if( obj->getType() != Formattable::kString ) {
1056 if( U_SUCCESS(*status) ){
1057 *status = U_INVALID_FORMAT_ERROR;
1058 }
1059 return NULL;
1060 }
1061
1062 // This should return a valid string
1063 UnicodeString &str = obj->getString(*status);
1064 if( U_SUCCESS(*status) && len != NULL ) {
1065 *len = str.length();
1066 }
1067 return str.getTerminatedBuffer();
1068}
1069
1070U_DRAFT int32_t U_EXPORT2
1071ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
1072 const Formattable *obj = Formattable::fromUFormattable(fmt);
1073
1074 int32_t count;
1075 (void)obj->getArray(count, *status);
1076 return count;
1077}
1078
1079U_DRAFT UFormattable * U_EXPORT2
1080ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
1081 Formattable *obj = Formattable::fromUFormattable(fmt);
1082 int32_t count;
1083 (void)obj->getArray(count, *status);
1084 if(U_FAILURE(*status)) {
1085 return NULL;
1086 } else if(n<0 || n>=count) {
1087 setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
1088 return NULL;
1089 } else {
1090 return (*obj)[n].toUFormattable(); // returns non-const Formattable
1091 }
1092}
1093
1094U_DRAFT const char * U_EXPORT2
1095ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
1096 if(U_FAILURE(*status)) {
1097 return "";
1098 }
1099 Formattable *obj = Formattable::fromUFormattable(fmt);
1100 CharString *charString = obj->internalGetCharString(*status);
1101 if(U_FAILURE(*status)) {
1102 return "";
1103 }
1104 if(charString == NULL) {
1105 *status = U_MEMORY_ALLOCATION_ERROR;
1106 return "";
1107 } else {
1108 if(len!=NULL) {
1109 *len = charString->length();
1110 }
1111 return charString->data();
1112 }
1113}
1114
1115U_DRAFT int64_t U_EXPORT2
1116ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
1117 Formattable *obj = Formattable::fromUFormattable(fmt);
1118 return obj->getInt64(*status);
1119}
1120
b75a7d8f
A
1121#endif /* #if !UCONFIG_NO_FORMATTING */
1122
1123//eof