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