1 // © 2018 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 #include "unicode/utypes.h"
6 #if !UCONFIG_NO_FORMATTING
8 // This file contains one implementation of FormattedValue.
9 // Other independent implementations should go into their own cpp file for
10 // better dependency modularization.
12 #include "formattedval_impl.h"
18 FormattedValueFieldPositionIteratorImpl::FormattedValueFieldPositionIteratorImpl(
19 int32_t initialFieldCapacity
,
21 : fFields(initialFieldCapacity
* 4, status
) {
24 FormattedValueFieldPositionIteratorImpl::~FormattedValueFieldPositionIteratorImpl() = default;
26 UnicodeString
FormattedValueFieldPositionIteratorImpl::toString(
31 UnicodeString
FormattedValueFieldPositionIteratorImpl::toTempString(
33 // The alias must point to memory owned by this object;
34 // fastCopyFrom doesn't do this when using a stack buffer.
35 return UnicodeString(TRUE
, fString
.getBuffer(), fString
.length());
38 Appendable
& FormattedValueFieldPositionIteratorImpl::appendTo(
39 Appendable
& appendable
,
41 appendable
.appendString(fString
.getBuffer(), fString
.length());
45 UBool
FormattedValueFieldPositionIteratorImpl::nextPosition(
46 ConstrainedFieldPosition
& cfpos
,
48 U_ASSERT(fFields
.size() % 4 == 0);
49 int32_t numFields
= fFields
.size() / 4;
50 int32_t i
= static_cast<int32_t>(cfpos
.getInt64IterationContext());
51 for (; i
< numFields
; i
++) {
52 UFieldCategory category
= static_cast<UFieldCategory
>(fFields
.elementAti(i
* 4));
53 int32_t field
= fFields
.elementAti(i
* 4 + 1);
54 if (cfpos
.matchesField(category
, field
)) {
55 int32_t start
= fFields
.elementAti(i
* 4 + 2);
56 int32_t limit
= fFields
.elementAti(i
* 4 + 3);
57 cfpos
.setState(category
, field
, start
, limit
);
61 cfpos
.setInt64IterationContext(i
== numFields
? i
: i
+ 1);
66 FieldPositionIteratorHandler
FormattedValueFieldPositionIteratorImpl::getHandler(
68 return FieldPositionIteratorHandler(&fFields
, status
);
71 void FormattedValueFieldPositionIteratorImpl::appendString(
74 if (U_FAILURE(status
)) {
77 fString
.append(string
);
78 // Make the string NUL-terminated
79 if (fString
.getTerminatedBuffer() == nullptr) {
80 status
= U_MEMORY_ALLOCATION_ERROR
;
86 void FormattedValueFieldPositionIteratorImpl::addOverlapSpans(
87 UFieldCategory spanCategory
,
90 // In order to avoid fancy data structures, this is an O(N^2) algorithm,
91 // which should be fine for all real-life applications of this function.
92 int32_t s1a
= INT32_MAX
;
94 int32_t s2a
= INT32_MAX
;
96 int32_t numFields
= fFields
.size() / 4;
97 for (int32_t i
= 0; i
<numFields
; i
++) {
98 int32_t field1
= fFields
.elementAti(i
* 4 + 1);
99 for (int32_t j
= i
+ 1; j
<numFields
; j
++) {
100 int32_t field2
= fFields
.elementAti(j
* 4 + 1);
101 if (field1
!= field2
) {
105 s1a
= uprv_min(s1a
, fFields
.elementAti(i
* 4 + 2));
106 s1b
= uprv_max(s1b
, fFields
.elementAti(i
* 4 + 3));
107 s2a
= uprv_min(s2a
, fFields
.elementAti(j
* 4 + 2));
108 s2b
= uprv_max(s2b
, fFields
.elementAti(j
* 4 + 3));
112 if (s1a
!= INT32_MAX
) {
113 // Success: add the two span fields
114 fFields
.addElement(spanCategory
, status
);
115 fFields
.addElement(firstIndex
, status
);
116 fFields
.addElement(s1a
, status
);
117 fFields
.addElement(s1b
, status
);
118 fFields
.addElement(spanCategory
, status
);
119 fFields
.addElement(1 - firstIndex
, status
);
120 fFields
.addElement(s2a
, status
);
121 fFields
.addElement(s2b
, status
);
126 void FormattedValueFieldPositionIteratorImpl::sort() {
127 // Use bubble sort, O(N^2) but easy and no fancy data structures.
128 int32_t numFields
= fFields
.size() / 4;
130 bool isSorted
= true;
131 for (int32_t i
=0; i
<numFields
-1; i
++) {
132 int32_t categ1
= fFields
.elementAti(i
*4 + 0);
133 int32_t field1
= fFields
.elementAti(i
*4 + 1);
134 int32_t start1
= fFields
.elementAti(i
*4 + 2);
135 int32_t limit1
= fFields
.elementAti(i
*4 + 3);
136 int32_t categ2
= fFields
.elementAti(i
*4 + 4);
137 int32_t field2
= fFields
.elementAti(i
*4 + 5);
138 int32_t start2
= fFields
.elementAti(i
*4 + 6);
139 int32_t limit2
= fFields
.elementAti(i
*4 + 7);
140 int64_t comparison
= 0;
141 if (start1
!= start2
) {
142 // Higher start index -> higher rank
143 comparison
= start2
- start1
;
144 } else if (limit1
!= limit2
) {
145 // Higher length (end index) -> lower rank
146 comparison
= limit1
- limit2
;
147 } else if (categ1
!= categ2
) {
148 // Higher field category -> lower rank
149 comparison
= categ1
- categ2
;
150 } else if (field1
!= field2
) {
151 // Higher field -> higher rank
152 comparison
= field2
- field1
;
154 if (comparison
< 0) {
157 fFields
.setElementAt(categ2
, i
*4 + 0);
158 fFields
.setElementAt(field2
, i
*4 + 1);
159 fFields
.setElementAt(start2
, i
*4 + 2);
160 fFields
.setElementAt(limit2
, i
*4 + 3);
161 fFields
.setElementAt(categ1
, i
*4 + 4);
162 fFields
.setElementAt(field1
, i
*4 + 5);
163 fFields
.setElementAt(start1
, i
*4 + 6);
164 fFields
.setElementAt(limit1
, i
*4 + 7);
176 #endif /* #if !UCONFIG_NO_FORMATTING */