1 /* 2 ******************************************************************************* 3 * Copyright (C) 1997-2008, 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 "unicode/fmtable.h" 21 #include "unicode/ustring.h" 22 #include "unicode/measure.h" 23 #include "unicode/curramt.h" 24 #include "cmemory.h" 25 26 // ***************************************************************************** 27 // class Formattable 28 // ***************************************************************************** 29 30 U_NAMESPACE_BEGIN 31 32 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable) 33 34 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. 35 36 // NOTE: As of 3.0, there are limitations to the UObject API. It does 37 // not (yet) support cloning, operator=, nor operator==. RTTI is also 38 // restricted in that subtype testing is not (yet) implemented. To 39 // work around this, I implement some simple inlines here. Later 40 // these can be modified or removed. [alan] 41 42 // NOTE: These inlines assume that all fObjects are in fact instances 43 // of the Measure class, which is true as of 3.0. [alan] 44 45 // Return TRUE if *a == *b. 46 static inline UBool objectEquals(const UObject* a, const UObject* b) { 47 // LATER: return *a == *b; 48 return *((const Measure*) a) == *((const Measure*) b); 49 } 50 51 // Return a clone of *a. 52 static inline UObject* objectClone(const UObject* a) { 53 // LATER: return a->clone(); 54 return ((const Measure*) a)->clone(); 55 } 56 57 // Return TRUE if *a is an instance of Measure. 58 static inline UBool instanceOfMeasure(const UObject* a) { 59 // LATER: return a->instanceof(Measure::getStaticClassID()); 60 return a->getDynamicClassID() == 61 CurrencyAmount::getStaticClassID(); 62 } 63 64 /** 65 * Creates a new Formattable array and copies the values from the specified 66 * original. 67 * @param array the original array 68 * @param count the original array count 69 * @return the new Formattable array. 70 */ 71 static inline Formattable* createArrayCopy(const Formattable* array, int32_t count) { 72 Formattable *result = new Formattable[count]; 73 if (result != NULL) { 74 for (int32_t i=0; i<count; ++i) 75 result[i] = array[i]; // Don't memcpy! 76 } 77 return result; 78 } 79 80 //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. 81 82 /** 83 * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode. 84 */ 85 static inline void setError(UErrorCode& ec, UErrorCode err) { 86 if (U_SUCCESS(ec)) { 87 ec = err; 88 } 89 } 90 91 // ------------------------------------- 92 // default constructor. 93 // Creates a formattable object with a long value 0. 94 95 Formattable::Formattable() 96 : UObject(), fType(kLong) 97 { 98 fBogus.setToBogus(); 99 fValue.fInt64 = 0; 100 } 101 102 // ------------------------------------- 103 // Creates a formattable object with a Date instance. 104 105 Formattable::Formattable(UDate date, ISDATE /*isDate*/) 106 : UObject(), fType(kDate) 107 { 108 fBogus.setToBogus(); 109 fValue.fDate = date; 110 } 111 112 // ------------------------------------- 113 // Creates a formattable object with a double value. 114 115 Formattable::Formattable(double value) 116 : UObject(), fType(kDouble) 117 { 118 fBogus.setToBogus(); 119 fValue.fDouble = value; 120 } 121 122 // ------------------------------------- 123 // Creates a formattable object with a long value. 124 125 Formattable::Formattable(int32_t value) 126 : UObject(), fType(kLong) 127 { 128 fBogus.setToBogus(); 129 fValue.fInt64 = value; 130 } 131 132 // ------------------------------------- 133 // Creates a formattable object with a long value. 134 135 Formattable::Formattable(int64_t value) 136 : UObject(), fType(kInt64) 137 { 138 fBogus.setToBogus(); 139 fValue.fInt64 = value; 140 } 141 142 // ------------------------------------- 143 // Creates a formattable object with a UnicodeString instance. 144 145 Formattable::Formattable(const UnicodeString& stringToCopy) 146 : UObject(), fType(kString) 147 { 148 fBogus.setToBogus(); 149 fValue.fString = new UnicodeString(stringToCopy); 150 } 151 152 // ------------------------------------- 153 // Creates a formattable object with a UnicodeString* value. 154 // (adopting symantics) 155 156 Formattable::Formattable(UnicodeString* stringToAdopt) 157 : UObject(), fType(kString) 158 { 159 fBogus.setToBogus(); 160 fValue.fString = stringToAdopt; 161 } 162 163 Formattable::Formattable(UObject* objectToAdopt) 164 : UObject(), fType(kObject) 165 { 166 fBogus.setToBogus(); 167 fValue.fObject = objectToAdopt; 168 } 169 170 // ------------------------------------- 171 172 Formattable::Formattable(const Formattable* arrayToCopy, int32_t count) 173 : UObject(), fType(kArray) 174 { 175 fBogus.setToBogus(); 176 fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count); 177 fValue.fArrayAndCount.fCount = count; 178 } 179 180 // ------------------------------------- 181 // copy constructor 182 183 Formattable::Formattable(const Formattable &source) 184 : UObject(source), fType(kLong) 185 { 186 fBogus.setToBogus(); 187 *this = source; 188 } 189 190 // ------------------------------------- 191 // assignment operator 192 193 Formattable& 194 Formattable::operator=(const Formattable& source) 195 { 196 if (this != &source) 197 { 198 // Disposes the current formattable value/setting. 199 dispose(); 200 201 // Sets the correct data type for this value. 202 fType = source.fType; 203 switch (fType) 204 { 205 case kArray: 206 // Sets each element in the array one by one and records the array count. 207 fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount; 208 fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray, 209 source.fValue.fArrayAndCount.fCount); 210 break; 211 case kString: 212 // Sets the string value. 213 fValue.fString = new UnicodeString(*source.fValue.fString); 214 break; 215 case kDouble: 216 // Sets the double value. 217 fValue.fDouble = source.fValue.fDouble; 218 break; 219 case kLong: 220 case kInt64: 221 // Sets the long value. 222 fValue.fInt64 = source.fValue.fInt64; 223 break; 224 case kDate: 225 // Sets the Date value. 226 fValue.fDate = source.fValue.fDate; 227 break; 228 case kObject: 229 fValue.fObject = objectClone(source.fValue.fObject); 230 break; 231 } 232 } 233 return *this; 234 } 235 236 // ------------------------------------- 237 238 UBool 239 Formattable::operator==(const Formattable& that) const 240 { 241 int32_t i; 242 243 if (this == &that) return TRUE; 244 245 // Returns FALSE if the data types are different. 246 if (fType != that.fType) return FALSE; 247 248 // Compares the actual data values. 249 UBool equal = TRUE; 250 switch (fType) { 251 case kDate: 252 equal = (fValue.fDate == that.fValue.fDate); 253 break; 254 case kDouble: 255 equal = (fValue.fDouble == that.fValue.fDouble); 256 break; 257 case kLong: 258 case kInt64: 259 equal = (fValue.fInt64 == that.fValue.fInt64); 260 break; 261 case kString: 262 equal = (*(fValue.fString) == *(that.fValue.fString)); 263 break; 264 case kArray: 265 if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) { 266 equal = FALSE; 267 break; 268 } 269 // Checks each element for equality. 270 for (i=0; i<fValue.fArrayAndCount.fCount; ++i) { 271 if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) { 272 equal = FALSE; 273 break; 274 } 275 } 276 break; 277 case kObject: 278 if (fValue.fObject == NULL || that.fValue.fObject == NULL) { 279 equal = FALSE; 280 } else { 281 equal = objectEquals(fValue.fObject, that.fValue.fObject); 282 } 283 break; 284 } 285 286 return equal; 287 } 288 289 // ------------------------------------- 290 291 Formattable::~Formattable() 292 { 293 dispose(); 294 } 295 296 // ------------------------------------- 297 298 void Formattable::dispose() 299 { 300 // Deletes the data value if necessary. 301 switch (fType) { 302 case kString: 303 delete fValue.fString; 304 break; 305 case kArray: 306 delete[] fValue.fArrayAndCount.fArray; 307 break; 308 case kObject: 309 delete fValue.fObject; 310 break; 311 default: 312 break; 313 } 314 } 315 316 Formattable * 317 Formattable::clone() const { 318 return new Formattable(*this); 319 } 320 321 // ------------------------------------- 322 // Gets the data type of this Formattable object. 323 Formattable::Type 324 Formattable::getType() const 325 { 326 return fType; 327 } 328 329 UBool 330 Formattable::isNumeric() const { 331 switch (fType) { 332 case kDouble: 333 case kLong: 334 case kInt64: 335 return TRUE; 336 default: 337 return FALSE; 338 } 339 } 340 341 // ------------------------------------- 342 int32_t 343 //Formattable::getLong(UErrorCode* status) const 344 Formattable::getLong(UErrorCode& status) const 345 { 346 if (U_FAILURE(status)) { 347 return 0; 348 } 349 350 switch (fType) { 351 case Formattable::kLong: 352 return (int32_t)fValue.fInt64; 353 case Formattable::kInt64: 354 if (fValue.fInt64 > INT32_MAX) { 355 status = U_INVALID_FORMAT_ERROR; 356 return INT32_MAX; 357 } else if (fValue.fInt64 < INT32_MIN) { 358 status = U_INVALID_FORMAT_ERROR; 359 return INT32_MIN; 360 } else { 361 return (int32_t)fValue.fInt64; 362 } 363 case Formattable::kDouble: 364 if (fValue.fDouble > INT32_MAX) { 365 status = U_INVALID_FORMAT_ERROR; 366 return INT32_MAX; 367 } else if (fValue.fDouble < INT32_MIN) { 368 status = U_INVALID_FORMAT_ERROR; 369 return INT32_MIN; 370 } else { 371 return (int32_t)fValue.fDouble; // loses fraction 372 } 373 case Formattable::kObject: 374 if (fValue.fObject == NULL) { 375 status = U_MEMORY_ALLOCATION_ERROR; 376 return 0; 377 } 378 // TODO Later replace this with instanceof call 379 if (instanceOfMeasure(fValue.fObject)) { 380 return ((const Measure*) fValue.fObject)-> 381 getNumber().getLong(status); 382 } 383 default: 384 status = U_INVALID_FORMAT_ERROR; 385 return 0; 386 } 387 } 388 389 // ------------------------------------- 390 int64_t 391 Formattable::getInt64(UErrorCode& status) const 392 { 393 if (U_FAILURE(status)) { 394 return 0; 395 } 396 397 switch (fType) { 398 case Formattable::kLong: 399 case Formattable::kInt64: 400 return fValue.fInt64; 401 case Formattable::kDouble: 402 if (fValue.fDouble > U_INT64_MAX) { 403 status = U_INVALID_FORMAT_ERROR; 404 return U_INT64_MAX; 405 } else if (fValue.fDouble < U_INT64_MIN) { 406 status = U_INVALID_FORMAT_ERROR; 407 return U_INT64_MIN; 408 } else { 409 return (int64_t)fValue.fDouble; 410 } 411 case Formattable::kObject: 412 if (fValue.fObject == NULL) { 413 status = U_MEMORY_ALLOCATION_ERROR; 414 return 0; 415 } 416 // TODO Later replace this with instanceof call 417 if (instanceOfMeasure(fValue.fObject)) { 418 return ((const Measure*) fValue.fObject)-> 419 getNumber().getInt64(status); 420 } 421 default: 422 status = U_INVALID_FORMAT_ERROR; 423 return 0; 424 } 425 } 426 427 // ------------------------------------- 428 double 429 Formattable::getDouble(UErrorCode& status) const 430 { 431 if (U_FAILURE(status)) { 432 return 0; 433 } 434 435 switch (fType) { 436 case Formattable::kLong: 437 case Formattable::kInt64: // loses precision 438 return (double)fValue.fInt64; 439 case Formattable::kDouble: 440 return fValue.fDouble; 441 case Formattable::kObject: 442 if (fValue.fObject == NULL) { 443 status = U_MEMORY_ALLOCATION_ERROR; 444 return 0; 445 } 446 // TODO Later replace this with instanceof call 447 if (instanceOfMeasure(fValue.fObject)) { 448 return ((const Measure*) fValue.fObject)-> 449 getNumber().getDouble(status); 450 } 451 default: 452 status = U_INVALID_FORMAT_ERROR; 453 return 0; 454 } 455 } 456 457 const UObject* 458 Formattable::getObject() const { 459 return (fType == kObject) ? fValue.fObject : NULL; 460 } 461 462 // ------------------------------------- 463 // Sets the value to a double value d. 464 465 void 466 Formattable::setDouble(double d) 467 { 468 dispose(); 469 fType = kDouble; 470 fValue.fDouble = d; 471 } 472 473 // ------------------------------------- 474 // Sets the value to a long value l. 475 476 void 477 Formattable::setLong(int32_t l) 478 { 479 dispose(); 480 fType = kLong; 481 fValue.fInt64 = l; 482 } 483 484 // ------------------------------------- 485 // Sets the value to an int64 value ll. 486 487 void 488 Formattable::setInt64(int64_t ll) 489 { 490 dispose(); 491 fType = kInt64; 492 fValue.fInt64 = ll; 493 } 494 495 // ------------------------------------- 496 // Sets the value to a Date instance d. 497 498 void 499 Formattable::setDate(UDate d) 500 { 501 dispose(); 502 fType = kDate; 503 fValue.fDate = d; 504 } 505 506 // ------------------------------------- 507 // Sets the value to a string value stringToCopy. 508 509 void 510 Formattable::setString(const UnicodeString& stringToCopy) 511 { 512 dispose(); 513 fType = kString; 514 fValue.fString = new UnicodeString(stringToCopy); 515 } 516 517 // ------------------------------------- 518 // Sets the value to an array of Formattable objects. 519 520 void 521 Formattable::setArray(const Formattable* array, int32_t count) 522 { 523 dispose(); 524 fType = kArray; 525 fValue.fArrayAndCount.fArray = createArrayCopy(array, count); 526 fValue.fArrayAndCount.fCount = count; 527 } 528 529 // ------------------------------------- 530 // Adopts the stringToAdopt value. 531 532 void 533 Formattable::adoptString(UnicodeString* stringToAdopt) 534 { 535 dispose(); 536 fType = kString; 537 fValue.fString = stringToAdopt; 538 } 539 540 // ------------------------------------- 541 // Adopts the array value and its count. 542 543 void 544 Formattable::adoptArray(Formattable* array, int32_t count) 545 { 546 dispose(); 547 fType = kArray; 548 fValue.fArrayAndCount.fArray = array; 549 fValue.fArrayAndCount.fCount = count; 550 } 551 552 void 553 Formattable::adoptObject(UObject* objectToAdopt) { 554 dispose(); 555 fType = kObject; 556 fValue.fObject = objectToAdopt; 557 } 558 559 // ------------------------------------- 560 UnicodeString& 561 Formattable::getString(UnicodeString& result, UErrorCode& status) const 562 { 563 if (fType != kString) { 564 setError(status, U_INVALID_FORMAT_ERROR); 565 result.setToBogus(); 566 } else { 567 if (fValue.fString == NULL) { 568 setError(status, U_MEMORY_ALLOCATION_ERROR); 569 } else { 570 result = *fValue.fString; 571 } 572 } 573 return result; 574 } 575 576 // ------------------------------------- 577 const UnicodeString& 578 Formattable::getString(UErrorCode& status) const 579 { 580 if (fType != kString) { 581 setError(status, U_INVALID_FORMAT_ERROR); 582 return *getBogus(); 583 } 584 if (fValue.fString == NULL) { 585 setError(status, U_MEMORY_ALLOCATION_ERROR); 586 return *getBogus(); 587 } 588 return *fValue.fString; 589 } 590 591 // ------------------------------------- 592 UnicodeString& 593 Formattable::getString(UErrorCode& status) 594 { 595 if (fType != kString) { 596 setError(status, U_INVALID_FORMAT_ERROR); 597 return *getBogus(); 598 } 599 if (fValue.fString == NULL) { 600 setError(status, U_MEMORY_ALLOCATION_ERROR); 601 return *getBogus(); 602 } 603 return *fValue.fString; 604 } 605 606 // ------------------------------------- 607 const Formattable* 608 Formattable::getArray(int32_t& count, UErrorCode& status) const 609 { 610 if (fType != kArray) { 611 setError(status, U_INVALID_FORMAT_ERROR); 612 count = 0; 613 return NULL; 614 } 615 count = fValue.fArrayAndCount.fCount; 616 return fValue.fArrayAndCount.fArray; 617 } 618 619 // ------------------------------------- 620 // Gets the bogus string, ensures mondo bogosity. 621 622 UnicodeString* 623 Formattable::getBogus() const 624 { 625 return (UnicodeString*)&fBogus; /* cast away const :-( */ 626 } 627 628 #if 0 629 //---------------------------------------------------- 630 // console I/O 631 //---------------------------------------------------- 632 #ifdef _DEBUG 633 634 #if U_IOSTREAM_SOURCE >= 199711 635 #include <iostream> 636 using namespace std; 637 #elif U_IOSTREAM_SOURCE >= 198506 638 #include <iostream.h> 639 #endif 640 641 #include "unicode/datefmt.h" 642 #include "unistrm.h" 643 644 class FormattableStreamer /* not : public UObject because all methods are static */ { 645 public: 646 static void streamOut(ostream& stream, const Formattable& obj); 647 648 private: 649 FormattableStreamer() {} // private - forbid instantiation 650 }; 651 652 // This is for debugging purposes only. This will send a displayable 653 // form of the Formattable object to the output stream. 654 655 void 656 FormattableStreamer::streamOut(ostream& stream, const Formattable& obj) 657 { 658 static DateFormat *defDateFormat = 0; 659 660 UnicodeString buffer; 661 switch(obj.getType()) { 662 case Formattable::kDate : 663 // Creates a DateFormat instance for formatting the 664 // Date instance. 665 if (defDateFormat == 0) { 666 defDateFormat = DateFormat::createInstance(); 667 } 668 defDateFormat->format(obj.getDate(), buffer); 669 stream << buffer; 670 break; 671 case Formattable::kDouble : 672 // Output the double as is. 673 stream << obj.getDouble() << 'D'; 674 break; 675 case Formattable::kLong : 676 // Output the double as is. 677 stream << obj.getLong() << 'L'; 678 break; 679 case Formattable::kString: 680 // Output the double as is. Please see UnicodeString console 681 // I/O routine for more details. 682 stream << '"' << obj.getString(buffer) << '"'; 683 break; 684 case Formattable::kArray: 685 int32_t i, count; 686 const Formattable* array; 687 array = obj.getArray(count); 688 stream << '['; 689 // Recursively calling the console I/O routine for each element in the array. 690 for (i=0; i<count; ++i) { 691 FormattableStreamer::streamOut(stream, array[i]); 692 stream << ( (i==(count-1)) ? "" : ", " ); 693 } 694 stream << ']'; 695 break; 696 default: 697 // Not a recognizable Formattable object. 698 stream << "INVALID_Formattable"; 699 } 700 stream.flush(); 701 } 702 #endif 703 704 #endif 705 706 U_NAMESPACE_END 707 708 #endif /* #if !UCONFIG_NO_FORMATTING */ 709 710 //eof 711