• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2012, 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 "charstr.h"
26 #include "cmemory.h"
27 #include "cstring.h"
28 #include "decNumber.h"
29 #include "digitlst.h"
30 
31 // *****************************************************************************
32 // class Formattable
33 // *****************************************************************************
34 
35 U_NAMESPACE_BEGIN
36 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)37 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
38 
39 #include "fmtableimp.h"
40 
41 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
42 
43 // NOTE: As of 3.0, there are limitations to the UObject API.  It does
44 // not (yet) support cloning, operator=, nor operator==.  To
45 // work around this, I implement some simple inlines here.  Later
46 // these can be modified or removed.  [alan]
47 
48 // NOTE: These inlines assume that all fObjects are in fact instances
49 // of the Measure class, which is true as of 3.0.  [alan]
50 
51 // Return TRUE if *a == *b.
52 static inline UBool objectEquals(const UObject* a, const UObject* b) {
53     // LATER: return *a == *b;
54     return *((const Measure*) a) == *((const Measure*) b);
55 }
56 
57 // Return a clone of *a.
objectClone(const UObject * a)58 static inline UObject* objectClone(const UObject* a) {
59     // LATER: return a->clone();
60     return ((const Measure*) a)->clone();
61 }
62 
63 // Return TRUE if *a is an instance of Measure.
instanceOfMeasure(const UObject * a)64 static inline UBool instanceOfMeasure(const UObject* a) {
65     return dynamic_cast<const Measure*>(a) != NULL;
66 }
67 
68 /**
69  * Creates a new Formattable array and copies the values from the specified
70  * original.
71  * @param array the original array
72  * @param count the original array count
73  * @return the new Formattable array.
74  */
createArrayCopy(const Formattable * array,int32_t count)75 static Formattable* createArrayCopy(const Formattable* array, int32_t count) {
76     Formattable *result = new Formattable[count];
77     if (result != NULL) {
78         for (int32_t i=0; i<count; ++i)
79             result[i] = array[i]; // Don't memcpy!
80     }
81     return result;
82 }
83 
84 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
85 
86 /**
87  * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
88  */
setError(UErrorCode & ec,UErrorCode err)89 static void setError(UErrorCode& ec, UErrorCode err) {
90     if (U_SUCCESS(ec)) {
91         ec = err;
92     }
93 }
94 
95 //
96 //  Common initialization code, shared by constructors.
97 //  Put everything into a known state.
98 //
init()99 void  Formattable::init() {
100     fValue.fInt64 = 0;
101     fType = kLong;
102     fDecimalStr = NULL;
103     fDecimalNum = NULL;
104     fBogus.setToBogus();
105 }
106 
107 // -------------------------------------
108 // default constructor.
109 // Creates a formattable object with a long value 0.
110 
Formattable()111 Formattable::Formattable() {
112     init();
113 }
114 
115 // -------------------------------------
116 // Creates a formattable object with a Date instance.
117 
Formattable(UDate date,ISDATE)118 Formattable::Formattable(UDate date, ISDATE /*isDate*/)
119 {
120     init();
121     fType = kDate;
122     fValue.fDate = date;
123 }
124 
125 // -------------------------------------
126 // Creates a formattable object with a double value.
127 
Formattable(double value)128 Formattable::Formattable(double value)
129 {
130     init();
131     fType = kDouble;
132     fValue.fDouble = value;
133 }
134 
135 // -------------------------------------
136 // Creates a formattable object with an int32_t value.
137 
Formattable(int32_t value)138 Formattable::Formattable(int32_t value)
139 {
140     init();
141     fValue.fInt64 = value;
142 }
143 
144 // -------------------------------------
145 // Creates a formattable object with an int64_t value.
146 
Formattable(int64_t value)147 Formattable::Formattable(int64_t value)
148 {
149     init();
150     fType = kInt64;
151     fValue.fInt64 = value;
152 }
153 
154 // -------------------------------------
155 // Creates a formattable object with a decimal number value from a string.
156 
Formattable(const StringPiece & number,UErrorCode & status)157 Formattable::Formattable(const StringPiece &number, UErrorCode &status) {
158     init();
159     setDecimalNumber(number, status);
160 }
161 
162 
163 // -------------------------------------
164 // Creates a formattable object with a UnicodeString instance.
165 
Formattable(const UnicodeString & stringToCopy)166 Formattable::Formattable(const UnicodeString& stringToCopy)
167 {
168     init();
169     fType = kString;
170     fValue.fString = new UnicodeString(stringToCopy);
171 }
172 
173 // -------------------------------------
174 // Creates a formattable object with a UnicodeString* value.
175 // (adopting symantics)
176 
Formattable(UnicodeString * stringToAdopt)177 Formattable::Formattable(UnicodeString* stringToAdopt)
178 {
179     init();
180     fType = kString;
181     fValue.fString = stringToAdopt;
182 }
183 
Formattable(UObject * objectToAdopt)184 Formattable::Formattable(UObject* objectToAdopt)
185 {
186     init();
187     fType = kObject;
188     fValue.fObject = objectToAdopt;
189 }
190 
191 // -------------------------------------
192 
Formattable(const Formattable * arrayToCopy,int32_t count)193 Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
194     :   UObject(), fType(kArray)
195 {
196     init();
197     fType = kArray;
198     fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
199     fValue.fArrayAndCount.fCount = count;
200 }
201 
202 // -------------------------------------
203 // copy constructor
204 
205 
Formattable(const Formattable & source)206 Formattable::Formattable(const Formattable &source)
207      :  UObject(*this)
208 {
209     init();
210     *this = source;
211 }
212 
213 // -------------------------------------
214 // assignment operator
215 
216 Formattable&
operator =(const Formattable & source)217 Formattable::operator=(const Formattable& source)
218 {
219     if (this != &source)
220     {
221         // Disposes the current formattable value/setting.
222         dispose();
223 
224         // Sets the correct data type for this value.
225         fType = source.fType;
226         switch (fType)
227         {
228         case kArray:
229             // Sets each element in the array one by one and records the array count.
230             fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount;
231             fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray,
232                                                            source.fValue.fArrayAndCount.fCount);
233             break;
234         case kString:
235             // Sets the string value.
236             fValue.fString = new UnicodeString(*source.fValue.fString);
237             break;
238         case kDouble:
239             // Sets the double value.
240             fValue.fDouble = source.fValue.fDouble;
241             break;
242         case kLong:
243         case kInt64:
244             // Sets the long value.
245             fValue.fInt64 = source.fValue.fInt64;
246             break;
247         case kDate:
248             // Sets the Date value.
249             fValue.fDate = source.fValue.fDate;
250             break;
251         case kObject:
252             fValue.fObject = objectClone(source.fValue.fObject);
253             break;
254         }
255 
256         UErrorCode status = U_ZERO_ERROR;
257         if (source.fDecimalNum != NULL) {
258           fDecimalNum = new DigitList(*source.fDecimalNum); // TODO: use internal digit list
259         }
260         if (source.fDecimalStr != NULL) {
261             fDecimalStr = new CharString(*source.fDecimalStr, status);
262             if (U_FAILURE(status)) {
263                 delete fDecimalStr;
264                 fDecimalStr = NULL;
265             }
266         }
267     }
268     return *this;
269 }
270 
271 // -------------------------------------
272 
273 UBool
operator ==(const Formattable & that) const274 Formattable::operator==(const Formattable& that) const
275 {
276     int32_t i;
277 
278     if (this == &that) return TRUE;
279 
280     // Returns FALSE if the data types are different.
281     if (fType != that.fType) return FALSE;
282 
283     // Compares the actual data values.
284     UBool equal = TRUE;
285     switch (fType) {
286     case kDate:
287         equal = (fValue.fDate == that.fValue.fDate);
288         break;
289     case kDouble:
290         equal = (fValue.fDouble == that.fValue.fDouble);
291         break;
292     case kLong:
293     case kInt64:
294         equal = (fValue.fInt64 == that.fValue.fInt64);
295         break;
296     case kString:
297         equal = (*(fValue.fString) == *(that.fValue.fString));
298         break;
299     case kArray:
300         if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
301             equal = FALSE;
302             break;
303         }
304         // Checks each element for equality.
305         for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
306             if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
307                 equal = FALSE;
308                 break;
309             }
310         }
311         break;
312     case kObject:
313         if (fValue.fObject == NULL || that.fValue.fObject == NULL) {
314             equal = FALSE;
315         } else {
316             equal = objectEquals(fValue.fObject, that.fValue.fObject);
317         }
318         break;
319     }
320 
321     // TODO:  compare digit lists if numeric.
322     return equal;
323 }
324 
325 // -------------------------------------
326 
~Formattable()327 Formattable::~Formattable()
328 {
329     dispose();
330 }
331 
332 // -------------------------------------
333 
dispose()334 void Formattable::dispose()
335 {
336     // Deletes the data value if necessary.
337     switch (fType) {
338     case kString:
339         delete fValue.fString;
340         break;
341     case kArray:
342         delete[] fValue.fArrayAndCount.fArray;
343         break;
344     case kObject:
345         delete fValue.fObject;
346         break;
347     default:
348         break;
349     }
350 
351     fType = kLong;
352     fValue.fInt64 = 0;
353 
354     delete fDecimalStr;
355     fDecimalStr = NULL;
356 
357     FmtStackData *stackData = (FmtStackData*)fStackData;
358     if(fDecimalNum != &(stackData->stackDecimalNum)) {
359       delete fDecimalNum;
360     } else {
361       fDecimalNum->~DigitList(); // destruct, don't deallocate
362     }
363     fDecimalNum = 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     default:
434         status = U_INVALID_FORMAT_ERROR;
435         return 0;
436     }
437 }
438 
439 // -------------------------------------
440 // Maximum int that can be represented exactly in a double.  (53 bits)
441 //    Larger ints may be rounded to a near-by value as not all are representable.
442 // TODO:  move this constant elsewhere, possibly configure it for different
443 //        floating point formats, if any non-standard ones are still in use.
444 static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
445 
446 int64_t
getInt64(UErrorCode & status) const447 Formattable::getInt64(UErrorCode& status) const
448 {
449     if (U_FAILURE(status)) {
450         return 0;
451     }
452 
453     switch (fType) {
454     case Formattable::kLong:
455     case Formattable::kInt64:
456         return fValue.fInt64;
457     case Formattable::kDouble:
458         if (fValue.fDouble > (double)U_INT64_MAX) {
459             status = U_INVALID_FORMAT_ERROR;
460             return U_INT64_MAX;
461         } else if (fValue.fDouble < (double)U_INT64_MIN) {
462             status = U_INVALID_FORMAT_ERROR;
463             return U_INT64_MIN;
464         } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalNum != NULL) {
465             int64_t val = fDecimalNum->getInt64();
466             if (val != 0) {
467                 return val;
468             } else {
469                 status = U_INVALID_FORMAT_ERROR;
470                 return fValue.fDouble > 0 ? U_INT64_MAX : U_INT64_MIN;
471             }
472         } else {
473             return (int64_t)fValue.fDouble;
474         }
475     case Formattable::kObject:
476         if (fValue.fObject == NULL) {
477             status = U_MEMORY_ALLOCATION_ERROR;
478             return 0;
479         }
480         if (instanceOfMeasure(fValue.fObject)) {
481             return ((const Measure*) fValue.fObject)->
482                 getNumber().getInt64(status);
483         }
484     default:
485         status = U_INVALID_FORMAT_ERROR;
486         return 0;
487     }
488 }
489 
490 // -------------------------------------
491 double
getDouble(UErrorCode & status) const492 Formattable::getDouble(UErrorCode& status) const
493 {
494     if (U_FAILURE(status)) {
495         return 0;
496     }
497 
498     switch (fType) {
499     case Formattable::kLong:
500     case Formattable::kInt64: // loses precision
501         return (double)fValue.fInt64;
502     case Formattable::kDouble:
503         return fValue.fDouble;
504     case Formattable::kObject:
505         if (fValue.fObject == NULL) {
506             status = U_MEMORY_ALLOCATION_ERROR;
507             return 0;
508         }
509         // TODO Later replace this with instanceof call
510         if (instanceOfMeasure(fValue.fObject)) {
511             return ((const Measure*) fValue.fObject)->
512                 getNumber().getDouble(status);
513         }
514     default:
515         status = U_INVALID_FORMAT_ERROR;
516         return 0;
517     }
518 }
519 
520 const UObject*
getObject() const521 Formattable::getObject() const {
522     return (fType == kObject) ? fValue.fObject : NULL;
523 }
524 
525 // -------------------------------------
526 // Sets the value to a double value d.
527 
528 void
setDouble(double d)529 Formattable::setDouble(double d)
530 {
531     dispose();
532     fType = kDouble;
533     fValue.fDouble = d;
534 }
535 
536 // -------------------------------------
537 // Sets the value to a long value l.
538 
539 void
setLong(int32_t l)540 Formattable::setLong(int32_t l)
541 {
542     dispose();
543     fType = kLong;
544     fValue.fInt64 = l;
545 }
546 
547 // -------------------------------------
548 // Sets the value to an int64 value ll.
549 
550 void
setInt64(int64_t ll)551 Formattable::setInt64(int64_t ll)
552 {
553     dispose();
554     fType = kInt64;
555     fValue.fInt64 = ll;
556 }
557 
558 // -------------------------------------
559 // Sets the value to a Date instance d.
560 
561 void
setDate(UDate d)562 Formattable::setDate(UDate d)
563 {
564     dispose();
565     fType = kDate;
566     fValue.fDate = d;
567 }
568 
569 // -------------------------------------
570 // Sets the value to a string value stringToCopy.
571 
572 void
setString(const UnicodeString & stringToCopy)573 Formattable::setString(const UnicodeString& stringToCopy)
574 {
575     dispose();
576     fType = kString;
577     fValue.fString = new UnicodeString(stringToCopy);
578 }
579 
580 // -------------------------------------
581 // Sets the value to an array of Formattable objects.
582 
583 void
setArray(const Formattable * array,int32_t count)584 Formattable::setArray(const Formattable* array, int32_t count)
585 {
586     dispose();
587     fType = kArray;
588     fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
589     fValue.fArrayAndCount.fCount = count;
590 }
591 
592 // -------------------------------------
593 // Adopts the stringToAdopt value.
594 
595 void
adoptString(UnicodeString * stringToAdopt)596 Formattable::adoptString(UnicodeString* stringToAdopt)
597 {
598     dispose();
599     fType = kString;
600     fValue.fString = stringToAdopt;
601 }
602 
603 // -------------------------------------
604 // Adopts the array value and its count.
605 
606 void
adoptArray(Formattable * array,int32_t count)607 Formattable::adoptArray(Formattable* array, int32_t count)
608 {
609     dispose();
610     fType = kArray;
611     fValue.fArrayAndCount.fArray = array;
612     fValue.fArrayAndCount.fCount = count;
613 }
614 
615 void
adoptObject(UObject * objectToAdopt)616 Formattable::adoptObject(UObject* objectToAdopt) {
617     dispose();
618     fType = kObject;
619     fValue.fObject = objectToAdopt;
620 }
621 
622 // -------------------------------------
623 UnicodeString&
getString(UnicodeString & result,UErrorCode & status) const624 Formattable::getString(UnicodeString& result, UErrorCode& status) const
625 {
626     if (fType != kString) {
627         setError(status, U_INVALID_FORMAT_ERROR);
628         result.setToBogus();
629     } else {
630         if (fValue.fString == NULL) {
631             setError(status, U_MEMORY_ALLOCATION_ERROR);
632         } else {
633             result = *fValue.fString;
634         }
635     }
636     return result;
637 }
638 
639 // -------------------------------------
640 const UnicodeString&
getString(UErrorCode & status) const641 Formattable::getString(UErrorCode& status) const
642 {
643     if (fType != kString) {
644         setError(status, U_INVALID_FORMAT_ERROR);
645         return *getBogus();
646     }
647     if (fValue.fString == NULL) {
648         setError(status, U_MEMORY_ALLOCATION_ERROR);
649         return *getBogus();
650     }
651     return *fValue.fString;
652 }
653 
654 // -------------------------------------
655 UnicodeString&
getString(UErrorCode & status)656 Formattable::getString(UErrorCode& status)
657 {
658     if (fType != kString) {
659         setError(status, U_INVALID_FORMAT_ERROR);
660         return *getBogus();
661     }
662     if (fValue.fString == NULL) {
663     	setError(status, U_MEMORY_ALLOCATION_ERROR);
664     	return *getBogus();
665     }
666     return *fValue.fString;
667 }
668 
669 // -------------------------------------
670 const Formattable*
getArray(int32_t & count,UErrorCode & status) const671 Formattable::getArray(int32_t& count, UErrorCode& status) const
672 {
673     if (fType != kArray) {
674         setError(status, U_INVALID_FORMAT_ERROR);
675         count = 0;
676         return NULL;
677     }
678     count = fValue.fArrayAndCount.fCount;
679     return fValue.fArrayAndCount.fArray;
680 }
681 
682 // -------------------------------------
683 // Gets the bogus string, ensures mondo bogosity.
684 
685 UnicodeString*
getBogus() const686 Formattable::getBogus() const
687 {
688     return (UnicodeString*)&fBogus; /* cast away const :-( */
689 }
690 
691 
692 // --------------------------------------
getDecimalNumber(UErrorCode & status)693 StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
694     if (U_FAILURE(status)) {
695         return "";
696     }
697     if (fDecimalStr != NULL) {
698         return fDecimalStr->toStringPiece();
699     }
700 
701     if (fDecimalNum == NULL) {
702         // No decimal number for the formattable yet.  Which means the value was
703         // set directly by the user as an int, int64 or double.  If the value came
704         // from parsing, or from the user setting a decimal number, fDecimalNum
705         // would already be set.
706         //
707       fDecimalNum = new DigitList; // TODO: use internal digit list
708         if (fDecimalNum == NULL) {
709             status = U_MEMORY_ALLOCATION_ERROR;
710             return "";
711         }
712 
713         switch (fType) {
714         case kDouble:
715             fDecimalNum->set(this->getDouble());
716             break;
717         case kLong:
718             fDecimalNum->set(this->getLong());
719             break;
720         case kInt64:
721             fDecimalNum->set(this->getInt64());
722             break;
723         default:
724             // The formattable's value is not a numeric type.
725             status = U_INVALID_STATE_ERROR;
726             return "";
727         }
728     }
729 
730     fDecimalStr = new CharString;
731     if (fDecimalStr == NULL) {
732         status = U_MEMORY_ALLOCATION_ERROR;
733         return "";
734     }
735     fDecimalNum->getDecimal(*fDecimalStr, status);
736 
737     return fDecimalStr->toStringPiece();
738 }
739 
740 
741 DigitList *
getInternalDigitList()742 Formattable::getInternalDigitList() {
743   FmtStackData *stackData = (FmtStackData*)fStackData;
744   if(fDecimalNum != &(stackData->stackDecimalNum)) {
745     delete fDecimalNum;
746     fDecimalNum = new (&(stackData->stackDecimalNum), kOnStack) DigitList();
747   } else {
748     fDecimalNum->clear();
749   }
750   return fDecimalNum;
751 }
752 
753 // ---------------------------------------
754 void
adoptDigitList(DigitList * dl)755 Formattable::adoptDigitList(DigitList *dl) {
756   if(fDecimalNum==dl) {
757     fDecimalNum = NULL; // don't delete
758   }
759   dispose();
760 
761   fDecimalNum = dl;
762 
763   if(dl==NULL) { // allow adoptDigitList(NULL) to clear
764     return;
765   }
766 
767     // Set the value into the Union of simple type values.
768     // Cannot use the set() functions because they would delete the fDecimalNum value,
769 
770     if (fDecimalNum->fitsIntoLong(FALSE)) {
771         fType = kLong;
772         fValue.fInt64 = fDecimalNum->getLong();
773     } else if (fDecimalNum->fitsIntoInt64(FALSE)) {
774         fType = kInt64;
775         fValue.fInt64 = fDecimalNum->getInt64();
776     } else {
777         fType = kDouble;
778         fValue.fDouble = fDecimalNum->getDouble();
779     }
780 }
781 
782 
783 // ---------------------------------------
784 void
setDecimalNumber(const StringPiece & numberString,UErrorCode & status)785 Formattable::setDecimalNumber(const StringPiece &numberString, UErrorCode &status) {
786     if (U_FAILURE(status)) {
787         return;
788     }
789     dispose();
790 
791     // Copy the input string and nul-terminate it.
792     //    The decNumber library requires nul-terminated input.  StringPiece input
793     //    is not guaranteed nul-terminated.  Too bad.
794     //    CharString automatically adds the nul.
795     DigitList *dnum = new DigitList(); // TODO: use getInternalDigitList
796     if (dnum == NULL) {
797         status = U_MEMORY_ALLOCATION_ERROR;
798         return;
799     }
800     dnum->set(CharString(numberString, status).toStringPiece(), status);
801     if (U_FAILURE(status)) {
802         delete dnum;
803         return;   // String didn't contain a decimal number.
804     }
805     adoptDigitList(dnum);
806 
807     // Note that we do not hang on to the caller's input string.
808     // If we are asked for the string, we will regenerate one from fDecimalNum.
809 }
810 
811 #if 0
812 //----------------------------------------------------
813 // console I/O
814 //----------------------------------------------------
815 #ifdef _DEBUG
816 
817 #include <iostream>
818 using namespace std;
819 
820 #include "unicode/datefmt.h"
821 #include "unistrm.h"
822 
823 class FormattableStreamer /* not : public UObject because all methods are static */ {
824 public:
825     static void streamOut(ostream& stream, const Formattable& obj);
826 
827 private:
828     FormattableStreamer() {} // private - forbid instantiation
829 };
830 
831 // This is for debugging purposes only.  This will send a displayable
832 // form of the Formattable object to the output stream.
833 
834 void
835 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
836 {
837     static DateFormat *defDateFormat = 0;
838 
839     UnicodeString buffer;
840     switch(obj.getType()) {
841         case Formattable::kDate :
842             // Creates a DateFormat instance for formatting the
843             // Date instance.
844             if (defDateFormat == 0) {
845                 defDateFormat = DateFormat::createInstance();
846             }
847             defDateFormat->format(obj.getDate(), buffer);
848             stream << buffer;
849             break;
850         case Formattable::kDouble :
851             // Output the double as is.
852             stream << obj.getDouble() << 'D';
853             break;
854         case Formattable::kLong :
855             // Output the double as is.
856             stream << obj.getLong() << 'L';
857             break;
858         case Formattable::kString:
859             // Output the double as is.  Please see UnicodeString console
860             // I/O routine for more details.
861             stream << '"' << obj.getString(buffer) << '"';
862             break;
863         case Formattable::kArray:
864             int32_t i, count;
865             const Formattable* array;
866             array = obj.getArray(count);
867             stream << '[';
868             // Recursively calling the console I/O routine for each element in the array.
869             for (i=0; i<count; ++i) {
870                 FormattableStreamer::streamOut(stream, array[i]);
871                 stream << ( (i==(count-1)) ? "" : ", " );
872             }
873             stream << ']';
874             break;
875         default:
876             // Not a recognizable Formattable object.
877             stream << "INVALID_Formattable";
878     }
879     stream.flush();
880 }
881 #endif
882 
883 #endif
884 
885 U_NAMESPACE_END
886 
887 #endif /* #if !UCONFIG_NO_FORMATTING */
888 
889 //eof
890