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