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 bool 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