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