intl/icu/source/i18n/fmtable.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/intl/icu/source/i18n/fmtable.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1046 @@
     1.4 +/*
     1.5 +*******************************************************************************
     1.6 +* Copyright (C) 1997-2013, International Business Machines Corporation and    *
     1.7 +* others. All Rights Reserved.                                                *
     1.8 +*******************************************************************************
     1.9 +*
    1.10 +* File FMTABLE.CPP
    1.11 +*
    1.12 +* Modification History:
    1.13 +*
    1.14 +*   Date        Name        Description
    1.15 +*   03/25/97    clhuang     Initial Implementation.
    1.16 +********************************************************************************
    1.17 +*/
    1.18 +
    1.19 +#include "unicode/utypes.h"
    1.20 +
    1.21 +#if !UCONFIG_NO_FORMATTING
    1.22 +
    1.23 +#include <math.h>
    1.24 +#include "unicode/fmtable.h"
    1.25 +#include "unicode/ustring.h"
    1.26 +#include "unicode/measure.h"
    1.27 +#include "unicode/curramt.h"
    1.28 +#include "unicode/uformattable.h"
    1.29 +#include "charstr.h"
    1.30 +#include "cmemory.h"
    1.31 +#include "cstring.h"
    1.32 +#include "decNumber.h"
    1.33 +#include "digitlst.h"
    1.34 +
    1.35 +// *****************************************************************************
    1.36 +// class Formattable
    1.37 +// *****************************************************************************
    1.38 +
    1.39 +U_NAMESPACE_BEGIN
    1.40 +
    1.41 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
    1.42 +
    1.43 +#include "fmtableimp.h"
    1.44 +
    1.45 +//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
    1.46 +
    1.47 +// NOTE: As of 3.0, there are limitations to the UObject API.  It does
    1.48 +// not (yet) support cloning, operator=, nor operator==.  To
    1.49 +// work around this, I implement some simple inlines here.  Later
    1.50 +// these can be modified or removed.  [alan]
    1.51 +
    1.52 +// NOTE: These inlines assume that all fObjects are in fact instances
    1.53 +// of the Measure class, which is true as of 3.0.  [alan]
    1.54 +
    1.55 +// Return TRUE if *a == *b.
    1.56 +static inline UBool objectEquals(const UObject* a, const UObject* b) {
    1.57 +    // LATER: return *a == *b;
    1.58 +    return *((const Measure*) a) == *((const Measure*) b);
    1.59 +}
    1.60 +
    1.61 +// Return a clone of *a.
    1.62 +static inline UObject* objectClone(const UObject* a) {
    1.63 +    // LATER: return a->clone();
    1.64 +    return ((const Measure*) a)->clone();
    1.65 +}
    1.66 +
    1.67 +// Return TRUE if *a is an instance of Measure.
    1.68 +static inline UBool instanceOfMeasure(const UObject* a) {
    1.69 +    return dynamic_cast<const Measure*>(a) != NULL;
    1.70 +}
    1.71 +
    1.72 +/**
    1.73 + * Creates a new Formattable array and copies the values from the specified
    1.74 + * original.
    1.75 + * @param array the original array
    1.76 + * @param count the original array count
    1.77 + * @return the new Formattable array.
    1.78 + */
    1.79 +static Formattable* createArrayCopy(const Formattable* array, int32_t count) {
    1.80 +    Formattable *result = new Formattable[count];
    1.81 +    if (result != NULL) {
    1.82 +        for (int32_t i=0; i<count; ++i)
    1.83 +            result[i] = array[i]; // Don't memcpy!
    1.84 +    }
    1.85 +    return result;
    1.86 +}
    1.87 +
    1.88 +//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
    1.89 +
    1.90 +/**
    1.91 + * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
    1.92 + */
    1.93 +static void setError(UErrorCode& ec, UErrorCode err) {
    1.94 +    if (U_SUCCESS(ec)) {
    1.95 +        ec = err;
    1.96 +    }
    1.97 +}
    1.98 +
    1.99 +//
   1.100 +//  Common initialization code, shared by constructors.
   1.101 +//  Put everything into a known state.
   1.102 +//
   1.103 +void  Formattable::init() {
   1.104 +    fValue.fInt64 = 0;
   1.105 +    fType = kLong;
   1.106 +    fDecimalStr = NULL;
   1.107 +    fDecimalNum = NULL;
   1.108 +    fBogus.setToBogus(); 
   1.109 +}
   1.110 +
   1.111 +// -------------------------------------
   1.112 +// default constructor.
   1.113 +// Creates a formattable object with a long value 0.
   1.114 +
   1.115 +Formattable::Formattable() {
   1.116 +    init();
   1.117 +}
   1.118 +
   1.119 +// -------------------------------------
   1.120 +// Creates a formattable object with a Date instance.
   1.121 +
   1.122 +Formattable::Formattable(UDate date, ISDATE /*isDate*/)
   1.123 +{
   1.124 +    init();
   1.125 +    fType = kDate;
   1.126 +    fValue.fDate = date;
   1.127 +}
   1.128 +
   1.129 +// -------------------------------------
   1.130 +// Creates a formattable object with a double value.
   1.131 +
   1.132 +Formattable::Formattable(double value)
   1.133 +{
   1.134 +    init();
   1.135 +    fType = kDouble;
   1.136 +    fValue.fDouble = value;
   1.137 +}
   1.138 +
   1.139 +// -------------------------------------
   1.140 +// Creates a formattable object with an int32_t value.
   1.141 +
   1.142 +Formattable::Formattable(int32_t value)
   1.143 +{
   1.144 +    init();
   1.145 +    fValue.fInt64 = value;
   1.146 +}
   1.147 +
   1.148 +// -------------------------------------
   1.149 +// Creates a formattable object with an int64_t value.
   1.150 +
   1.151 +Formattable::Formattable(int64_t value)
   1.152 +{
   1.153 +    init();
   1.154 +    fType = kInt64;
   1.155 +    fValue.fInt64 = value;
   1.156 +}
   1.157 +
   1.158 +// -------------------------------------
   1.159 +// Creates a formattable object with a decimal number value from a string.
   1.160 +
   1.161 +Formattable::Formattable(const StringPiece &number, UErrorCode &status) {
   1.162 +    init();
   1.163 +    setDecimalNumber(number, status);
   1.164 +}
   1.165 +
   1.166 +
   1.167 +// -------------------------------------
   1.168 +// Creates a formattable object with a UnicodeString instance.
   1.169 +
   1.170 +Formattable::Formattable(const UnicodeString& stringToCopy)
   1.171 +{
   1.172 +    init();
   1.173 +    fType = kString;
   1.174 +    fValue.fString = new UnicodeString(stringToCopy);
   1.175 +}
   1.176 +
   1.177 +// -------------------------------------
   1.178 +// Creates a formattable object with a UnicodeString* value.
   1.179 +// (adopting symantics)
   1.180 +
   1.181 +Formattable::Formattable(UnicodeString* stringToAdopt)
   1.182 +{
   1.183 +    init();
   1.184 +    fType = kString;
   1.185 +    fValue.fString = stringToAdopt;
   1.186 +}
   1.187 +
   1.188 +Formattable::Formattable(UObject* objectToAdopt)
   1.189 +{
   1.190 +    init();
   1.191 +    fType = kObject;
   1.192 +    fValue.fObject = objectToAdopt;
   1.193 +}
   1.194 +
   1.195 +// -------------------------------------
   1.196 +
   1.197 +Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
   1.198 +    :   UObject(), fType(kArray)
   1.199 +{
   1.200 +    init();
   1.201 +    fType = kArray;
   1.202 +    fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
   1.203 +    fValue.fArrayAndCount.fCount = count;
   1.204 +}
   1.205 +
   1.206 +// -------------------------------------
   1.207 +// copy constructor
   1.208 +
   1.209 +
   1.210 +Formattable::Formattable(const Formattable &source)
   1.211 +     :  UObject(*this)
   1.212 +{
   1.213 +    init();
   1.214 +    *this = source;
   1.215 +}
   1.216 +
   1.217 +// -------------------------------------
   1.218 +// assignment operator
   1.219 +
   1.220 +Formattable&
   1.221 +Formattable::operator=(const Formattable& source)
   1.222 +{
   1.223 +    if (this != &source)
   1.224 +    {
   1.225 +        // Disposes the current formattable value/setting.
   1.226 +        dispose();
   1.227 +
   1.228 +        // Sets the correct data type for this value.
   1.229 +        fType = source.fType;
   1.230 +        switch (fType)
   1.231 +        {
   1.232 +        case kArray:
   1.233 +            // Sets each element in the array one by one and records the array count.
   1.234 +            fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount;
   1.235 +            fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray,
   1.236 +                                                           source.fValue.fArrayAndCount.fCount);
   1.237 +            break;
   1.238 +        case kString:
   1.239 +            // Sets the string value.
   1.240 +            fValue.fString = new UnicodeString(*source.fValue.fString);
   1.241 +            break;
   1.242 +        case kDouble:
   1.243 +            // Sets the double value.
   1.244 +            fValue.fDouble = source.fValue.fDouble;
   1.245 +            break;
   1.246 +        case kLong:
   1.247 +        case kInt64:
   1.248 +            // Sets the long value.
   1.249 +            fValue.fInt64 = source.fValue.fInt64;
   1.250 +            break;
   1.251 +        case kDate:
   1.252 +            // Sets the Date value.
   1.253 +            fValue.fDate = source.fValue.fDate;
   1.254 +            break;
   1.255 +        case kObject:
   1.256 +            fValue.fObject = objectClone(source.fValue.fObject);
   1.257 +            break;
   1.258 +        }
   1.259 +
   1.260 +        UErrorCode status = U_ZERO_ERROR;
   1.261 +        if (source.fDecimalNum != NULL) {
   1.262 +          fDecimalNum = new DigitList(*source.fDecimalNum); // TODO: use internal digit list
   1.263 +        }
   1.264 +        if (source.fDecimalStr != NULL) {
   1.265 +            fDecimalStr = new CharString(*source.fDecimalStr, status);
   1.266 +            if (U_FAILURE(status)) {
   1.267 +                delete fDecimalStr;
   1.268 +                fDecimalStr = NULL;
   1.269 +            }
   1.270 +        }
   1.271 +    }
   1.272 +    return *this;
   1.273 +}
   1.274 +
   1.275 +// -------------------------------------
   1.276 +
   1.277 +UBool
   1.278 +Formattable::operator==(const Formattable& that) const
   1.279 +{
   1.280 +    int32_t i;
   1.281 +
   1.282 +    if (this == &that) return TRUE;
   1.283 +
   1.284 +    // Returns FALSE if the data types are different.
   1.285 +    if (fType != that.fType) return FALSE;
   1.286 +
   1.287 +    // Compares the actual data values.
   1.288 +    UBool equal = TRUE;
   1.289 +    switch (fType) {
   1.290 +    case kDate:
   1.291 +        equal = (fValue.fDate == that.fValue.fDate);
   1.292 +        break;
   1.293 +    case kDouble:
   1.294 +        equal = (fValue.fDouble == that.fValue.fDouble);
   1.295 +        break;
   1.296 +    case kLong:
   1.297 +    case kInt64:
   1.298 +        equal = (fValue.fInt64 == that.fValue.fInt64);
   1.299 +        break;
   1.300 +    case kString:
   1.301 +        equal = (*(fValue.fString) == *(that.fValue.fString));
   1.302 +        break;
   1.303 +    case kArray:
   1.304 +        if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
   1.305 +            equal = FALSE;
   1.306 +            break;
   1.307 +        }
   1.308 +        // Checks each element for equality.
   1.309 +        for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
   1.310 +            if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
   1.311 +                equal = FALSE;
   1.312 +                break;
   1.313 +            }
   1.314 +        }
   1.315 +        break;
   1.316 +    case kObject:
   1.317 +        if (fValue.fObject == NULL || that.fValue.fObject == NULL) {
   1.318 +            equal = FALSE;
   1.319 +        } else {
   1.320 +            equal = objectEquals(fValue.fObject, that.fValue.fObject);
   1.321 +        }
   1.322 +        break;
   1.323 +    }
   1.324 +
   1.325 +    // TODO:  compare digit lists if numeric.
   1.326 +    return equal;
   1.327 +}
   1.328 +
   1.329 +// -------------------------------------
   1.330 +
   1.331 +Formattable::~Formattable()
   1.332 +{
   1.333 +    dispose();
   1.334 +}
   1.335 +
   1.336 +// -------------------------------------
   1.337 +
   1.338 +void Formattable::dispose()
   1.339 +{
   1.340 +    // Deletes the data value if necessary.
   1.341 +    switch (fType) {
   1.342 +    case kString:
   1.343 +        delete fValue.fString;
   1.344 +        break;
   1.345 +    case kArray:
   1.346 +        delete[] fValue.fArrayAndCount.fArray;
   1.347 +        break;
   1.348 +    case kObject:
   1.349 +        delete fValue.fObject;
   1.350 +        break;
   1.351 +    default:
   1.352 +        break;
   1.353 +    }
   1.354 +
   1.355 +    fType = kLong;
   1.356 +    fValue.fInt64 = 0;
   1.357 +
   1.358 +    delete fDecimalStr;
   1.359 +    fDecimalStr = NULL;
   1.360 +    
   1.361 +    FmtStackData *stackData = (FmtStackData*)fStackData;
   1.362 +    if(fDecimalNum != &(stackData->stackDecimalNum)) {
   1.363 +      delete fDecimalNum;
   1.364 +    } else {
   1.365 +      fDecimalNum->~DigitList(); // destruct, don't deallocate
   1.366 +    }
   1.367 +    fDecimalNum = NULL;
   1.368 +}
   1.369 +
   1.370 +Formattable *
   1.371 +Formattable::clone() const {
   1.372 +    return new Formattable(*this);
   1.373 +}
   1.374 +
   1.375 +// -------------------------------------
   1.376 +// Gets the data type of this Formattable object. 
   1.377 +Formattable::Type
   1.378 +Formattable::getType() const
   1.379 +{
   1.380 +    return fType;
   1.381 +}
   1.382 +
   1.383 +UBool
   1.384 +Formattable::isNumeric() const {
   1.385 +    switch (fType) {
   1.386 +    case kDouble:
   1.387 +    case kLong:
   1.388 +    case kInt64:
   1.389 +        return TRUE;
   1.390 +    default:
   1.391 +        return FALSE;
   1.392 +    }
   1.393 +}
   1.394 +
   1.395 +// -------------------------------------
   1.396 +int32_t
   1.397 +//Formattable::getLong(UErrorCode* status) const
   1.398 +Formattable::getLong(UErrorCode& status) const
   1.399 +{
   1.400 +    if (U_FAILURE(status)) {
   1.401 +        return 0;
   1.402 +    }
   1.403 +        
   1.404 +    switch (fType) {
   1.405 +    case Formattable::kLong: 
   1.406 +        return (int32_t)fValue.fInt64;
   1.407 +    case Formattable::kInt64:
   1.408 +        if (fValue.fInt64 > INT32_MAX) {
   1.409 +            status = U_INVALID_FORMAT_ERROR;
   1.410 +            return INT32_MAX;
   1.411 +        } else if (fValue.fInt64 < INT32_MIN) {
   1.412 +            status = U_INVALID_FORMAT_ERROR;
   1.413 +            return INT32_MIN;
   1.414 +        } else {
   1.415 +            return (int32_t)fValue.fInt64;
   1.416 +        }
   1.417 +    case Formattable::kDouble:
   1.418 +        if (fValue.fDouble > INT32_MAX) {
   1.419 +            status = U_INVALID_FORMAT_ERROR;
   1.420 +            return INT32_MAX;
   1.421 +        } else if (fValue.fDouble < INT32_MIN) {
   1.422 +            status = U_INVALID_FORMAT_ERROR;
   1.423 +            return INT32_MIN;
   1.424 +        } else {
   1.425 +            return (int32_t)fValue.fDouble; // loses fraction
   1.426 +        }
   1.427 +    case Formattable::kObject:
   1.428 +        if (fValue.fObject == NULL) {
   1.429 +            status = U_MEMORY_ALLOCATION_ERROR;
   1.430 +            return 0;
   1.431 +        }
   1.432 +        // TODO Later replace this with instanceof call
   1.433 +        if (instanceOfMeasure(fValue.fObject)) {
   1.434 +            return ((const Measure*) fValue.fObject)->
   1.435 +                getNumber().getLong(status);
   1.436 +        }
   1.437 +    default: 
   1.438 +        status = U_INVALID_FORMAT_ERROR;
   1.439 +        return 0;
   1.440 +    }
   1.441 +}
   1.442 +
   1.443 +// -------------------------------------
   1.444 +// Maximum int that can be represented exactly in a double.  (53 bits)
   1.445 +//    Larger ints may be rounded to a near-by value as not all are representable.
   1.446 +// TODO:  move this constant elsewhere, possibly configure it for different
   1.447 +//        floating point formats, if any non-standard ones are still in use.
   1.448 +static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
   1.449 +
   1.450 +int64_t
   1.451 +Formattable::getInt64(UErrorCode& status) const
   1.452 +{
   1.453 +    if (U_FAILURE(status)) {
   1.454 +        return 0;
   1.455 +    }
   1.456 +        
   1.457 +    switch (fType) {
   1.458 +    case Formattable::kLong: 
   1.459 +    case Formattable::kInt64: 
   1.460 +        return fValue.fInt64;
   1.461 +    case Formattable::kDouble:
   1.462 +        if (fValue.fDouble > (double)U_INT64_MAX) {
   1.463 +            status = U_INVALID_FORMAT_ERROR;
   1.464 +            return U_INT64_MAX;
   1.465 +        } else if (fValue.fDouble < (double)U_INT64_MIN) {
   1.466 +            status = U_INVALID_FORMAT_ERROR;
   1.467 +            return U_INT64_MIN;
   1.468 +        } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalNum != NULL) {
   1.469 +            int64_t val = fDecimalNum->getInt64();
   1.470 +            if (val != 0) {
   1.471 +                return val;
   1.472 +            } else {
   1.473 +                status = U_INVALID_FORMAT_ERROR;
   1.474 +                return fValue.fDouble > 0 ? U_INT64_MAX : U_INT64_MIN;
   1.475 +            }
   1.476 +        } else {
   1.477 +            return (int64_t)fValue.fDouble;
   1.478 +        } 
   1.479 +    case Formattable::kObject:
   1.480 +        if (fValue.fObject == NULL) {
   1.481 +            status = U_MEMORY_ALLOCATION_ERROR;
   1.482 +            return 0;
   1.483 +        }
   1.484 +        if (instanceOfMeasure(fValue.fObject)) {
   1.485 +            return ((const Measure*) fValue.fObject)->
   1.486 +                getNumber().getInt64(status);
   1.487 +        }
   1.488 +    default: 
   1.489 +        status = U_INVALID_FORMAT_ERROR;
   1.490 +        return 0;
   1.491 +    }
   1.492 +}
   1.493 +
   1.494 +// -------------------------------------
   1.495 +double
   1.496 +Formattable::getDouble(UErrorCode& status) const
   1.497 +{
   1.498 +    if (U_FAILURE(status)) {
   1.499 +        return 0;
   1.500 +    }
   1.501 +        
   1.502 +    switch (fType) {
   1.503 +    case Formattable::kLong: 
   1.504 +    case Formattable::kInt64: // loses precision
   1.505 +        return (double)fValue.fInt64;
   1.506 +    case Formattable::kDouble:
   1.507 +        return fValue.fDouble;
   1.508 +    case Formattable::kObject:
   1.509 +        if (fValue.fObject == NULL) {
   1.510 +            status = U_MEMORY_ALLOCATION_ERROR;
   1.511 +            return 0;
   1.512 +        }
   1.513 +        // TODO Later replace this with instanceof call
   1.514 +        if (instanceOfMeasure(fValue.fObject)) {
   1.515 +            return ((const Measure*) fValue.fObject)->
   1.516 +                getNumber().getDouble(status);
   1.517 +        }
   1.518 +    default: 
   1.519 +        status = U_INVALID_FORMAT_ERROR;
   1.520 +        return 0;
   1.521 +    }
   1.522 +}
   1.523 +
   1.524 +const UObject*
   1.525 +Formattable::getObject() const {
   1.526 +    return (fType == kObject) ? fValue.fObject : NULL;
   1.527 +}
   1.528 +
   1.529 +// -------------------------------------
   1.530 +// Sets the value to a double value d.
   1.531 +
   1.532 +void
   1.533 +Formattable::setDouble(double d)
   1.534 +{
   1.535 +    dispose();
   1.536 +    fType = kDouble;
   1.537 +    fValue.fDouble = d;
   1.538 +}
   1.539 +
   1.540 +// -------------------------------------
   1.541 +// Sets the value to a long value l.
   1.542 +
   1.543 +void
   1.544 +Formattable::setLong(int32_t l)
   1.545 +{
   1.546 +    dispose();
   1.547 +    fType = kLong;
   1.548 +    fValue.fInt64 = l;
   1.549 +}
   1.550 +
   1.551 +// -------------------------------------
   1.552 +// Sets the value to an int64 value ll.
   1.553 +
   1.554 +void
   1.555 +Formattable::setInt64(int64_t ll)
   1.556 +{
   1.557 +    dispose();
   1.558 +    fType = kInt64;
   1.559 +    fValue.fInt64 = ll;
   1.560 +}
   1.561 +
   1.562 +// -------------------------------------
   1.563 +// Sets the value to a Date instance d.
   1.564 +
   1.565 +void
   1.566 +Formattable::setDate(UDate d)
   1.567 +{
   1.568 +    dispose();
   1.569 +    fType = kDate;
   1.570 +    fValue.fDate = d;
   1.571 +}
   1.572 +
   1.573 +// -------------------------------------
   1.574 +// Sets the value to a string value stringToCopy.
   1.575 +
   1.576 +void
   1.577 +Formattable::setString(const UnicodeString& stringToCopy)
   1.578 +{
   1.579 +    dispose();
   1.580 +    fType = kString;
   1.581 +    fValue.fString = new UnicodeString(stringToCopy);
   1.582 +}
   1.583 +
   1.584 +// -------------------------------------
   1.585 +// Sets the value to an array of Formattable objects.
   1.586 +
   1.587 +void
   1.588 +Formattable::setArray(const Formattable* array, int32_t count)
   1.589 +{
   1.590 +    dispose();
   1.591 +    fType = kArray;
   1.592 +    fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
   1.593 +    fValue.fArrayAndCount.fCount = count;
   1.594 +}
   1.595 +
   1.596 +// -------------------------------------
   1.597 +// Adopts the stringToAdopt value.
   1.598 +
   1.599 +void
   1.600 +Formattable::adoptString(UnicodeString* stringToAdopt)
   1.601 +{
   1.602 +    dispose();
   1.603 +    fType = kString;
   1.604 +    fValue.fString = stringToAdopt;
   1.605 +}
   1.606 +
   1.607 +// -------------------------------------
   1.608 +// Adopts the array value and its count.
   1.609 +
   1.610 +void
   1.611 +Formattable::adoptArray(Formattable* array, int32_t count)
   1.612 +{
   1.613 +    dispose();
   1.614 +    fType = kArray;
   1.615 +    fValue.fArrayAndCount.fArray = array;
   1.616 +    fValue.fArrayAndCount.fCount = count;
   1.617 +}
   1.618 +
   1.619 +void
   1.620 +Formattable::adoptObject(UObject* objectToAdopt) {
   1.621 +    dispose();
   1.622 +    fType = kObject;
   1.623 +    fValue.fObject = objectToAdopt;
   1.624 +}
   1.625 +
   1.626 +// -------------------------------------
   1.627 +UnicodeString& 
   1.628 +Formattable::getString(UnicodeString& result, UErrorCode& status) const 
   1.629 +{
   1.630 +    if (fType != kString) {
   1.631 +        setError(status, U_INVALID_FORMAT_ERROR);
   1.632 +        result.setToBogus();
   1.633 +    } else {
   1.634 +        if (fValue.fString == NULL) {
   1.635 +            setError(status, U_MEMORY_ALLOCATION_ERROR);
   1.636 +        } else {
   1.637 +            result = *fValue.fString;
   1.638 +        }
   1.639 +    }
   1.640 +    return result;
   1.641 +}
   1.642 +
   1.643 +// -------------------------------------
   1.644 +const UnicodeString& 
   1.645 +Formattable::getString(UErrorCode& status) const 
   1.646 +{
   1.647 +    if (fType != kString) {
   1.648 +        setError(status, U_INVALID_FORMAT_ERROR);
   1.649 +        return *getBogus();
   1.650 +    }
   1.651 +    if (fValue.fString == NULL) {
   1.652 +        setError(status, U_MEMORY_ALLOCATION_ERROR);
   1.653 +        return *getBogus();
   1.654 +    }
   1.655 +    return *fValue.fString;
   1.656 +}
   1.657 +
   1.658 +// -------------------------------------
   1.659 +UnicodeString& 
   1.660 +Formattable::getString(UErrorCode& status) 
   1.661 +{
   1.662 +    if (fType != kString) {
   1.663 +        setError(status, U_INVALID_FORMAT_ERROR);
   1.664 +        return *getBogus();
   1.665 +    }
   1.666 +    if (fValue.fString == NULL) {
   1.667 +    	setError(status, U_MEMORY_ALLOCATION_ERROR);
   1.668 +    	return *getBogus();
   1.669 +    }
   1.670 +    return *fValue.fString;
   1.671 +}
   1.672 +
   1.673 +// -------------------------------------
   1.674 +const Formattable* 
   1.675 +Formattable::getArray(int32_t& count, UErrorCode& status) const 
   1.676 +{
   1.677 +    if (fType != kArray) {
   1.678 +        setError(status, U_INVALID_FORMAT_ERROR);
   1.679 +        count = 0;
   1.680 +        return NULL;
   1.681 +    }
   1.682 +    count = fValue.fArrayAndCount.fCount; 
   1.683 +    return fValue.fArrayAndCount.fArray;
   1.684 +}
   1.685 +
   1.686 +// -------------------------------------
   1.687 +// Gets the bogus string, ensures mondo bogosity.
   1.688 +
   1.689 +UnicodeString*
   1.690 +Formattable::getBogus() const 
   1.691 +{
   1.692 +    return (UnicodeString*)&fBogus; /* cast away const :-( */
   1.693 +}
   1.694 +
   1.695 +
   1.696 +// --------------------------------------
   1.697 +StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
   1.698 +    if (U_FAILURE(status)) {
   1.699 +        return "";
   1.700 +    }
   1.701 +    if (fDecimalStr != NULL) {
   1.702 +      return fDecimalStr->toStringPiece();
   1.703 +    }
   1.704 +
   1.705 +    CharString *decimalStr = internalGetCharString(status);
   1.706 +    if(decimalStr == NULL) {
   1.707 +      return ""; // getDecimalNumber returns "" for error cases
   1.708 +    } else {
   1.709 +      return decimalStr->toStringPiece();
   1.710 +    }
   1.711 +}
   1.712 +
   1.713 +CharString *Formattable::internalGetCharString(UErrorCode &status) {
   1.714 +    if(fDecimalStr == NULL) {
   1.715 +      if (fDecimalNum == NULL) {
   1.716 +        // No decimal number for the formattable yet.  Which means the value was
   1.717 +        // set directly by the user as an int, int64 or double.  If the value came
   1.718 +        // from parsing, or from the user setting a decimal number, fDecimalNum
   1.719 +        // would already be set.
   1.720 +        //
   1.721 +        fDecimalNum = new DigitList; // TODO: use internal digit list
   1.722 +        if (fDecimalNum == NULL) {
   1.723 +          status = U_MEMORY_ALLOCATION_ERROR;
   1.724 +          return NULL;
   1.725 +        }
   1.726 +
   1.727 +        switch (fType) {
   1.728 +        case kDouble:
   1.729 +          fDecimalNum->set(this->getDouble());
   1.730 +          break;
   1.731 +        case kLong:
   1.732 +          fDecimalNum->set(this->getLong());
   1.733 +          break;
   1.734 +        case kInt64:
   1.735 +          fDecimalNum->set(this->getInt64());
   1.736 +          break;
   1.737 +        default:
   1.738 +          // The formattable's value is not a numeric type.
   1.739 +          status = U_INVALID_STATE_ERROR;
   1.740 +          return NULL;
   1.741 +        }
   1.742 +      }
   1.743 +
   1.744 +      fDecimalStr = new CharString;
   1.745 +      if (fDecimalStr == NULL) {
   1.746 +        status = U_MEMORY_ALLOCATION_ERROR;
   1.747 +        return NULL;
   1.748 +      }
   1.749 +      fDecimalNum->getDecimal(*fDecimalStr, status);
   1.750 +    }
   1.751 +    return fDecimalStr;
   1.752 +}
   1.753 +
   1.754 +
   1.755 +DigitList *
   1.756 +Formattable::getInternalDigitList() {
   1.757 +  FmtStackData *stackData = (FmtStackData*)fStackData;
   1.758 +  if(fDecimalNum != &(stackData->stackDecimalNum)) {
   1.759 +    delete fDecimalNum;
   1.760 +    fDecimalNum = new (&(stackData->stackDecimalNum), kOnStack) DigitList();
   1.761 +  } else {
   1.762 +    fDecimalNum->clear();
   1.763 +  }
   1.764 +  return fDecimalNum;
   1.765 +}
   1.766 +
   1.767 +// ---------------------------------------
   1.768 +void
   1.769 +Formattable::adoptDigitList(DigitList *dl) {
   1.770 +  if(fDecimalNum==dl) {
   1.771 +    fDecimalNum = NULL; // don't delete
   1.772 +  }
   1.773 +  dispose();
   1.774 +
   1.775 +  fDecimalNum = dl;
   1.776 +
   1.777 +  if(dl==NULL) { // allow adoptDigitList(NULL) to clear
   1.778 +    return;
   1.779 +  }
   1.780 +
   1.781 +    // Set the value into the Union of simple type values.
   1.782 +    // Cannot use the set() functions because they would delete the fDecimalNum value,
   1.783 +
   1.784 +    if (fDecimalNum->fitsIntoLong(FALSE)) {
   1.785 +        fType = kLong;
   1.786 +        fValue.fInt64 = fDecimalNum->getLong();
   1.787 +    } else if (fDecimalNum->fitsIntoInt64(FALSE)) {
   1.788 +        fType = kInt64;
   1.789 +        fValue.fInt64 = fDecimalNum->getInt64();
   1.790 +    } else {
   1.791 +        fType = kDouble;
   1.792 +        fValue.fDouble = fDecimalNum->getDouble();
   1.793 +    }
   1.794 +}
   1.795 +
   1.796 +
   1.797 +// ---------------------------------------
   1.798 +void
   1.799 +Formattable::setDecimalNumber(const StringPiece &numberString, UErrorCode &status) {
   1.800 +    if (U_FAILURE(status)) {
   1.801 +        return;
   1.802 +    }
   1.803 +    dispose();
   1.804 +
   1.805 +    // Copy the input string and nul-terminate it.
   1.806 +    //    The decNumber library requires nul-terminated input.  StringPiece input
   1.807 +    //    is not guaranteed nul-terminated.  Too bad.
   1.808 +    //    CharString automatically adds the nul.
   1.809 +    DigitList *dnum = new DigitList(); // TODO: use getInternalDigitList
   1.810 +    if (dnum == NULL) {
   1.811 +        status = U_MEMORY_ALLOCATION_ERROR;
   1.812 +        return;
   1.813 +    }
   1.814 +    dnum->set(CharString(numberString, status).toStringPiece(), status);
   1.815 +    if (U_FAILURE(status)) {
   1.816 +        delete dnum;
   1.817 +        return;   // String didn't contain a decimal number.
   1.818 +    }
   1.819 +    adoptDigitList(dnum);
   1.820 +
   1.821 +    // Note that we do not hang on to the caller's input string.
   1.822 +    // If we are asked for the string, we will regenerate one from fDecimalNum.
   1.823 +}
   1.824 +
   1.825 +#if 0
   1.826 +//----------------------------------------------------
   1.827 +// console I/O
   1.828 +//----------------------------------------------------
   1.829 +#ifdef _DEBUG
   1.830 +
   1.831 +#include <iostream>
   1.832 +using namespace std;
   1.833 +
   1.834 +#include "unicode/datefmt.h"
   1.835 +#include "unistrm.h"
   1.836 +
   1.837 +class FormattableStreamer /* not : public UObject because all methods are static */ {
   1.838 +public:
   1.839 +    static void streamOut(ostream& stream, const Formattable& obj);
   1.840 +
   1.841 +private:
   1.842 +    FormattableStreamer() {} // private - forbid instantiation
   1.843 +};
   1.844 +
   1.845 +// This is for debugging purposes only.  This will send a displayable
   1.846 +// form of the Formattable object to the output stream.
   1.847 +
   1.848 +void
   1.849 +FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
   1.850 +{
   1.851 +    static DateFormat *defDateFormat = 0;
   1.852 +
   1.853 +    UnicodeString buffer;
   1.854 +    switch(obj.getType()) {
   1.855 +        case Formattable::kDate : 
   1.856 +            // Creates a DateFormat instance for formatting the
   1.857 +            // Date instance.
   1.858 +            if (defDateFormat == 0) {
   1.859 +                defDateFormat = DateFormat::createInstance();
   1.860 +            }
   1.861 +            defDateFormat->format(obj.getDate(), buffer);
   1.862 +            stream << buffer;
   1.863 +            break;
   1.864 +        case Formattable::kDouble :
   1.865 +            // Output the double as is.
   1.866 +            stream << obj.getDouble() << 'D';
   1.867 +            break;
   1.868 +        case Formattable::kLong :
   1.869 +            // Output the double as is.
   1.870 +            stream << obj.getLong() << 'L';
   1.871 +            break;
   1.872 +        case Formattable::kString:
   1.873 +            // Output the double as is.  Please see UnicodeString console
   1.874 +            // I/O routine for more details.
   1.875 +            stream << '"' << obj.getString(buffer) << '"';
   1.876 +            break;
   1.877 +        case Formattable::kArray:
   1.878 +            int32_t i, count;
   1.879 +            const Formattable* array;
   1.880 +            array = obj.getArray(count);
   1.881 +            stream << '[';
   1.882 +            // Recursively calling the console I/O routine for each element in the array.
   1.883 +            for (i=0; i<count; ++i) {
   1.884 +                FormattableStreamer::streamOut(stream, array[i]);
   1.885 +                stream << ( (i==(count-1)) ? "" : ", " );
   1.886 +            }
   1.887 +            stream << ']';
   1.888 +            break;
   1.889 +        default:
   1.890 +            // Not a recognizable Formattable object.
   1.891 +            stream << "INVALID_Formattable";
   1.892 +    }
   1.893 +    stream.flush();
   1.894 +}
   1.895 +#endif
   1.896 +
   1.897 +#endif
   1.898 +
   1.899 +U_NAMESPACE_END
   1.900 +
   1.901 +/* ---- UFormattable implementation ---- */
   1.902 +
   1.903 +U_NAMESPACE_USE
   1.904 +
   1.905 +U_DRAFT UFormattable* U_EXPORT2
   1.906 +ufmt_open(UErrorCode *status) {
   1.907 +  if( U_FAILURE(*status) ) {
   1.908 +    return NULL;
   1.909 +  }
   1.910 +  UFormattable *fmt = (new Formattable())->toUFormattable();
   1.911 +
   1.912 +  if( fmt == NULL ) {
   1.913 +    *status = U_MEMORY_ALLOCATION_ERROR;
   1.914 +  }
   1.915 +  return fmt;
   1.916 +}
   1.917 +
   1.918 +U_DRAFT void U_EXPORT2
   1.919 +ufmt_close(UFormattable *fmt) {
   1.920 +  Formattable *obj = Formattable::fromUFormattable(fmt);
   1.921 +
   1.922 +  delete obj;
   1.923 +}
   1.924 +
   1.925 +U_INTERNAL UFormattableType U_EXPORT2
   1.926 +ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
   1.927 +  if(U_FAILURE(*status)) {
   1.928 +    return (UFormattableType)UFMT_COUNT;
   1.929 +  }
   1.930 +  const Formattable *obj = Formattable::fromUFormattable(fmt);
   1.931 +  return (UFormattableType)obj->getType();
   1.932 +}
   1.933 +
   1.934 +
   1.935 +U_INTERNAL UBool U_EXPORT2
   1.936 +ufmt_isNumeric(const UFormattable *fmt) {
   1.937 +  const Formattable *obj = Formattable::fromUFormattable(fmt);
   1.938 +  return obj->isNumeric();
   1.939 +}
   1.940 +
   1.941 +U_DRAFT UDate U_EXPORT2
   1.942 +ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
   1.943 +  const Formattable *obj = Formattable::fromUFormattable(fmt);
   1.944 +
   1.945 +  return obj->getDate(*status);
   1.946 +}
   1.947 +
   1.948 +U_DRAFT double U_EXPORT2
   1.949 +ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
   1.950 +  Formattable *obj = Formattable::fromUFormattable(fmt);
   1.951 +
   1.952 +  return obj->getDouble(*status);
   1.953 +}
   1.954 +
   1.955 +U_DRAFT int32_t U_EXPORT2
   1.956 +ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
   1.957 +  Formattable *obj = Formattable::fromUFormattable(fmt);
   1.958 +
   1.959 +  return obj->getLong(*status);
   1.960 +}
   1.961 +
   1.962 +
   1.963 +U_DRAFT const void *U_EXPORT2
   1.964 +ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
   1.965 +  const Formattable *obj = Formattable::fromUFormattable(fmt);
   1.966 +
   1.967 +  const void *ret = obj->getObject();
   1.968 +  if( ret==NULL &&
   1.969 +      (obj->getType() != Formattable::kObject) &&
   1.970 +      U_SUCCESS( *status )) {
   1.971 +    *status = U_INVALID_FORMAT_ERROR;
   1.972 +  }
   1.973 +  return ret;
   1.974 +}
   1.975 +
   1.976 +U_DRAFT const UChar* U_EXPORT2
   1.977 +ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
   1.978 +  Formattable *obj = Formattable::fromUFormattable(fmt);
   1.979 +
   1.980 +  // avoid bogosity by checking the type first.
   1.981 +  if( obj->getType() != Formattable::kString ) {
   1.982 +    if( U_SUCCESS(*status) ){
   1.983 +      *status = U_INVALID_FORMAT_ERROR;
   1.984 +    }
   1.985 +    return NULL;
   1.986 +  }
   1.987 +
   1.988 +  // This should return a valid string
   1.989 +  UnicodeString &str = obj->getString(*status);
   1.990 +  if( U_SUCCESS(*status) && len != NULL ) {
   1.991 +    *len = str.length();
   1.992 +  }
   1.993 +  return str.getTerminatedBuffer();
   1.994 +}
   1.995 +
   1.996 +U_DRAFT int32_t U_EXPORT2
   1.997 +ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
   1.998 +  const Formattable *obj = Formattable::fromUFormattable(fmt);
   1.999 +
  1.1000 +  int32_t count;
  1.1001 +  (void)obj->getArray(count, *status);
  1.1002 +  return count;
  1.1003 +}
  1.1004 +
  1.1005 +U_DRAFT UFormattable * U_EXPORT2
  1.1006 +ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
  1.1007 +  Formattable *obj = Formattable::fromUFormattable(fmt);
  1.1008 +  int32_t count;
  1.1009 +  (void)obj->getArray(count, *status);
  1.1010 +  if(U_FAILURE(*status)) {
  1.1011 +    return NULL;
  1.1012 +  } else if(n<0 || n>=count) {
  1.1013 +    setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
  1.1014 +    return NULL;
  1.1015 +  } else {
  1.1016 +    return (*obj)[n].toUFormattable(); // returns non-const Formattable
  1.1017 +  }
  1.1018 +}
  1.1019 +
  1.1020 +U_DRAFT const char * U_EXPORT2
  1.1021 +ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
  1.1022 +  if(U_FAILURE(*status)) {
  1.1023 +    return "";
  1.1024 +  }
  1.1025 +  Formattable *obj = Formattable::fromUFormattable(fmt);
  1.1026 +  CharString *charString = obj->internalGetCharString(*status);
  1.1027 +  if(U_FAILURE(*status)) {
  1.1028 +    return "";
  1.1029 +  }
  1.1030 +  if(charString == NULL) {
  1.1031 +    *status = U_MEMORY_ALLOCATION_ERROR;
  1.1032 +    return "";
  1.1033 +  } else {
  1.1034 +    if(len!=NULL) {
  1.1035 +      *len = charString->length();
  1.1036 +    }
  1.1037 +    return charString->data();
  1.1038 +  }
  1.1039 +}
  1.1040 +
  1.1041 +U_DRAFT int64_t U_EXPORT2
  1.1042 +ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
  1.1043 +  Formattable *obj = Formattable::fromUFormattable(fmt);
  1.1044 +  return obj->getInt64(*status);
  1.1045 +}
  1.1046 +
  1.1047 +#endif /* #if !UCONFIG_NO_FORMATTING */
  1.1048 +
  1.1049 +//eof

mercurial