]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/fmtable.cpp
ICU-400.42.tar.gz
[apple/icu.git] / icuSources / i18n / fmtable.cpp
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