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