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
20using namespace icu;
21using namespace icu::number;
22using namespace icu::number::impl;
23
24UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocalizedNumberFormatterAsFormat)
25
26LocalizedNumberFormatterAsFormat::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
33LocalizedNumberFormatterAsFormat::~LocalizedNumberFormatterAsFormat() = default;
34
35UBool 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
46LocalizedNumberFormatterAsFormat* LocalizedNumberFormatterAsFormat::clone() const {
47 return new LocalizedNumberFormatterAsFormat(*this);
48}
49
50UnicodeString& 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
74UnicodeString& 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
95void LocalizedNumberFormatterAsFormat::parseObject(const UnicodeString&, Formattable&,
96 ParsePosition& parse_pos) const {
97 // Not supported.
98 parse_pos.setErrorIndex(0);
99}
100
101const LocalizedNumberFormatter& LocalizedNumberFormatterAsFormat::getNumberFormatter() const {
102 return fFormatter;
103}
104
105
106// Definitions of public API methods (put here for dependency disentanglement)
107
108Format* 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