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