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