Coverage Report

Created: 2026-02-05 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/icu/icu4c/source/i18n/fmtable.cpp
Line
Count
Source
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 "cmemory.h"
30
#include "cstring.h"
31
#include "fixedstring.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) == *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) != nullptr;
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 != nullptr) {
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
56.1M
void  Formattable::init() {
105
56.1M
    fValue.fInt64 = 0;
106
56.1M
    fType = kLong;
107
56.1M
    fDecimalStr = nullptr;
108
56.1M
    fDecimalQuantity = nullptr;
109
56.1M
    fBogus.setToBogus(); 
110
56.1M
}
111
112
// -------------------------------------
113
// default constructor.
114
// Creates a formattable object with a long value 0.
115
116
56.1M
Formattable::Formattable() {
117
56.1M
    init();
118
56.1M
}
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
896k
{
224
896k
    if (this != &source)
225
896k
    {
226
        // Disposes the current formattable value/setting.
227
896k
        dispose();
228
229
        // Sets the correct data type for this value.
230
896k
        fType = source.fType;
231
896k
        switch (fType)
232
896k
        {
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
894k
        case kDouble:
244
            // Sets the double value.
245
894k
            fValue.fDouble = source.fValue.fDouble;
246
894k
            break;
247
2.71k
        case kLong:
248
2.71k
        case kInt64:
249
            // Sets the long value.
250
2.71k
            fValue.fInt64 = source.fValue.fInt64;
251
2.71k
            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
896k
        }
260
261
896k
        if (source.fDecimalQuantity != nullptr) {
262
0
          fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity);
263
0
        }
264
896k
        if (source.fDecimalStr != nullptr) {
265
0
            fDecimalStr = new FixedString(*source.fDecimalStr);
266
0
        }
267
896k
    }
268
896k
    return *this;
269
896k
}
270
271
// -------------------------------------
272
273
bool
274
Formattable::operator==(const Formattable& that) const
275
0
{
276
0
    int32_t i;
277
278
0
    if (this == &that) return true;
279
280
    // Returns false if the data types are different.
281
0
    if (fType != that.fType) return false;
282
283
    // Compares the actual data values.
284
0
    bool equal = true;
285
0
    switch (fType) {
286
0
    case kDate:
287
0
        equal = (fValue.fDate == that.fValue.fDate);
288
0
        break;
289
0
    case kDouble:
290
0
        equal = (fValue.fDouble == that.fValue.fDouble);
291
0
        break;
292
0
    case kLong:
293
0
    case kInt64:
294
0
        equal = (fValue.fInt64 == that.fValue.fInt64);
295
0
        break;
296
0
    case kString:
297
0
        equal = (*(fValue.fString) == *(that.fValue.fString));
298
0
        break;
299
0
    case kArray:
300
0
        if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
301
0
            equal = false;
302
0
            break;
303
0
        }
304
        // Checks each element for equality.
305
0
        for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
306
0
            if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
307
0
                equal = false;
308
0
                break;
309
0
            }
310
0
        }
311
0
        break;
312
0
    case kObject:
313
0
        if (fValue.fObject == nullptr || that.fValue.fObject == nullptr) {
314
0
            equal = false;
315
0
        } else {
316
0
            equal = objectEquals(fValue.fObject, that.fValue.fObject);
317
0
        }
318
0
        break;
319
0
    }
320
321
    // TODO:  compare digit lists if numeric.
322
0
    return equal;
323
0
}
324
325
// -------------------------------------
326
327
Formattable::~Formattable()
328
56.1M
{
329
56.1M
    dispose();
330
56.1M
}
331
332
// -------------------------------------
333
334
void Formattable::dispose()
335
126M
{
336
    // Deletes the data value if necessary.
337
126M
    switch (fType) {
338
0
    case kString:
339
0
        delete fValue.fString;
340
0
        break;
341
0
    case kArray:
342
0
        delete[] fValue.fArrayAndCount.fArray;
343
0
        break;
344
0
    case kObject:
345
0
        delete fValue.fObject;
346
0
        break;
347
126M
    default:
348
126M
        break;
349
126M
    }
350
351
126M
    fType = kLong;
352
126M
    fValue.fInt64 = 0;
353
354
126M
    delete fDecimalStr;
355
126M
    fDecimalStr = nullptr;
356
357
126M
    delete fDecimalQuantity;
358
126M
    fDecimalQuantity = nullptr;
359
126M
}
360
361
Formattable *
362
0
Formattable::clone() const {
363
0
    return new Formattable(*this);
364
0
}
365
366
// -------------------------------------
367
// Gets the data type of this Formattable object. 
368
Formattable::Type
369
Formattable::getType() const
370
9.85k
{
371
9.85k
    return fType;
372
9.85k
}
373
374
UBool
375
0
Formattable::isNumeric() const {
376
0
    switch (fType) {
377
0
    case kDouble:
378
0
    case kLong:
379
0
    case kInt64:
380
0
        return true;
381
0
    default:
382
0
        return false;
383
0
    }
384
0
}
385
386
// -------------------------------------
387
int32_t
388
//Formattable::getLong(UErrorCode* status) const
389
Formattable::getLong(UErrorCode& status) const
390
297k
{
391
297k
    if (U_FAILURE(status)) {
392
0
        return 0;
393
0
    }
394
        
395
297k
    switch (fType) {
396
274k
    case Formattable::kLong: 
397
274k
        return static_cast<int32_t>(fValue.fInt64);
398
0
    case Formattable::kInt64:
399
0
        if (fValue.fInt64 > INT32_MAX) {
400
0
            status = U_INVALID_FORMAT_ERROR;
401
0
            return INT32_MAX;
402
0
        } else if (fValue.fInt64 < INT32_MIN) {
403
0
            status = U_INVALID_FORMAT_ERROR;
404
0
            return INT32_MIN;
405
0
        } else {
406
0
            return static_cast<int32_t>(fValue.fInt64);
407
0
        }
408
23.3k
    case Formattable::kDouble:
409
23.3k
        if (fValue.fDouble > INT32_MAX) {
410
1.07k
            status = U_INVALID_FORMAT_ERROR;
411
1.07k
            return INT32_MAX;
412
22.2k
        } else if (fValue.fDouble < INT32_MIN) {
413
1.04k
            status = U_INVALID_FORMAT_ERROR;
414
1.04k
            return INT32_MIN;
415
21.2k
        } else {
416
21.2k
            return static_cast<int32_t>(fValue.fDouble); // loses fraction
417
21.2k
        }
418
0
    case Formattable::kObject:
419
0
        if (fValue.fObject == nullptr) {
420
0
            status = U_MEMORY_ALLOCATION_ERROR;
421
0
            return 0;
422
0
        }
423
        // TODO Later replace this with instanceof call
424
0
        if (instanceOfMeasure(fValue.fObject)) {
425
0
            return ((const Measure*) fValue.fObject)->
426
0
                getNumber().getLong(status);
427
0
        }
428
0
        U_FALLTHROUGH;
429
0
    default:
430
0
        status = U_INVALID_FORMAT_ERROR;
431
0
        return 0;
432
297k
    }
433
297k
}
434
435
// -------------------------------------
436
// Maximum int that can be represented exactly in a double.  (53 bits)
437
//    Larger ints may be rounded to a near-by value as not all are representable.
438
// TODO:  move this constant elsewhere, possibly configure it for different
439
//        floating point formats, if any non-standard ones are still in use.
440
static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
441
442
int64_t
443
Formattable::getInt64(UErrorCode& status) const
444
0
{
445
0
    if (U_FAILURE(status)) {
446
0
        return 0;
447
0
    }
448
        
449
0
    switch (fType) {
450
0
    case Formattable::kLong: 
451
0
    case Formattable::kInt64: 
452
0
        return fValue.fInt64;
453
0
    case Formattable::kDouble:
454
0
        if (fValue.fDouble > static_cast<double>(U_INT64_MAX)) {
455
0
            status = U_INVALID_FORMAT_ERROR;
456
0
            return U_INT64_MAX;
457
0
        } else if (fValue.fDouble < static_cast<double>(U_INT64_MIN)) {
458
0
            status = U_INVALID_FORMAT_ERROR;
459
0
            return U_INT64_MIN;
460
0
        } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalQuantity != nullptr) {
461
0
            if (fDecimalQuantity->fitsInLong(true)) {
462
0
                return fDecimalQuantity->toLong();
463
0
            } else {
464
                // Unexpected
465
0
                status = U_INVALID_FORMAT_ERROR;
466
0
                return fDecimalQuantity->isNegative() ? U_INT64_MIN : U_INT64_MAX;
467
0
            }
468
0
        } else {
469
0
            return static_cast<int64_t>(fValue.fDouble);
470
0
        } 
471
0
    case Formattable::kObject:
472
0
        if (fValue.fObject == nullptr) {
473
0
            status = U_MEMORY_ALLOCATION_ERROR;
474
0
            return 0;
475
0
        }
476
0
        if (instanceOfMeasure(fValue.fObject)) {
477
0
            return ((const Measure*) fValue.fObject)->
478
0
                getNumber().getInt64(status);
479
0
        }
480
0
        U_FALLTHROUGH;
481
0
    default:
482
0
        status = U_INVALID_FORMAT_ERROR;
483
0
        return 0;
484
0
    }
485
0
}
486
487
// -------------------------------------
488
double
489
Formattable::getDouble(UErrorCode& status) const
490
1.76M
{
491
1.76M
    if (U_FAILURE(status)) {
492
0
        return 0;
493
0
    }
494
        
495
1.76M
    switch (fType) {
496
510k
    case Formattable::kLong: 
497
589k
    case Formattable::kInt64: // loses precision
498
589k
        return static_cast<double>(fValue.fInt64);
499
1.17M
    case Formattable::kDouble:
500
1.17M
        return fValue.fDouble;
501
0
    case Formattable::kObject:
502
0
        if (fValue.fObject == nullptr) {
503
0
            status = U_MEMORY_ALLOCATION_ERROR;
504
0
            return 0;
505
0
        }
506
        // TODO Later replace this with instanceof call
507
0
        if (instanceOfMeasure(fValue.fObject)) {
508
0
            return ((const Measure*) fValue.fObject)->
509
0
                getNumber().getDouble(status);
510
0
        }
511
0
        U_FALLTHROUGH;
512
0
    default:
513
0
        status = U_INVALID_FORMAT_ERROR;
514
0
        return 0;
515
1.76M
    }
516
1.76M
}
517
518
const UObject*
519
0
Formattable::getObject() const {
520
0
    return (fType == kObject) ? fValue.fObject : nullptr;
521
0
}
522
523
// -------------------------------------
524
// Sets the value to a double value d.
525
526
void
527
Formattable::setDouble(double d)
528
32.2M
{
529
32.2M
    dispose();
530
32.2M
    fType = kDouble;
531
32.2M
    fValue.fDouble = d;
532
32.2M
}
533
534
// -------------------------------------
535
// Sets the value to a long value l.
536
537
void
538
Formattable::setLong(int32_t l)
539
37.0M
{
540
37.0M
    dispose();
541
37.0M
    fType = kLong;
542
37.0M
    fValue.fInt64 = l;
543
37.0M
}
544
545
// -------------------------------------
546
// Sets the value to an int64 value ll.
547
548
void
549
Formattable::setInt64(int64_t ll)
550
0
{
551
0
    dispose();
552
0
    fType = kInt64;
553
0
    fValue.fInt64 = ll;
554
0
}
555
556
// -------------------------------------
557
// Sets the value to a Date instance d.
558
559
void
560
Formattable::setDate(UDate d)
561
0
{
562
0
    dispose();
563
0
    fType = kDate;
564
0
    fValue.fDate = d;
565
0
}
566
567
// -------------------------------------
568
// Sets the value to a string value stringToCopy.
569
570
void
571
Formattable::setString(const UnicodeString& stringToCopy)
572
0
{
573
0
    dispose();
574
0
    fType = kString;
575
0
    fValue.fString = new UnicodeString(stringToCopy);
576
0
}
577
578
// -------------------------------------
579
// Sets the value to an array of Formattable objects.
580
581
void
582
Formattable::setArray(const Formattable* array, int32_t count)
583
0
{
584
0
    dispose();
585
0
    fType = kArray;
586
0
    fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
587
0
    fValue.fArrayAndCount.fCount = count;
588
0
}
589
590
// -------------------------------------
591
// Adopts the stringToAdopt value.
592
593
void
594
Formattable::adoptString(UnicodeString* stringToAdopt)
595
0
{
596
0
    dispose();
597
0
    fType = kString;
598
0
    fValue.fString = stringToAdopt;
599
0
}
600
601
// -------------------------------------
602
// Adopts the array value and its count.
603
604
void
605
Formattable::adoptArray(Formattable* array, int32_t count)
606
0
{
607
0
    dispose();
608
0
    fType = kArray;
609
0
    fValue.fArrayAndCount.fArray = array;
610
0
    fValue.fArrayAndCount.fCount = count;
611
0
}
612
613
void
614
0
Formattable::adoptObject(UObject* objectToAdopt) {
615
0
    dispose();
616
0
    fType = kObject;
617
0
    fValue.fObject = objectToAdopt;
618
0
}
619
620
// -------------------------------------
621
UnicodeString& 
622
Formattable::getString(UnicodeString& result, UErrorCode& status) const 
623
0
{
624
0
    if (fType != kString) {
625
0
        setError(status, U_INVALID_FORMAT_ERROR);
626
0
        result.setToBogus();
627
0
    } else {
628
0
        if (fValue.fString == nullptr) {
629
0
            setError(status, U_MEMORY_ALLOCATION_ERROR);
630
0
        } else {
631
0
            result = *fValue.fString;
632
0
        }
633
0
    }
634
0
    return result;
635
0
}
636
637
// -------------------------------------
638
const UnicodeString& 
639
Formattable::getString(UErrorCode& status) const 
640
0
{
641
0
    if (fType != kString) {
642
0
        setError(status, U_INVALID_FORMAT_ERROR);
643
0
        return *getBogus();
644
0
    }
645
0
    if (fValue.fString == nullptr) {
646
0
        setError(status, U_MEMORY_ALLOCATION_ERROR);
647
0
        return *getBogus();
648
0
    }
649
0
    return *fValue.fString;
650
0
}
651
652
// -------------------------------------
653
UnicodeString& 
654
Formattable::getString(UErrorCode& status) 
655
0
{
656
0
    if (fType != kString) {
657
0
        setError(status, U_INVALID_FORMAT_ERROR);
658
0
        return *getBogus();
659
0
    }
660
0
    if (fValue.fString == nullptr) {
661
0
      setError(status, U_MEMORY_ALLOCATION_ERROR);
662
0
      return *getBogus();
663
0
    }
664
0
    return *fValue.fString;
665
0
}
666
667
// -------------------------------------
668
const Formattable* 
669
Formattable::getArray(int32_t& count, UErrorCode& status) const 
670
0
{
671
0
    if (fType != kArray) {
672
0
        setError(status, U_INVALID_FORMAT_ERROR);
673
0
        count = 0;
674
0
        return nullptr;
675
0
    }
676
0
    count = fValue.fArrayAndCount.fCount; 
677
0
    return fValue.fArrayAndCount.fArray;
678
0
}
679
680
// -------------------------------------
681
// Gets the bogus string, ensures mondo bogosity.
682
683
UnicodeString*
684
Formattable::getBogus() const 
685
0
{
686
0
    return const_cast<UnicodeString*>(&fBogus); /* cast away const :-( */
687
0
}
688
689
690
// --------------------------------------
691
0
StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
692
0
    if (U_FAILURE(status)) {
693
0
        return "";
694
0
    }
695
0
    if (fDecimalStr != nullptr) {
696
0
      return fDecimalStr->data();
697
0
    }
698
699
0
    FixedString* decimalStr = internalGetFixedString(status);
700
0
    if(decimalStr == nullptr) {
701
0
      return ""; // getDecimalNumber returns "" for error cases
702
0
    } else {
703
0
      return decimalStr->data();
704
0
    }
705
0
}
706
707
0
FixedString *Formattable::internalGetFixedString(UErrorCode &status) {
708
0
    if(fDecimalStr == nullptr) {
709
0
      if (fDecimalQuantity == nullptr) {
710
        // No decimal number for the formattable yet.  Which means the value was
711
        // set directly by the user as an int, int64 or double.  If the value came
712
        // from parsing, or from the user setting a decimal number, fDecimalNum
713
        // would already be set.
714
        //
715
0
        LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status);
716
0
        if (U_FAILURE(status)) { return nullptr; }
717
0
        populateDecimalQuantity(*dq, status);
718
0
        if (U_FAILURE(status)) { return nullptr; }
719
0
        fDecimalQuantity = dq.orphan();
720
0
      }
721
722
0
      fDecimalStr = new FixedString();
723
0
      if (fDecimalStr == nullptr) {
724
0
        status = U_MEMORY_ALLOCATION_ERROR;
725
0
        return nullptr;
726
0
      }
727
      // Older ICUs called uprv_decNumberToString here, which is not exactly the same as
728
      // DecimalQuantity::toScientificString(). The biggest difference is that uprv_decNumberToString does
729
      // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?).
730
0
      if (fDecimalQuantity->isInfinite()) {
731
0
        *fDecimalStr = "Infinity";
732
0
      } else if (fDecimalQuantity->isNaN()) {
733
0
        *fDecimalStr = "NaN";
734
0
      } else if (fDecimalQuantity->isZeroish()) {
735
0
        *fDecimalStr = "0";
736
0
      } else if (fType==kLong || fType==kInt64 || // use toPlainString for integer types
737
0
                  (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5)) {
738
0
        copyInvariantChars(fDecimalQuantity->toPlainString(), *fDecimalStr, status);
739
0
      } else {
740
0
        copyInvariantChars(fDecimalQuantity->toScientificString(), *fDecimalStr, status);
741
0
      }
742
0
      if (U_SUCCESS(status) && fDecimalStr->isEmpty()) {
743
0
        status = U_MEMORY_ALLOCATION_ERROR;
744
0
        return nullptr;
745
0
      }
746
0
    }
747
0
    return fDecimalStr;
748
0
}
749
750
void
751
0
Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const {
752
0
    if (fDecimalQuantity != nullptr) {
753
0
        output = *fDecimalQuantity;
754
0
        return;
755
0
    }
756
757
0
    switch (fType) {
758
0
        case kDouble:
759
0
            output.setToDouble(this->getDouble());
760
0
            output.roundToInfinity();
761
0
            break;
762
0
        case kLong:
763
0
            output.setToInt(this->getLong());
764
0
            break;
765
0
        case kInt64:
766
0
            output.setToLong(this->getInt64());
767
0
            break;
768
0
        default:
769
            // The formattable's value is not a numeric type.
770
0
            status = U_INVALID_STATE_ERROR;
771
0
    }
772
0
}
773
774
// ---------------------------------------
775
void
776
865k
Formattable::adoptDecimalQuantity(DecimalQuantity *dq) {
777
865k
    delete fDecimalQuantity;
778
865k
    fDecimalQuantity = dq;
779
865k
    if (dq == nullptr) { // allow adoptDigitList(nullptr) to clear
780
0
        return;
781
0
    }
782
783
    // Set the value into the Union of simple type values.
784
    // Cannot use the set() functions because they would delete the fDecimalNum value.
785
865k
    if (fDecimalQuantity->fitsInLong()) {
786
597k
        fValue.fInt64 = fDecimalQuantity->toLong();
787
597k
        if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) {
788
517k
            fType = kLong;
789
517k
        } else {
790
80.7k
            fType = kInt64;
791
80.7k
        }
792
597k
    } else {
793
267k
        fType = kDouble;
794
267k
        fValue.fDouble = fDecimalQuantity->toDouble();
795
267k
    }
796
865k
}
797
798
799
// ---------------------------------------
800
void
801
0
Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) {
802
0
    if (U_FAILURE(status)) {
803
0
        return;
804
0
    }
805
0
    dispose();
806
807
0
    auto* dq = new DecimalQuantity();
808
0
    dq->setToDecNumber(numberString, status);
809
0
    adoptDecimalQuantity(dq);
810
811
    // Note that we do not hang on to the caller's input string.
812
    // If we are asked for the string, we will regenerate one from fDecimalQuantity.
813
0
}
814
815
#if 0
816
//----------------------------------------------------
817
// console I/O
818
//----------------------------------------------------
819
#ifdef _DEBUG
820
821
#include <iostream>
822
using namespace std;
823
824
#include "unicode/datefmt.h"
825
#include "unistrm.h"
826
827
class FormattableStreamer /* not : public UObject because all methods are static */ {
828
public:
829
    static void streamOut(ostream& stream, const Formattable& obj);
830
831
private:
832
    FormattableStreamer() {} // private - forbid instantiation
833
};
834
835
// This is for debugging purposes only.  This will send a displayable
836
// form of the Formattable object to the output stream.
837
838
void
839
FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
840
{
841
    static DateFormat *defDateFormat = 0;
842
843
    UnicodeString buffer;
844
    switch(obj.getType()) {
845
        case Formattable::kDate : 
846
            // Creates a DateFormat instance for formatting the
847
            // Date instance.
848
            if (defDateFormat == 0) {
849
                defDateFormat = DateFormat::createInstance();
850
            }
851
            defDateFormat->format(obj.getDate(), buffer);
852
            stream << buffer;
853
            break;
854
        case Formattable::kDouble :
855
            // Output the double as is.
856
            stream << obj.getDouble() << 'D';
857
            break;
858
        case Formattable::kLong :
859
            // Output the double as is.
860
            stream << obj.getLong() << 'L';
861
            break;
862
        case Formattable::kString:
863
            // Output the double as is.  Please see UnicodeString console
864
            // I/O routine for more details.
865
            stream << '"' << obj.getString(buffer) << '"';
866
            break;
867
        case Formattable::kArray:
868
            int32_t i, count;
869
            const Formattable* array;
870
            array = obj.getArray(count);
871
            stream << '[';
872
            // Recursively calling the console I/O routine for each element in the array.
873
            for (i=0; i<count; ++i) {
874
                FormattableStreamer::streamOut(stream, array[i]);
875
                stream << ( (i==(count-1)) ? "" : ", " );
876
            }
877
            stream << ']';
878
            break;
879
        default:
880
            // Not a recognizable Formattable object.
881
            stream << "INVALID_Formattable";
882
    }
883
    stream.flush();
884
}
885
#endif
886
887
#endif
888
889
U_NAMESPACE_END
890
891
/* ---- UFormattable implementation ---- */
892
893
U_NAMESPACE_USE
894
895
U_CAPI UFormattable* U_EXPORT2
896
0
ufmt_open(UErrorCode *status) {
897
0
  if( U_FAILURE(*status) ) {
898
0
    return nullptr;
899
0
  }
900
0
  UFormattable *fmt = (new Formattable())->toUFormattable();
901
902
0
  if( fmt == nullptr ) {
903
0
    *status = U_MEMORY_ALLOCATION_ERROR;
904
0
  }
905
0
  return fmt;
906
0
}
907
908
U_CAPI void U_EXPORT2
909
0
ufmt_close(UFormattable *fmt) {
910
0
  Formattable *obj = Formattable::fromUFormattable(fmt);
911
912
0
  delete obj;
913
0
}
914
915
U_CAPI UFormattableType U_EXPORT2
916
0
ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
917
0
  if(U_FAILURE(*status)) {
918
0
    return (UFormattableType)UFMT_COUNT;
919
0
  }
920
0
  const Formattable *obj = Formattable::fromUFormattable(fmt);
921
0
  return (UFormattableType)obj->getType();
922
0
}
923
924
925
U_CAPI UBool U_EXPORT2
926
0
ufmt_isNumeric(const UFormattable *fmt) {
927
0
  const Formattable *obj = Formattable::fromUFormattable(fmt);
928
0
  return obj->isNumeric();
929
0
}
930
931
U_CAPI UDate U_EXPORT2
932
0
ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
933
0
  const Formattable *obj = Formattable::fromUFormattable(fmt);
934
935
0
  return obj->getDate(*status);
936
0
}
937
938
U_CAPI double U_EXPORT2
939
0
ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
940
0
  Formattable *obj = Formattable::fromUFormattable(fmt);
941
942
0
  return obj->getDouble(*status);
943
0
}
944
945
U_CAPI int32_t U_EXPORT2
946
0
ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
947
0
  Formattable *obj = Formattable::fromUFormattable(fmt);
948
949
0
  return obj->getLong(*status);
950
0
}
951
952
953
U_CAPI const void *U_EXPORT2
954
0
ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
955
0
  const Formattable *obj = Formattable::fromUFormattable(fmt);
956
957
0
  const void *ret = obj->getObject();
958
0
  if( ret==nullptr &&
959
0
      (obj->getType() != Formattable::kObject) &&
960
0
      U_SUCCESS( *status )) {
961
0
    *status = U_INVALID_FORMAT_ERROR;
962
0
  }
963
0
  return ret;
964
0
}
965
966
U_CAPI const char16_t* U_EXPORT2
967
0
ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
968
0
  Formattable *obj = Formattable::fromUFormattable(fmt);
969
970
  // avoid bogosity by checking the type first.
971
0
  if( obj->getType() != Formattable::kString ) {
972
0
    if( U_SUCCESS(*status) ){
973
0
      *status = U_INVALID_FORMAT_ERROR;
974
0
    }
975
0
    return nullptr;
976
0
  }
977
978
  // This should return a valid string
979
0
  UnicodeString &str = obj->getString(*status);
980
0
  if( U_SUCCESS(*status) && len != nullptr ) {
981
0
    *len = str.length();
982
0
  }
983
0
  return str.getTerminatedBuffer();
984
0
}
985
986
U_CAPI int32_t U_EXPORT2
987
0
ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
988
0
  const Formattable *obj = Formattable::fromUFormattable(fmt);
989
990
0
  int32_t count;
991
0
  (void)obj->getArray(count, *status);
992
0
  return count;
993
0
}
994
995
U_CAPI UFormattable * U_EXPORT2
996
0
ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
997
0
  Formattable *obj = Formattable::fromUFormattable(fmt);
998
0
  int32_t count;
999
0
  (void)obj->getArray(count, *status);
1000
0
  if(U_FAILURE(*status)) {
1001
0
    return nullptr;
1002
0
  } else if(n<0 || n>=count) {
1003
0
    setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
1004
0
    return nullptr;
1005
0
  } else {
1006
0
    return (*obj)[n].toUFormattable(); // returns non-const Formattable
1007
0
  }
1008
0
}
1009
1010
U_CAPI const char * U_EXPORT2
1011
0
ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
1012
0
  if(U_FAILURE(*status)) {
1013
0
    return "";
1014
0
  }
1015
0
  Formattable *obj = Formattable::fromUFormattable(fmt);
1016
0
  FixedString *charString = obj->internalGetFixedString(*status);
1017
0
  if(U_FAILURE(*status)) {
1018
0
    return "";
1019
0
  }
1020
0
  if(charString == nullptr) {
1021
0
    *status = U_MEMORY_ALLOCATION_ERROR;
1022
0
    return "";
1023
0
  } else {
1024
0
    if(len!=nullptr) {
1025
0
      *len = static_cast<int32_t>(uprv_strlen(charString->data()));
1026
0
    }
1027
0
    return charString->data();
1028
0
  }
1029
0
}
1030
1031
U_CAPI int64_t U_EXPORT2
1032
0
ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
1033
0
  Formattable *obj = Formattable::fromUFormattable(fmt);
1034
0
  return obj->getInt64(*status);
1035
0
}
1036
1037
#endif /* #if !UCONFIG_NO_FORMATTING */
1038
1039
//eof