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