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