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