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