]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/i18n/formattedval_impl.h
ICU-64243.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / formattedval_impl.h
... / ...
CommitLineData
1// © 2018 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3
4#ifndef __FORMVAL_IMPL_H__
5#define __FORMVAL_IMPL_H__
6
7#include "unicode/utypes.h"
8#if !UCONFIG_NO_FORMATTING
9
10// This file contains compliant implementations of FormattedValue which can be
11// leveraged by ICU formatters.
12//
13// Each implementation is defined in its own cpp file in order to split
14// dependencies more modularly.
15
16#include "unicode/formattedvalue.h"
17#include "capi_helper.h"
18#include "fphdlimp.h"
19#include "util.h"
20#include "uvectr32.h"
21#include "number_stringbuilder.h"
22
23
24/**
25 * Represents the type of constraint for ConstrainedFieldPosition.
26 *
27 * Constraints are used to control the behavior of iteration in FormattedValue.
28 *
29 * @internal
30 */
31typedef enum UCFPosConstraintType {
32 /**
33 * Represents the lack of a constraint.
34 *
35 * This is the value of fConstraint if no "constrain" methods were called.
36 *
37 * @internal
38 */
39 UCFPOS_CONSTRAINT_NONE = 0,
40
41 /**
42 * Represents that the field category is constrained.
43 *
44 * This is the value of fConstraint if constraintCategory was called.
45 *
46 * FormattedValue implementations should not change the field category
47 * while this constraint is active.
48 *
49 * @internal
50 */
51 UCFPOS_CONSTRAINT_CATEGORY,
52
53 /**
54 * Represents that the field and field category are constrained.
55 *
56 * This is the value of fConstraint if constraintField was called.
57 *
58 * FormattedValue implementations should not change the field or field category
59 * while this constraint is active.
60 *
61 * @internal
62 */
63 UCFPOS_CONSTRAINT_FIELD
64} UCFPosConstraintType;
65
66
67U_NAMESPACE_BEGIN
68
69
70/** Implementation using FieldPositionHandler to accept fields. */
71class FormattedValueFieldPositionIteratorImpl : public UMemory, public FormattedValue {
72public:
73
74 /** @param initialFieldCapacity Initially allocate space for this many fields. */
75 FormattedValueFieldPositionIteratorImpl(int32_t initialFieldCapacity, UErrorCode& status);
76
77 virtual ~FormattedValueFieldPositionIteratorImpl();
78
79 // Implementation of FormattedValue (const):
80
81 UnicodeString toString(UErrorCode& status) const U_OVERRIDE;
82 UnicodeString toTempString(UErrorCode& status) const U_OVERRIDE;
83 Appendable& appendTo(Appendable& appendable, UErrorCode& status) const U_OVERRIDE;
84 UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
85
86 // Additional methods used during construction phase only (non-const):
87
88 FieldPositionIteratorHandler getHandler(UErrorCode& status);
89 void appendString(UnicodeString string, UErrorCode& status);
90
91 /**
92 * Computes the spans for duplicated values.
93 * For example, if the string has fields:
94 *
95 * ...aa..[b.cc]..d.[bb.e.c]..a..
96 *
97 * then the spans will be the bracketed regions.
98 *
99 * Assumes that the currently known fields are sorted
100 * and all in the same category.
101 */
102 void addOverlapSpans(UFieldCategory spanCategory, int8_t firstIndex, UErrorCode& status);
103
104 /**
105 * Sorts the fields: start index first, length second.
106 */
107 void sort();
108
109private:
110 UnicodeString fString;
111 UVector32 fFields;
112};
113
114
115class FormattedValueNumberStringBuilderImpl : public UMemory, public FormattedValue {
116public:
117
118 FormattedValueNumberStringBuilderImpl(number::impl::Field numericField);
119
120 virtual ~FormattedValueNumberStringBuilderImpl();
121
122 // Implementation of FormattedValue (const):
123
124 UnicodeString toString(UErrorCode& status) const U_OVERRIDE;
125 UnicodeString toTempString(UErrorCode& status) const U_OVERRIDE;
126 Appendable& appendTo(Appendable& appendable, UErrorCode& status) const U_OVERRIDE;
127 UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
128
129 inline number::impl::NumberStringBuilder& getStringRef() {
130 return fString;
131 }
132
133 inline const number::impl::NumberStringBuilder& getStringRef() const {
134 return fString;
135 }
136
137private:
138 number::impl::NumberStringBuilder fString;
139 number::impl::Field fNumericField;
140};
141
142
143// C API Helpers for FormattedValue
144// Magic number as ASCII == "UFV"
145struct UFormattedValueImpl;
146typedef IcuCApiHelper<UFormattedValue, UFormattedValueImpl, 0x55465600> UFormattedValueApiHelper;
147struct UFormattedValueImpl : public UMemory, public UFormattedValueApiHelper {
148 // This pointer should be set by the child class.
149 FormattedValue* fFormattedValue = nullptr;
150};
151
152
153/** Boilerplate to check for valid status before dereferencing the fData pointer. */
154#define UPRV_FORMATTED_VALUE_METHOD_GUARD(returnExpression) \
155 if (U_FAILURE(status)) { \
156 return returnExpression; \
157 } \
158 if (fData == nullptr) { \
159 status = fErrorCode; \
160 return returnExpression; \
161 } \
162
163
164/** Implementation of the methods from U_FORMATTED_VALUE_SUBCLASS_AUTO. */
165#define UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(Name) \
166 Name::Name(Name&& src) U_NOEXCEPT \
167 : fData(src.fData), fErrorCode(src.fErrorCode) { \
168 src.fData = nullptr; \
169 src.fErrorCode = U_INVALID_STATE_ERROR; \
170 } \
171 Name::~Name() { \
172 delete fData; \
173 fData = nullptr; \
174 } \
175 Name& Name::operator=(Name&& src) U_NOEXCEPT { \
176 delete fData; \
177 fData = src.fData; \
178 src.fData = nullptr; \
179 fErrorCode = src.fErrorCode; \
180 src.fErrorCode = U_INVALID_STATE_ERROR; \
181 return *this; \
182 } \
183 UnicodeString Name::toString(UErrorCode& status) const { \
184 UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString()) \
185 return fData->toString(status); \
186 } \
187 UnicodeString Name::toTempString(UErrorCode& status) const { \
188 UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString()) \
189 return fData->toTempString(status); \
190 } \
191 Appendable& Name::appendTo(Appendable& appendable, UErrorCode& status) const { \
192 UPRV_FORMATTED_VALUE_METHOD_GUARD(appendable) \
193 return fData->appendTo(appendable, status); \
194 } \
195 UBool Name::nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const { \
196 UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE) \
197 return fData->nextPosition(cfpos, status); \
198 }
199
200
201/** Like UPRV_FORMATTED_VALUE_CAPI_AUTO_IMPL but without impl type declarations. */
202#define UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(CType, ImplType, HelperType, Prefix) \
203 U_CAPI CType* U_EXPORT2 \
204 Prefix ## _openResult (UErrorCode* ec) { \
205 if (U_FAILURE(*ec)) { \
206 return nullptr; \
207 } \
208 ImplType* impl = new ImplType(); \
209 if (impl == nullptr) { \
210 *ec = U_MEMORY_ALLOCATION_ERROR; \
211 return nullptr; \
212 } \
213 return static_cast<HelperType*>(impl)->exportForC(); \
214 } \
215 U_DRAFT const UFormattedValue* U_EXPORT2 \
216 Prefix ## _resultAsValue (const CType* uresult, UErrorCode* ec) { \
217 const ImplType* result = HelperType::validate(uresult, *ec); \
218 if (U_FAILURE(*ec)) { return nullptr; } \
219 return static_cast<const UFormattedValueApiHelper*>(result)->exportConstForC(); \
220 } \
221 U_CAPI void U_EXPORT2 \
222 Prefix ## _closeResult (CType* uresult) { \
223 UErrorCode localStatus = U_ZERO_ERROR; \
224 const ImplType* impl = HelperType::validate(uresult, localStatus); \
225 delete impl; \
226 }
227
228
229/**
230 * Implementation of the standard methods for a UFormattedValue "subclass" C API.
231 * @param CPPType The public C++ type, like FormattedList
232 * @param CType The public C type, like UFormattedList
233 * @param ImplType A name to use for the implementation class
234 * @param HelperType A name to use for the "mixin" typedef for C API conversion
235 * @param Prefix The C API prefix, like ulistfmt
236 * @param MagicNumber A unique 32-bit number to use to identify this type
237 */
238#define UPRV_FORMATTED_VALUE_CAPI_AUTO_IMPL(CPPType, CType, ImplType, HelperType, Prefix, MagicNumber) \
239 U_NAMESPACE_BEGIN \
240 class ImplType; \
241 typedef IcuCApiHelper<CType, ImplType, MagicNumber> HelperType; \
242 class ImplType : public UFormattedValueImpl, public HelperType { \
243 public: \
244 ImplType(); \
245 ~ImplType(); \
246 CPPType fImpl; \
247 }; \
248 ImplType::ImplType() { \
249 fFormattedValue = &fImpl; \
250 } \
251 ImplType::~ImplType() {} \
252 U_NAMESPACE_END \
253 UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(CType, ImplType, HelperType, Prefix)
254
255
256U_NAMESPACE_END
257
258#endif /* #if !UCONFIG_NO_FORMATTING */
259#endif // __FORMVAL_IMPL_H__