1 // © 2018 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 
4 #include "unicode/utypes.h"
5 
6 #if !UCONFIG_NO_FORMATTING
7 
8 // Allow implicit conversion from char16_t* to UnicodeString for this file:
9 // Helpful in toString methods and elsewhere.
10 #define UNISTR_FROM_STRING_EXPLICIT
11 
12 #include <stdlib.h>
13 #include <cmath>
14 #include "number_asformat.h"
15 #include "number_types.h"
16 #include "number_utils.h"
17 #include "fphdlimp.h"
18 #include "number_utypes.h"
19 
20 using namespace icu;
21 using namespace icu::number;
22 using namespace icu::number::impl;
23 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocalizedNumberFormatterAsFormat)24 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocalizedNumberFormatterAsFormat)
25 
26 LocalizedNumberFormatterAsFormat::LocalizedNumberFormatterAsFormat(
27         const LocalizedNumberFormatter& formatter, const Locale& locale)
28         : fFormatter(formatter), fLocale(locale) {
29     const char* localeName = locale.getName();
30     setLocaleIDs(localeName, localeName);
31 }
32 
33 LocalizedNumberFormatterAsFormat::~LocalizedNumberFormatterAsFormat() = default;
34 
operator ==(const Format & other) const35 UBool LocalizedNumberFormatterAsFormat::operator==(const Format& other) const {
36     auto* _other = dynamic_cast<const LocalizedNumberFormatterAsFormat*>(&other);
37     if (_other == nullptr) {
38         return false;
39     }
40     // TODO: Change this to use LocalizedNumberFormatter::operator== if it is ever proposed.
41     // This implementation is fine, but not particularly efficient.
42     UErrorCode localStatus = U_ZERO_ERROR;
43     return fFormatter.toSkeleton(localStatus) == _other->fFormatter.toSkeleton(localStatus);
44 }
45 
clone() const46 LocalizedNumberFormatterAsFormat* LocalizedNumberFormatterAsFormat::clone() const {
47     return new LocalizedNumberFormatterAsFormat(*this);
48 }
49 
format(const Formattable & obj,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const50 UnicodeString& LocalizedNumberFormatterAsFormat::format(const Formattable& obj, UnicodeString& appendTo,
51                                                         FieldPosition& pos, UErrorCode& status) const {
52     if (U_FAILURE(status)) { return appendTo; }
53     UFormattedNumberData data;
54     obj.populateDecimalQuantity(data.quantity, status);
55     if (U_FAILURE(status)) {
56         return appendTo;
57     }
58     fFormatter.formatImpl(&data, status);
59     if (U_FAILURE(status)) {
60         return appendTo;
61     }
62     // always return first occurrence:
63     pos.setBeginIndex(0);
64     pos.setEndIndex(0);
65     bool found = data.nextFieldPosition(pos, status);
66     if (found && appendTo.length() != 0) {
67         pos.setBeginIndex(pos.getBeginIndex() + appendTo.length());
68         pos.setEndIndex(pos.getEndIndex() + appendTo.length());
69     }
70     appendTo.append(data.toTempString(status));
71     return appendTo;
72 }
73 
format(const Formattable & obj,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const74 UnicodeString& LocalizedNumberFormatterAsFormat::format(const Formattable& obj, UnicodeString& appendTo,
75                                                         FieldPositionIterator* posIter,
76                                                         UErrorCode& status) const {
77     if (U_FAILURE(status)) { return appendTo; }
78     UFormattedNumberData data;
79     obj.populateDecimalQuantity(data.quantity, status);
80     if (U_FAILURE(status)) {
81         return appendTo;
82     }
83     fFormatter.formatImpl(&data, status);
84     if (U_FAILURE(status)) {
85         return appendTo;
86     }
87     appendTo.append(data.toTempString(status));
88     if (posIter != nullptr) {
89         FieldPositionIteratorHandler fpih(posIter, status);
90         data.getAllFieldPositions(fpih, status);
91     }
92     return appendTo;
93 }
94 
parseObject(const UnicodeString &,Formattable &,ParsePosition & parse_pos) const95 void LocalizedNumberFormatterAsFormat::parseObject(const UnicodeString&, Formattable&,
96                                                    ParsePosition& parse_pos) const {
97     // Not supported.
98     parse_pos.setErrorIndex(0);
99 }
100 
getNumberFormatter() const101 const LocalizedNumberFormatter& LocalizedNumberFormatterAsFormat::getNumberFormatter() const {
102     return fFormatter;
103 }
104 
105 
106 // Definitions of public API methods (put here for dependency disentanglement)
107 
toFormat(UErrorCode & status) const108 Format* LocalizedNumberFormatter::toFormat(UErrorCode& status) const {
109     if (U_FAILURE(status)) {
110         return nullptr;
111     }
112     LocalPointer<LocalizedNumberFormatterAsFormat> retval(
113             new LocalizedNumberFormatterAsFormat(*this, fMacros.locale), status);
114     return retval.orphan();
115 }
116 
117 #endif /* #if !UCONFIG_NO_FORMATTING */
118