jpayne@69
|
1 // © 2016 and later: Unicode, Inc. and others.
|
jpayne@69
|
2 // License & terms of use: http://www.unicode.org/copyright.html
|
jpayne@69
|
3 /*
|
jpayne@69
|
4 *******************************************************************************
|
jpayne@69
|
5 *
|
jpayne@69
|
6 * Copyright (C) 2011-2014 International Business Machines
|
jpayne@69
|
7 * Corporation and others. All Rights Reserved.
|
jpayne@69
|
8 *
|
jpayne@69
|
9 *******************************************************************************
|
jpayne@69
|
10 */
|
jpayne@69
|
11
|
jpayne@69
|
12 #ifndef INDEXCHARS_H
|
jpayne@69
|
13 #define INDEXCHARS_H
|
jpayne@69
|
14
|
jpayne@69
|
15 #include "unicode/utypes.h"
|
jpayne@69
|
16
|
jpayne@69
|
17 #if U_SHOW_CPLUSPLUS_API
|
jpayne@69
|
18
|
jpayne@69
|
19 #include "unicode/uobject.h"
|
jpayne@69
|
20 #include "unicode/locid.h"
|
jpayne@69
|
21 #include "unicode/unistr.h"
|
jpayne@69
|
22
|
jpayne@69
|
23 #if !UCONFIG_NO_COLLATION
|
jpayne@69
|
24
|
jpayne@69
|
25 /**
|
jpayne@69
|
26 * \file
|
jpayne@69
|
27 * \brief C++ API: Index Characters
|
jpayne@69
|
28 */
|
jpayne@69
|
29
|
jpayne@69
|
30 U_CDECL_BEGIN
|
jpayne@69
|
31
|
jpayne@69
|
32 /**
|
jpayne@69
|
33 * Constants for Alphabetic Index Label Types.
|
jpayne@69
|
34 * The form of these enum constants anticipates having a plain C API
|
jpayne@69
|
35 * for Alphabetic Indexes that will also use them.
|
jpayne@69
|
36 * @stable ICU 4.8
|
jpayne@69
|
37 */
|
jpayne@69
|
38 typedef enum UAlphabeticIndexLabelType {
|
jpayne@69
|
39 /**
|
jpayne@69
|
40 * Normal Label, typically the starting letter of the names
|
jpayne@69
|
41 * in the bucket with this label.
|
jpayne@69
|
42 * @stable ICU 4.8
|
jpayne@69
|
43 */
|
jpayne@69
|
44 U_ALPHAINDEX_NORMAL = 0,
|
jpayne@69
|
45
|
jpayne@69
|
46 /**
|
jpayne@69
|
47 * Undeflow Label. The bucket with this label contains names
|
jpayne@69
|
48 * in scripts that sort before any of the bucket labels in this index.
|
jpayne@69
|
49 * @stable ICU 4.8
|
jpayne@69
|
50 */
|
jpayne@69
|
51 U_ALPHAINDEX_UNDERFLOW = 1,
|
jpayne@69
|
52
|
jpayne@69
|
53 /**
|
jpayne@69
|
54 * Inflow Label. The bucket with this label contains names
|
jpayne@69
|
55 * in scripts that sort between two of the bucket labels in this index.
|
jpayne@69
|
56 * Inflow labels are created when an index contains normal labels for
|
jpayne@69
|
57 * multiple scripts, and skips other scripts that sort between some of the
|
jpayne@69
|
58 * included scripts.
|
jpayne@69
|
59 * @stable ICU 4.8
|
jpayne@69
|
60 */
|
jpayne@69
|
61 U_ALPHAINDEX_INFLOW = 2,
|
jpayne@69
|
62
|
jpayne@69
|
63 /**
|
jpayne@69
|
64 * Overflow Label. Te bucket with this label contains names in scripts
|
jpayne@69
|
65 * that sort after all of the bucket labels in this index.
|
jpayne@69
|
66 * @stable ICU 4.8
|
jpayne@69
|
67 */
|
jpayne@69
|
68 U_ALPHAINDEX_OVERFLOW = 3
|
jpayne@69
|
69 } UAlphabeticIndexLabelType;
|
jpayne@69
|
70
|
jpayne@69
|
71
|
jpayne@69
|
72 struct UHashtable;
|
jpayne@69
|
73 U_CDECL_END
|
jpayne@69
|
74
|
jpayne@69
|
75 U_NAMESPACE_BEGIN
|
jpayne@69
|
76
|
jpayne@69
|
77 // Forward Declarations
|
jpayne@69
|
78
|
jpayne@69
|
79 class BucketList;
|
jpayne@69
|
80 class Collator;
|
jpayne@69
|
81 class RuleBasedCollator;
|
jpayne@69
|
82 class StringEnumeration;
|
jpayne@69
|
83 class UnicodeSet;
|
jpayne@69
|
84 class UVector;
|
jpayne@69
|
85
|
jpayne@69
|
86 /**
|
jpayne@69
|
87 * AlphabeticIndex supports the creation of a UI index appropriate for a given language.
|
jpayne@69
|
88 * It can support either direct use, or use with a client that doesn't support localized collation.
|
jpayne@69
|
89 * The following is an example of what an index might look like in a UI:
|
jpayne@69
|
90 *
|
jpayne@69
|
91 * <pre>
|
jpayne@69
|
92 * <b>... A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ...</b>
|
jpayne@69
|
93 *
|
jpayne@69
|
94 * <b>A</b>
|
jpayne@69
|
95 * Addison
|
jpayne@69
|
96 * Albertson
|
jpayne@69
|
97 * Azensky
|
jpayne@69
|
98 * <b>B</b>
|
jpayne@69
|
99 * Baker
|
jpayne@69
|
100 * ...
|
jpayne@69
|
101 * </pre>
|
jpayne@69
|
102 *
|
jpayne@69
|
103 * The class can generate a list of labels for use as a UI "index", that is, a list of
|
jpayne@69
|
104 * clickable characters (or character sequences) that allow the user to see a segment
|
jpayne@69
|
105 * (bucket) of a larger "target" list. That is, each label corresponds to a bucket in
|
jpayne@69
|
106 * the target list, where everything in the bucket is greater than or equal to the character
|
jpayne@69
|
107 * (according to the locale's collation). Strings can be added to the index;
|
jpayne@69
|
108 * they will be in sorted order in the right bucket.
|
jpayne@69
|
109 * <p>
|
jpayne@69
|
110 * The class also supports having buckets for strings before the first (underflow),
|
jpayne@69
|
111 * after the last (overflow), and between scripts (inflow). For example, if the index
|
jpayne@69
|
112 * is constructed with labels for Russian and English, Greek characters would fall
|
jpayne@69
|
113 * into an inflow bucket between the other two scripts.
|
jpayne@69
|
114 * <p>
|
jpayne@69
|
115 * The AlphabeticIndex class is not intended for public subclassing.
|
jpayne@69
|
116 *
|
jpayne@69
|
117 * <p><em>Note:</em> If you expect to have a lot of ASCII or Latin characters
|
jpayne@69
|
118 * as well as characters from the user's language,
|
jpayne@69
|
119 * then it is a good idea to call addLabels(Locale::getEnglish(), status).</p>
|
jpayne@69
|
120 *
|
jpayne@69
|
121 * <h2>Direct Use</h2>
|
jpayne@69
|
122 * <p>The following shows an example of building an index directly.
|
jpayne@69
|
123 * The "show..." methods below are just to illustrate usage.
|
jpayne@69
|
124 *
|
jpayne@69
|
125 * <pre>
|
jpayne@69
|
126 * // Create a simple index. "Item" is assumed to be an application
|
jpayne@69
|
127 * // defined type that the application's UI and other processing knows about,
|
jpayne@69
|
128 * // and that has a name.
|
jpayne@69
|
129 *
|
jpayne@69
|
130 * UErrorCode status = U_ZERO_ERROR;
|
jpayne@69
|
131 * AlphabeticIndex index = new AlphabeticIndex(desiredLocale, status);
|
jpayne@69
|
132 * index->addLabels(additionalLocale, status);
|
jpayne@69
|
133 * for (Item *item in some source of Items ) {
|
jpayne@69
|
134 * index->addRecord(item->name(), item, status);
|
jpayne@69
|
135 * }
|
jpayne@69
|
136 * ...
|
jpayne@69
|
137 * // Show index at top. We could skip or gray out empty buckets
|
jpayne@69
|
138 *
|
jpayne@69
|
139 * while (index->nextBucket(status)) {
|
jpayne@69
|
140 * if (showAll || index->getBucketRecordCount() != 0) {
|
jpayne@69
|
141 * showLabelAtTop(UI, index->getBucketLabel());
|
jpayne@69
|
142 * }
|
jpayne@69
|
143 * }
|
jpayne@69
|
144 * ...
|
jpayne@69
|
145 * // Show the buckets with their contents, skipping empty buckets
|
jpayne@69
|
146 *
|
jpayne@69
|
147 * index->resetBucketIterator(status);
|
jpayne@69
|
148 * while (index->nextBucket(status)) {
|
jpayne@69
|
149 * if (index->getBucketRecordCount() != 0) {
|
jpayne@69
|
150 * showLabelInList(UI, index->getBucketLabel());
|
jpayne@69
|
151 * while (index->nextRecord(status)) {
|
jpayne@69
|
152 * showIndexedItem(UI, static_cast<Item *>(index->getRecordData()))
|
jpayne@69
|
153 * </pre>
|
jpayne@69
|
154 *
|
jpayne@69
|
155 * The caller can build different UIs using this class.
|
jpayne@69
|
156 * For example, an index character could be omitted or grayed-out
|
jpayne@69
|
157 * if its bucket is empty. Small buckets could also be combined based on size, such as:
|
jpayne@69
|
158 *
|
jpayne@69
|
159 * <pre>
|
jpayne@69
|
160 * <b>... A-F G-N O-Z ...</b>
|
jpayne@69
|
161 * </pre>
|
jpayne@69
|
162 *
|
jpayne@69
|
163 * <h2>Client Support</h2>
|
jpayne@69
|
164 * <p>Callers can also use the AlphabeticIndex::ImmutableIndex, or the AlphabeticIndex itself,
|
jpayne@69
|
165 * to support sorting on a client that doesn't support AlphabeticIndex functionality.
|
jpayne@69
|
166 *
|
jpayne@69
|
167 * <p>The ImmutableIndex is both immutable and thread-safe.
|
jpayne@69
|
168 * The corresponding AlphabeticIndex methods are not thread-safe because
|
jpayne@69
|
169 * they "lazily" build the index buckets.
|
jpayne@69
|
170 * <ul>
|
jpayne@69
|
171 * <li>ImmutableIndex.getBucket(index) provides random access to all
|
jpayne@69
|
172 * buckets and their labels and label types.
|
jpayne@69
|
173 * <li>The AlphabeticIndex bucket iterator or ImmutableIndex.getBucket(0..getBucketCount-1)
|
jpayne@69
|
174 * can be used to get a list of the labels,
|
jpayne@69
|
175 * such as "...", "A", "B",..., and send that list to the client.
|
jpayne@69
|
176 * <li>When the client has a new name, it sends that name to the server.
|
jpayne@69
|
177 * The server needs to call the following methods,
|
jpayne@69
|
178 * and communicate the bucketIndex and collationKey back to the client.
|
jpayne@69
|
179 *
|
jpayne@69
|
180 * <pre>
|
jpayne@69
|
181 * int32_t bucketIndex = index.getBucketIndex(name, status);
|
jpayne@69
|
182 * const UnicodeString &label = immutableIndex.getBucket(bucketIndex)->getLabel(); // optional
|
jpayne@69
|
183 * int32_t skLength = collator.getSortKey(name, sk, skCapacity);
|
jpayne@69
|
184 * </pre>
|
jpayne@69
|
185 *
|
jpayne@69
|
186 * <li>The client would put the name (and associated information) into its bucket for bucketIndex. The sort key sk is a
|
jpayne@69
|
187 * sequence of bytes that can be compared with a binary compare, and produce the right localized result.</li>
|
jpayne@69
|
188 * </ul>
|
jpayne@69
|
189 *
|
jpayne@69
|
190 * @stable ICU 4.8
|
jpayne@69
|
191 */
|
jpayne@69
|
192 class U_I18N_API AlphabeticIndex: public UObject {
|
jpayne@69
|
193 public:
|
jpayne@69
|
194 /**
|
jpayne@69
|
195 * An index "bucket" with a label string and type.
|
jpayne@69
|
196 * It is referenced by getBucketIndex(),
|
jpayne@69
|
197 * and returned by ImmutableIndex.getBucket().
|
jpayne@69
|
198 *
|
jpayne@69
|
199 * The Bucket class is not intended for public subclassing.
|
jpayne@69
|
200 * @stable ICU 51
|
jpayne@69
|
201 */
|
jpayne@69
|
202 class U_I18N_API Bucket : public UObject {
|
jpayne@69
|
203 public:
|
jpayne@69
|
204 /**
|
jpayne@69
|
205 * Destructor.
|
jpayne@69
|
206 * @stable ICU 51
|
jpayne@69
|
207 */
|
jpayne@69
|
208 virtual ~Bucket();
|
jpayne@69
|
209
|
jpayne@69
|
210 /**
|
jpayne@69
|
211 * Returns the label string.
|
jpayne@69
|
212 *
|
jpayne@69
|
213 * @return the label string for the bucket
|
jpayne@69
|
214 * @stable ICU 51
|
jpayne@69
|
215 */
|
jpayne@69
|
216 const UnicodeString &getLabel() const { return label_; }
|
jpayne@69
|
217 /**
|
jpayne@69
|
218 * Returns whether this bucket is a normal, underflow, overflow, or inflow bucket.
|
jpayne@69
|
219 *
|
jpayne@69
|
220 * @return the bucket label type
|
jpayne@69
|
221 * @stable ICU 51
|
jpayne@69
|
222 */
|
jpayne@69
|
223 UAlphabeticIndexLabelType getLabelType() const { return labelType_; }
|
jpayne@69
|
224
|
jpayne@69
|
225 private:
|
jpayne@69
|
226 friend class AlphabeticIndex;
|
jpayne@69
|
227 friend class BucketList;
|
jpayne@69
|
228
|
jpayne@69
|
229 UnicodeString label_;
|
jpayne@69
|
230 UnicodeString lowerBoundary_;
|
jpayne@69
|
231 UAlphabeticIndexLabelType labelType_;
|
jpayne@69
|
232 Bucket *displayBucket_;
|
jpayne@69
|
233 int32_t displayIndex_;
|
jpayne@69
|
234 UVector *records_; // Records are owned by the inputList_ vector.
|
jpayne@69
|
235
|
jpayne@69
|
236 Bucket(const UnicodeString &label, // Parameter strings are copied.
|
jpayne@69
|
237 const UnicodeString &lowerBoundary,
|
jpayne@69
|
238 UAlphabeticIndexLabelType type);
|
jpayne@69
|
239 };
|
jpayne@69
|
240
|
jpayne@69
|
241 /**
|
jpayne@69
|
242 * Immutable, thread-safe version of AlphabeticIndex.
|
jpayne@69
|
243 * This class provides thread-safe methods for bucketing,
|
jpayne@69
|
244 * and random access to buckets and their properties,
|
jpayne@69
|
245 * but does not offer adding records to the index.
|
jpayne@69
|
246 *
|
jpayne@69
|
247 * The ImmutableIndex class is not intended for public subclassing.
|
jpayne@69
|
248 *
|
jpayne@69
|
249 * @stable ICU 51
|
jpayne@69
|
250 */
|
jpayne@69
|
251 class U_I18N_API ImmutableIndex : public UObject {
|
jpayne@69
|
252 public:
|
jpayne@69
|
253 /**
|
jpayne@69
|
254 * Destructor.
|
jpayne@69
|
255 * @stable ICU 51
|
jpayne@69
|
256 */
|
jpayne@69
|
257 virtual ~ImmutableIndex();
|
jpayne@69
|
258
|
jpayne@69
|
259 /**
|
jpayne@69
|
260 * Returns the number of index buckets and labels, including underflow/inflow/overflow.
|
jpayne@69
|
261 *
|
jpayne@69
|
262 * @return the number of index buckets
|
jpayne@69
|
263 * @stable ICU 51
|
jpayne@69
|
264 */
|
jpayne@69
|
265 int32_t getBucketCount() const;
|
jpayne@69
|
266
|
jpayne@69
|
267 /**
|
jpayne@69
|
268 * Finds the index bucket for the given name and returns the number of that bucket.
|
jpayne@69
|
269 * Use getBucket() to get the bucket's properties.
|
jpayne@69
|
270 *
|
jpayne@69
|
271 * @param name the string to be sorted into an index bucket
|
jpayne@69
|
272 * @param errorCode Error code, will be set with the reason if the
|
jpayne@69
|
273 * operation fails.
|
jpayne@69
|
274 * @return the bucket number for the name
|
jpayne@69
|
275 * @stable ICU 51
|
jpayne@69
|
276 */
|
jpayne@69
|
277 int32_t getBucketIndex(const UnicodeString &name, UErrorCode &errorCode) const;
|
jpayne@69
|
278
|
jpayne@69
|
279 /**
|
jpayne@69
|
280 * Returns the index-th bucket. Returns NULL if the index is out of range.
|
jpayne@69
|
281 *
|
jpayne@69
|
282 * @param index bucket number
|
jpayne@69
|
283 * @return the index-th bucket
|
jpayne@69
|
284 * @stable ICU 51
|
jpayne@69
|
285 */
|
jpayne@69
|
286 const Bucket *getBucket(int32_t index) const;
|
jpayne@69
|
287
|
jpayne@69
|
288 private:
|
jpayne@69
|
289 friend class AlphabeticIndex;
|
jpayne@69
|
290
|
jpayne@69
|
291 ImmutableIndex(BucketList *bucketList, Collator *collatorPrimaryOnly)
|
jpayne@69
|
292 : buckets_(bucketList), collatorPrimaryOnly_(collatorPrimaryOnly) {}
|
jpayne@69
|
293
|
jpayne@69
|
294 BucketList *buckets_;
|
jpayne@69
|
295 Collator *collatorPrimaryOnly_;
|
jpayne@69
|
296 };
|
jpayne@69
|
297
|
jpayne@69
|
298 /**
|
jpayne@69
|
299 * Construct an AlphabeticIndex object for the specified locale. If the locale's
|
jpayne@69
|
300 * data does not include index characters, a set of them will be
|
jpayne@69
|
301 * synthesized based on the locale's exemplar characters. The locale
|
jpayne@69
|
302 * determines the sorting order for both the index characters and the
|
jpayne@69
|
303 * user item names appearing under each Index character.
|
jpayne@69
|
304 *
|
jpayne@69
|
305 * @param locale the desired locale.
|
jpayne@69
|
306 * @param status Error code, will be set with the reason if the construction
|
jpayne@69
|
307 * of the AlphabeticIndex object fails.
|
jpayne@69
|
308 * @stable ICU 4.8
|
jpayne@69
|
309 */
|
jpayne@69
|
310 AlphabeticIndex(const Locale &locale, UErrorCode &status);
|
jpayne@69
|
311
|
jpayne@69
|
312 /**
|
jpayne@69
|
313 * Construct an AlphabeticIndex that uses a specific collator.
|
jpayne@69
|
314 *
|
jpayne@69
|
315 * The index will be created with no labels; the addLabels() function must be called
|
jpayne@69
|
316 * after creation to add the desired labels to the index.
|
jpayne@69
|
317 *
|
jpayne@69
|
318 * The index adopts the collator, and is responsible for deleting it.
|
jpayne@69
|
319 * The caller should make no further use of the collator after creating the index.
|
jpayne@69
|
320 *
|
jpayne@69
|
321 * @param collator The collator to use to order the contents of this index.
|
jpayne@69
|
322 * @param status Error code, will be set with the reason if the
|
jpayne@69
|
323 * operation fails.
|
jpayne@69
|
324 * @stable ICU 51
|
jpayne@69
|
325 */
|
jpayne@69
|
326 AlphabeticIndex(RuleBasedCollator *collator, UErrorCode &status);
|
jpayne@69
|
327
|
jpayne@69
|
328 /**
|
jpayne@69
|
329 * Add Labels to this Index. The labels are additions to those
|
jpayne@69
|
330 * that are already in the index; they do not replace the existing
|
jpayne@69
|
331 * ones.
|
jpayne@69
|
332 * @param additions The additional characters to add to the index, such as A-Z.
|
jpayne@69
|
333 * @param status Error code, will be set with the reason if the
|
jpayne@69
|
334 * operation fails.
|
jpayne@69
|
335 * @return this, for chaining
|
jpayne@69
|
336 * @stable ICU 4.8
|
jpayne@69
|
337 */
|
jpayne@69
|
338 virtual AlphabeticIndex &addLabels(const UnicodeSet &additions, UErrorCode &status);
|
jpayne@69
|
339
|
jpayne@69
|
340 /**
|
jpayne@69
|
341 * Add the index characters from a Locale to the index. The labels
|
jpayne@69
|
342 * are added to those that are already in the index; they do not replace the
|
jpayne@69
|
343 * existing index characters. The collation order for this index is not
|
jpayne@69
|
344 * changed; it remains that of the locale that was originally specified
|
jpayne@69
|
345 * when creating this Index.
|
jpayne@69
|
346 *
|
jpayne@69
|
347 * @param locale The locale whose index characters are to be added.
|
jpayne@69
|
348 * @param status Error code, will be set with the reason if the
|
jpayne@69
|
349 * operation fails.
|
jpayne@69
|
350 * @return this, for chaining
|
jpayne@69
|
351 * @stable ICU 4.8
|
jpayne@69
|
352 */
|
jpayne@69
|
353 virtual AlphabeticIndex &addLabels(const Locale &locale, UErrorCode &status);
|
jpayne@69
|
354
|
jpayne@69
|
355 /**
|
jpayne@69
|
356 * Destructor
|
jpayne@69
|
357 * @stable ICU 4.8
|
jpayne@69
|
358 */
|
jpayne@69
|
359 virtual ~AlphabeticIndex();
|
jpayne@69
|
360
|
jpayne@69
|
361 /**
|
jpayne@69
|
362 * Builds an immutable, thread-safe version of this instance, without data records.
|
jpayne@69
|
363 *
|
jpayne@69
|
364 * @return an immutable index instance
|
jpayne@69
|
365 * @stable ICU 51
|
jpayne@69
|
366 */
|
jpayne@69
|
367 ImmutableIndex *buildImmutableIndex(UErrorCode &errorCode);
|
jpayne@69
|
368
|
jpayne@69
|
369 /**
|
jpayne@69
|
370 * Get the Collator that establishes the ordering of the items in this index.
|
jpayne@69
|
371 * Ownership of the collator remains with the AlphabeticIndex instance.
|
jpayne@69
|
372 *
|
jpayne@69
|
373 * The returned collator is a reference to the internal collator used by this
|
jpayne@69
|
374 * index. It may be safely used to compare the names of items or to get
|
jpayne@69
|
375 * sort keys for names. However if any settings need to be changed,
|
jpayne@69
|
376 * or other non-const methods called, a cloned copy must be made first.
|
jpayne@69
|
377 *
|
jpayne@69
|
378 * @return The collator
|
jpayne@69
|
379 * @stable ICU 4.8
|
jpayne@69
|
380 */
|
jpayne@69
|
381 virtual const RuleBasedCollator &getCollator() const;
|
jpayne@69
|
382
|
jpayne@69
|
383
|
jpayne@69
|
384 /**
|
jpayne@69
|
385 * Get the default label used for abbreviated buckets *between* other index characters.
|
jpayne@69
|
386 * For example, consider the labels when Latin (X Y Z) and Greek (Α Β Γ) are used:
|
jpayne@69
|
387 *
|
jpayne@69
|
388 * X Y Z ... Α Β Γ.
|
jpayne@69
|
389 *
|
jpayne@69
|
390 * @return inflow label
|
jpayne@69
|
391 * @stable ICU 4.8
|
jpayne@69
|
392 */
|
jpayne@69
|
393 virtual const UnicodeString &getInflowLabel() const;
|
jpayne@69
|
394
|
jpayne@69
|
395 /**
|
jpayne@69
|
396 * Set the default label used for abbreviated buckets <i>between</i> other index characters.
|
jpayne@69
|
397 * An inflow label will be automatically inserted if two otherwise-adjacent label characters
|
jpayne@69
|
398 * are from different scripts, e.g. Latin and Cyrillic, and a third script, e.g. Greek,
|
jpayne@69
|
399 * sorts between the two. The default inflow character is an ellipsis (...)
|
jpayne@69
|
400 *
|
jpayne@69
|
401 * @param inflowLabel the new Inflow label.
|
jpayne@69
|
402 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
403 * @return this
|
jpayne@69
|
404 * @stable ICU 4.8
|
jpayne@69
|
405 */
|
jpayne@69
|
406 virtual AlphabeticIndex &setInflowLabel(const UnicodeString &inflowLabel, UErrorCode &status);
|
jpayne@69
|
407
|
jpayne@69
|
408
|
jpayne@69
|
409 /**
|
jpayne@69
|
410 * Get the special label used for items that sort after the last normal label,
|
jpayne@69
|
411 * and that would not otherwise have an appropriate label.
|
jpayne@69
|
412 *
|
jpayne@69
|
413 * @return the overflow label
|
jpayne@69
|
414 * @stable ICU 4.8
|
jpayne@69
|
415 */
|
jpayne@69
|
416 virtual const UnicodeString &getOverflowLabel() const;
|
jpayne@69
|
417
|
jpayne@69
|
418
|
jpayne@69
|
419 /**
|
jpayne@69
|
420 * Set the label used for items that sort after the last normal label,
|
jpayne@69
|
421 * and that would not otherwise have an appropriate label.
|
jpayne@69
|
422 *
|
jpayne@69
|
423 * @param overflowLabel the new overflow label.
|
jpayne@69
|
424 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
425 * @return this
|
jpayne@69
|
426 * @stable ICU 4.8
|
jpayne@69
|
427 */
|
jpayne@69
|
428 virtual AlphabeticIndex &setOverflowLabel(const UnicodeString &overflowLabel, UErrorCode &status);
|
jpayne@69
|
429
|
jpayne@69
|
430 /**
|
jpayne@69
|
431 * Get the special label used for items that sort before the first normal label,
|
jpayne@69
|
432 * and that would not otherwise have an appropriate label.
|
jpayne@69
|
433 *
|
jpayne@69
|
434 * @return underflow label
|
jpayne@69
|
435 * @stable ICU 4.8
|
jpayne@69
|
436 */
|
jpayne@69
|
437 virtual const UnicodeString &getUnderflowLabel() const;
|
jpayne@69
|
438
|
jpayne@69
|
439 /**
|
jpayne@69
|
440 * Set the label used for items that sort before the first normal label,
|
jpayne@69
|
441 * and that would not otherwise have an appropriate label.
|
jpayne@69
|
442 *
|
jpayne@69
|
443 * @param underflowLabel the new underflow label.
|
jpayne@69
|
444 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
445 * @return this
|
jpayne@69
|
446 * @stable ICU 4.8
|
jpayne@69
|
447 */
|
jpayne@69
|
448 virtual AlphabeticIndex &setUnderflowLabel(const UnicodeString &underflowLabel, UErrorCode &status);
|
jpayne@69
|
449
|
jpayne@69
|
450
|
jpayne@69
|
451 /**
|
jpayne@69
|
452 * Get the limit on the number of labels permitted in the index.
|
jpayne@69
|
453 * The number does not include over, under and inflow labels.
|
jpayne@69
|
454 *
|
jpayne@69
|
455 * @return maxLabelCount maximum number of labels.
|
jpayne@69
|
456 * @stable ICU 4.8
|
jpayne@69
|
457 */
|
jpayne@69
|
458 virtual int32_t getMaxLabelCount() const;
|
jpayne@69
|
459
|
jpayne@69
|
460 /**
|
jpayne@69
|
461 * Set a limit on the number of labels permitted in the index.
|
jpayne@69
|
462 * The number does not include over, under and inflow labels.
|
jpayne@69
|
463 * Currently, if the number is exceeded, then every
|
jpayne@69
|
464 * nth item is removed to bring the count down.
|
jpayne@69
|
465 * A more sophisticated mechanism may be available in the future.
|
jpayne@69
|
466 *
|
jpayne@69
|
467 * @param maxLabelCount the maximum number of labels.
|
jpayne@69
|
468 * @param status error code
|
jpayne@69
|
469 * @return This, for chaining
|
jpayne@69
|
470 * @stable ICU 4.8
|
jpayne@69
|
471 */
|
jpayne@69
|
472 virtual AlphabeticIndex &setMaxLabelCount(int32_t maxLabelCount, UErrorCode &status);
|
jpayne@69
|
473
|
jpayne@69
|
474
|
jpayne@69
|
475 /**
|
jpayne@69
|
476 * Add a record to the index. Each record will be associated with an index Bucket
|
jpayne@69
|
477 * based on the record's name. The list of records for each bucket will be sorted
|
jpayne@69
|
478 * based on the collation ordering of the names in the index's locale.
|
jpayne@69
|
479 * Records with duplicate names are permitted; they will be kept in the order
|
jpayne@69
|
480 * that they were added.
|
jpayne@69
|
481 *
|
jpayne@69
|
482 * @param name The display name for the Record. The Record will be placed in
|
jpayne@69
|
483 * a bucket based on this name.
|
jpayne@69
|
484 * @param data An optional pointer to user data associated with this
|
jpayne@69
|
485 * item. When iterating the contents of a bucket, both the
|
jpayne@69
|
486 * data pointer the name will be available for each Record.
|
jpayne@69
|
487 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
488 * @return This, for chaining.
|
jpayne@69
|
489 * @stable ICU 4.8
|
jpayne@69
|
490 */
|
jpayne@69
|
491 virtual AlphabeticIndex &addRecord(const UnicodeString &name, const void *data, UErrorCode &status);
|
jpayne@69
|
492
|
jpayne@69
|
493 /**
|
jpayne@69
|
494 * Remove all Records from the Index. The set of Buckets, which define the headings under
|
jpayne@69
|
495 * which records are classified, is not altered.
|
jpayne@69
|
496 *
|
jpayne@69
|
497 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
498 * @return This, for chaining.
|
jpayne@69
|
499 * @stable ICU 4.8
|
jpayne@69
|
500 */
|
jpayne@69
|
501 virtual AlphabeticIndex &clearRecords(UErrorCode &status);
|
jpayne@69
|
502
|
jpayne@69
|
503
|
jpayne@69
|
504 /** Get the number of labels in this index.
|
jpayne@69
|
505 * Note: may trigger lazy index construction.
|
jpayne@69
|
506 *
|
jpayne@69
|
507 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
508 * @return The number of labels in this index, including any under, over or
|
jpayne@69
|
509 * in-flow labels.
|
jpayne@69
|
510 * @stable ICU 4.8
|
jpayne@69
|
511 */
|
jpayne@69
|
512 virtual int32_t getBucketCount(UErrorCode &status);
|
jpayne@69
|
513
|
jpayne@69
|
514
|
jpayne@69
|
515 /** Get the total number of Records in this index, that is, the number
|
jpayne@69
|
516 * of <name, data> pairs added.
|
jpayne@69
|
517 *
|
jpayne@69
|
518 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
519 * @return The number of records in this index, that is, the total number
|
jpayne@69
|
520 * of (name, data) items added with addRecord().
|
jpayne@69
|
521 * @stable ICU 4.8
|
jpayne@69
|
522 */
|
jpayne@69
|
523 virtual int32_t getRecordCount(UErrorCode &status);
|
jpayne@69
|
524
|
jpayne@69
|
525
|
jpayne@69
|
526
|
jpayne@69
|
527 /**
|
jpayne@69
|
528 * Given the name of a record, return the zero-based index of the Bucket
|
jpayne@69
|
529 * in which the item should appear. The name need not be in the index.
|
jpayne@69
|
530 * A Record will not be added to the index by this function.
|
jpayne@69
|
531 * Bucket numbers are zero-based, in Bucket iteration order.
|
jpayne@69
|
532 *
|
jpayne@69
|
533 * @param itemName The name whose bucket position in the index is to be determined.
|
jpayne@69
|
534 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
535 * @return The bucket number for this name.
|
jpayne@69
|
536 * @stable ICU 4.8
|
jpayne@69
|
537 *
|
jpayne@69
|
538 */
|
jpayne@69
|
539 virtual int32_t getBucketIndex(const UnicodeString &itemName, UErrorCode &status);
|
jpayne@69
|
540
|
jpayne@69
|
541
|
jpayne@69
|
542 /**
|
jpayne@69
|
543 * Get the zero based index of the current Bucket from an iteration
|
jpayne@69
|
544 * over the Buckets of this index. Return -1 if no iteration is in process.
|
jpayne@69
|
545 * @return the index of the current Bucket
|
jpayne@69
|
546 * @stable ICU 4.8
|
jpayne@69
|
547 */
|
jpayne@69
|
548 virtual int32_t getBucketIndex() const;
|
jpayne@69
|
549
|
jpayne@69
|
550
|
jpayne@69
|
551 /**
|
jpayne@69
|
552 * Advance the iteration over the Buckets of this index. Return FALSE if
|
jpayne@69
|
553 * there are no more Buckets.
|
jpayne@69
|
554 *
|
jpayne@69
|
555 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
556 * U_ENUM_OUT_OF_SYNC_ERROR will be reported if the index is modified while
|
jpayne@69
|
557 * an enumeration of its contents are in process.
|
jpayne@69
|
558 *
|
jpayne@69
|
559 * @return TRUE if success, FALSE if at end of iteration
|
jpayne@69
|
560 * @stable ICU 4.8
|
jpayne@69
|
561 */
|
jpayne@69
|
562 virtual UBool nextBucket(UErrorCode &status);
|
jpayne@69
|
563
|
jpayne@69
|
564 /**
|
jpayne@69
|
565 * Return the name of the Label of the current bucket from an iteration over the buckets.
|
jpayne@69
|
566 * If the iteration is before the first Bucket (nextBucket() has not been called),
|
jpayne@69
|
567 * or after the last, return an empty string.
|
jpayne@69
|
568 *
|
jpayne@69
|
569 * @return the bucket label.
|
jpayne@69
|
570 * @stable ICU 4.8
|
jpayne@69
|
571 */
|
jpayne@69
|
572 virtual const UnicodeString &getBucketLabel() const;
|
jpayne@69
|
573
|
jpayne@69
|
574 /**
|
jpayne@69
|
575 * Return the type of the label for the current Bucket (selected by the
|
jpayne@69
|
576 * iteration over Buckets.)
|
jpayne@69
|
577 *
|
jpayne@69
|
578 * @return the label type.
|
jpayne@69
|
579 * @stable ICU 4.8
|
jpayne@69
|
580 */
|
jpayne@69
|
581 virtual UAlphabeticIndexLabelType getBucketLabelType() const;
|
jpayne@69
|
582
|
jpayne@69
|
583 /**
|
jpayne@69
|
584 * Get the number of <name, data> Records in the current Bucket.
|
jpayne@69
|
585 * If the current bucket iteration position is before the first label or after the
|
jpayne@69
|
586 * last, return 0.
|
jpayne@69
|
587 *
|
jpayne@69
|
588 * @return the number of Records.
|
jpayne@69
|
589 * @stable ICU 4.8
|
jpayne@69
|
590 */
|
jpayne@69
|
591 virtual int32_t getBucketRecordCount() const;
|
jpayne@69
|
592
|
jpayne@69
|
593
|
jpayne@69
|
594 /**
|
jpayne@69
|
595 * Reset the Bucket iteration for this index. The next call to nextBucket()
|
jpayne@69
|
596 * will restart the iteration at the first label.
|
jpayne@69
|
597 *
|
jpayne@69
|
598 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
599 * @return this, for chaining.
|
jpayne@69
|
600 * @stable ICU 4.8
|
jpayne@69
|
601 */
|
jpayne@69
|
602 virtual AlphabeticIndex &resetBucketIterator(UErrorCode &status);
|
jpayne@69
|
603
|
jpayne@69
|
604 /**
|
jpayne@69
|
605 * Advance to the next record in the current Bucket.
|
jpayne@69
|
606 * When nextBucket() is called, Record iteration is reset to just before the
|
jpayne@69
|
607 * first Record in the new Bucket.
|
jpayne@69
|
608 *
|
jpayne@69
|
609 * @param status Error code, will be set with the reason if the operation fails.
|
jpayne@69
|
610 * U_ENUM_OUT_OF_SYNC_ERROR will be reported if the index is modified while
|
jpayne@69
|
611 * an enumeration of its contents are in process.
|
jpayne@69
|
612 * @return TRUE if successful, FALSE when the iteration advances past the last item.
|
jpayne@69
|
613 * @stable ICU 4.8
|
jpayne@69
|
614 */
|
jpayne@69
|
615 virtual UBool nextRecord(UErrorCode &status);
|
jpayne@69
|
616
|
jpayne@69
|
617 /**
|
jpayne@69
|
618 * Get the name of the current Record.
|
jpayne@69
|
619 * Return an empty string if the Record iteration position is before first
|
jpayne@69
|
620 * or after the last.
|
jpayne@69
|
621 *
|
jpayne@69
|
622 * @return The name of the current index item.
|
jpayne@69
|
623 * @stable ICU 4.8
|
jpayne@69
|
624 */
|
jpayne@69
|
625 virtual const UnicodeString &getRecordName() const;
|
jpayne@69
|
626
|
jpayne@69
|
627
|
jpayne@69
|
628 /**
|
jpayne@69
|
629 * Return the data pointer of the Record currently being iterated over.
|
jpayne@69
|
630 * Return NULL if the current iteration position before the first item in this Bucket,
|
jpayne@69
|
631 * or after the last.
|
jpayne@69
|
632 *
|
jpayne@69
|
633 * @return The current Record's data pointer.
|
jpayne@69
|
634 * @stable ICU 4.8
|
jpayne@69
|
635 */
|
jpayne@69
|
636 virtual const void *getRecordData() const;
|
jpayne@69
|
637
|
jpayne@69
|
638
|
jpayne@69
|
639 /**
|
jpayne@69
|
640 * Reset the Record iterator position to before the first Record in the current Bucket.
|
jpayne@69
|
641 *
|
jpayne@69
|
642 * @return This, for chaining.
|
jpayne@69
|
643 * @stable ICU 4.8
|
jpayne@69
|
644 */
|
jpayne@69
|
645 virtual AlphabeticIndex &resetRecordIterator();
|
jpayne@69
|
646
|
jpayne@69
|
647 private:
|
jpayne@69
|
648 /**
|
jpayne@69
|
649 * No Copy constructor.
|
jpayne@69
|
650 * @internal
|
jpayne@69
|
651 */
|
jpayne@69
|
652 AlphabeticIndex(const AlphabeticIndex &other);
|
jpayne@69
|
653
|
jpayne@69
|
654 /**
|
jpayne@69
|
655 * No assignment.
|
jpayne@69
|
656 */
|
jpayne@69
|
657 AlphabeticIndex &operator =(const AlphabeticIndex & /*other*/) { return *this;}
|
jpayne@69
|
658
|
jpayne@69
|
659 /**
|
jpayne@69
|
660 * No Equality operators.
|
jpayne@69
|
661 * @internal
|
jpayne@69
|
662 */
|
jpayne@69
|
663 virtual UBool operator==(const AlphabeticIndex& other) const;
|
jpayne@69
|
664
|
jpayne@69
|
665 /**
|
jpayne@69
|
666 * Inequality operator.
|
jpayne@69
|
667 * @internal
|
jpayne@69
|
668 */
|
jpayne@69
|
669 virtual UBool operator!=(const AlphabeticIndex& other) const;
|
jpayne@69
|
670
|
jpayne@69
|
671 // Common initialization, for use from all constructors.
|
jpayne@69
|
672 void init(const Locale *locale, UErrorCode &status);
|
jpayne@69
|
673
|
jpayne@69
|
674 /**
|
jpayne@69
|
675 * This method is called to get the index exemplars. Normally these come from the locale directly,
|
jpayne@69
|
676 * but if they aren't available, we have to synthesize them.
|
jpayne@69
|
677 */
|
jpayne@69
|
678 void addIndexExemplars(const Locale &locale, UErrorCode &status);
|
jpayne@69
|
679 /**
|
jpayne@69
|
680 * Add Chinese index characters from the tailoring.
|
jpayne@69
|
681 */
|
jpayne@69
|
682 UBool addChineseIndexCharacters(UErrorCode &errorCode);
|
jpayne@69
|
683
|
jpayne@69
|
684 UVector *firstStringsInScript(UErrorCode &status);
|
jpayne@69
|
685
|
jpayne@69
|
686 static UnicodeString separated(const UnicodeString &item);
|
jpayne@69
|
687
|
jpayne@69
|
688 /**
|
jpayne@69
|
689 * Determine the best labels to use.
|
jpayne@69
|
690 * This is based on the exemplars, but we also process to make sure that they are unique,
|
jpayne@69
|
691 * and sort differently, and that the overall list is small enough.
|
jpayne@69
|
692 */
|
jpayne@69
|
693 void initLabels(UVector &indexCharacters, UErrorCode &errorCode) const;
|
jpayne@69
|
694 BucketList *createBucketList(UErrorCode &errorCode) const;
|
jpayne@69
|
695 void initBuckets(UErrorCode &errorCode);
|
jpayne@69
|
696 void clearBuckets();
|
jpayne@69
|
697 void internalResetBucketIterator();
|
jpayne@69
|
698
|
jpayne@69
|
699 public:
|
jpayne@69
|
700
|
jpayne@69
|
701 // The Record is declared public only to allow access from
|
jpayne@69
|
702 // implementation code written in plain C.
|
jpayne@69
|
703 // It is not intended for public use.
|
jpayne@69
|
704
|
jpayne@69
|
705 #ifndef U_HIDE_INTERNAL_API
|
jpayne@69
|
706 /**
|
jpayne@69
|
707 * A (name, data) pair, to be sorted by name into one of the index buckets.
|
jpayne@69
|
708 * The user data is not used by the index implementation.
|
jpayne@69
|
709 * \cond
|
jpayne@69
|
710 * @internal
|
jpayne@69
|
711 */
|
jpayne@69
|
712 struct Record: public UMemory {
|
jpayne@69
|
713 const UnicodeString name_;
|
jpayne@69
|
714 const void *data_;
|
jpayne@69
|
715 Record(const UnicodeString &name, const void *data);
|
jpayne@69
|
716 ~Record();
|
jpayne@69
|
717 };
|
jpayne@69
|
718 /** \endcond */
|
jpayne@69
|
719 #endif /* U_HIDE_INTERNAL_API */
|
jpayne@69
|
720
|
jpayne@69
|
721 private:
|
jpayne@69
|
722
|
jpayne@69
|
723 /**
|
jpayne@69
|
724 * Holds all user records before they are distributed into buckets.
|
jpayne@69
|
725 * Type of contents is (Record *)
|
jpayne@69
|
726 * @internal
|
jpayne@69
|
727 */
|
jpayne@69
|
728 UVector *inputList_;
|
jpayne@69
|
729
|
jpayne@69
|
730 int32_t labelsIterIndex_; // Index of next item to return.
|
jpayne@69
|
731 int32_t itemsIterIndex_;
|
jpayne@69
|
732 Bucket *currentBucket_; // While an iteration of the index in underway,
|
jpayne@69
|
733 // point to the bucket for the current label.
|
jpayne@69
|
734 // NULL when no iteration underway.
|
jpayne@69
|
735
|
jpayne@69
|
736 int32_t maxLabelCount_; // Limit on # of labels permitted in the index.
|
jpayne@69
|
737
|
jpayne@69
|
738 UnicodeSet *initialLabels_; // Initial (unprocessed) set of Labels. Union
|
jpayne@69
|
739 // of those explicitly set by the user plus
|
jpayne@69
|
740 // those from locales. Raw values, before
|
jpayne@69
|
741 // crunching into bucket labels.
|
jpayne@69
|
742
|
jpayne@69
|
743 UVector *firstCharsInScripts_; // The first character from each script,
|
jpayne@69
|
744 // in collation order.
|
jpayne@69
|
745
|
jpayne@69
|
746 RuleBasedCollator *collator_;
|
jpayne@69
|
747 RuleBasedCollator *collatorPrimaryOnly_;
|
jpayne@69
|
748
|
jpayne@69
|
749 // Lazy evaluated: null means that we have not built yet.
|
jpayne@69
|
750 BucketList *buckets_;
|
jpayne@69
|
751
|
jpayne@69
|
752 UnicodeString inflowLabel_;
|
jpayne@69
|
753 UnicodeString overflowLabel_;
|
jpayne@69
|
754 UnicodeString underflowLabel_;
|
jpayne@69
|
755 UnicodeString overflowComparisonString_;
|
jpayne@69
|
756
|
jpayne@69
|
757 UnicodeString emptyString_;
|
jpayne@69
|
758 };
|
jpayne@69
|
759
|
jpayne@69
|
760 U_NAMESPACE_END
|
jpayne@69
|
761
|
jpayne@69
|
762 #endif // !UCONFIG_NO_COLLATION
|
jpayne@69
|
763
|
jpayne@69
|
764 #endif /* U_SHOW_CPLUSPLUS_API */
|
jpayne@69
|
765
|
jpayne@69
|
766 #endif
|