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 37U_NAMESPACE_BEGIN 38 39UOBJECT_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. 53static 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. 59static 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. 65static 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 */ 76static 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 */ 90static 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// 100void 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 112Formattable::Formattable() { 113 init(); 114} 115 116// ------------------------------------- 117// Creates a formattable object with a Date instance. 118 119Formattable::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 129Formattable::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 139Formattable::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 148Formattable::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 158Formattable::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 167Formattable::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 178Formattable::Formattable(UnicodeString* stringToAdopt) 179{ 180 init(); 181 fType = kString; 182 fValue.fString = stringToAdopt; 183} 184 185Formattable::Formattable(UObject* objectToAdopt) 186{ 187 init(); 188 fType = kObject; 189 fValue.fObject = objectToAdopt; 190} 191 192// ------------------------------------- 193 194Formattable::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 207Formattable::Formattable(const Formattable &source) 208 : UObject(*this) 209{ 210 init(); 211 *this = source; 212} 213 214// ------------------------------------- 215// assignment operator 216 217Formattable& 218Formattable::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 274UBool 275Formattable::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 328Formattable::~Formattable() 329{ 330 dispose(); 331} 332 333// ------------------------------------- 334 335void 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 367Formattable * 368Formattable::clone() const { 369 return new Formattable(*this); 370} 371 372// ------------------------------------- 373// Gets the data type of this Formattable object. 374Formattable::Type 375Formattable::getType() const 376{ 377 return fType; 378} 379 380UBool 381Formattable::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// ------------------------------------- 393int32_t 394//Formattable::getLong(UErrorCode* status) const 395Formattable::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. 445static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL; 446 447int64_t 448Formattable::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// ------------------------------------- 492double 493Formattable::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 521const UObject* 522Formattable::getObject() const { 523 return (fType == kObject) ? fValue.fObject : NULL; 524} 525 526// ------------------------------------- 527// Sets the value to a double value d. 528 529void 530Formattable::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 540void 541Formattable::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 551void 552Formattable::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 562void 563Formattable::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 573void 574Formattable::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 584void 585Formattable::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 596void 597Formattable::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 607void 608Formattable::adoptArray(Formattable* array, int32_t count) 609{ 610 dispose(); 611 fType = kArray; 612 fValue.fArrayAndCount.fArray = array; 613 fValue.fArrayAndCount.fCount = count; 614} 615 616void 617Formattable::adoptObject(UObject* objectToAdopt) { 618 dispose(); 619 fType = kObject; 620 fValue.fObject = objectToAdopt; 621} 622 623// ------------------------------------- 624UnicodeString& 625Formattable::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// ------------------------------------- 641const UnicodeString& 642Formattable::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// ------------------------------------- 656UnicodeString& 657Formattable::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// ------------------------------------- 671const Formattable* 672Formattable::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 686UnicodeString* 687Formattable::getBogus() const 688{ 689 return (UnicodeString*)&fBogus; /* cast away const :-( */ 690} 691 692 693// -------------------------------------- 694StringPiece 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 710CharString *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 752DigitList * 753Formattable::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// --------------------------------------- 765void 766Formattable::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// --------------------------------------- 795void 796Formattable::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> 829using namespace std; 830 831#include "unicode/datefmt.h" 832#include "unistrm.h" 833 834class FormattableStreamer /* not : public UObject because all methods are static */ { 835public: 836 static void streamOut(ostream& stream, const Formattable& obj); 837 838private: 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 845void 846FormattableStreamer::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 896U_NAMESPACE_END 897 898/* ---- UFormattable implementation ---- */ 899 900U_NAMESPACE_USE 901 902U_DRAFT UFormattable* U_EXPORT2 903ufmt_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 915U_DRAFT void U_EXPORT2 916ufmt_close(UFormattable *fmt) { 917 Formattable *obj = Formattable::fromUFormattable(fmt); 918 919 delete obj; 920} 921 922U_INTERNAL UFormattableType U_EXPORT2 923ufmt_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 932U_INTERNAL UBool U_EXPORT2 933ufmt_isNumeric(const UFormattable *fmt) { 934 const Formattable *obj = Formattable::fromUFormattable(fmt); 935 return obj->isNumeric(); 936} 937 938U_DRAFT UDate U_EXPORT2 939ufmt_getDate(const UFormattable *fmt, UErrorCode *status) { 940 const Formattable *obj = Formattable::fromUFormattable(fmt); 941 942 return obj->getDate(*status); 943} 944 945U_DRAFT double U_EXPORT2 946ufmt_getDouble(UFormattable *fmt, UErrorCode *status) { 947 Formattable *obj = Formattable::fromUFormattable(fmt); 948 949 return obj->getDouble(*status); 950} 951 952U_DRAFT int32_t U_EXPORT2 953ufmt_getLong(UFormattable *fmt, UErrorCode *status) { 954 Formattable *obj = Formattable::fromUFormattable(fmt); 955 956 return obj->getLong(*status); 957} 958 959 960U_DRAFT const void *U_EXPORT2 961ufmt_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 973U_DRAFT const UChar* U_EXPORT2 974ufmt_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 993U_DRAFT int32_t U_EXPORT2 994ufmt_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 1002U_DRAFT UFormattable * U_EXPORT2 1003ufmt_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 1017U_DRAFT const char * U_EXPORT2 1018ufmt_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 1038U_DRAFT int64_t U_EXPORT2 1039ufmt_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