fmtable.cpp (28109B)
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 "cmemory.h" 30 #include "cstring.h" 31 #include "fixedstring.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) == *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) != nullptr; 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 != nullptr) { 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 = nullptr; 108 fDecimalQuantity = nullptr; 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 semantics) 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 if (source.fDecimalQuantity != nullptr) { 262 fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity); 263 } 264 if (source.fDecimalStr != nullptr) { 265 fDecimalStr = new FixedString(*source.fDecimalStr); 266 } 267 } 268 return *this; 269 } 270 271 // ------------------------------------- 272 273 bool 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 bool 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 == nullptr || that.fValue.fObject == nullptr) { 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 354 delete fDecimalStr; 355 fDecimalStr = nullptr; 356 357 delete fDecimalQuantity; 358 fDecimalQuantity = nullptr; 359 } 360 361 Formattable * 362 Formattable::clone() const { 363 return new Formattable(*this); 364 } 365 366 // ------------------------------------- 367 // Gets the data type of this Formattable object. 368 Formattable::Type 369 Formattable::getType() const 370 { 371 return fType; 372 } 373 374 UBool 375 Formattable::isNumeric() const { 376 switch (fType) { 377 case kDouble: 378 case kLong: 379 case kInt64: 380 return true; 381 default: 382 return false; 383 } 384 } 385 386 // ------------------------------------- 387 int32_t 388 //Formattable::getLong(UErrorCode* status) const 389 Formattable::getLong(UErrorCode& status) const 390 { 391 if (U_FAILURE(status)) { 392 return 0; 393 } 394 395 switch (fType) { 396 case Formattable::kLong: 397 return static_cast<int32_t>(fValue.fInt64); 398 case Formattable::kInt64: 399 if (fValue.fInt64 > INT32_MAX) { 400 status = U_INVALID_FORMAT_ERROR; 401 return INT32_MAX; 402 } else if (fValue.fInt64 < INT32_MIN) { 403 status = U_INVALID_FORMAT_ERROR; 404 return INT32_MIN; 405 } else { 406 return static_cast<int32_t>(fValue.fInt64); 407 } 408 case Formattable::kDouble: 409 if (fValue.fDouble > INT32_MAX) { 410 status = U_INVALID_FORMAT_ERROR; 411 return INT32_MAX; 412 } else if (fValue.fDouble < INT32_MIN) { 413 status = U_INVALID_FORMAT_ERROR; 414 return INT32_MIN; 415 } else { 416 return static_cast<int32_t>(fValue.fDouble); // loses fraction 417 } 418 case Formattable::kObject: 419 if (fValue.fObject == nullptr) { 420 status = U_MEMORY_ALLOCATION_ERROR; 421 return 0; 422 } 423 // TODO Later replace this with instanceof call 424 if (instanceOfMeasure(fValue.fObject)) { 425 return ((const Measure*) fValue.fObject)-> 426 getNumber().getLong(status); 427 } 428 U_FALLTHROUGH; 429 default: 430 status = U_INVALID_FORMAT_ERROR; 431 return 0; 432 } 433 } 434 435 // ------------------------------------- 436 // Maximum int that can be represented exactly in a double. (53 bits) 437 // Larger ints may be rounded to a near-by value as not all are representable. 438 // TODO: move this constant elsewhere, possibly configure it for different 439 // floating point formats, if any non-standard ones are still in use. 440 static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL; 441 442 int64_t 443 Formattable::getInt64(UErrorCode& status) const 444 { 445 if (U_FAILURE(status)) { 446 return 0; 447 } 448 449 switch (fType) { 450 case Formattable::kLong: 451 case Formattable::kInt64: 452 return fValue.fInt64; 453 case Formattable::kDouble: 454 if (fValue.fDouble > static_cast<double>(U_INT64_MAX)) { 455 status = U_INVALID_FORMAT_ERROR; 456 return U_INT64_MAX; 457 } else if (fValue.fDouble < static_cast<double>(U_INT64_MIN)) { 458 status = U_INVALID_FORMAT_ERROR; 459 return U_INT64_MIN; 460 } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalQuantity != nullptr) { 461 if (fDecimalQuantity->fitsInLong(true)) { 462 return fDecimalQuantity->toLong(); 463 } else { 464 // Unexpected 465 status = U_INVALID_FORMAT_ERROR; 466 return fDecimalQuantity->isNegative() ? U_INT64_MIN : U_INT64_MAX; 467 } 468 } else { 469 return static_cast<int64_t>(fValue.fDouble); 470 } 471 case Formattable::kObject: 472 if (fValue.fObject == nullptr) { 473 status = U_MEMORY_ALLOCATION_ERROR; 474 return 0; 475 } 476 if (instanceOfMeasure(fValue.fObject)) { 477 return ((const Measure*) fValue.fObject)-> 478 getNumber().getInt64(status); 479 } 480 U_FALLTHROUGH; 481 default: 482 status = U_INVALID_FORMAT_ERROR; 483 return 0; 484 } 485 } 486 487 // ------------------------------------- 488 double 489 Formattable::getDouble(UErrorCode& status) const 490 { 491 if (U_FAILURE(status)) { 492 return 0; 493 } 494 495 switch (fType) { 496 case Formattable::kLong: 497 case Formattable::kInt64: // loses precision 498 return static_cast<double>(fValue.fInt64); 499 case Formattable::kDouble: 500 return fValue.fDouble; 501 case Formattable::kObject: 502 if (fValue.fObject == nullptr) { 503 status = U_MEMORY_ALLOCATION_ERROR; 504 return 0; 505 } 506 // TODO Later replace this with instanceof call 507 if (instanceOfMeasure(fValue.fObject)) { 508 return ((const Measure*) fValue.fObject)-> 509 getNumber().getDouble(status); 510 } 511 U_FALLTHROUGH; 512 default: 513 status = U_INVALID_FORMAT_ERROR; 514 return 0; 515 } 516 } 517 518 const UObject* 519 Formattable::getObject() const { 520 return (fType == kObject) ? fValue.fObject : nullptr; 521 } 522 523 // ------------------------------------- 524 // Sets the value to a double value d. 525 526 void 527 Formattable::setDouble(double d) 528 { 529 dispose(); 530 fType = kDouble; 531 fValue.fDouble = d; 532 } 533 534 // ------------------------------------- 535 // Sets the value to a long value l. 536 537 void 538 Formattable::setLong(int32_t l) 539 { 540 dispose(); 541 fType = kLong; 542 fValue.fInt64 = l; 543 } 544 545 // ------------------------------------- 546 // Sets the value to an int64 value ll. 547 548 void 549 Formattable::setInt64(int64_t ll) 550 { 551 dispose(); 552 fType = kInt64; 553 fValue.fInt64 = ll; 554 } 555 556 // ------------------------------------- 557 // Sets the value to a Date instance d. 558 559 void 560 Formattable::setDate(UDate d) 561 { 562 dispose(); 563 fType = kDate; 564 fValue.fDate = d; 565 } 566 567 // ------------------------------------- 568 // Sets the value to a string value stringToCopy. 569 570 void 571 Formattable::setString(const UnicodeString& stringToCopy) 572 { 573 dispose(); 574 fType = kString; 575 fValue.fString = new UnicodeString(stringToCopy); 576 } 577 578 // ------------------------------------- 579 // Sets the value to an array of Formattable objects. 580 581 void 582 Formattable::setArray(const Formattable* array, int32_t count) 583 { 584 dispose(); 585 fType = kArray; 586 fValue.fArrayAndCount.fArray = createArrayCopy(array, count); 587 fValue.fArrayAndCount.fCount = count; 588 } 589 590 // ------------------------------------- 591 // Adopts the stringToAdopt value. 592 593 void 594 Formattable::adoptString(UnicodeString* stringToAdopt) 595 { 596 dispose(); 597 fType = kString; 598 fValue.fString = stringToAdopt; 599 } 600 601 // ------------------------------------- 602 // Adopts the array value and its count. 603 604 void 605 Formattable::adoptArray(Formattable* array, int32_t count) 606 { 607 dispose(); 608 fType = kArray; 609 fValue.fArrayAndCount.fArray = array; 610 fValue.fArrayAndCount.fCount = count; 611 } 612 613 void 614 Formattable::adoptObject(UObject* objectToAdopt) { 615 dispose(); 616 fType = kObject; 617 fValue.fObject = objectToAdopt; 618 } 619 620 // ------------------------------------- 621 UnicodeString& 622 Formattable::getString(UnicodeString& result, UErrorCode& status) const 623 { 624 if (fType != kString) { 625 setError(status, U_INVALID_FORMAT_ERROR); 626 result.setToBogus(); 627 } else { 628 if (fValue.fString == nullptr) { 629 setError(status, U_MEMORY_ALLOCATION_ERROR); 630 } else { 631 result = *fValue.fString; 632 } 633 } 634 return result; 635 } 636 637 // ------------------------------------- 638 const UnicodeString& 639 Formattable::getString(UErrorCode& status) const 640 { 641 if (fType != kString) { 642 setError(status, U_INVALID_FORMAT_ERROR); 643 return *getBogus(); 644 } 645 if (fValue.fString == nullptr) { 646 setError(status, U_MEMORY_ALLOCATION_ERROR); 647 return *getBogus(); 648 } 649 return *fValue.fString; 650 } 651 652 // ------------------------------------- 653 UnicodeString& 654 Formattable::getString(UErrorCode& status) 655 { 656 if (fType != kString) { 657 setError(status, U_INVALID_FORMAT_ERROR); 658 return *getBogus(); 659 } 660 if (fValue.fString == nullptr) { 661 setError(status, U_MEMORY_ALLOCATION_ERROR); 662 return *getBogus(); 663 } 664 return *fValue.fString; 665 } 666 667 // ------------------------------------- 668 const Formattable* 669 Formattable::getArray(int32_t& count, UErrorCode& status) const 670 { 671 if (fType != kArray) { 672 setError(status, U_INVALID_FORMAT_ERROR); 673 count = 0; 674 return nullptr; 675 } 676 count = fValue.fArrayAndCount.fCount; 677 return fValue.fArrayAndCount.fArray; 678 } 679 680 // ------------------------------------- 681 // Gets the bogus string, ensures mondo bogosity. 682 683 UnicodeString* 684 Formattable::getBogus() const 685 { 686 return const_cast<UnicodeString*>(&fBogus); /* cast away const :-( */ 687 } 688 689 690 // -------------------------------------- 691 StringPiece Formattable::getDecimalNumber(UErrorCode &status) { 692 if (U_FAILURE(status)) { 693 return ""; 694 } 695 if (fDecimalStr != nullptr) { 696 return fDecimalStr->data(); 697 } 698 699 FixedString* decimalStr = internalGetFixedString(status); 700 if(decimalStr == nullptr) { 701 return ""; // getDecimalNumber returns "" for error cases 702 } else { 703 return decimalStr->data(); 704 } 705 } 706 707 FixedString *Formattable::internalGetFixedString(UErrorCode &status) { 708 if(fDecimalStr == nullptr) { 709 if (fDecimalQuantity == nullptr) { 710 // No decimal number for the formattable yet. Which means the value was 711 // set directly by the user as an int, int64 or double. If the value came 712 // from parsing, or from the user setting a decimal number, fDecimalNum 713 // would already be set. 714 // 715 LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status); 716 if (U_FAILURE(status)) { return nullptr; } 717 populateDecimalQuantity(*dq, status); 718 if (U_FAILURE(status)) { return nullptr; } 719 fDecimalQuantity = dq.orphan(); 720 } 721 722 fDecimalStr = new FixedString(); 723 if (fDecimalStr == nullptr) { 724 status = U_MEMORY_ALLOCATION_ERROR; 725 return nullptr; 726 } 727 // Older ICUs called uprv_decNumberToString here, which is not exactly the same as 728 // DecimalQuantity::toScientificString(). The biggest difference is that uprv_decNumberToString does 729 // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?). 730 if (fDecimalQuantity->isInfinite()) { 731 *fDecimalStr = "Infinity"; 732 } else if (fDecimalQuantity->isNaN()) { 733 *fDecimalStr = "NaN"; 734 } else if (fDecimalQuantity->isZeroish()) { 735 *fDecimalStr = "0"; 736 } else if (fType==kLong || fType==kInt64 || // use toPlainString for integer types 737 (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5)) { 738 copyInvariantChars(fDecimalQuantity->toPlainString(), *fDecimalStr, status); 739 } else { 740 copyInvariantChars(fDecimalQuantity->toScientificString(), *fDecimalStr, status); 741 } 742 if (U_SUCCESS(status) && fDecimalStr->isEmpty()) { 743 status = U_MEMORY_ALLOCATION_ERROR; 744 return nullptr; 745 } 746 } 747 return fDecimalStr; 748 } 749 750 void 751 Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const { 752 if (fDecimalQuantity != nullptr) { 753 output = *fDecimalQuantity; 754 return; 755 } 756 757 switch (fType) { 758 case kDouble: 759 output.setToDouble(this->getDouble()); 760 output.roundToInfinity(); 761 break; 762 case kLong: 763 output.setToInt(this->getLong()); 764 break; 765 case kInt64: 766 output.setToLong(this->getInt64()); 767 break; 768 default: 769 // The formattable's value is not a numeric type. 770 status = U_INVALID_STATE_ERROR; 771 } 772 } 773 774 // --------------------------------------- 775 void 776 Formattable::adoptDecimalQuantity(DecimalQuantity *dq) { 777 delete fDecimalQuantity; 778 fDecimalQuantity = dq; 779 if (dq == nullptr) { // allow adoptDigitList(nullptr) to clear 780 return; 781 } 782 783 // Set the value into the Union of simple type values. 784 // Cannot use the set() functions because they would delete the fDecimalNum value. 785 if (fDecimalQuantity->fitsInLong()) { 786 fValue.fInt64 = fDecimalQuantity->toLong(); 787 if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) { 788 fType = kLong; 789 } else { 790 fType = kInt64; 791 } 792 } else { 793 fType = kDouble; 794 fValue.fDouble = fDecimalQuantity->toDouble(); 795 } 796 } 797 798 799 // --------------------------------------- 800 void 801 Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) { 802 if (U_FAILURE(status)) { 803 return; 804 } 805 dispose(); 806 807 auto* dq = new DecimalQuantity(); 808 dq->setToDecNumber(numberString, status); 809 adoptDecimalQuantity(dq); 810 811 // Note that we do not hang on to the caller's input string. 812 // If we are asked for the string, we will regenerate one from fDecimalQuantity. 813 } 814 815 #if 0 816 //---------------------------------------------------- 817 // console I/O 818 //---------------------------------------------------- 819 #ifdef _DEBUG 820 821 #include <iostream> 822 using namespace std; 823 824 #include "unicode/datefmt.h" 825 #include "unistrm.h" 826 827 class FormattableStreamer /* not : public UObject because all methods are static */ { 828 public: 829 static void streamOut(ostream& stream, const Formattable& obj); 830 831 private: 832 FormattableStreamer() {} // private - forbid instantiation 833 }; 834 835 // This is for debugging purposes only. This will send a displayable 836 // form of the Formattable object to the output stream. 837 838 void 839 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj) 840 { 841 static DateFormat *defDateFormat = 0; 842 843 UnicodeString buffer; 844 switch(obj.getType()) { 845 case Formattable::kDate : 846 // Creates a DateFormat instance for formatting the 847 // Date instance. 848 if (defDateFormat == 0) { 849 defDateFormat = DateFormat::createInstance(); 850 } 851 defDateFormat->format(obj.getDate(), buffer); 852 stream << buffer; 853 break; 854 case Formattable::kDouble : 855 // Output the double as is. 856 stream << obj.getDouble() << 'D'; 857 break; 858 case Formattable::kLong : 859 // Output the double as is. 860 stream << obj.getLong() << 'L'; 861 break; 862 case Formattable::kString: 863 // Output the double as is. Please see UnicodeString console 864 // I/O routine for more details. 865 stream << '"' << obj.getString(buffer) << '"'; 866 break; 867 case Formattable::kArray: 868 int32_t i, count; 869 const Formattable* array; 870 array = obj.getArray(count); 871 stream << '['; 872 // Recursively calling the console I/O routine for each element in the array. 873 for (i=0; i<count; ++i) { 874 FormattableStreamer::streamOut(stream, array[i]); 875 stream << ( (i==(count-1)) ? "" : ", " ); 876 } 877 stream << ']'; 878 break; 879 default: 880 // Not a recognizable Formattable object. 881 stream << "INVALID_Formattable"; 882 } 883 stream.flush(); 884 } 885 #endif 886 887 #endif 888 889 U_NAMESPACE_END 890 891 /* ---- UFormattable implementation ---- */ 892 893 U_NAMESPACE_USE 894 895 U_CAPI UFormattable* U_EXPORT2 896 ufmt_open(UErrorCode *status) { 897 if( U_FAILURE(*status) ) { 898 return nullptr; 899 } 900 UFormattable *fmt = (new Formattable())->toUFormattable(); 901 902 if( fmt == nullptr ) { 903 *status = U_MEMORY_ALLOCATION_ERROR; 904 } 905 return fmt; 906 } 907 908 U_CAPI void U_EXPORT2 909 ufmt_close(UFormattable *fmt) { 910 Formattable *obj = Formattable::fromUFormattable(fmt); 911 912 delete obj; 913 } 914 915 U_CAPI UFormattableType U_EXPORT2 916 ufmt_getType(const UFormattable *fmt, UErrorCode *status) { 917 if(U_FAILURE(*status)) { 918 return (UFormattableType)UFMT_COUNT; 919 } 920 const Formattable *obj = Formattable::fromUFormattable(fmt); 921 return (UFormattableType)obj->getType(); 922 } 923 924 925 U_CAPI UBool U_EXPORT2 926 ufmt_isNumeric(const UFormattable *fmt) { 927 const Formattable *obj = Formattable::fromUFormattable(fmt); 928 return obj->isNumeric(); 929 } 930 931 U_CAPI UDate U_EXPORT2 932 ufmt_getDate(const UFormattable *fmt, UErrorCode *status) { 933 const Formattable *obj = Formattable::fromUFormattable(fmt); 934 935 return obj->getDate(*status); 936 } 937 938 U_CAPI double U_EXPORT2 939 ufmt_getDouble(UFormattable *fmt, UErrorCode *status) { 940 Formattable *obj = Formattable::fromUFormattable(fmt); 941 942 return obj->getDouble(*status); 943 } 944 945 U_CAPI int32_t U_EXPORT2 946 ufmt_getLong(UFormattable *fmt, UErrorCode *status) { 947 Formattable *obj = Formattable::fromUFormattable(fmt); 948 949 return obj->getLong(*status); 950 } 951 952 953 U_CAPI const void *U_EXPORT2 954 ufmt_getObject(const UFormattable *fmt, UErrorCode *status) { 955 const Formattable *obj = Formattable::fromUFormattable(fmt); 956 957 const void *ret = obj->getObject(); 958 if( ret==nullptr && 959 (obj->getType() != Formattable::kObject) && 960 U_SUCCESS( *status )) { 961 *status = U_INVALID_FORMAT_ERROR; 962 } 963 return ret; 964 } 965 966 U_CAPI const char16_t* U_EXPORT2 967 ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) { 968 Formattable *obj = Formattable::fromUFormattable(fmt); 969 970 // avoid bogosity by checking the type first. 971 if( obj->getType() != Formattable::kString ) { 972 if( U_SUCCESS(*status) ){ 973 *status = U_INVALID_FORMAT_ERROR; 974 } 975 return nullptr; 976 } 977 978 // This should return a valid string 979 UnicodeString &str = obj->getString(*status); 980 if( U_SUCCESS(*status) && len != nullptr ) { 981 *len = str.length(); 982 } 983 return str.getTerminatedBuffer(); 984 } 985 986 U_CAPI int32_t U_EXPORT2 987 ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) { 988 const Formattable *obj = Formattable::fromUFormattable(fmt); 989 990 int32_t count; 991 (void)obj->getArray(count, *status); 992 return count; 993 } 994 995 U_CAPI UFormattable * U_EXPORT2 996 ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) { 997 Formattable *obj = Formattable::fromUFormattable(fmt); 998 int32_t count; 999 (void)obj->getArray(count, *status); 1000 if(U_FAILURE(*status)) { 1001 return nullptr; 1002 } else if(n<0 || n>=count) { 1003 setError(*status, U_INDEX_OUTOFBOUNDS_ERROR); 1004 return nullptr; 1005 } else { 1006 return (*obj)[n].toUFormattable(); // returns non-const Formattable 1007 } 1008 } 1009 1010 U_CAPI const char * U_EXPORT2 1011 ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) { 1012 if(U_FAILURE(*status)) { 1013 return ""; 1014 } 1015 Formattable *obj = Formattable::fromUFormattable(fmt); 1016 FixedString *charString = obj->internalGetFixedString(*status); 1017 if(U_FAILURE(*status)) { 1018 return ""; 1019 } 1020 if(charString == nullptr) { 1021 *status = U_MEMORY_ALLOCATION_ERROR; 1022 return ""; 1023 } else { 1024 if(len!=nullptr) { 1025 *len = static_cast<int32_t>(uprv_strlen(charString->data())); 1026 } 1027 return charString->data(); 1028 } 1029 } 1030 1031 U_CAPI int64_t U_EXPORT2 1032 ufmt_getInt64(UFormattable *fmt, UErrorCode *status) { 1033 Formattable *obj = Formattable::fromUFormattable(fmt); 1034 return obj->getInt64(*status); 1035 } 1036 1037 #endif /* #if !UCONFIG_NO_FORMATTING */ 1038 1039 //eof