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