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 #include "unicode/formattedvalue.h"
9 #include "formattedval_impl.h"
10 #include "capi_helper.h"
11 
12 U_NAMESPACE_BEGIN
13 
14 
ConstrainedFieldPosition()15 ConstrainedFieldPosition::ConstrainedFieldPosition() {}
16 
~ConstrainedFieldPosition()17 ConstrainedFieldPosition::~ConstrainedFieldPosition() {}
18 
reset()19 void ConstrainedFieldPosition::reset() {
20     fContext = 0LL;
21     fField = 0;
22     fStart = 0;
23     fLimit = 0;
24     fConstraint = UCFPOS_CONSTRAINT_NONE;
25     fCategory = UFIELD_CATEGORY_UNDEFINED;
26 }
27 
constrainCategory(int32_t category)28 void ConstrainedFieldPosition::constrainCategory(int32_t category) {
29     fConstraint = UCFPOS_CONSTRAINT_CATEGORY;
30     fCategory = category;
31 }
32 
constrainField(int32_t category,int32_t field)33 void ConstrainedFieldPosition::constrainField(int32_t category, int32_t field) {
34     fConstraint = UCFPOS_CONSTRAINT_FIELD;
35     fCategory = category;
36     fField = field;
37 }
38 
setInt64IterationContext(int64_t context)39 void ConstrainedFieldPosition::setInt64IterationContext(int64_t context) {
40     fContext = context;
41 }
42 
matchesField(int32_t category,int32_t field) const43 UBool ConstrainedFieldPosition::matchesField(int32_t category, int32_t field) const {
44     switch (fConstraint) {
45     case UCFPOS_CONSTRAINT_NONE:
46         return TRUE;
47     case UCFPOS_CONSTRAINT_CATEGORY:
48         return fCategory == category;
49     case UCFPOS_CONSTRAINT_FIELD:
50         return fCategory == category && fField == field;
51     default:
52         UPRV_UNREACHABLE;
53     }
54 }
55 
setState(int32_t category,int32_t field,int32_t start,int32_t limit)56 void ConstrainedFieldPosition::setState(
57         int32_t category,
58         int32_t field,
59         int32_t start,
60         int32_t limit) {
61     fCategory = category;
62     fField = field;
63     fStart = start;
64     fLimit = limit;
65 }
66 
67 
68 FormattedValue::~FormattedValue() = default;
69 
70 
71 ///////////////////////
72 /// C API FUNCTIONS ///
73 ///////////////////////
74 
75 struct UConstrainedFieldPositionImpl : public UMemory,
76         // Magic number as ASCII == "UCF"
77         public IcuCApiHelper<UConstrainedFieldPosition, UConstrainedFieldPositionImpl, 0x55434600> {
78     ConstrainedFieldPosition fImpl;
79 };
80 
81 U_CAPI UConstrainedFieldPosition* U_EXPORT2
ucfpos_open(UErrorCode * ec)82 ucfpos_open(UErrorCode* ec) {
83     auto* impl = new UConstrainedFieldPositionImpl();
84     if (impl == nullptr) {
85         *ec = U_MEMORY_ALLOCATION_ERROR;
86         return nullptr;
87     }
88     return impl->exportForC();
89 }
90 
91 U_CAPI void U_EXPORT2
ucfpos_reset(UConstrainedFieldPosition * ptr,UErrorCode * ec)92 ucfpos_reset(UConstrainedFieldPosition* ptr, UErrorCode* ec) {
93     auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
94     if (U_FAILURE(*ec)) {
95         return;
96     }
97     impl->fImpl.reset();
98 }
99 
100 U_CAPI void U_EXPORT2
ucfpos_constrainCategory(UConstrainedFieldPosition * ptr,int32_t category,UErrorCode * ec)101 ucfpos_constrainCategory(UConstrainedFieldPosition* ptr, int32_t category, UErrorCode* ec) {
102     auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
103     if (U_FAILURE(*ec)) {
104         return;
105     }
106     impl->fImpl.constrainCategory(category);
107 }
108 
109 U_CAPI void U_EXPORT2
ucfpos_constrainField(UConstrainedFieldPosition * ptr,int32_t category,int32_t field,UErrorCode * ec)110 ucfpos_constrainField(UConstrainedFieldPosition* ptr, int32_t category, int32_t field, UErrorCode* ec) {
111     auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
112     if (U_FAILURE(*ec)) {
113         return;
114     }
115     impl->fImpl.constrainField(category, field);
116 }
117 
118 U_CAPI int32_t U_EXPORT2
ucfpos_getCategory(const UConstrainedFieldPosition * ptr,UErrorCode * ec)119 ucfpos_getCategory(const UConstrainedFieldPosition* ptr, UErrorCode* ec) {
120     const auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
121     if (U_FAILURE(*ec)) {
122         return UFIELD_CATEGORY_UNDEFINED;
123     }
124     return impl->fImpl.getCategory();
125 }
126 
127 U_CAPI int32_t U_EXPORT2
ucfpos_getField(const UConstrainedFieldPosition * ptr,UErrorCode * ec)128 ucfpos_getField(const UConstrainedFieldPosition* ptr, UErrorCode* ec) {
129     const auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
130     if (U_FAILURE(*ec)) {
131         return 0;
132     }
133     return impl->fImpl.getField();
134 }
135 
136 U_CAPI void U_EXPORT2
ucfpos_getIndexes(const UConstrainedFieldPosition * ptr,int32_t * pStart,int32_t * pLimit,UErrorCode * ec)137 ucfpos_getIndexes(const UConstrainedFieldPosition* ptr, int32_t* pStart, int32_t* pLimit, UErrorCode* ec) {
138     const auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
139     if (U_FAILURE(*ec)) {
140         return;
141     }
142     *pStart = impl->fImpl.getStart();
143     *pLimit = impl->fImpl.getLimit();
144 }
145 
146 U_CAPI int64_t U_EXPORT2
ucfpos_getInt64IterationContext(const UConstrainedFieldPosition * ptr,UErrorCode * ec)147 ucfpos_getInt64IterationContext(const UConstrainedFieldPosition* ptr, UErrorCode* ec) {
148     const auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
149     if (U_FAILURE(*ec)) {
150         return 0;
151     }
152     return impl->fImpl.getInt64IterationContext();
153 }
154 
155 U_CAPI void U_EXPORT2
ucfpos_setInt64IterationContext(UConstrainedFieldPosition * ptr,int64_t context,UErrorCode * ec)156 ucfpos_setInt64IterationContext(UConstrainedFieldPosition* ptr, int64_t context, UErrorCode* ec) {
157     auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
158     if (U_FAILURE(*ec)) {
159         return;
160     }
161     impl->fImpl.setInt64IterationContext(context);
162 }
163 
164 U_CAPI UBool U_EXPORT2
ucfpos_matchesField(const UConstrainedFieldPosition * ptr,int32_t category,int32_t field,UErrorCode * ec)165 ucfpos_matchesField(const UConstrainedFieldPosition* ptr, int32_t category, int32_t field, UErrorCode* ec) {
166     const auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
167     if (U_FAILURE(*ec)) {
168         return 0;
169     }
170     return impl->fImpl.matchesField(category, field);
171 }
172 
173 U_CAPI void U_EXPORT2
ucfpos_setState(UConstrainedFieldPosition * ptr,int32_t category,int32_t field,int32_t start,int32_t limit,UErrorCode * ec)174 ucfpos_setState(
175         UConstrainedFieldPosition* ptr,
176         int32_t category,
177         int32_t field,
178         int32_t start,
179         int32_t limit,
180         UErrorCode* ec) {
181     auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
182     if (U_FAILURE(*ec)) {
183         return;
184     }
185     impl->fImpl.setState(category, field, start, limit);
186 }
187 
188 U_CAPI void U_EXPORT2
ucfpos_close(UConstrainedFieldPosition * ptr)189 ucfpos_close(UConstrainedFieldPosition* ptr) {
190     UErrorCode localStatus = U_ZERO_ERROR;
191     auto* impl = UConstrainedFieldPositionImpl::validate(ptr, localStatus);
192     delete impl;
193 }
194 
195 
196 U_CAPI const UChar* U_EXPORT2
ufmtval_getString(const UFormattedValue * ufmtval,int32_t * pLength,UErrorCode * ec)197 ufmtval_getString(
198         const UFormattedValue* ufmtval,
199         int32_t* pLength,
200         UErrorCode* ec) {
201     const auto* impl = UFormattedValueApiHelper::validate(ufmtval, *ec);
202     if (U_FAILURE(*ec)) {
203         return nullptr;
204     }
205     UnicodeString readOnlyAlias = impl->fFormattedValue->toTempString(*ec);
206     if (U_FAILURE(*ec)) {
207         return nullptr;
208     }
209     if (pLength != nullptr) {
210         *pLength = readOnlyAlias.length();
211     }
212     return readOnlyAlias.getBuffer();
213 }
214 
215 
216 U_CAPI UBool U_EXPORT2
ufmtval_nextPosition(const UFormattedValue * ufmtval,UConstrainedFieldPosition * ucfpos,UErrorCode * ec)217 ufmtval_nextPosition(
218         const UFormattedValue* ufmtval,
219         UConstrainedFieldPosition* ucfpos,
220         UErrorCode* ec) {
221     const auto* fmtval = UFormattedValueApiHelper::validate(ufmtval, *ec);
222     auto* cfpos = UConstrainedFieldPositionImpl::validate(ucfpos, *ec);
223     if (U_FAILURE(*ec)) {
224         return FALSE;
225     }
226     return fmtval->fFormattedValue->nextPosition(cfpos->fImpl, *ec);
227 }
228 
229 
230 U_NAMESPACE_END
231 
232 #endif /* #if !UCONFIG_NO_FORMATTING */
233