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