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