intl/icu/source/i18n/fmtable.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2 *******************************************************************************
     3 * Copyright (C) 1997-2013, 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 */
    16 #include "unicode/utypes.h"
    18 #if !UCONFIG_NO_FORMATTING
    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"
    32 // *****************************************************************************
    33 // class Formattable
    34 // *****************************************************************************
    36 U_NAMESPACE_BEGIN
    38 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
    40 #include "fmtableimp.h"
    42 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
    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]
    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]
    52 // Return TRUE if *a == *b.
    53 static inline UBool objectEquals(const UObject* a, const UObject* b) {
    54     // LATER: return *a == *b;
    55     return *((const Measure*) a) == *((const Measure*) b);
    56 }
    58 // Return a clone of *a.
    59 static inline UObject* objectClone(const UObject* a) {
    60     // LATER: return a->clone();
    61     return ((const Measure*) a)->clone();
    62 }
    64 // Return TRUE if *a is an instance of Measure.
    65 static inline UBool instanceOfMeasure(const UObject* a) {
    66     return dynamic_cast<const Measure*>(a) != NULL;
    67 }
    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  */
    76 static 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 }
    85 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
    87 /**
    88  * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
    89  */
    90 static void setError(UErrorCode& ec, UErrorCode err) {
    91     if (U_SUCCESS(ec)) {
    92         ec = err;
    93     }
    94 }
    96 //
    97 //  Common initialization code, shared by constructors.
    98 //  Put everything into a known state.
    99 //
   100 void  Formattable::init() {
   101     fValue.fInt64 = 0;
   102     fType = kLong;
   103     fDecimalStr = NULL;
   104     fDecimalNum = NULL;
   105     fBogus.setToBogus(); 
   106 }
   108 // -------------------------------------
   109 // default constructor.
   110 // Creates a formattable object with a long value 0.
   112 Formattable::Formattable() {
   113     init();
   114 }
   116 // -------------------------------------
   117 // Creates a formattable object with a Date instance.
   119 Formattable::Formattable(UDate date, ISDATE /*isDate*/)
   120 {
   121     init();
   122     fType = kDate;
   123     fValue.fDate = date;
   124 }
   126 // -------------------------------------
   127 // Creates a formattable object with a double value.
   129 Formattable::Formattable(double value)
   130 {
   131     init();
   132     fType = kDouble;
   133     fValue.fDouble = value;
   134 }
   136 // -------------------------------------
   137 // Creates a formattable object with an int32_t value.
   139 Formattable::Formattable(int32_t value)
   140 {
   141     init();
   142     fValue.fInt64 = value;
   143 }
   145 // -------------------------------------
   146 // Creates a formattable object with an int64_t value.
   148 Formattable::Formattable(int64_t value)
   149 {
   150     init();
   151     fType = kInt64;
   152     fValue.fInt64 = value;
   153 }
   155 // -------------------------------------
   156 // Creates a formattable object with a decimal number value from a string.
   158 Formattable::Formattable(const StringPiece &number, UErrorCode &status) {
   159     init();
   160     setDecimalNumber(number, status);
   161 }
   164 // -------------------------------------
   165 // Creates a formattable object with a UnicodeString instance.
   167 Formattable::Formattable(const UnicodeString& stringToCopy)
   168 {
   169     init();
   170     fType = kString;
   171     fValue.fString = new UnicodeString(stringToCopy);
   172 }
   174 // -------------------------------------
   175 // Creates a formattable object with a UnicodeString* value.
   176 // (adopting symantics)
   178 Formattable::Formattable(UnicodeString* stringToAdopt)
   179 {
   180     init();
   181     fType = kString;
   182     fValue.fString = stringToAdopt;
   183 }
   185 Formattable::Formattable(UObject* objectToAdopt)
   186 {
   187     init();
   188     fType = kObject;
   189     fValue.fObject = objectToAdopt;
   190 }
   192 // -------------------------------------
   194 Formattable::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 }
   203 // -------------------------------------
   204 // copy constructor
   207 Formattable::Formattable(const Formattable &source)
   208      :  UObject(*this)
   209 {
   210     init();
   211     *this = source;
   212 }
   214 // -------------------------------------
   215 // assignment operator
   217 Formattable&
   218 Formattable::operator=(const Formattable& source)
   219 {
   220     if (this != &source)
   221     {
   222         // Disposes the current formattable value/setting.
   223         dispose();
   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         }
   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 }
   272 // -------------------------------------
   274 UBool
   275 Formattable::operator==(const Formattable& that) const
   276 {
   277     int32_t i;
   279     if (this == &that) return TRUE;
   281     // Returns FALSE if the data types are different.
   282     if (fType != that.fType) return FALSE;
   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     }
   322     // TODO:  compare digit lists if numeric.
   323     return equal;
   324 }
   326 // -------------------------------------
   328 Formattable::~Formattable()
   329 {
   330     dispose();
   331 }
   333 // -------------------------------------
   335 void 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     }
   352     fType = kLong;
   353     fValue.fInt64 = 0;
   355     delete fDecimalStr;
   356     fDecimalStr = NULL;
   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 }
   367 Formattable *
   368 Formattable::clone() const {
   369     return new Formattable(*this);
   370 }
   372 // -------------------------------------
   373 // Gets the data type of this Formattable object. 
   374 Formattable::Type
   375 Formattable::getType() const
   376 {
   377     return fType;
   378 }
   380 UBool
   381 Formattable::isNumeric() const {
   382     switch (fType) {
   383     case kDouble:
   384     case kLong:
   385     case kInt64:
   386         return TRUE;
   387     default:
   388         return FALSE;
   389     }
   390 }
   392 // -------------------------------------
   393 int32_t
   394 //Formattable::getLong(UErrorCode* status) const
   395 Formattable::getLong(UErrorCode& status) const
   396 {
   397     if (U_FAILURE(status)) {
   398         return 0;
   399     }
   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 }
   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.
   445 static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
   447 int64_t
   448 Formattable::getInt64(UErrorCode& status) const
   449 {
   450     if (U_FAILURE(status)) {
   451         return 0;
   452     }
   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 }
   491 // -------------------------------------
   492 double
   493 Formattable::getDouble(UErrorCode& status) const
   494 {
   495     if (U_FAILURE(status)) {
   496         return 0;
   497     }
   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 }
   521 const UObject*
   522 Formattable::getObject() const {
   523     return (fType == kObject) ? fValue.fObject : NULL;
   524 }
   526 // -------------------------------------
   527 // Sets the value to a double value d.
   529 void
   530 Formattable::setDouble(double d)
   531 {
   532     dispose();
   533     fType = kDouble;
   534     fValue.fDouble = d;
   535 }
   537 // -------------------------------------
   538 // Sets the value to a long value l.
   540 void
   541 Formattable::setLong(int32_t l)
   542 {
   543     dispose();
   544     fType = kLong;
   545     fValue.fInt64 = l;
   546 }
   548 // -------------------------------------
   549 // Sets the value to an int64 value ll.
   551 void
   552 Formattable::setInt64(int64_t ll)
   553 {
   554     dispose();
   555     fType = kInt64;
   556     fValue.fInt64 = ll;
   557 }
   559 // -------------------------------------
   560 // Sets the value to a Date instance d.
   562 void
   563 Formattable::setDate(UDate d)
   564 {
   565     dispose();
   566     fType = kDate;
   567     fValue.fDate = d;
   568 }
   570 // -------------------------------------
   571 // Sets the value to a string value stringToCopy.
   573 void
   574 Formattable::setString(const UnicodeString& stringToCopy)
   575 {
   576     dispose();
   577     fType = kString;
   578     fValue.fString = new UnicodeString(stringToCopy);
   579 }
   581 // -------------------------------------
   582 // Sets the value to an array of Formattable objects.
   584 void
   585 Formattable::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 }
   593 // -------------------------------------
   594 // Adopts the stringToAdopt value.
   596 void
   597 Formattable::adoptString(UnicodeString* stringToAdopt)
   598 {
   599     dispose();
   600     fType = kString;
   601     fValue.fString = stringToAdopt;
   602 }
   604 // -------------------------------------
   605 // Adopts the array value and its count.
   607 void
   608 Formattable::adoptArray(Formattable* array, int32_t count)
   609 {
   610     dispose();
   611     fType = kArray;
   612     fValue.fArrayAndCount.fArray = array;
   613     fValue.fArrayAndCount.fCount = count;
   614 }
   616 void
   617 Formattable::adoptObject(UObject* objectToAdopt) {
   618     dispose();
   619     fType = kObject;
   620     fValue.fObject = objectToAdopt;
   621 }
   623 // -------------------------------------
   624 UnicodeString& 
   625 Formattable::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 }
   640 // -------------------------------------
   641 const UnicodeString& 
   642 Formattable::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 }
   655 // -------------------------------------
   656 UnicodeString& 
   657 Formattable::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 }
   670 // -------------------------------------
   671 const Formattable* 
   672 Formattable::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 }
   683 // -------------------------------------
   684 // Gets the bogus string, ensures mondo bogosity.
   686 UnicodeString*
   687 Formattable::getBogus() const 
   688 {
   689     return (UnicodeString*)&fBogus; /* cast away const :-( */
   690 }
   693 // --------------------------------------
   694 StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
   695     if (U_FAILURE(status)) {
   696         return "";
   697     }
   698     if (fDecimalStr != NULL) {
   699       return fDecimalStr->toStringPiece();
   700     }
   702     CharString *decimalStr = internalGetCharString(status);
   703     if(decimalStr == NULL) {
   704       return ""; // getDecimalNumber returns "" for error cases
   705     } else {
   706       return decimalStr->toStringPiece();
   707     }
   708 }
   710 CharString *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         }
   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       }
   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 }
   752 DigitList *
   753 Formattable::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 }
   764 // ---------------------------------------
   765 void
   766 Formattable::adoptDigitList(DigitList *dl) {
   767   if(fDecimalNum==dl) {
   768     fDecimalNum = NULL; // don't delete
   769   }
   770   dispose();
   772   fDecimalNum = dl;
   774   if(dl==NULL) { // allow adoptDigitList(NULL) to clear
   775     return;
   776   }
   778     // Set the value into the Union of simple type values.
   779     // Cannot use the set() functions because they would delete the fDecimalNum value,
   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 }
   794 // ---------------------------------------
   795 void
   796 Formattable::setDecimalNumber(const StringPiece &numberString, UErrorCode &status) {
   797     if (U_FAILURE(status)) {
   798         return;
   799     }
   800     dispose();
   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);
   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 }
   822 #if 0
   823 //----------------------------------------------------
   824 // console I/O
   825 //----------------------------------------------------
   826 #ifdef _DEBUG
   828 #include <iostream>
   829 using namespace std;
   831 #include "unicode/datefmt.h"
   832 #include "unistrm.h"
   834 class FormattableStreamer /* not : public UObject because all methods are static */ {
   835 public:
   836     static void streamOut(ostream& stream, const Formattable& obj);
   838 private:
   839     FormattableStreamer() {} // private - forbid instantiation
   840 };
   842 // This is for debugging purposes only.  This will send a displayable
   843 // form of the Formattable object to the output stream.
   845 void
   846 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
   847 {
   848     static DateFormat *defDateFormat = 0;
   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
   894 #endif
   896 U_NAMESPACE_END
   898 /* ---- UFormattable implementation ---- */
   900 U_NAMESPACE_USE
   902 U_DRAFT UFormattable* U_EXPORT2
   903 ufmt_open(UErrorCode *status) {
   904   if( U_FAILURE(*status) ) {
   905     return NULL;
   906   }
   907   UFormattable *fmt = (new Formattable())->toUFormattable();
   909   if( fmt == NULL ) {
   910     *status = U_MEMORY_ALLOCATION_ERROR;
   911   }
   912   return fmt;
   913 }
   915 U_DRAFT void U_EXPORT2
   916 ufmt_close(UFormattable *fmt) {
   917   Formattable *obj = Formattable::fromUFormattable(fmt);
   919   delete obj;
   920 }
   922 U_INTERNAL UFormattableType U_EXPORT2
   923 ufmt_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 }
   932 U_INTERNAL UBool U_EXPORT2
   933 ufmt_isNumeric(const UFormattable *fmt) {
   934   const Formattable *obj = Formattable::fromUFormattable(fmt);
   935   return obj->isNumeric();
   936 }
   938 U_DRAFT UDate U_EXPORT2
   939 ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
   940   const Formattable *obj = Formattable::fromUFormattable(fmt);
   942   return obj->getDate(*status);
   943 }
   945 U_DRAFT double U_EXPORT2
   946 ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
   947   Formattable *obj = Formattable::fromUFormattable(fmt);
   949   return obj->getDouble(*status);
   950 }
   952 U_DRAFT int32_t U_EXPORT2
   953 ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
   954   Formattable *obj = Formattable::fromUFormattable(fmt);
   956   return obj->getLong(*status);
   957 }
   960 U_DRAFT const void *U_EXPORT2
   961 ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
   962   const Formattable *obj = Formattable::fromUFormattable(fmt);
   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 }
   973 U_DRAFT const UChar* U_EXPORT2
   974 ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
   975   Formattable *obj = Formattable::fromUFormattable(fmt);
   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   }
   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 }
   993 U_DRAFT int32_t U_EXPORT2
   994 ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
   995   const Formattable *obj = Formattable::fromUFormattable(fmt);
   997   int32_t count;
   998   (void)obj->getArray(count, *status);
   999   return count;
  1002 U_DRAFT UFormattable * U_EXPORT2
  1003 ufmt_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
  1017 U_DRAFT const char * U_EXPORT2
  1018 ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
  1019   if(U_FAILURE(*status)) {
  1020     return "";
  1022   Formattable *obj = Formattable::fromUFormattable(fmt);
  1023   CharString *charString = obj->internalGetCharString(*status);
  1024   if(U_FAILURE(*status)) {
  1025     return "";
  1027   if(charString == NULL) {
  1028     *status = U_MEMORY_ALLOCATION_ERROR;
  1029     return "";
  1030   } else {
  1031     if(len!=NULL) {
  1032       *len = charString->length();
  1034     return charString->data();
  1038 U_DRAFT int64_t U_EXPORT2
  1039 ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
  1040   Formattable *obj = Formattable::fromUFormattable(fmt);
  1041   return obj->getInt64(*status);
  1044 #endif /* #if !UCONFIG_NO_FORMATTING */
  1046 //eof

mercurial