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