Line data Source code
1 : // © 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 :
41 0 : 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 0 : static inline UBool objectEquals(const UObject* a, const UObject* b) {
56 : // LATER: return *a == *b;
57 0 : return *((const Measure*) a) == *((const Measure*) b);
58 : }
59 :
60 : // Return a clone of *a.
61 0 : static inline UObject* objectClone(const UObject* a) {
62 : // LATER: return a->clone();
63 0 : return ((const Measure*) a)->clone();
64 : }
65 :
66 : // Return TRUE if *a is an instance of Measure.
67 0 : static inline UBool instanceOfMeasure(const UObject* a) {
68 0 : 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 : */
78 0 : static Formattable* createArrayCopy(const Formattable* array, int32_t count) {
79 0 : Formattable *result = new Formattable[count];
80 0 : if (result != NULL) {
81 0 : for (int32_t i=0; i<count; ++i)
82 0 : result[i] = array[i]; // Don't memcpy!
83 : }
84 0 : return result;
85 : }
86 :
87 : //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
88 :
89 : /**
90 : * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
91 : */
92 0 : static void setError(UErrorCode& ec, UErrorCode err) {
93 0 : if (U_SUCCESS(ec)) {
94 0 : ec = err;
95 : }
96 0 : }
97 :
98 : //
99 : // Common initialization code, shared by constructors.
100 : // Put everything into a known state.
101 : //
102 0 : void Formattable::init() {
103 0 : fValue.fInt64 = 0;
104 0 : fType = kLong;
105 0 : fDecimalStr = NULL;
106 0 : fDecimalNum = NULL;
107 0 : fBogus.setToBogus();
108 0 : }
109 :
110 : // -------------------------------------
111 : // default constructor.
112 : // Creates a formattable object with a long value 0.
113 :
114 0 : Formattable::Formattable() {
115 0 : init();
116 0 : }
117 :
118 : // -------------------------------------
119 : // Creates a formattable object with a Date instance.
120 :
121 0 : Formattable::Formattable(UDate date, ISDATE /*isDate*/)
122 : {
123 0 : init();
124 0 : fType = kDate;
125 0 : fValue.fDate = date;
126 0 : }
127 :
128 : // -------------------------------------
129 : // Creates a formattable object with a double value.
130 :
131 0 : Formattable::Formattable(double value)
132 : {
133 0 : init();
134 0 : fType = kDouble;
135 0 : fValue.fDouble = value;
136 0 : }
137 :
138 : // -------------------------------------
139 : // Creates a formattable object with an int32_t value.
140 :
141 0 : Formattable::Formattable(int32_t value)
142 : {
143 0 : init();
144 0 : fValue.fInt64 = value;
145 0 : }
146 :
147 : // -------------------------------------
148 : // Creates a formattable object with an int64_t value.
149 :
150 0 : Formattable::Formattable(int64_t value)
151 : {
152 0 : init();
153 0 : fType = kInt64;
154 0 : fValue.fInt64 = value;
155 0 : }
156 :
157 : // -------------------------------------
158 : // Creates a formattable object with a decimal number value from a string.
159 :
160 0 : Formattable::Formattable(StringPiece number, UErrorCode &status) {
161 0 : init();
162 0 : setDecimalNumber(number, status);
163 0 : }
164 :
165 :
166 : // -------------------------------------
167 : // Creates a formattable object with a UnicodeString instance.
168 :
169 0 : Formattable::Formattable(const UnicodeString& stringToCopy)
170 : {
171 0 : init();
172 0 : fType = kString;
173 0 : fValue.fString = new UnicodeString(stringToCopy);
174 0 : }
175 :
176 : // -------------------------------------
177 : // Creates a formattable object with a UnicodeString* value.
178 : // (adopting symantics)
179 :
180 0 : Formattable::Formattable(UnicodeString* stringToAdopt)
181 : {
182 0 : init();
183 0 : fType = kString;
184 0 : fValue.fString = stringToAdopt;
185 0 : }
186 :
187 0 : Formattable::Formattable(UObject* objectToAdopt)
188 : {
189 0 : init();
190 0 : fType = kObject;
191 0 : fValue.fObject = objectToAdopt;
192 0 : }
193 :
194 : // -------------------------------------
195 :
196 0 : Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
197 0 : : UObject(), fType(kArray)
198 : {
199 0 : init();
200 0 : fType = kArray;
201 0 : fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
202 0 : fValue.fArrayAndCount.fCount = count;
203 0 : }
204 :
205 : // -------------------------------------
206 : // copy constructor
207 :
208 :
209 0 : Formattable::Formattable(const Formattable &source)
210 0 : : UObject(*this)
211 : {
212 0 : init();
213 0 : *this = source;
214 0 : }
215 :
216 : // -------------------------------------
217 : // assignment operator
218 :
219 : Formattable&
220 0 : Formattable::operator=(const Formattable& source)
221 : {
222 0 : if (this != &source)
223 : {
224 : // Disposes the current formattable value/setting.
225 0 : dispose();
226 :
227 : // Sets the correct data type for this value.
228 0 : fType = source.fType;
229 0 : switch (fType)
230 : {
231 : case kArray:
232 : // Sets each element in the array one by one and records the array count.
233 0 : fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount;
234 0 : fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray,
235 0 : source.fValue.fArrayAndCount.fCount);
236 0 : break;
237 : case kString:
238 : // Sets the string value.
239 0 : fValue.fString = new UnicodeString(*source.fValue.fString);
240 0 : break;
241 : case kDouble:
242 : // Sets the double value.
243 0 : fValue.fDouble = source.fValue.fDouble;
244 0 : break;
245 : case kLong:
246 : case kInt64:
247 : // Sets the long value.
248 0 : fValue.fInt64 = source.fValue.fInt64;
249 0 : break;
250 : case kDate:
251 : // Sets the Date value.
252 0 : fValue.fDate = source.fValue.fDate;
253 0 : break;
254 : case kObject:
255 0 : fValue.fObject = objectClone(source.fValue.fObject);
256 0 : break;
257 : }
258 :
259 0 : UErrorCode status = U_ZERO_ERROR;
260 0 : if (source.fDecimalNum != NULL) {
261 0 : fDecimalNum = new DigitList(*source.fDecimalNum); // TODO: use internal digit list
262 : }
263 0 : if (source.fDecimalStr != NULL) {
264 0 : fDecimalStr = new CharString(*source.fDecimalStr, status);
265 0 : if (U_FAILURE(status)) {
266 0 : delete fDecimalStr;
267 0 : fDecimalStr = NULL;
268 : }
269 : }
270 : }
271 0 : return *this;
272 : }
273 :
274 : // -------------------------------------
275 :
276 : UBool
277 0 : Formattable::operator==(const Formattable& that) const
278 : {
279 : int32_t i;
280 :
281 0 : if (this == &that) return TRUE;
282 :
283 : // Returns FALSE if the data types are different.
284 0 : if (fType != that.fType) return FALSE;
285 :
286 : // Compares the actual data values.
287 0 : UBool equal = TRUE;
288 0 : switch (fType) {
289 : case kDate:
290 0 : equal = (fValue.fDate == that.fValue.fDate);
291 0 : break;
292 : case kDouble:
293 0 : equal = (fValue.fDouble == that.fValue.fDouble);
294 0 : break;
295 : case kLong:
296 : case kInt64:
297 0 : equal = (fValue.fInt64 == that.fValue.fInt64);
298 0 : break;
299 : case kString:
300 0 : equal = (*(fValue.fString) == *(that.fValue.fString));
301 0 : break;
302 : case kArray:
303 0 : if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
304 0 : equal = FALSE;
305 0 : break;
306 : }
307 : // Checks each element for equality.
308 0 : for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
309 0 : if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
310 0 : equal = FALSE;
311 0 : break;
312 : }
313 : }
314 0 : break;
315 : case kObject:
316 0 : if (fValue.fObject == NULL || that.fValue.fObject == NULL) {
317 0 : equal = FALSE;
318 : } else {
319 0 : equal = objectEquals(fValue.fObject, that.fValue.fObject);
320 : }
321 0 : break;
322 : }
323 :
324 : // TODO: compare digit lists if numeric.
325 0 : return equal;
326 : }
327 :
328 : // -------------------------------------
329 :
330 0 : Formattable::~Formattable()
331 : {
332 0 : dispose();
333 0 : }
334 :
335 : // -------------------------------------
336 :
337 0 : void Formattable::dispose()
338 : {
339 : // Deletes the data value if necessary.
340 0 : switch (fType) {
341 : case kString:
342 0 : delete fValue.fString;
343 0 : break;
344 : case kArray:
345 0 : delete[] fValue.fArrayAndCount.fArray;
346 0 : break;
347 : case kObject:
348 0 : delete fValue.fObject;
349 0 : break;
350 : default:
351 0 : break;
352 : }
353 :
354 0 : fType = kLong;
355 0 : fValue.fInt64 = 0;
356 :
357 0 : delete fDecimalStr;
358 0 : fDecimalStr = NULL;
359 :
360 0 : FmtStackData *stackData = (FmtStackData*)fStackData;
361 0 : if(fDecimalNum != &(stackData->stackDecimalNum)) {
362 0 : delete fDecimalNum;
363 : } else {
364 0 : fDecimalNum->~DigitList(); // destruct, don't deallocate
365 : }
366 0 : fDecimalNum = NULL;
367 0 : }
368 :
369 : Formattable *
370 0 : Formattable::clone() const {
371 0 : return new Formattable(*this);
372 : }
373 :
374 : // -------------------------------------
375 : // Gets the data type of this Formattable object.
376 : Formattable::Type
377 0 : Formattable::getType() const
378 : {
379 0 : return fType;
380 : }
381 :
382 : UBool
383 0 : Formattable::isNumeric() const {
384 0 : switch (fType) {
385 : case kDouble:
386 : case kLong:
387 : case kInt64:
388 0 : return TRUE;
389 : default:
390 0 : return FALSE;
391 : }
392 : }
393 :
394 : // -------------------------------------
395 : int32_t
396 : //Formattable::getLong(UErrorCode* status) const
397 0 : Formattable::getLong(UErrorCode& status) const
398 : {
399 0 : if (U_FAILURE(status)) {
400 0 : return 0;
401 : }
402 :
403 0 : switch (fType) {
404 : case Formattable::kLong:
405 0 : return (int32_t)fValue.fInt64;
406 : case Formattable::kInt64:
407 0 : if (fValue.fInt64 > INT32_MAX) {
408 0 : status = U_INVALID_FORMAT_ERROR;
409 0 : return INT32_MAX;
410 0 : } else if (fValue.fInt64 < INT32_MIN) {
411 0 : status = U_INVALID_FORMAT_ERROR;
412 0 : return INT32_MIN;
413 : } else {
414 0 : return (int32_t)fValue.fInt64;
415 : }
416 : case Formattable::kDouble:
417 0 : if (fValue.fDouble > INT32_MAX) {
418 0 : status = U_INVALID_FORMAT_ERROR;
419 0 : return INT32_MAX;
420 0 : } else if (fValue.fDouble < INT32_MIN) {
421 0 : status = U_INVALID_FORMAT_ERROR;
422 0 : return INT32_MIN;
423 : } else {
424 0 : return (int32_t)fValue.fDouble; // loses fraction
425 : }
426 : case Formattable::kObject:
427 0 : if (fValue.fObject == NULL) {
428 0 : status = U_MEMORY_ALLOCATION_ERROR;
429 0 : return 0;
430 : }
431 : // TODO Later replace this with instanceof call
432 0 : if (instanceOfMeasure(fValue.fObject)) {
433 0 : return ((const Measure*) fValue.fObject)->
434 0 : getNumber().getLong(status);
435 : }
436 : U_FALLTHROUGH;
437 : default:
438 0 : status = U_INVALID_FORMAT_ERROR;
439 0 : 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
451 0 : Formattable::getInt64(UErrorCode& status) const
452 : {
453 0 : if (U_FAILURE(status)) {
454 0 : return 0;
455 : }
456 :
457 0 : switch (fType) {
458 : case Formattable::kLong:
459 : case Formattable::kInt64:
460 0 : return fValue.fInt64;
461 : case Formattable::kDouble:
462 0 : if (fValue.fDouble > (double)U_INT64_MAX) {
463 0 : status = U_INVALID_FORMAT_ERROR;
464 0 : return U_INT64_MAX;
465 0 : } else if (fValue.fDouble < (double)U_INT64_MIN) {
466 0 : status = U_INVALID_FORMAT_ERROR;
467 0 : return U_INT64_MIN;
468 0 : } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalNum != NULL) {
469 0 : int64_t val = fDecimalNum->getInt64();
470 0 : if (val != 0) {
471 0 : return val;
472 : } else {
473 0 : status = U_INVALID_FORMAT_ERROR;
474 0 : return fValue.fDouble > 0 ? U_INT64_MAX : U_INT64_MIN;
475 : }
476 : } else {
477 0 : return (int64_t)fValue.fDouble;
478 : }
479 : case Formattable::kObject:
480 0 : if (fValue.fObject == NULL) {
481 0 : status = U_MEMORY_ALLOCATION_ERROR;
482 0 : return 0;
483 : }
484 0 : if (instanceOfMeasure(fValue.fObject)) {
485 0 : return ((const Measure*) fValue.fObject)->
486 0 : getNumber().getInt64(status);
487 : }
488 : U_FALLTHROUGH;
489 : default:
490 0 : status = U_INVALID_FORMAT_ERROR;
491 0 : return 0;
492 : }
493 : }
494 :
495 : // -------------------------------------
496 : double
497 0 : Formattable::getDouble(UErrorCode& status) const
498 : {
499 0 : if (U_FAILURE(status)) {
500 0 : return 0;
501 : }
502 :
503 0 : switch (fType) {
504 : case Formattable::kLong:
505 : case Formattable::kInt64: // loses precision
506 0 : return (double)fValue.fInt64;
507 : case Formattable::kDouble:
508 0 : return fValue.fDouble;
509 : case Formattable::kObject:
510 0 : if (fValue.fObject == NULL) {
511 0 : status = U_MEMORY_ALLOCATION_ERROR;
512 0 : return 0;
513 : }
514 : // TODO Later replace this with instanceof call
515 0 : if (instanceOfMeasure(fValue.fObject)) {
516 0 : return ((const Measure*) fValue.fObject)->
517 0 : getNumber().getDouble(status);
518 : }
519 : U_FALLTHROUGH;
520 : default:
521 0 : status = U_INVALID_FORMAT_ERROR;
522 0 : return 0;
523 : }
524 : }
525 :
526 : const UObject*
527 0 : Formattable::getObject() const {
528 0 : return (fType == kObject) ? fValue.fObject : NULL;
529 : }
530 :
531 : // -------------------------------------
532 : // Sets the value to a double value d.
533 :
534 : void
535 0 : Formattable::setDouble(double d)
536 : {
537 0 : dispose();
538 0 : fType = kDouble;
539 0 : fValue.fDouble = d;
540 0 : }
541 :
542 : // -------------------------------------
543 : // Sets the value to a long value l.
544 :
545 : void
546 0 : Formattable::setLong(int32_t l)
547 : {
548 0 : dispose();
549 0 : fType = kLong;
550 0 : fValue.fInt64 = l;
551 0 : }
552 :
553 : // -------------------------------------
554 : // Sets the value to an int64 value ll.
555 :
556 : void
557 0 : Formattable::setInt64(int64_t ll)
558 : {
559 0 : dispose();
560 0 : fType = kInt64;
561 0 : fValue.fInt64 = ll;
562 0 : }
563 :
564 : // -------------------------------------
565 : // Sets the value to a Date instance d.
566 :
567 : void
568 0 : Formattable::setDate(UDate d)
569 : {
570 0 : dispose();
571 0 : fType = kDate;
572 0 : fValue.fDate = d;
573 0 : }
574 :
575 : // -------------------------------------
576 : // Sets the value to a string value stringToCopy.
577 :
578 : void
579 0 : Formattable::setString(const UnicodeString& stringToCopy)
580 : {
581 0 : dispose();
582 0 : fType = kString;
583 0 : fValue.fString = new UnicodeString(stringToCopy);
584 0 : }
585 :
586 : // -------------------------------------
587 : // Sets the value to an array of Formattable objects.
588 :
589 : void
590 0 : Formattable::setArray(const Formattable* array, int32_t count)
591 : {
592 0 : dispose();
593 0 : fType = kArray;
594 0 : fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
595 0 : fValue.fArrayAndCount.fCount = count;
596 0 : }
597 :
598 : // -------------------------------------
599 : // Adopts the stringToAdopt value.
600 :
601 : void
602 0 : Formattable::adoptString(UnicodeString* stringToAdopt)
603 : {
604 0 : dispose();
605 0 : fType = kString;
606 0 : fValue.fString = stringToAdopt;
607 0 : }
608 :
609 : // -------------------------------------
610 : // Adopts the array value and its count.
611 :
612 : void
613 0 : Formattable::adoptArray(Formattable* array, int32_t count)
614 : {
615 0 : dispose();
616 0 : fType = kArray;
617 0 : fValue.fArrayAndCount.fArray = array;
618 0 : fValue.fArrayAndCount.fCount = count;
619 0 : }
620 :
621 : void
622 0 : Formattable::adoptObject(UObject* objectToAdopt) {
623 0 : dispose();
624 0 : fType = kObject;
625 0 : fValue.fObject = objectToAdopt;
626 0 : }
627 :
628 : // -------------------------------------
629 : UnicodeString&
630 0 : Formattable::getString(UnicodeString& result, UErrorCode& status) const
631 : {
632 0 : if (fType != kString) {
633 0 : setError(status, U_INVALID_FORMAT_ERROR);
634 0 : result.setToBogus();
635 : } else {
636 0 : if (fValue.fString == NULL) {
637 0 : setError(status, U_MEMORY_ALLOCATION_ERROR);
638 : } else {
639 0 : result = *fValue.fString;
640 : }
641 : }
642 0 : return result;
643 : }
644 :
645 : // -------------------------------------
646 : const UnicodeString&
647 0 : Formattable::getString(UErrorCode& status) const
648 : {
649 0 : if (fType != kString) {
650 0 : setError(status, U_INVALID_FORMAT_ERROR);
651 0 : return *getBogus();
652 : }
653 0 : if (fValue.fString == NULL) {
654 0 : setError(status, U_MEMORY_ALLOCATION_ERROR);
655 0 : return *getBogus();
656 : }
657 0 : return *fValue.fString;
658 : }
659 :
660 : // -------------------------------------
661 : UnicodeString&
662 0 : Formattable::getString(UErrorCode& status)
663 : {
664 0 : if (fType != kString) {
665 0 : setError(status, U_INVALID_FORMAT_ERROR);
666 0 : return *getBogus();
667 : }
668 0 : if (fValue.fString == NULL) {
669 0 : setError(status, U_MEMORY_ALLOCATION_ERROR);
670 0 : return *getBogus();
671 : }
672 0 : return *fValue.fString;
673 : }
674 :
675 : // -------------------------------------
676 : const Formattable*
677 0 : Formattable::getArray(int32_t& count, UErrorCode& status) const
678 : {
679 0 : if (fType != kArray) {
680 0 : setError(status, U_INVALID_FORMAT_ERROR);
681 0 : count = 0;
682 0 : return NULL;
683 : }
684 0 : count = fValue.fArrayAndCount.fCount;
685 0 : return fValue.fArrayAndCount.fArray;
686 : }
687 :
688 : // -------------------------------------
689 : // Gets the bogus string, ensures mondo bogosity.
690 :
691 : UnicodeString*
692 0 : Formattable::getBogus() const
693 : {
694 0 : return (UnicodeString*)&fBogus; /* cast away const :-( */
695 : }
696 :
697 :
698 : // --------------------------------------
699 0 : StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
700 0 : if (U_FAILURE(status)) {
701 0 : return "";
702 : }
703 0 : if (fDecimalStr != NULL) {
704 0 : return fDecimalStr->toStringPiece();
705 : }
706 :
707 0 : CharString *decimalStr = internalGetCharString(status);
708 0 : if(decimalStr == NULL) {
709 0 : return ""; // getDecimalNumber returns "" for error cases
710 : } else {
711 0 : return decimalStr->toStringPiece();
712 : }
713 : }
714 :
715 0 : CharString *Formattable::internalGetCharString(UErrorCode &status) {
716 0 : if(fDecimalStr == NULL) {
717 0 : 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 0 : fDecimalNum = new DigitList; // TODO: use internal digit list
724 0 : if (fDecimalNum == NULL) {
725 0 : status = U_MEMORY_ALLOCATION_ERROR;
726 0 : return NULL;
727 : }
728 :
729 0 : switch (fType) {
730 : case kDouble:
731 0 : fDecimalNum->set(this->getDouble());
732 0 : break;
733 : case kLong:
734 0 : fDecimalNum->set(this->getLong());
735 0 : break;
736 : case kInt64:
737 0 : fDecimalNum->set(this->getInt64());
738 0 : break;
739 : default:
740 : // The formattable's value is not a numeric type.
741 0 : status = U_INVALID_STATE_ERROR;
742 0 : return NULL;
743 : }
744 : }
745 :
746 0 : fDecimalStr = new CharString;
747 0 : if (fDecimalStr == NULL) {
748 0 : status = U_MEMORY_ALLOCATION_ERROR;
749 0 : return NULL;
750 : }
751 0 : fDecimalNum->getDecimal(*fDecimalStr, status);
752 : }
753 0 : return fDecimalStr;
754 : }
755 :
756 :
757 : DigitList *
758 0 : Formattable::getInternalDigitList() {
759 0 : FmtStackData *stackData = (FmtStackData*)fStackData;
760 0 : if(fDecimalNum != &(stackData->stackDecimalNum)) {
761 0 : delete fDecimalNum;
762 0 : fDecimalNum = new (&(stackData->stackDecimalNum), kOnStack) DigitList();
763 : } else {
764 0 : fDecimalNum->clear();
765 : }
766 0 : return fDecimalNum;
767 : }
768 :
769 : // ---------------------------------------
770 : void
771 0 : Formattable::adoptDigitList(DigitList *dl) {
772 0 : if(fDecimalNum==dl) {
773 0 : fDecimalNum = NULL; // don't delete
774 : }
775 0 : dispose();
776 :
777 0 : fDecimalNum = dl;
778 :
779 0 : if(dl==NULL) { // allow adoptDigitList(NULL) to clear
780 0 : 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 0 : if (fDecimalNum->fitsIntoLong(FALSE)) {
787 0 : fType = kLong;
788 0 : fValue.fInt64 = fDecimalNum->getLong();
789 0 : } else if (fDecimalNum->fitsIntoInt64(FALSE)) {
790 0 : fType = kInt64;
791 0 : fValue.fInt64 = fDecimalNum->getInt64();
792 : } else {
793 0 : fType = kDouble;
794 0 : fValue.fDouble = fDecimalNum->getDouble();
795 : }
796 : }
797 :
798 :
799 : // ---------------------------------------
800 : void
801 0 : Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) {
802 0 : if (U_FAILURE(status)) {
803 0 : return;
804 : }
805 0 : 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 0 : DigitList *dnum = new DigitList(); // TODO: use getInternalDigitList
812 0 : if (dnum == NULL) {
813 0 : status = U_MEMORY_ALLOCATION_ERROR;
814 0 : return;
815 : }
816 0 : dnum->set(CharString(numberString, status).toStringPiece(), status);
817 0 : if (U_FAILURE(status)) {
818 0 : delete dnum;
819 0 : return; // String didn't contain a decimal number.
820 : }
821 0 : 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
908 0 : ufmt_open(UErrorCode *status) {
909 0 : if( U_FAILURE(*status) ) {
910 0 : return NULL;
911 : }
912 0 : UFormattable *fmt = (new Formattable())->toUFormattable();
913 :
914 0 : if( fmt == NULL ) {
915 0 : *status = U_MEMORY_ALLOCATION_ERROR;
916 : }
917 0 : return fmt;
918 : }
919 :
920 : U_DRAFT void U_EXPORT2
921 0 : ufmt_close(UFormattable *fmt) {
922 0 : Formattable *obj = Formattable::fromUFormattable(fmt);
923 :
924 0 : delete obj;
925 0 : }
926 :
927 : U_INTERNAL UFormattableType U_EXPORT2
928 0 : ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
929 0 : if(U_FAILURE(*status)) {
930 0 : return (UFormattableType)UFMT_COUNT;
931 : }
932 0 : const Formattable *obj = Formattable::fromUFormattable(fmt);
933 0 : return (UFormattableType)obj->getType();
934 : }
935 :
936 :
937 : U_INTERNAL UBool U_EXPORT2
938 0 : ufmt_isNumeric(const UFormattable *fmt) {
939 0 : const Formattable *obj = Formattable::fromUFormattable(fmt);
940 0 : return obj->isNumeric();
941 : }
942 :
943 : U_DRAFT UDate U_EXPORT2
944 0 : ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
945 0 : const Formattable *obj = Formattable::fromUFormattable(fmt);
946 :
947 0 : return obj->getDate(*status);
948 : }
949 :
950 : U_DRAFT double U_EXPORT2
951 0 : ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
952 0 : Formattable *obj = Formattable::fromUFormattable(fmt);
953 :
954 0 : return obj->getDouble(*status);
955 : }
956 :
957 : U_DRAFT int32_t U_EXPORT2
958 0 : ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
959 0 : Formattable *obj = Formattable::fromUFormattable(fmt);
960 :
961 0 : return obj->getLong(*status);
962 : }
963 :
964 :
965 : U_DRAFT const void *U_EXPORT2
966 0 : ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
967 0 : const Formattable *obj = Formattable::fromUFormattable(fmt);
968 :
969 0 : const void *ret = obj->getObject();
970 0 : if( ret==NULL &&
971 0 : (obj->getType() != Formattable::kObject) &&
972 0 : U_SUCCESS( *status )) {
973 0 : *status = U_INVALID_FORMAT_ERROR;
974 : }
975 0 : return ret;
976 : }
977 :
978 : U_DRAFT const UChar* U_EXPORT2
979 0 : ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
980 0 : Formattable *obj = Formattable::fromUFormattable(fmt);
981 :
982 : // avoid bogosity by checking the type first.
983 0 : if( obj->getType() != Formattable::kString ) {
984 0 : if( U_SUCCESS(*status) ){
985 0 : *status = U_INVALID_FORMAT_ERROR;
986 : }
987 0 : return NULL;
988 : }
989 :
990 : // This should return a valid string
991 0 : UnicodeString &str = obj->getString(*status);
992 0 : if( U_SUCCESS(*status) && len != NULL ) {
993 0 : *len = str.length();
994 : }
995 0 : return str.getTerminatedBuffer();
996 : }
997 :
998 : U_DRAFT int32_t U_EXPORT2
999 0 : ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
1000 0 : const Formattable *obj = Formattable::fromUFormattable(fmt);
1001 :
1002 : int32_t count;
1003 0 : (void)obj->getArray(count, *status);
1004 0 : return count;
1005 : }
1006 :
1007 : U_DRAFT UFormattable * U_EXPORT2
1008 0 : ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
1009 0 : Formattable *obj = Formattable::fromUFormattable(fmt);
1010 : int32_t count;
1011 0 : (void)obj->getArray(count, *status);
1012 0 : if(U_FAILURE(*status)) {
1013 0 : return NULL;
1014 0 : } else if(n<0 || n>=count) {
1015 0 : setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
1016 0 : return NULL;
1017 : } else {
1018 0 : return (*obj)[n].toUFormattable(); // returns non-const Formattable
1019 : }
1020 : }
1021 :
1022 : U_DRAFT const char * U_EXPORT2
1023 0 : ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
1024 0 : if(U_FAILURE(*status)) {
1025 0 : return "";
1026 : }
1027 0 : Formattable *obj = Formattable::fromUFormattable(fmt);
1028 0 : CharString *charString = obj->internalGetCharString(*status);
1029 0 : if(U_FAILURE(*status)) {
1030 0 : return "";
1031 : }
1032 0 : if(charString == NULL) {
1033 0 : *status = U_MEMORY_ALLOCATION_ERROR;
1034 0 : return "";
1035 : } else {
1036 0 : if(len!=NULL) {
1037 0 : *len = charString->length();
1038 : }
1039 0 : return charString->data();
1040 : }
1041 : }
1042 :
1043 : U_DRAFT int64_t U_EXPORT2
1044 0 : ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
1045 0 : Formattable *obj = Formattable::fromUFormattable(fmt);
1046 0 : return obj->getInt64(*status);
1047 : }
1048 :
1049 : #endif /* #if !UCONFIG_NO_FORMATTING */
1050 :
1051 : //eof
|