Coverage Report

Created: 2025-06-24 06:43

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