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