Coverage Report

Created: 2026-10-31 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/icu/icu4c/source/i18n/collationweights.cpp
Line
Count
Source
1
// © 2016 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
/*  
4
*******************************************************************************
5
*
6
*   Copyright (C) 1999-2015, International Business Machines
7
*   Corporation and others.  All Rights Reserved.
8
*
9
*******************************************************************************
10
*   file name:  collationweights.cpp
11
*   encoding:   UTF-8
12
*   tab size:   8 (not used)
13
*   indentation:4
14
*
15
*   created on: 2001mar08 as ucol_wgt.cpp
16
*   created by: Markus W. Scherer
17
*
18
*   This file contains code for allocating n collation element weights
19
*   between two exclusive limits.
20
*   It is used only internally by the collation tailoring builder.
21
*/
22
23
#include "unicode/utypes.h"
24
25
#if !UCONFIG_NO_COLLATION
26
27
#include "cmemory.h"
28
#include "collation.h"
29
#include "collationweights.h"
30
#include "uarrsort.h"
31
#include "uassert.h"
32
33
#ifdef UCOL_DEBUG
34
#   include <stdio.h>
35
#endif
36
37
U_NAMESPACE_BEGIN
38
39
/* collation element weight allocation -------------------------------------- */
40
41
/* helper functions for CE weights */
42
43
static inline uint32_t
44
2.14M
getWeightTrail(uint32_t weight, int32_t length) {
45
2.14M
    return (weight >> (8 * (4 - length))) & 0xff;
46
2.14M
}
47
48
static inline uint32_t
49
23.8k
setWeightTrail(uint32_t weight, int32_t length, uint32_t trail) {
50
23.8k
    length=8*(4-length);
51
23.8k
    return static_cast<uint32_t>((weight & (0xffffff00 << length)) | (trail << length));
52
23.8k
}
53
54
static inline uint32_t
55
2.11M
getWeightByte(uint32_t weight, int32_t idx) {
56
2.11M
    return getWeightTrail(weight, idx); /* same calculation */
57
2.11M
}
58
59
static inline uint32_t
60
2.11M
setWeightByte(uint32_t weight, int32_t idx, uint32_t byte) {
61
2.11M
    uint32_t mask; /* 0xffffffff except a 00 "hole" for the index-th byte */
62
63
2.11M
    idx*=8;
64
2.11M
    if(idx<32) {
65
1.34M
        mask = (static_cast<uint32_t>(0xffffffff)) >> idx;
66
1.34M
    } else {
67
        // Do not use uint32_t>>32 because on some platforms that does not shift at all
68
        // while we need it to become 0.
69
        // PowerPC: 0xffffffff>>32 = 0           (wanted)
70
        // x86:     0xffffffff>>32 = 0xffffffff  (not wanted)
71
        //
72
        // ANSI C99 6.5.7 Bitwise shift operators:
73
        // "If the value of the right operand is negative
74
        // or is greater than or equal to the width of the promoted left operand,
75
        // the behavior is undefined."
76
766k
        mask=0;
77
766k
    }
78
2.11M
    idx=32-idx;
79
2.11M
    mask|=0xffffff00<<idx;
80
2.11M
    return ((weight & mask) | (byte << idx));
81
2.11M
}
82
83
static inline uint32_t
84
20.1k
truncateWeight(uint32_t weight, int32_t length) {
85
20.1k
    return static_cast<uint32_t>(weight & (0xffffffff << (8 * (4 - length))));
86
20.1k
}
87
88
static inline uint32_t
89
29.6k
incWeightTrail(uint32_t weight, int32_t length) {
90
29.6k
    return static_cast<uint32_t>(weight + (1UL << (8 * (4 - length))));
91
29.6k
}
92
93
static inline uint32_t
94
29.5k
decWeightTrail(uint32_t weight, int32_t length) {
95
29.5k
    return static_cast<uint32_t>(weight - (1UL << (8 * (4 - length))));
96
29.5k
}
97
98
CollationWeights::CollationWeights()
99
11.3k
        : middleLength(0), rangeIndex(0), rangeCount(0) {
100
68.3k
    for(int32_t i = 0; i < 5; ++i) {
101
56.9k
        minBytes[i] = maxBytes[i] = 0;
102
56.9k
    }
103
11.3k
}
104
105
void
106
7.51k
CollationWeights::initForPrimary(UBool compressible) {
107
7.51k
    middleLength=1;
108
7.51k
    minBytes[1] = Collation::MERGE_SEPARATOR_BYTE + 1;
109
7.51k
    maxBytes[1] = Collation::TRAIL_WEIGHT_BYTE;
110
7.51k
    if(compressible) {
111
2.96k
        minBytes[2] = Collation::PRIMARY_COMPRESSION_LOW_BYTE + 1;
112
2.96k
        maxBytes[2] = Collation::PRIMARY_COMPRESSION_HIGH_BYTE - 1;
113
4.54k
    } else {
114
4.54k
        minBytes[2] = 2;
115
4.54k
        maxBytes[2] = 0xff;
116
4.54k
    }
117
7.51k
    minBytes[3] = 2;
118
7.51k
    maxBytes[3] = 0xff;
119
7.51k
    minBytes[4] = 2;
120
7.51k
    maxBytes[4] = 0xff;
121
7.51k
}
122
123
void
124
5.85k
CollationWeights::initForSecondary() {
125
    // We use only the lower 16 bits for secondary weights.
126
5.85k
    middleLength=3;
127
5.85k
    minBytes[1] = 0;
128
5.85k
    maxBytes[1] = 0;
129
5.85k
    minBytes[2] = 0;
130
5.85k
    maxBytes[2] = 0;
131
5.85k
    minBytes[3] = Collation::LEVEL_SEPARATOR_BYTE + 1;
132
5.85k
    maxBytes[3] = 0xff;
133
5.85k
    minBytes[4] = 2;
134
5.85k
    maxBytes[4] = 0xff;
135
5.85k
}
136
137
void
138
7.17k
CollationWeights::initForTertiary() {
139
    // We use only the lower 16 bits for tertiary weights.
140
7.17k
    middleLength=3;
141
7.17k
    minBytes[1] = 0;
142
7.17k
    maxBytes[1] = 0;
143
7.17k
    minBytes[2] = 0;
144
7.17k
    maxBytes[2] = 0;
145
    // We use only 6 bits per byte.
146
    // The other bits are used for case & quaternary weights.
147
7.17k
    minBytes[3] = Collation::LEVEL_SEPARATOR_BYTE + 1;
148
7.17k
    maxBytes[3] = 0x3f;
149
7.17k
    minBytes[4] = 2;
150
7.17k
    maxBytes[4] = 0x3f;
151
7.17k
}
152
153
uint32_t
154
2.10M
CollationWeights::incWeight(uint32_t weight, int32_t length) const {
155
2.11M
    for(;;) {
156
2.11M
        uint32_t byte=getWeightByte(weight, length);
157
2.11M
        if(byte<maxBytes[length]) {
158
2.10M
            return setWeightByte(weight, length, byte+1);
159
2.10M
        } else {
160
            // Roll over, set this byte to the minimum and increment the previous one.
161
8.50k
            weight=setWeightByte(weight, length, minBytes[length]);
162
8.50k
            --length;
163
8.50k
            U_ASSERT(length > 0);
164
8.50k
        }
165
2.11M
    }
166
2.10M
}
167
168
uint32_t
169
850
CollationWeights::incWeightByOffset(uint32_t weight, int32_t length, int32_t offset) const {
170
890
    for(;;) {
171
890
        offset += getWeightByte(weight, length);
172
890
        if (static_cast<uint32_t>(offset) <= maxBytes[length]) {
173
850
            return setWeightByte(weight, length, offset);
174
850
        } else {
175
            // Split the offset between this byte and the previous one.
176
40
            offset -= minBytes[length];
177
40
            weight = setWeightByte(weight, length, minBytes[length] + offset % countBytes(length));
178
40
            offset /= countBytes(length);
179
40
            --length;
180
40
            U_ASSERT(length > 0);
181
40
        }
182
890
    }
183
850
}
184
185
void
186
2.90k
CollationWeights::lengthenRange(WeightRange &range) const {
187
2.90k
    int32_t length=range.length+1;
188
2.90k
    range.start=setWeightTrail(range.start, length, minBytes[length]);
189
2.90k
    range.end=setWeightTrail(range.end, length, maxBytes[length]);
190
2.90k
    range.count*=countBytes(length);
191
2.90k
    range.length=length;
192
2.90k
}
193
194
/* for uprv_sortArray: sort ranges in weight order */
195
static int32_t U_CALLCONV
196
69
compareRanges(const void * /*context*/, const void *left, const void *right) {
197
69
    uint32_t l, r;
198
199
69
    l = static_cast<const CollationWeights::WeightRange*>(left)->start;
200
69
    r = static_cast<const CollationWeights::WeightRange*>(right)->start;
201
69
    if(l<r) {
202
69
        return -1;
203
69
    } else if(l>r) {
204
0
        return 1;
205
0
    } else {
206
0
        return 0;
207
0
    }
208
69
}
209
210
UBool
211
20.5k
CollationWeights::getWeightRanges(uint32_t lowerLimit, uint32_t upperLimit) {
212
20.5k
    U_ASSERT(lowerLimit != 0);
213
20.5k
    U_ASSERT(upperLimit != 0);
214
215
    /* get the lengths of the limits */
216
20.5k
    int32_t lowerLength=lengthOfWeight(lowerLimit);
217
20.5k
    int32_t upperLength=lengthOfWeight(upperLimit);
218
219
#ifdef UCOL_DEBUG
220
    printf("length of lower limit 0x%08lx is %ld\n", lowerLimit, lowerLength);
221
    printf("length of upper limit 0x%08lx is %ld\n", upperLimit, upperLength);
222
#endif
223
20.5k
    U_ASSERT(lowerLength>=middleLength);
224
    // Permit upperLength<middleLength: The upper limit for secondaries is 0x10000.
225
226
20.5k
    if(lowerLimit>=upperLimit) {
227
#ifdef UCOL_DEBUG
228
        printf("error: no space between lower & upper limits\n");
229
#endif
230
0
        return false;
231
0
    }
232
233
    /* check that neither is a prefix of the other */
234
20.5k
    if(lowerLength<upperLength) {
235
1.37k
        if(lowerLimit==truncateWeight(upperLimit, lowerLength)) {
236
#ifdef UCOL_DEBUG
237
            printf("error: lower limit 0x%08lx is a prefix of upper limit 0x%08lx\n", lowerLimit, upperLimit);
238
#endif
239
0
            return false;
240
0
        }
241
1.37k
    }
242
    /* if the upper limit is a prefix of the lower limit then the earlier test lowerLimit>=upperLimit has caught it */
243
244
20.5k
    WeightRange lower[5], middle, upper[5]; /* [0] and [1] are not used - this simplifies indexing */
245
20.5k
    uprv_memset(lower, 0, sizeof(lower));
246
20.5k
    uprv_memset(&middle, 0, sizeof(middle));
247
20.5k
    uprv_memset(upper, 0, sizeof(upper));
248
249
    /*
250
     * With the limit lengths of 1..4, there are up to 7 ranges for allocation:
251
     * range     minimum length
252
     * lower[4]  4
253
     * lower[3]  3
254
     * lower[2]  2
255
     * middle    1
256
     * upper[2]  2
257
     * upper[3]  3
258
     * upper[4]  4
259
     *
260
     * We are now going to calculate up to 7 ranges.
261
     * Some of them will typically overlap, so we will then have to merge and eliminate ranges.
262
     */
263
20.5k
    uint32_t weight=lowerLimit;
264
29.6k
    for(int32_t length=lowerLength; length>middleLength; --length) {
265
9.11k
        uint32_t trail=getWeightTrail(weight, length);
266
9.11k
        if(trail<maxBytes[length]) {
267
9.06k
            lower[length].start=incWeightTrail(weight, length);
268
9.06k
            lower[length].end=setWeightTrail(weight, length, maxBytes[length]);
269
9.06k
            lower[length].length=length;
270
9.06k
            lower[length].count=maxBytes[length]-trail;
271
9.06k
        }
272
9.11k
        weight=truncateWeight(weight, length-1);
273
9.11k
    }
274
20.5k
    if(weight<0xff000000) {
275
20.5k
        middle.start=incWeightTrail(weight, middleLength);
276
20.5k
    } else {
277
        // Prevent overflow for primary lead byte FF
278
        // which would yield a middle range starting at 0.
279
0
        middle.start=0xffffffff;  // no middle range
280
0
    }
281
282
20.5k
    weight=upperLimit;
283
30.2k
    for(int32_t length=upperLength; length>middleLength; --length) {
284
9.71k
        uint32_t trail=getWeightTrail(weight, length);
285
9.71k
        if(trail>minBytes[length]) {
286
8.97k
            upper[length].start=setWeightTrail(weight, length, minBytes[length]);
287
8.97k
            upper[length].end=decWeightTrail(weight, length);
288
8.97k
            upper[length].length=length;
289
8.97k
            upper[length].count=trail-minBytes[length];
290
8.97k
        }
291
9.71k
        weight=truncateWeight(weight, length-1);
292
9.71k
    }
293
20.5k
    middle.end=decWeightTrail(weight, middleLength);
294
295
    /* set the middle range */
296
20.5k
    middle.length=middleLength;
297
20.5k
    if(middle.end>=middle.start) {
298
12.5k
        middle.count = static_cast<int32_t>((middle.end - middle.start) >> (8 * (4 - middleLength))) + 1;
299
12.5k
    } else {
300
        /* no middle range, eliminate overlaps */
301
22.4k
        for(int32_t length=4; length>middleLength; --length) {
302
20.9k
            if(lower[length].count>0 && upper[length].count>0) {
303
                // Note: The lowerEnd and upperStart weights are versions of
304
                // lowerLimit and upperLimit (which are lowerLimit<upperLimit),
305
                // truncated (still less-or-equal)
306
                // and then with their last bytes changed to the
307
                // maxByte (for lowerEnd) or minByte (for upperStart).
308
6.47k
                const uint32_t lowerEnd=lower[length].end;
309
6.47k
                const uint32_t upperStart=upper[length].start;
310
6.47k
                UBool merged=false;
311
312
6.47k
                if(lowerEnd>upperStart) {
313
                    // These two lower and upper ranges collide.
314
                    // Since lowerLimit<upperLimit and lowerEnd and upperStart
315
                    // are versions with only their last bytes modified
316
                    // (and following ones removed/reset to 0),
317
                    // lowerEnd>upperStart is only possible
318
                    // if the leading bytes are equal
319
                    // and lastByte(lowerEnd)>lastByte(upperStart).
320
6.04k
                    U_ASSERT(truncateWeight(lowerEnd, length-1)==
321
6.04k
                            truncateWeight(upperStart, length-1));
322
                    // Intersect these two ranges.
323
6.04k
                    lower[length].end=upper[length].end;
324
6.04k
                    lower[length].count=
325
6.04k
                            static_cast<int32_t>(getWeightTrail(lower[length].end, length)) -
326
6.04k
                            static_cast<int32_t>(getWeightTrail(lower[length].start, length)) + 1;
327
                    // count might be <=0 in which case there is no room,
328
                    // and the range-collecting code below will ignore this range.
329
6.04k
                    merged=true;
330
6.04k
                } else if(lowerEnd==upperStart) {
331
                    // Not possible, unless minByte==maxByte which is not allowed.
332
0
                    U_ASSERT(minBytes[length]<maxBytes[length]);
333
436
                } else /* lowerEnd<upperStart */ {
334
436
                    if(incWeight(lowerEnd, length)==upperStart) {
335
                        // Merge adjacent ranges.
336
436
                        lower[length].end=upper[length].end;
337
436
                        lower[length].count+=upper[length].count;  // might be >countBytes
338
436
                        merged=true;
339
436
                    }
340
436
                }
341
6.47k
                if(merged) {
342
                    // Remove all shorter ranges.
343
                    // There was no room available for them between the ranges we just merged.
344
6.47k
                    upper[length].count=0;
345
8.24k
                    while(--length>middleLength) {
346
1.76k
                        lower[length].count=upper[length].count=0;
347
1.76k
                    }
348
6.47k
                    break;
349
6.47k
                }
350
6.47k
            }
351
20.9k
        }
352
7.98k
    }
353
354
#ifdef UCOL_DEBUG
355
    /* print ranges */
356
    for(int32_t length=4; length>=2; --length) {
357
        if(lower[length].count>0) {
358
            printf("lower[%ld] .start=0x%08lx .end=0x%08lx .count=%ld\n", length, lower[length].start, lower[length].end, lower[length].count);
359
        }
360
    }
361
    if(middle.count>0) {
362
        printf("middle   .start=0x%08lx .end=0x%08lx .count=%ld\n", middle.start, middle.end, middle.count);
363
    }
364
    for(int32_t length=2; length<=4; ++length) {
365
        if(upper[length].count>0) {
366
            printf("upper[%ld] .start=0x%08lx .end=0x%08lx .count=%ld\n", length, upper[length].start, upper[length].end, upper[length].count);
367
        }
368
    }
369
#endif
370
371
    /* copy the ranges, shortest first, into the result array */
372
20.5k
    rangeCount=0;
373
20.5k
    if(middle.count>0) {
374
12.5k
        uprv_memcpy(ranges, &middle, sizeof(WeightRange));
375
12.5k
        rangeCount=1;
376
12.5k
    }
377
56.0k
    for(int32_t length=middleLength+1; length<=4; ++length) {
378
        /* copy upper first so that later the middle range is more likely the first one to use */
379
35.5k
        if(upper[length].count>0) {
380
808
            uprv_memcpy(ranges+rangeCount, upper+length, sizeof(WeightRange));
381
808
            ++rangeCount;
382
808
        }
383
35.5k
        if(lower[length].count>0) {
384
7.32k
            uprv_memcpy(ranges+rangeCount, lower+length, sizeof(WeightRange));
385
7.32k
            ++rangeCount;
386
7.32k
        }
387
35.5k
    }
388
20.5k
    return rangeCount>0;
389
20.5k
}
390
391
UBool
392
20.7k
CollationWeights::allocWeightsInShortRanges(int32_t n, int32_t minLength) {
393
    // See if the first few minLength and minLength+1 ranges have enough weights.
394
23.8k
    for(int32_t i = 0; i < rangeCount && ranges[i].length <= (minLength + 1); ++i) {
395
20.9k
        if(n <= ranges[i].count) {
396
            // Use the first few minLength and minLength+1 ranges.
397
17.8k
            if(ranges[i].length > minLength) {
398
                // Reduce the number of weights from the last minLength+1 range
399
                // which might sort before some minLength ranges,
400
                // so that we use all weights in the minLength ranges.
401
51
                ranges[i].count = n;
402
51
            }
403
17.8k
            rangeCount = i + 1;
404
#ifdef UCOL_DEBUG
405
            printf("take first %ld ranges\n", rangeCount);
406
#endif
407
408
17.8k
            if(rangeCount>1) {
409
                /* sort the ranges by weight values */
410
69
                UErrorCode errorCode=U_ZERO_ERROR;
411
69
                uprv_sortArray(ranges, rangeCount, sizeof(WeightRange),
412
69
                               compareRanges, nullptr, false, &errorCode);
413
                /* ignore error code: we know that the internal sort function will not fail here */
414
69
            }
415
17.8k
            return true;
416
17.8k
        }
417
3.07k
        n -= ranges[i].count;  // still >0
418
3.07k
    }
419
2.93k
    return false;
420
20.7k
}
421
422
UBool
423
2.90k
CollationWeights::allocWeightsInMinLengthRanges(int32_t n, int32_t minLength) {
424
    // See if the minLength ranges have enough weights
425
    // when we split one and lengthen the following ones.
426
2.90k
    int32_t count = 0;
427
2.90k
    int32_t minLengthRangeCount;
428
2.90k
    for(minLengthRangeCount = 0;
429
5.81k
            minLengthRangeCount < rangeCount &&
430
2.97k
                ranges[minLengthRangeCount].length == minLength;
431
2.91k
            ++minLengthRangeCount) {
432
2.91k
        count += ranges[minLengthRangeCount].count;
433
2.91k
    }
434
435
2.90k
    int32_t nextCountBytes = countBytes(minLength + 1);
436
2.90k
    if(n > count * nextCountBytes) { return false; }
437
438
    // Use the minLength ranges. Merge them, and then split again as necessary.
439
2.65k
    uint32_t start = ranges[0].start;
440
2.65k
    uint32_t end = ranges[0].end;
441
2.66k
    for(int32_t i = 1; i < minLengthRangeCount; ++i) {
442
10
        if(ranges[i].start < start) { start = ranges[i].start; }
443
10
        if(ranges[i].end > end) { end = ranges[i].end; }
444
10
    }
445
446
    // Calculate how to split the range between minLength (count1) and minLength+1 (count2).
447
    // Goal:
448
    //   count1 + count2 * nextCountBytes = n
449
    //   count1 + count2 = count
450
    // These turn into
451
    //   (count - count2) + count2 * nextCountBytes = n
452
    // and then into the following count1 & count2 computations.
453
2.65k
    int32_t count2 = (n - count) / (nextCountBytes - 1);  // number of weights to be lengthened
454
2.65k
    int32_t count1 = count - count2;  // number of minLength weights
455
2.65k
    if(count2 == 0 || (count1 + count2 * nextCountBytes) < n) {
456
        // round up
457
2.63k
        ++count2;
458
2.63k
        --count1;
459
2.63k
        U_ASSERT((count1 + count2 * nextCountBytes) >= n);
460
2.63k
    }
461
462
2.65k
    ranges[0].start = start;
463
464
2.65k
    if(count1 == 0) {
465
        // Make one long range.
466
1.80k
        ranges[0].end = end;
467
1.80k
        ranges[0].count = count;
468
1.80k
        lengthenRange(ranges[0]);
469
1.80k
        rangeCount = 1;
470
1.80k
    } else {
471
        // Split the range, lengthen the second part.
472
#ifdef UCOL_DEBUG
473
        printf("split the range number %ld (out of %ld minLength ranges) by %ld:%ld\n",
474
               splitRange, rangeCount, count1, count2);
475
#endif
476
477
        // Next start = start + count1. First end = 1 before that.
478
850
        ranges[0].end = incWeightByOffset(start, minLength, count1 - 1);
479
850
        ranges[0].count = count1;
480
481
850
        ranges[1].start = incWeight(ranges[0].end, minLength);
482
850
        ranges[1].end = end;
483
850
        ranges[1].length = minLength;  // +1 when lengthened
484
850
        ranges[1].count = count2;  // *countBytes when lengthened
485
850
        lengthenRange(ranges[1]);
486
850
        rangeCount = 2;
487
850
    }
488
2.65k
    return true;
489
2.90k
}
490
491
/*
492
 * call getWeightRanges and then determine heuristically
493
 * which ranges to use for a given number of weights between (excluding)
494
 * two limits
495
 */
496
UBool
497
20.5k
CollationWeights::allocWeights(uint32_t lowerLimit, uint32_t upperLimit, int32_t n) {
498
#ifdef UCOL_DEBUG
499
    puts("");
500
#endif
501
502
20.5k
    if(!getWeightRanges(lowerLimit, upperLimit)) {
503
#ifdef UCOL_DEBUG
504
        printf("error: unable to get Weight ranges\n");
505
#endif
506
0
        return false;
507
0
    }
508
509
    /* try until we find suitably large ranges */
510
20.7k
    for(;;) {
511
        /* get the smallest number of bytes in a range */
512
20.7k
        int32_t minLength=ranges[0].length;
513
514
20.7k
        if(allocWeightsInShortRanges(n, minLength)) { break; }
515
516
2.93k
        if(minLength == 4) {
517
#ifdef UCOL_DEBUG
518
            printf("error: the maximum number of %ld weights is insufficient for n=%ld\n",
519
                   minLengthCount, n);
520
#endif
521
26
            return false;
522
26
        }
523
524
2.90k
        if(allocWeightsInMinLengthRanges(n, minLength)) { break; }
525
526
        /* no good match, lengthen all minLength ranges and iterate */
527
#ifdef UCOL_DEBUG
528
        printf("lengthen the short ranges from %ld bytes to %ld and iterate\n", minLength, minLength+1);
529
#endif
530
492
        for(int32_t i=0; i<rangeCount && ranges[i].length==minLength; ++i) {
531
246
            lengthenRange(ranges[i]);
532
246
        }
533
246
    }
534
535
#ifdef UCOL_DEBUG
536
    puts("final ranges:");
537
    for(int32_t i=0; i<rangeCount; ++i) {
538
        printf("ranges[%ld] .start=0x%08lx .end=0x%08lx .length=%ld .count=%ld\n",
539
               i, ranges[i].start, ranges[i].end, ranges[i].length, ranges[i].count);
540
    }
541
#endif
542
543
20.5k
    rangeIndex = 0;
544
20.5k
    return true;
545
20.5k
}
546
547
uint32_t
548
2.10M
CollationWeights::nextWeight() {
549
2.10M
    if(rangeIndex >= rangeCount) {
550
0
        return 0xffffffff;
551
2.10M
    } else {
552
        /* get the next weight */
553
2.10M
        WeightRange &range = ranges[rangeIndex];
554
2.10M
        uint32_t weight = range.start;
555
2.10M
        if(--range.count == 0) {
556
            /* this range is finished */
557
5.07k
            ++rangeIndex;
558
2.10M
        } else {
559
            /* increment the weight for the next value */
560
2.10M
            range.start = incWeight(weight, range.length);
561
2.10M
            U_ASSERT(range.start <= range.end);
562
2.10M
        }
563
564
2.10M
        return weight;
565
2.10M
    }
566
2.10M
}
567
568
U_NAMESPACE_END
569
570
#endif /* #if !UCONFIG_NO_COLLATION */