]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/fmtable.cpp
ICU-57149.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / fmtable.cpp
1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2016, 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
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.
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.
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 */
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 */
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 //
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
112 Formattable::Formattable() {
113 init();
114 }
115
116 // -------------------------------------
117 // Creates a formattable object with a Date instance.
118
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
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
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
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
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
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
178 Formattable::Formattable(UnicodeString* stringToAdopt)
179 {
180 init();
181 fType = kString;
182 fValue.fString = stringToAdopt;
183 }
184
185 Formattable::Formattable(UObject* objectToAdopt)
186 {
187 init();
188 fType = kObject;
189 fValue.fObject = objectToAdopt;
190 }
191
192 // -------------------------------------
193
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
207 Formattable::Formattable(const Formattable &source)
208 : UObject(*this)
209 {
210 init();
211 *this = source;
212 }
213
214 // -------------------------------------
215 // assignment operator
216
217 Formattable&
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
275 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
328 Formattable::~Formattable()
329 {
330 dispose();
331 }
332
333 // -------------------------------------
334
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 *
368 Formattable::clone() const {
369 return new Formattable(*this);
370 }
371
372 // -------------------------------------
373 // Gets the data type of this Formattable object.
374 Formattable::Type
375 Formattable::getType() const
376 {
377 return fType;
378 }
379
380 UBool
381 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
395 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 U_FALLTHROUGH;
435 default:
436 status = U_INVALID_FORMAT_ERROR;
437 return 0;
438 }
439 }
440
441 // -------------------------------------
442 // Maximum int that can be represented exactly in a double. (53 bits)
443 // Larger ints may be rounded to a near-by value as not all are representable.
444 // TODO: move this constant elsewhere, possibly configure it for different
445 // floating point formats, if any non-standard ones are still in use.
446 static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
447
448 int64_t
449 Formattable::getInt64(UErrorCode& status) const
450 {
451 if (U_FAILURE(status)) {
452 return 0;
453 }
454
455 switch (fType) {
456 case Formattable::kLong:
457 case Formattable::kInt64:
458 return fValue.fInt64;
459 case Formattable::kDouble:
460 if (fValue.fDouble > (double)U_INT64_MAX) {
461 status = U_INVALID_FORMAT_ERROR;
462 return U_INT64_MAX;
463 } else if (fValue.fDouble < (double)U_INT64_MIN) {
464 status = U_INVALID_FORMAT_ERROR;
465 return U_INT64_MIN;
466 } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalNum != NULL) {
467 int64_t val = fDecimalNum->getInt64();
468 if (val != 0) {
469 return val;
470 } else {
471 status = U_INVALID_FORMAT_ERROR;
472 return fValue.fDouble > 0 ? U_INT64_MAX : U_INT64_MIN;
473 }
474 } else {
475 return (int64_t)fValue.fDouble;
476 }
477 case Formattable::kObject:
478 if (fValue.fObject == NULL) {
479 status = U_MEMORY_ALLOCATION_ERROR;
480 return 0;
481 }
482 if (instanceOfMeasure(fValue.fObject)) {
483 return ((const Measure*) fValue.fObject)->
484 getNumber().getInt64(status);
485 }
486 U_FALLTHROUGH;
487 default:
488 status = U_INVALID_FORMAT_ERROR;
489 return 0;
490 }
491 }
492
493 // -------------------------------------
494 double
495 Formattable::getDouble(UErrorCode& status) const
496 {
497 if (U_FAILURE(status)) {
498 return 0;
499 }
500
501 switch (fType) {
502 case Formattable::kLong:
503 case Formattable::kInt64: // loses precision
504 return (double)fValue.fInt64;
505 case Formattable::kDouble:
506 return fValue.fDouble;
507 case Formattable::kObject:
508 if (fValue.fObject == NULL) {
509 status = U_MEMORY_ALLOCATION_ERROR;
510 return 0;
511 }
512 // TODO Later replace this with instanceof call
513 if (instanceOfMeasure(fValue.fObject)) {
514 return ((const Measure*) fValue.fObject)->
515 getNumber().getDouble(status);
516 }
517 U_FALLTHROUGH;
518 default:
519 status = U_INVALID_FORMAT_ERROR;
520 return 0;
521 }
522 }
523
524 const UObject*
525 Formattable::getObject() const {
526 return (fType == kObject) ? fValue.fObject : NULL;
527 }
528
529 // -------------------------------------
530 // Sets the value to a double value d.
531
532 void
533 Formattable::setDouble(double d)
534 {
535 dispose();
536 fType = kDouble;
537 fValue.fDouble = d;
538 }
539
540 // -------------------------------------
541 // Sets the value to a long value l.
542
543 void
544 Formattable::setLong(int32_t l)
545 {
546 dispose();
547 fType = kLong;
548 fValue.fInt64 = l;
549 }
550
551 // -------------------------------------
552 // Sets the value to an int64 value ll.
553
554 void
555 Formattable::setInt64(int64_t ll)
556 {
557 dispose();
558 fType = kInt64;
559 fValue.fInt64 = ll;
560 }
561
562 // -------------------------------------
563 // Sets the value to a Date instance d.
564
565 void
566 Formattable::setDate(UDate d)
567 {
568 dispose();
569 fType = kDate;
570 fValue.fDate = d;
571 }
572
573 // -------------------------------------
574 // Sets the value to a string value stringToCopy.
575
576 void
577 Formattable::setString(const UnicodeString& stringToCopy)
578 {
579 dispose();
580 fType = kString;
581 fValue.fString = new UnicodeString(stringToCopy);
582 }
583
584 // -------------------------------------
585 // Sets the value to an array of Formattable objects.
586
587 void
588 Formattable::setArray(const Formattable* array, int32_t count)
589 {
590 dispose();
591 fType = kArray;
592 fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
593 fValue.fArrayAndCount.fCount = count;
594 }
595
596 // -------------------------------------
597 // Adopts the stringToAdopt value.
598
599 void
600 Formattable::adoptString(UnicodeString* stringToAdopt)
601 {
602 dispose();
603 fType = kString;
604 fValue.fString = stringToAdopt;
605 }
606
607 // -------------------------------------
608 // Adopts the array value and its count.
609
610 void
611 Formattable::adoptArray(Formattable* array, int32_t count)
612 {
613 dispose();
614 fType = kArray;
615 fValue.fArrayAndCount.fArray = array;
616 fValue.fArrayAndCount.fCount = count;
617 }
618
619 void
620 Formattable::adoptObject(UObject* objectToAdopt) {
621 dispose();
622 fType = kObject;
623 fValue.fObject = objectToAdopt;
624 }
625
626 // -------------------------------------
627 UnicodeString&
628 Formattable::getString(UnicodeString& result, UErrorCode& status) const
629 {
630 if (fType != kString) {
631 setError(status, U_INVALID_FORMAT_ERROR);
632 result.setToBogus();
633 } else {
634 if (fValue.fString == NULL) {
635 setError(status, U_MEMORY_ALLOCATION_ERROR);
636 } else {
637 result = *fValue.fString;
638 }
639 }
640 return result;
641 }
642
643 // -------------------------------------
644 const UnicodeString&
645 Formattable::getString(UErrorCode& status) const
646 {
647 if (fType != kString) {
648 setError(status, U_INVALID_FORMAT_ERROR);
649 return *getBogus();
650 }
651 if (fValue.fString == NULL) {
652 setError(status, U_MEMORY_ALLOCATION_ERROR);
653 return *getBogus();
654 }
655 return *fValue.fString;
656 }
657
658 // -------------------------------------
659 UnicodeString&
660 Formattable::getString(UErrorCode& status)
661 {
662 if (fType != kString) {
663 setError(status, U_INVALID_FORMAT_ERROR);
664 return *getBogus();
665 }
666 if (fValue.fString == NULL) {
667 setError(status, U_MEMORY_ALLOCATION_ERROR);
668 return *getBogus();
669 }
670 return *fValue.fString;
671 }
672
673 // -------------------------------------
674 const Formattable*
675 Formattable::getArray(int32_t& count, UErrorCode& status) const
676 {
677 if (fType != kArray) {
678 setError(status, U_INVALID_FORMAT_ERROR);
679 count = 0;
680 return NULL;
681 }
682 count = fValue.fArrayAndCount.fCount;
683 return fValue.fArrayAndCount.fArray;
684 }
685
686 // -------------------------------------
687 // Gets the bogus string, ensures mondo bogosity.
688
689 UnicodeString*
690 Formattable::getBogus() const
691 {
692 return (UnicodeString*)&fBogus; /* cast away const :-( */
693 }
694
695
696 // --------------------------------------
697 StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
698 if (U_FAILURE(status)) {
699 return "";
700 }
701 if (fDecimalStr != NULL) {
702 return fDecimalStr->toStringPiece();
703 }
704
705 CharString *decimalStr = internalGetCharString(status);
706 if(decimalStr == NULL) {
707 return ""; // getDecimalNumber returns "" for error cases
708 } else {
709 return decimalStr->toStringPiece();
710 }
711 }
712
713 CharString *Formattable::internalGetCharString(UErrorCode &status) {
714 if(fDecimalStr == NULL) {
715 if (fDecimalNum == NULL) {
716 // No decimal number for the formattable yet. Which means the value was
717 // set directly by the user as an int, int64 or double. If the value came
718 // from parsing, or from the user setting a decimal number, fDecimalNum
719 // would already be set.
720 //
721 fDecimalNum = new DigitList; // TODO: use internal digit list
722 if (fDecimalNum == NULL) {
723 status = U_MEMORY_ALLOCATION_ERROR;
724 return NULL;
725 }
726
727 switch (fType) {
728 case kDouble:
729 fDecimalNum->set(this->getDouble());
730 break;
731 case kLong:
732 fDecimalNum->set(this->getLong());
733 break;
734 case kInt64:
735 fDecimalNum->set(this->getInt64());
736 break;
737 default:
738 // The formattable's value is not a numeric type.
739 status = U_INVALID_STATE_ERROR;
740 return NULL;
741 }
742 }
743
744 fDecimalStr = new CharString;
745 if (fDecimalStr == NULL) {
746 status = U_MEMORY_ALLOCATION_ERROR;
747 return NULL;
748 }
749 fDecimalNum->getDecimal(*fDecimalStr, status);
750 }
751 return fDecimalStr;
752 }
753
754
755 DigitList *
756 Formattable::getInternalDigitList() {
757 FmtStackData *stackData = (FmtStackData*)fStackData;
758 if(fDecimalNum != &(stackData->stackDecimalNum)) {
759 delete fDecimalNum;
760 fDecimalNum = new (&(stackData->stackDecimalNum), kOnStack) DigitList();
761 } else {
762 fDecimalNum->clear();
763 }
764 return fDecimalNum;
765 }
766
767 // ---------------------------------------
768 void
769 Formattable::adoptDigitList(DigitList *dl) {
770 if(fDecimalNum==dl) {
771 fDecimalNum = NULL; // don't delete
772 }
773 dispose();
774
775 fDecimalNum = dl;
776
777 if(dl==NULL) { // allow adoptDigitList(NULL) to clear
778 return;
779 }
780
781 // Set the value into the Union of simple type values.
782 // Cannot use the set() functions because they would delete the fDecimalNum value,
783
784 if (fDecimalNum->fitsIntoLong(FALSE)) {
785 fType = kLong;
786 fValue.fInt64 = fDecimalNum->getLong();
787 } else if (fDecimalNum->fitsIntoInt64(FALSE)) {
788 fType = kInt64;
789 fValue.fInt64 = fDecimalNum->getInt64();
790 } else {
791 fType = kDouble;
792 fValue.fDouble = fDecimalNum->getDouble();
793 }
794 }
795
796
797 // ---------------------------------------
798 void
799 Formattable::setDecimalNumber(const StringPiece &numberString, UErrorCode &status) {
800 if (U_FAILURE(status)) {
801 return;
802 }
803 dispose();
804
805 // Copy the input string and nul-terminate it.
806 // The decNumber library requires nul-terminated input. StringPiece input
807 // is not guaranteed nul-terminated. Too bad.
808 // CharString automatically adds the nul.
809 DigitList *dnum = new DigitList(); // TODO: use getInternalDigitList
810 if (dnum == NULL) {
811 status = U_MEMORY_ALLOCATION_ERROR;
812 return;
813 }
814 dnum->set(CharString(numberString, status).toStringPiece(), status);
815 if (U_FAILURE(status)) {
816 delete dnum;
817 return; // String didn't contain a decimal number.
818 }
819 adoptDigitList(dnum);
820
821 // Note that we do not hang on to the caller's input string.
822 // If we are asked for the string, we will regenerate one from fDecimalNum.
823 }
824
825 #if 0
826 //----------------------------------------------------
827 // console I/O
828 //----------------------------------------------------
829 #ifdef _DEBUG
830
831 #include <iostream>
832 using namespace std;
833
834 #include "unicode/datefmt.h"
835 #include "unistrm.h"
836
837 class FormattableStreamer /* not : public UObject because all methods are static */ {
838 public:
839 static void streamOut(ostream& stream, const Formattable& obj);
840
841 private:
842 FormattableStreamer() {} // private - forbid instantiation
843 };
844
845 // This is for debugging purposes only. This will send a displayable
846 // form of the Formattable object to the output stream.
847
848 void
849 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
850 {
851 static DateFormat *defDateFormat = 0;
852
853 UnicodeString buffer;
854 switch(obj.getType()) {
855 case Formattable::kDate :
856 // Creates a DateFormat instance for formatting the
857 // Date instance.
858 if (defDateFormat == 0) {
859 defDateFormat = DateFormat::createInstance();
860 }
861 defDateFormat->format(obj.getDate(), buffer);
862 stream << buffer;
863 break;
864 case Formattable::kDouble :
865 // Output the double as is.
866 stream << obj.getDouble() << 'D';
867 break;
868 case Formattable::kLong :
869 // Output the double as is.
870 stream << obj.getLong() << 'L';
871 break;
872 case Formattable::kString:
873 // Output the double as is. Please see UnicodeString console
874 // I/O routine for more details.
875 stream << '"' << obj.getString(buffer) << '"';
876 break;
877 case Formattable::kArray:
878 int32_t i, count;
879 const Formattable* array;
880 array = obj.getArray(count);
881 stream << '[';
882 // Recursively calling the console I/O routine for each element in the array.
883 for (i=0; i<count; ++i) {
884 FormattableStreamer::streamOut(stream, array[i]);
885 stream << ( (i==(count-1)) ? "" : ", " );
886 }
887 stream << ']';
888 break;
889 default:
890 // Not a recognizable Formattable object.
891 stream << "INVALID_Formattable";
892 }
893 stream.flush();
894 }
895 #endif
896
897 #endif
898
899 U_NAMESPACE_END
900
901 /* ---- UFormattable implementation ---- */
902
903 U_NAMESPACE_USE
904
905 U_DRAFT UFormattable* U_EXPORT2
906 ufmt_open(UErrorCode *status) {
907 if( U_FAILURE(*status) ) {
908 return NULL;
909 }
910 UFormattable *fmt = (new Formattable())->toUFormattable();
911
912 if( fmt == NULL ) {
913 *status = U_MEMORY_ALLOCATION_ERROR;
914 }
915 return fmt;
916 }
917
918 U_DRAFT void U_EXPORT2
919 ufmt_close(UFormattable *fmt) {
920 Formattable *obj = Formattable::fromUFormattable(fmt);
921
922 delete obj;
923 }
924
925 U_INTERNAL UFormattableType U_EXPORT2
926 ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
927 if(U_FAILURE(*status)) {
928 return (UFormattableType)UFMT_COUNT;
929 }
930 const Formattable *obj = Formattable::fromUFormattable(fmt);
931 return (UFormattableType)obj->getType();
932 }
933
934
935 U_INTERNAL UBool U_EXPORT2
936 ufmt_isNumeric(const UFormattable *fmt) {
937 const Formattable *obj = Formattable::fromUFormattable(fmt);
938 return obj->isNumeric();
939 }
940
941 U_DRAFT UDate U_EXPORT2
942 ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
943 const Formattable *obj = Formattable::fromUFormattable(fmt);
944
945 return obj->getDate(*status);
946 }
947
948 U_DRAFT double U_EXPORT2
949 ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
950 Formattable *obj = Formattable::fromUFormattable(fmt);
951
952 return obj->getDouble(*status);
953 }
954
955 U_DRAFT int32_t U_EXPORT2
956 ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
957 Formattable *obj = Formattable::fromUFormattable(fmt);
958
959 return obj->getLong(*status);
960 }
961
962
963 U_DRAFT const void *U_EXPORT2
964 ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
965 const Formattable *obj = Formattable::fromUFormattable(fmt);
966
967 const void *ret = obj->getObject();
968 if( ret==NULL &&
969 (obj->getType() != Formattable::kObject) &&
970 U_SUCCESS( *status )) {
971 *status = U_INVALID_FORMAT_ERROR;
972 }
973 return ret;
974 }
975
976 U_DRAFT const UChar* U_EXPORT2
977 ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
978 Formattable *obj = Formattable::fromUFormattable(fmt);
979
980 // avoid bogosity by checking the type first.
981 if( obj->getType() != Formattable::kString ) {
982 if( U_SUCCESS(*status) ){
983 *status = U_INVALID_FORMAT_ERROR;
984 }
985 return NULL;
986 }
987
988 // This should return a valid string
989 UnicodeString &str = obj->getString(*status);
990 if( U_SUCCESS(*status) && len != NULL ) {
991 *len = str.length();
992 }
993 return str.getTerminatedBuffer();
994 }
995
996 U_DRAFT int32_t U_EXPORT2
997 ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
998 const Formattable *obj = Formattable::fromUFormattable(fmt);
999
1000 int32_t count;
1001 (void)obj->getArray(count, *status);
1002 return count;
1003 }
1004
1005 U_DRAFT UFormattable * U_EXPORT2
1006 ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
1007 Formattable *obj = Formattable::fromUFormattable(fmt);
1008 int32_t count;
1009 (void)obj->getArray(count, *status);
1010 if(U_FAILURE(*status)) {
1011 return NULL;
1012 } else if(n<0 || n>=count) {
1013 setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
1014 return NULL;
1015 } else {
1016 return (*obj)[n].toUFormattable(); // returns non-const Formattable
1017 }
1018 }
1019
1020 U_DRAFT const char * U_EXPORT2
1021 ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
1022 if(U_FAILURE(*status)) {
1023 return "";
1024 }
1025 Formattable *obj = Formattable::fromUFormattable(fmt);
1026 CharString *charString = obj->internalGetCharString(*status);
1027 if(U_FAILURE(*status)) {
1028 return "";
1029 }
1030 if(charString == NULL) {
1031 *status = U_MEMORY_ALLOCATION_ERROR;
1032 return "";
1033 } else {
1034 if(len!=NULL) {
1035 *len = charString->length();
1036 }
1037 return charString->data();
1038 }
1039 }
1040
1041 U_DRAFT int64_t U_EXPORT2
1042 ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
1043 Formattable *obj = Formattable::fromUFormattable(fmt);
1044 return obj->getInt64(*status);
1045 }
1046
1047 #endif /* #if !UCONFIG_NO_FORMATTING */
1048
1049 //eof