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