LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - fmtable.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 451 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 63 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13