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 34U_NAMESPACE_BEGIN 35 36UOBJECT_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. 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 // 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 */ 75static 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 */ 89static 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// 99void 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 111Formattable::Formattable() { 112 init(); 113} 114 115// ------------------------------------- 116// Creates a formattable object with a Date instance. 117 118Formattable::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 128Formattable::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 138Formattable::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 147Formattable::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 157Formattable::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 166Formattable::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 177Formattable::Formattable(UnicodeString* stringToAdopt) 178{ 179 init(); 180 fType = kString; 181 fValue.fString = stringToAdopt; 182} 183 184Formattable::Formattable(UObject* objectToAdopt) 185{ 186 init(); 187 fType = kObject; 188 fValue.fObject = objectToAdopt; 189} 190 191// ------------------------------------- 192 193Formattable::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 206Formattable::Formattable(const Formattable &source) 207 : UObject(*this) 208{ 209 init(); 210 *this = source; 211} 212 213// ------------------------------------- 214// assignment operator 215 216Formattable& 217Formattable::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 273UBool 274Formattable::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 327Formattable::~Formattable() 328{ 329 dispose(); 330} 331 332// ------------------------------------- 333 334void 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 359Formattable * 360Formattable::clone() const { 361 return new Formattable(*this); 362} 363 364// ------------------------------------- 365// Gets the data type of this Formattable object. 366Formattable::Type 367Formattable::getType() const 368{ 369 return fType; 370} 371 372UBool 373Formattable::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// ------------------------------------- 385int32_t 386//Formattable::getLong(UErrorCode* status) const 387Formattable::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// ------------------------------------- 433int64_t 434Formattable::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// ------------------------------------- 471double 472Formattable::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 500const UObject* 501Formattable::getObject() const { 502 return (fType == kObject) ? fValue.fObject : NULL; 503} 504 505// ------------------------------------- 506// Sets the value to a double value d. 507 508void 509Formattable::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 519void 520Formattable::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 530void 531Formattable::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 541void 542Formattable::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 552void 553Formattable::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 563void 564Formattable::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 575void 576Formattable::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 586void 587Formattable::adoptArray(Formattable* array, int32_t count) 588{ 589 dispose(); 590 fType = kArray; 591 fValue.fArrayAndCount.fArray = array; 592 fValue.fArrayAndCount.fCount = count; 593} 594 595void 596Formattable::adoptObject(UObject* objectToAdopt) { 597 dispose(); 598 fType = kObject; 599 fValue.fObject = objectToAdopt; 600} 601 602// ------------------------------------- 603UnicodeString& 604Formattable::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// ------------------------------------- 620const UnicodeString& 621Formattable::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// ------------------------------------- 635UnicodeString& 636Formattable::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// ------------------------------------- 650const Formattable* 651Formattable::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 665UnicodeString* 666Formattable::getBogus() const 667{ 668 return (UnicodeString*)&fBogus; /* cast away const :-( */ 669} 670 671 672// -------------------------------------- 673StringPiece 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// --------------------------------------- 723void 724Formattable::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// --------------------------------------- 746void 747Formattable::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> 786using 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 794class FormattableStreamer /* not : public UObject because all methods are static */ { 795public: 796 static void streamOut(ostream& stream, const Formattable& obj); 797 798private: 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 805void 806FormattableStreamer::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 856U_NAMESPACE_END 857 858#endif /* #if !UCONFIG_NO_FORMATTING */ 859 860//eof 861