• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2019 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 package ohos.global.icu.impl;
5 
6 import java.text.AttributedCharacterIterator;
7 import java.text.AttributedString;
8 import java.text.FieldPosition;
9 import java.text.Format;
10 import java.util.List;
11 
12 import ohos.global.icu.text.ConstrainedFieldPosition;
13 
14 /**
15  * Implementation of FormattedValue based on FieldPositionIterator.
16  *
17  * In C++, this implements FormattedValue. In Java, it is a stateless
18  * collection of static functions to avoid having to use nested objects.
19  * @hide exposed on OHOS
20  */
21 public class FormattedValueFieldPositionIteratorImpl {
22 
23     /** Do not construct instances of this class */
FormattedValueFieldPositionIteratorImpl()24     private FormattedValueFieldPositionIteratorImpl() {}
25 
26     /** Helper class to keep track of fields with values in Java */
27     private static class FieldWithValue extends Format.Field {
28         private static final long serialVersionUID = -3850076447157793465L;
29 
30         public final Format.Field field;
31         public final int value;
32 
FieldWithValue(Format.Field field, int value)33         public FieldWithValue(Format.Field field, int value) {
34             super(field.toString());
35             this.field = field;
36             this.value = value;
37         }
38     }
39 
nextPosition(List<FieldPosition> attributes, ConstrainedFieldPosition cfpos)40     public static boolean nextPosition(List<FieldPosition> attributes, ConstrainedFieldPosition cfpos) {
41         int numFields = attributes.size();
42         int i = (int) cfpos.getInt64IterationContext();
43         for (; i < numFields; i++) {
44             FieldPosition fpos = attributes.get(i);
45             Format.Field field = fpos.getFieldAttribute();
46             Object value = null;
47             if (field instanceof FieldWithValue) {
48                 value = ((FieldWithValue) field).value;
49                 field = ((FieldWithValue) field).field;
50             }
51             if (cfpos.matchesField(field, value)) {
52                 int start = fpos.getBeginIndex();
53                 int limit = fpos.getEndIndex();
54                 cfpos.setState(field, value, start, limit);
55                 break;
56             }
57         }
58         cfpos.setInt64IterationContext(i == numFields ? i : i + 1);
59         return i < numFields;
60     }
61 
toCharacterIterator(CharSequence cs, List<FieldPosition> attributes)62     public static AttributedCharacterIterator toCharacterIterator(CharSequence cs, List<FieldPosition> attributes) {
63         AttributedString as = new AttributedString(cs.toString());
64 
65         // add attributes to the AttributedString
66         for (int i = 0; i < attributes.size(); i++) {
67             FieldPosition fp = attributes.get(i);
68             Format.Field field = fp.getFieldAttribute();
69             Object value = field;
70             if (field instanceof FieldWithValue) {
71                 value = ((FieldWithValue) field).value;
72                 field = ((FieldWithValue) field).field;
73             }
74             as.addAttribute(field, value, fp.getBeginIndex(), fp.getEndIndex());
75         }
76 
77         // return the CharacterIterator from AttributedString
78         return as.getIterator();
79     }
80 
addOverlapSpans(List<FieldPosition> attributes, Format.Field spanField, int firstIndex)81     public static void addOverlapSpans(List<FieldPosition> attributes, Format.Field spanField, int firstIndex) {
82         // In order to avoid fancy data structures, this is an O(N^2) algorithm,
83         // which should be fine for all real-life applications of this function.
84         int s1a = Integer.MAX_VALUE;
85         int s1b = 0;
86         int s2a = Integer.MAX_VALUE;
87         int s2b = 0;
88         int numFields = attributes.size();
89         for (int i = 0; i<numFields; i++) {
90             FieldPosition fp1 = attributes.get(i);
91             for (int j = i + 1; j<numFields; j++) {
92                 FieldPosition fp2 = attributes.get(j);
93                 if (fp1.getFieldAttribute() != fp2.getFieldAttribute()) {
94                     continue;
95                 }
96                 // Found a duplicate
97                 s1a = Math.min(s1a, fp1.getBeginIndex());
98                 s1b = Math.max(s1b, fp1.getEndIndex());
99                 s2a = Math.min(s2a, fp2.getBeginIndex());
100                 s2b = Math.max(s2b, fp2.getEndIndex());
101                 break;
102             }
103         }
104         if (s1a != Integer.MAX_VALUE) {
105             // Success: add the two span fields
106             FieldPosition newPos = new FieldPosition(new FieldWithValue(spanField, firstIndex));
107             newPos.setBeginIndex(s1a);
108             newPos.setEndIndex(s1b);
109             attributes.add(newPos);
110             newPos = new FieldPosition(new FieldWithValue(spanField, 1 - firstIndex));
111             newPos.setBeginIndex(s2a);
112             newPos.setEndIndex(s2b);
113             attributes.add(newPos);
114         }
115     }
116 
sort(List<FieldPosition> attributes)117     public static void sort(List<FieldPosition> attributes) {
118         // Use bubble sort, O(N^2) but easy and no fancy data structures.
119         int numFields = attributes.size();
120         while (true) {
121             boolean isSorted = true;
122             for (int i=0; i<numFields-1; i++) {
123                 FieldPosition fp1 = attributes.get(i);
124                 FieldPosition fp2 = attributes.get(i + 1);
125                 long comparison = 0;
126                 if (fp1.getBeginIndex() != fp2.getBeginIndex()) {
127                     // Higher start index -> higher rank
128                     comparison = fp2.getBeginIndex() - fp1.getBeginIndex();
129                 } else if (fp1.getEndIndex() != fp2.getEndIndex()) {
130                     // Higher length (end index) -> lower rank
131                     comparison = fp1.getEndIndex() - fp2.getEndIndex();
132                 } else if (fp1.getFieldAttribute() != fp2.getFieldAttribute()) {
133                     // Span category -> lower rank
134                     // Pick other orders arbitrarily
135                     boolean fp1isSpan = fp1.getFieldAttribute() instanceof FieldWithValue;
136                     boolean fp2isSpan = fp2.getFieldAttribute() instanceof FieldWithValue;
137                     if (fp1isSpan && !fp2isSpan) {
138                         comparison = 1;
139                     } else if (fp2isSpan && !fp1isSpan) {
140                         comparison = -1;
141                     } else {
142                         comparison = fp1.hashCode() - fp2.hashCode();
143                     }
144                 }
145                 if (comparison < 0) {
146                     // Perform a swap
147                     isSorted = false;
148                     attributes.set(i, fp2);
149                     attributes.set(i + 1, fp1);
150                 }
151             }
152             if (isSorted) {
153                 break;
154             }
155         }
156     }
157 }
158