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 "charstr.h" 25 #include "cmemory.h" 26 #include "cstring.h" 27 #include "decNumber.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==. To 42 // work around this, I implement some simple inlines here. Later 43 // these can be modified or removed. [alan] 44 45 // NOTE: These inlines assume that all fObjects are in fact instances 46 // of the Measure class, which is true as of 3.0. [alan] 47 48 // Return TRUE if *a == *b. 49 static inline UBool objectEquals(const UObject* a, const UObject* b) { 50 // LATER: return *a == *b; 51 return *((const Measure*) a) == *((const Measure*) b); 52 } 53 54 // Return a clone of *a. 55 static inline UObject* objectClone(const UObject* a) { 56 // LATER: return a->clone(); 57 return ((const Measure*) a)->clone(); 58 } 59 60 // Return TRUE if *a is an instance of Measure. 61 static inline UBool instanceOfMeasure(const UObject* a) { 62 return dynamic_cast<const Measure*>(a) != NULL; 63 } 64 65 /** 66 * Creates a new Formattable array and copies the values from the specified 67 * original. 68 * @param array the original array 69 * @param count the original array count 70 * @return the new Formattable array. 71 */ 72 static Formattable* createArrayCopy(const Formattable* array, int32_t count) { 73 Formattable *result = new Formattable[count]; 74 if (result != NULL) { 75 for (int32_t i=0; i<count; ++i) 76 result[i] = array[i]; // Don't memcpy! 77 } 78 return result; 79 } 80 81 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. 82 83 /** 84 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode. 85 */ 86 static void setError(UErrorCode& ec, UErrorCode err) { 87 if (U_SUCCESS(ec)) { 88 ec = err; 89 } 90 } 91 92 // 93 // Common initialization code, shared by constructors. 94 // Put everything into a known state. 95 // 96 void Formattable::init() { 97 fValue.fInt64 = 0; 98 fType = kLong; 99 fDecimalStr = NULL; 100 fDecimalNum = NULL; 101 fBogus.setToBogus(); 102 } 103 104 // ------------------------------------- 105 // default constructor. 106 // Creates a formattable object with a long value 0. 107 108 Formattable::Formattable() { 109 init(); 110 } 111 112 // ------------------------------------- 113 // Creates a formattable object with a Date instance. 114 115 Formattable::Formattable(UDate date, ISDATE /*isDate*/) 116 { 117 init(); 118 fType = kDate; 119 fValue.fDate = date; 120 } 121 122 // ------------------------------------- 123 // Creates a formattable object with a double value. 124 125 Formattable::Formattable(double value) 126 { 127 init(); 128 fType = kDouble; 129 fValue.fDouble = value; 130 } 131 132 // ------------------------------------- 133 // Creates a formattable object with an int32_t value. 134 135 Formattable::Formattable(int32_t value) 136 { 137 init(); 138 fValue.fInt64 = value; 139 } 140 141 // ------------------------------------- 142 // Creates a formattable object with an int64_t value. 143 144 Formattable::Formattable(int64_t value) 145 { 146 init(); 147 fType = kInt64; 148 fValue.fInt64 = value; 149 } 150 151 // ------------------------------------- 152 // Creates a formattable object with a decimal number value from a string. 153 154 Formattable::Formattable(const StringPiece &number, UErrorCode &status) { 155 init(); 156 setDecimalNumber(number, status); 157 } 158 159 160 // ------------------------------------- 161 // Creates a formattable object with a UnicodeString instance. 162 163 Formattable::Formattable(const UnicodeString& stringToCopy) 164 { 165 init(); 166 fType = kString; 167 fValue.fString = new UnicodeString(stringToCopy); 168 } 169 170 // ------------------------------------- 171 // Creates a formattable object with a UnicodeString* value. 172 // (adopting symantics) 173 174 Formattable::Formattable(UnicodeString* stringToAdopt) 175 { 176 init(); 177 fType = kString; 178 fValue.fString = stringToAdopt; 179 } 180 181 Formattable::Formattable(UObject* objectToAdopt) 182 { 183 init(); 184 fType = kObject; 185 fValue.fObject = objectToAdopt; 186 } 187 188 // ------------------------------------- 189 190 Formattable::Formattable(const Formattable* arrayToCopy, int32_t count) 191 : UObject(), fType(kArray) 192 { 193 init(); 194 fType = kArray; 195 fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count); 196 fValue.fArrayAndCount.fCount = count; 197 } 198 199 // ------------------------------------- 200 // copy constructor 201 202 #ifdef U_WINODWS 203 #pragram warning(disable: 4996) 204 #endif 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 CharString(*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->toStringPiece(); 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 CharString; 711 if (fDecimalStr == NULL) { 712 status = U_MEMORY_ALLOCATION_ERROR; 713 return ""; 714 } 715 fDecimalNum->getDecimal(*fDecimalStr, status); 716 717 return fDecimalStr->toStringPiece(); 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 // CharString automatically adds the nul. 757 DigitList *dnum = new DigitList(); 758 if (dnum == NULL) { 759 status = U_MEMORY_ALLOCATION_ERROR; 760 return; 761 } 762 dnum->set(CharString(numberString, status).toStringPiece(), status); 763 if (U_FAILURE(status)) { 764 delete dnum; 765 return; // String didn't contain a decimal number. 766 } 767 adoptDigitList(dnum); 768 769 // Note that we do not hang on to the caller's input string. 770 // If we are asked for the string, we will regenerate one from fDecimalNum. 771 } 772 773 #if 0 774 //---------------------------------------------------- 775 // console I/O 776 //---------------------------------------------------- 777 #ifdef _DEBUG 778 779 #if U_IOSTREAM_SOURCE >= 199711 780 #include <iostream> 781 using namespace std; 782 #elif U_IOSTREAM_SOURCE >= 198506 783 #include <iostream.h> 784 #endif 785 786 #include "unicode/datefmt.h" 787 #include "unistrm.h" 788 789 class FormattableStreamer /* not : public UObject because all methods are static */ { 790 public: 791 static void streamOut(ostream& stream, const Formattable& obj); 792 793 private: 794 FormattableStreamer() {} // private - forbid instantiation 795 }; 796 797 // This is for debugging purposes only. This will send a displayable 798 // form of the Formattable object to the output stream. 799 800 void 801 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj) 802 { 803 static DateFormat *defDateFormat = 0; 804 805 UnicodeString buffer; 806 switch(obj.getType()) { 807 case Formattable::kDate : 808 // Creates a DateFormat instance for formatting the 809 // Date instance. 810 if (defDateFormat == 0) { 811 defDateFormat = DateFormat::createInstance(); 812 } 813 defDateFormat->format(obj.getDate(), buffer); 814 stream << buffer; 815 break; 816 case Formattable::kDouble : 817 // Output the double as is. 818 stream << obj.getDouble() << 'D'; 819 break; 820 case Formattable::kLong : 821 // Output the double as is. 822 stream << obj.getLong() << 'L'; 823 break; 824 case Formattable::kString: 825 // Output the double as is. Please see UnicodeString console 826 // I/O routine for more details. 827 stream << '"' << obj.getString(buffer) << '"'; 828 break; 829 case Formattable::kArray: 830 int32_t i, count; 831 const Formattable* array; 832 array = obj.getArray(count); 833 stream << '['; 834 // Recursively calling the console I/O routine for each element in the array. 835 for (i=0; i<count; ++i) { 836 FormattableStreamer::streamOut(stream, array[i]); 837 stream << ( (i==(count-1)) ? "" : ", " ); 838 } 839 stream << ']'; 840 break; 841 default: 842 // Not a recognizable Formattable object. 843 stream << "INVALID_Formattable"; 844 } 845 stream.flush(); 846 } 847 #endif 848 849 #endif 850 851 U_NAMESPACE_END 852 853 #endif /* #if !UCONFIG_NO_FORMATTING */ 854 855 //eof 856