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