intl/icu/source/i18n/ucol_wgt.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/intl/icu/source/i18n/ucol_wgt.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,577 @@
     1.4 +/*  
     1.5 +*******************************************************************************
     1.6 +*
     1.7 +*   Copyright (C) 1999-2011, International Business Machines
     1.8 +*   Corporation and others.  All Rights Reserved.
     1.9 +*
    1.10 +*******************************************************************************
    1.11 +*   file name:  ucol_wgt.cpp
    1.12 +*   encoding:   US-ASCII
    1.13 +*   tab size:   8 (not used)
    1.14 +*   indentation:4
    1.15 +*
    1.16 +*   created on: 2001mar08
    1.17 +*   created by: Markus W. Scherer
    1.18 +*
    1.19 +*   This file contains code for allocating n collation element weights
    1.20 +*   between two exclusive limits.
    1.21 +*   It is used only internally by ucol_bld.
    1.22 +*/
    1.23 +
    1.24 +#include "unicode/utypes.h"
    1.25 +
    1.26 +#if !UCONFIG_NO_COLLATION
    1.27 +
    1.28 +#include "ucol_imp.h"
    1.29 +#include "ucol_wgt.h"
    1.30 +#include "cmemory.h"
    1.31 +#include "uarrsort.h"
    1.32 +
    1.33 +#ifdef UCOL_DEBUG
    1.34 +#   include <stdio.h>
    1.35 +#endif
    1.36 +
    1.37 +/* collation element weight allocation -------------------------------------- */
    1.38 +
    1.39 +/* helper functions for CE weights */
    1.40 +
    1.41 +static inline int32_t
    1.42 +lengthOfWeight(uint32_t weight) {
    1.43 +    if((weight&0xffffff)==0) {
    1.44 +        return 1;
    1.45 +    } else if((weight&0xffff)==0) {
    1.46 +        return 2;
    1.47 +    } else if((weight&0xff)==0) {
    1.48 +        return 3;
    1.49 +    } else {
    1.50 +        return 4;
    1.51 +    }
    1.52 +}
    1.53 +
    1.54 +static inline uint32_t
    1.55 +getWeightTrail(uint32_t weight, int32_t length) {
    1.56 +    return (uint32_t)(weight>>(8*(4-length)))&0xff;
    1.57 +}
    1.58 +
    1.59 +static inline uint32_t
    1.60 +setWeightTrail(uint32_t weight, int32_t length, uint32_t trail) {
    1.61 +    length=8*(4-length);
    1.62 +    return (uint32_t)((weight&(0xffffff00<<length))|(trail<<length));
    1.63 +}
    1.64 +
    1.65 +static inline uint32_t
    1.66 +getWeightByte(uint32_t weight, int32_t idx) {
    1.67 +    return getWeightTrail(weight, idx); /* same calculation */
    1.68 +}
    1.69 +
    1.70 +static inline uint32_t
    1.71 +setWeightByte(uint32_t weight, int32_t idx, uint32_t byte) {
    1.72 +    uint32_t mask; /* 0xffffffff except a 00 "hole" for the index-th byte */
    1.73 +
    1.74 +    idx*=8;
    1.75 +    if(idx<32) {
    1.76 +        mask=((uint32_t)0xffffffff)>>idx;
    1.77 +    } else {
    1.78 +        // Do not use uint32_t>>32 because on some platforms that does not shift at all
    1.79 +        // while we need it to become 0.
    1.80 +        // PowerPC: 0xffffffff>>32 = 0           (wanted)
    1.81 +        // x86:     0xffffffff>>32 = 0xffffffff  (not wanted)
    1.82 +        //
    1.83 +        // ANSI C99 6.5.7 Bitwise shift operators:
    1.84 +        // "If the value of the right operand is negative
    1.85 +        // or is greater than or equal to the width of the promoted left operand,
    1.86 +        // the behavior is undefined."
    1.87 +        mask=0;
    1.88 +    }
    1.89 +    idx=32-idx;
    1.90 +    mask|=0xffffff00<<idx;
    1.91 +    return (uint32_t)((weight&mask)|(byte<<idx));
    1.92 +}
    1.93 +
    1.94 +static inline uint32_t
    1.95 +truncateWeight(uint32_t weight, int32_t length) {
    1.96 +    return (uint32_t)(weight&(0xffffffff<<(8*(4-length))));
    1.97 +}
    1.98 +
    1.99 +static inline uint32_t
   1.100 +incWeightTrail(uint32_t weight, int32_t length) {
   1.101 +    return (uint32_t)(weight+(1UL<<(8*(4-length))));
   1.102 +}
   1.103 +
   1.104 +static inline uint32_t
   1.105 +decWeightTrail(uint32_t weight, int32_t length) {
   1.106 +    return (uint32_t)(weight-(1UL<<(8*(4-length))));
   1.107 +}
   1.108 +
   1.109 +static inline uint32_t
   1.110 +incWeight(uint32_t weight, int32_t length, uint32_t maxByte) {
   1.111 +    uint32_t byte;
   1.112 +
   1.113 +    for(;;) {
   1.114 +        byte=getWeightByte(weight, length);
   1.115 +        if(byte<maxByte) {
   1.116 +            return setWeightByte(weight, length, byte+1);
   1.117 +        } else {
   1.118 +            /* roll over, set this byte to UCOL_BYTE_FIRST_TAILORED and increment the previous one */
   1.119 +            weight=setWeightByte(weight, length, UCOL_BYTE_FIRST_TAILORED);
   1.120 +            --length;
   1.121 +        }
   1.122 +    }
   1.123 +}
   1.124 +
   1.125 +static inline int32_t
   1.126 +lengthenRange(WeightRange *range, uint32_t maxByte, uint32_t countBytes) {
   1.127 +    int32_t length;
   1.128 +
   1.129 +    length=range->length2+1;
   1.130 +    range->start=setWeightTrail(range->start, length, UCOL_BYTE_FIRST_TAILORED);
   1.131 +    range->end=setWeightTrail(range->end, length, maxByte);
   1.132 +    range->count2*=countBytes;
   1.133 +    range->length2=length;
   1.134 +    return length;
   1.135 +}
   1.136 +
   1.137 +/* for uprv_sortArray: sort ranges in weight order */
   1.138 +static int32_t U_CALLCONV
   1.139 +compareRanges(const void * /*context*/, const void *left, const void *right) {
   1.140 +    uint32_t l, r;
   1.141 +
   1.142 +    l=((const WeightRange *)left)->start;
   1.143 +    r=((const WeightRange *)right)->start;
   1.144 +    if(l<r) {
   1.145 +        return -1;
   1.146 +    } else if(l>r) {
   1.147 +        return 1;
   1.148 +    } else {
   1.149 +        return 0;
   1.150 +    }
   1.151 +}
   1.152 +
   1.153 +/*
   1.154 + * take two CE weights and calculate the
   1.155 + * possible ranges of weights between the two limits, excluding them
   1.156 + * for weights with up to 4 bytes there are up to 2*4-1=7 ranges
   1.157 + */
   1.158 +static inline int32_t
   1.159 +getWeightRanges(uint32_t lowerLimit, uint32_t upperLimit,
   1.160 +                uint32_t maxByte, uint32_t countBytes,
   1.161 +                WeightRange ranges[7]) {
   1.162 +    WeightRange lower[5], middle, upper[5]; /* [0] and [1] are not used - this simplifies indexing */
   1.163 +    uint32_t weight, trail;
   1.164 +    int32_t length, lowerLength, upperLength, rangeCount;
   1.165 +
   1.166 +    /* assume that both lowerLimit & upperLimit are not 0 */
   1.167 +
   1.168 +    /* get the lengths of the limits */
   1.169 +    lowerLength=lengthOfWeight(lowerLimit);
   1.170 +    upperLength=lengthOfWeight(upperLimit);
   1.171 +
   1.172 +#ifdef UCOL_DEBUG
   1.173 +    printf("length of lower limit 0x%08lx is %ld\n", lowerLimit, lowerLength);
   1.174 +    printf("length of upper limit 0x%08lx is %ld\n", upperLimit, upperLength);
   1.175 +#endif
   1.176 +
   1.177 +    if(lowerLimit>=upperLimit) {
   1.178 +#ifdef UCOL_DEBUG
   1.179 +        printf("error: no space between lower & upper limits\n");
   1.180 +#endif
   1.181 +        return 0;
   1.182 +    }
   1.183 +
   1.184 +    /* check that neither is a prefix of the other */
   1.185 +    if(lowerLength<upperLength) {
   1.186 +        if(lowerLimit==truncateWeight(upperLimit, lowerLength)) {
   1.187 +#ifdef UCOL_DEBUG
   1.188 +            printf("error: lower limit 0x%08lx is a prefix of upper limit 0x%08lx\n", lowerLimit, upperLimit);
   1.189 +#endif
   1.190 +            return 0;
   1.191 +        }
   1.192 +    }
   1.193 +    /* if the upper limit is a prefix of the lower limit then the earlier test lowerLimit>=upperLimit has caught it */
   1.194 +
   1.195 +    /* reset local variables */
   1.196 +    uprv_memset(lower, 0, sizeof(lower));
   1.197 +    uprv_memset(&middle, 0, sizeof(middle));
   1.198 +    uprv_memset(upper, 0, sizeof(upper));
   1.199 +
   1.200 +    /*
   1.201 +     * With the limit lengths of 1..4, there are up to 7 ranges for allocation:
   1.202 +     * range     minimum length
   1.203 +     * lower[4]  4
   1.204 +     * lower[3]  3
   1.205 +     * lower[2]  2
   1.206 +     * middle    1
   1.207 +     * upper[2]  2
   1.208 +     * upper[3]  3
   1.209 +     * upper[4]  4
   1.210 +     *
   1.211 +     * We are now going to calculate up to 7 ranges.
   1.212 +     * Some of them will typically overlap, so we will then have to merge and eliminate ranges.
   1.213 +     */
   1.214 +    weight=lowerLimit;
   1.215 +    for(length=lowerLength; length>=2; --length) {
   1.216 +        trail=getWeightTrail(weight, length);
   1.217 +        if(trail<maxByte) {
   1.218 +            lower[length].start=incWeightTrail(weight, length);
   1.219 +            lower[length].end=setWeightTrail(weight, length, maxByte);
   1.220 +            lower[length].length=length;
   1.221 +            lower[length].count=maxByte-trail;
   1.222 +        }
   1.223 +        weight=truncateWeight(weight, length-1);
   1.224 +    }
   1.225 +    middle.start=incWeightTrail(weight, 1);
   1.226 +
   1.227 +    weight=upperLimit;
   1.228 +    for(length=upperLength; length>=2; --length) {
   1.229 +        trail=getWeightTrail(weight, length);
   1.230 +        if(trail>UCOL_BYTE_FIRST_TAILORED) {
   1.231 +            upper[length].start=setWeightTrail(weight, length, UCOL_BYTE_FIRST_TAILORED);
   1.232 +            upper[length].end=decWeightTrail(weight, length);
   1.233 +            upper[length].length=length;
   1.234 +            upper[length].count=trail-UCOL_BYTE_FIRST_TAILORED;
   1.235 +        }
   1.236 +        weight=truncateWeight(weight, length-1);
   1.237 +    }
   1.238 +    middle.end=decWeightTrail(weight, 1);
   1.239 +
   1.240 +    /* set the middle range */
   1.241 +    middle.length=1;
   1.242 +    if(middle.end>=middle.start) {
   1.243 +        middle.count=(int32_t)((middle.end-middle.start)>>24)+1;
   1.244 +    } else {
   1.245 +        /* eliminate overlaps */
   1.246 +        uint32_t start, end;
   1.247 +
   1.248 +        /* remove the middle range */
   1.249 +        middle.count=0;
   1.250 +
   1.251 +        /* reduce or remove the lower ranges that go beyond upperLimit */
   1.252 +        for(length=4; length>=2; --length) {
   1.253 +            if(lower[length].count>0 && upper[length].count>0) {
   1.254 +                start=upper[length].start;
   1.255 +                end=lower[length].end;
   1.256 +
   1.257 +                if(end>=start || incWeight(end, length, maxByte)==start) {
   1.258 +                    /* lower and upper ranges collide or are directly adjacent: merge these two and remove all shorter ranges */
   1.259 +                    start=lower[length].start;
   1.260 +                    end=lower[length].end=upper[length].end;
   1.261 +                    /*
   1.262 +                     * merging directly adjacent ranges needs to subtract the 0/1 gaps in between;
   1.263 +                     * it may result in a range with count>countBytes
   1.264 +                     */
   1.265 +                    lower[length].count=
   1.266 +                        (int32_t)(getWeightTrail(end, length)-getWeightTrail(start, length)+1+
   1.267 +                                  countBytes*(getWeightByte(end, length-1)-getWeightByte(start, length-1)));
   1.268 +                    upper[length].count=0;
   1.269 +                    while(--length>=2) {
   1.270 +                        lower[length].count=upper[length].count=0;
   1.271 +                    }
   1.272 +                    break;
   1.273 +                }
   1.274 +            }
   1.275 +        }
   1.276 +    }
   1.277 +
   1.278 +#ifdef UCOL_DEBUG
   1.279 +    /* print ranges */
   1.280 +    for(length=4; length>=2; --length) {
   1.281 +        if(lower[length].count>0) {
   1.282 +            printf("lower[%ld] .start=0x%08lx .end=0x%08lx .count=%ld\n", length, lower[length].start, lower[length].end, lower[length].count);
   1.283 +        }
   1.284 +    }
   1.285 +    if(middle.count>0) {
   1.286 +        printf("middle   .start=0x%08lx .end=0x%08lx .count=%ld\n", middle.start, middle.end, middle.count);
   1.287 +    }
   1.288 +    for(length=2; length<=4; ++length) {
   1.289 +        if(upper[length].count>0) {
   1.290 +            printf("upper[%ld] .start=0x%08lx .end=0x%08lx .count=%ld\n", length, upper[length].start, upper[length].end, upper[length].count);
   1.291 +        }
   1.292 +    }
   1.293 +#endif
   1.294 +
   1.295 +    /* copy the ranges, shortest first, into the result array */
   1.296 +    rangeCount=0;
   1.297 +    if(middle.count>0) {
   1.298 +        uprv_memcpy(ranges, &middle, sizeof(WeightRange));
   1.299 +        rangeCount=1;
   1.300 +    }
   1.301 +    for(length=2; length<=4; ++length) {
   1.302 +        /* copy upper first so that later the middle range is more likely the first one to use */
   1.303 +        if(upper[length].count>0) {
   1.304 +            uprv_memcpy(ranges+rangeCount, upper+length, sizeof(WeightRange));
   1.305 +            ++rangeCount;
   1.306 +        }
   1.307 +        if(lower[length].count>0) {
   1.308 +            uprv_memcpy(ranges+rangeCount, lower+length, sizeof(WeightRange));
   1.309 +            ++rangeCount;
   1.310 +        }
   1.311 +    }
   1.312 +    return rangeCount;
   1.313 +}
   1.314 +
   1.315 +/*
   1.316 + * call getWeightRanges and then determine heuristically
   1.317 + * which ranges to use for a given number of weights between (excluding)
   1.318 + * two limits
   1.319 + */
   1.320 +U_CFUNC int32_t
   1.321 +ucol_allocWeights(uint32_t lowerLimit, uint32_t upperLimit,
   1.322 +                  uint32_t n,
   1.323 +                  uint32_t maxByte,
   1.324 +                  WeightRange ranges[7]) {
   1.325 +    /* number of usable byte values 3..maxByte */
   1.326 +    uint32_t countBytes=maxByte-UCOL_BYTE_FIRST_TAILORED+1;
   1.327 +
   1.328 +    uint32_t lengthCounts[6]; /* [0] unused, [5] to make index checks unnecessary */
   1.329 +    uint32_t maxCount;
   1.330 +    int32_t i, rangeCount, minLength/*, maxLength*/;
   1.331 +
   1.332 +    /* countBytes to the power of index */
   1.333 +    uint32_t powers[5];
   1.334 +    /* gcc requires explicit initialization */
   1.335 +    powers[0] = 1;
   1.336 +    powers[1] = countBytes;
   1.337 +    powers[2] = countBytes*countBytes;
   1.338 +    powers[3] = countBytes*countBytes*countBytes;
   1.339 +    powers[4] = countBytes*countBytes*countBytes*countBytes;
   1.340 +
   1.341 +#ifdef UCOL_DEBUG
   1.342 +    puts("");
   1.343 +#endif
   1.344 +
   1.345 +    rangeCount=getWeightRanges(lowerLimit, upperLimit, maxByte, countBytes, ranges);
   1.346 +    if(rangeCount<=0) {
   1.347 +#ifdef UCOL_DEBUG
   1.348 +        printf("error: unable to get Weight ranges\n");
   1.349 +#endif
   1.350 +        return 0;
   1.351 +    }
   1.352 +
   1.353 +    /* what is the maximum number of weights with these ranges? */
   1.354 +    maxCount=0;
   1.355 +    for(i=0; i<rangeCount; ++i) {
   1.356 +        maxCount+=(uint32_t)ranges[i].count*powers[4-ranges[i].length];
   1.357 +    }
   1.358 +    if(maxCount>=n) {
   1.359 +#ifdef UCOL_DEBUG
   1.360 +        printf("the maximum number of %lu weights is sufficient for n=%lu\n", maxCount, n);
   1.361 +#endif
   1.362 +    } else {
   1.363 +#ifdef UCOL_DEBUG
   1.364 +        printf("error: the maximum number of %lu weights is insufficient for n=%lu\n", maxCount, n);
   1.365 +#endif
   1.366 +        return 0;
   1.367 +    }
   1.368 +
   1.369 +    /* set the length2 and count2 fields */
   1.370 +    for(i=0; i<rangeCount; ++i) {
   1.371 +        ranges[i].length2=ranges[i].length;
   1.372 +        ranges[i].count2=(uint32_t)ranges[i].count;
   1.373 +    }
   1.374 +
   1.375 +    /* try until we find suitably large ranges */
   1.376 +    for(;;) {
   1.377 +        /* get the smallest number of bytes in a range */
   1.378 +        minLength=ranges[0].length2;
   1.379 +
   1.380 +        /* sum up the number of elements that fit into ranges of each byte length */
   1.381 +        uprv_memset(lengthCounts, 0, sizeof(lengthCounts));
   1.382 +        for(i=0; i<rangeCount; ++i) {
   1.383 +            lengthCounts[ranges[i].length2]+=ranges[i].count2;
   1.384 +        }
   1.385 +
   1.386 +        /* now try to allocate n elements in the available short ranges */
   1.387 +        if(n<=(lengthCounts[minLength]+lengthCounts[minLength+1])) {
   1.388 +            /* trivial cases, use the first few ranges */
   1.389 +            maxCount=0;
   1.390 +            rangeCount=0;
   1.391 +            do {
   1.392 +                maxCount+=ranges[rangeCount].count2;
   1.393 +                ++rangeCount;
   1.394 +            } while(n>maxCount);
   1.395 +#ifdef UCOL_DEBUG
   1.396 +            printf("take first %ld ranges\n", rangeCount);
   1.397 +#endif
   1.398 +            break;
   1.399 +        } else if(n<=ranges[0].count2*countBytes) {
   1.400 +            /* easy case, just make this one range large enough by lengthening it once more, possibly split it */
   1.401 +            uint32_t count1, count2, power_1, power;
   1.402 +
   1.403 +            /*maxLength=minLength+1;*/
   1.404 +
   1.405 +            /* calculate how to split the range between maxLength-1 (count1) and maxLength (count2) */
   1.406 +            power_1=powers[minLength-ranges[0].length];
   1.407 +            power=power_1*countBytes;
   1.408 +            count2=(n+power-1)/power;
   1.409 +            count1=ranges[0].count-count2;
   1.410 +
   1.411 +            /* split the range */
   1.412 +#ifdef UCOL_DEBUG
   1.413 +            printf("split the first range %ld:%ld\n", count1, count2);
   1.414 +#endif
   1.415 +            if(count1<1) {
   1.416 +                rangeCount=1;
   1.417 +
   1.418 +                /* lengthen the entire range to maxLength */
   1.419 +                lengthenRange(ranges, maxByte, countBytes);
   1.420 +            } else {
   1.421 +                /* really split the range */
   1.422 +                uint32_t byte;
   1.423 +
   1.424 +                /* create a new range with the end and initial and current length of the old one */
   1.425 +                rangeCount=2;
   1.426 +                ranges[1].end=ranges[0].end;
   1.427 +                ranges[1].length=ranges[0].length;
   1.428 +                ranges[1].length2=minLength;
   1.429 +
   1.430 +                /* set the end of the first range according to count1 */
   1.431 +                i=ranges[0].length;
   1.432 +                byte=getWeightByte(ranges[0].start, i)+count1-1;
   1.433 +
   1.434 +                /*
   1.435 +                 * ranges[0].count and count1 may be >countBytes
   1.436 +                 * from merging adjacent ranges;
   1.437 +                 * byte>maxByte is possible
   1.438 +                 */
   1.439 +                if(byte<=maxByte) {
   1.440 +                    ranges[0].end=setWeightByte(ranges[0].start, i, byte);
   1.441 +                } else /* byte>maxByte */ {
   1.442 +                    ranges[0].end=setWeightByte(incWeight(ranges[0].start, i-1, maxByte), i, byte-countBytes);
   1.443 +                }
   1.444 +
   1.445 +                /* set the bytes in the end weight at length+1..length2 to maxByte */
   1.446 +                byte=(maxByte<<24)|(maxByte<<16)|(maxByte<<8)|maxByte; /* this used to be 0xffffffff */
   1.447 +                ranges[0].end=truncateWeight(ranges[0].end, i)|
   1.448 +                              ((byte>>(8*i))&(byte<<(8*(4-minLength))));
   1.449 +
   1.450 +                /* set the start of the second range to immediately follow the end of the first one */
   1.451 +                ranges[1].start=incWeight(ranges[0].end, minLength, maxByte);
   1.452 +
   1.453 +                /* set the count values (informational) */
   1.454 +                ranges[0].count=count1;
   1.455 +                ranges[1].count=count2;
   1.456 +
   1.457 +                ranges[0].count2=count1*power_1;
   1.458 +                ranges[1].count2=count2*power_1; /* will be *countBytes when lengthened */
   1.459 +
   1.460 +                /* lengthen the second range to maxLength */
   1.461 +                lengthenRange(ranges+1, maxByte, countBytes);
   1.462 +            }
   1.463 +            break;
   1.464 +        }
   1.465 +
   1.466 +        /* no good match, lengthen all minLength ranges and iterate */
   1.467 +#ifdef UCOL_DEBUG
   1.468 +        printf("lengthen the short ranges from %ld bytes to %ld and iterate\n", minLength, minLength+1);
   1.469 +#endif
   1.470 +        for(i=0; ranges[i].length2==minLength; ++i) {
   1.471 +            lengthenRange(ranges+i, maxByte, countBytes);
   1.472 +        }
   1.473 +    }
   1.474 +
   1.475 +    if(rangeCount>1) {
   1.476 +        /* sort the ranges by weight values */
   1.477 +        UErrorCode errorCode=U_ZERO_ERROR;
   1.478 +        uprv_sortArray(ranges, rangeCount, sizeof(WeightRange), compareRanges, NULL, FALSE, &errorCode);
   1.479 +        /* ignore error code: we know that the internal sort function will not fail here */
   1.480 +    }
   1.481 +
   1.482 +#ifdef UCOL_DEBUG
   1.483 +    puts("final ranges:");
   1.484 +    for(i=0; i<rangeCount; ++i) {
   1.485 +        printf("ranges[%ld] .start=0x%08lx .end=0x%08lx .length=%ld .length2=%ld .count=%ld .count2=%lu\n",
   1.486 +               i, ranges[i].start, ranges[i].end, ranges[i].length, ranges[i].length2, ranges[i].count, ranges[i].count2);
   1.487 +    }
   1.488 +#endif
   1.489 +
   1.490 +    /* set maxByte in ranges[0] for ucol_nextWeight() */
   1.491 +    ranges[0].count=maxByte;
   1.492 +
   1.493 +    return rangeCount;
   1.494 +}
   1.495 +
   1.496 +/*
   1.497 + * given a set of ranges calculated by ucol_allocWeights(),
   1.498 + * iterate through the weights
   1.499 + */
   1.500 +U_CFUNC uint32_t
   1.501 +ucol_nextWeight(WeightRange ranges[], int32_t *pRangeCount) {
   1.502 +    if(*pRangeCount<=0) {
   1.503 +        return 0xffffffff;
   1.504 +    } else {
   1.505 +        uint32_t weight, maxByte;
   1.506 +
   1.507 +        /* get maxByte from the .count field */
   1.508 +        maxByte=ranges[0].count;
   1.509 +
   1.510 +        /* get the next weight */
   1.511 +        weight=ranges[0].start;
   1.512 +        if(weight==ranges[0].end) {
   1.513 +            /* this range is finished, remove it and move the following ones up */
   1.514 +            if(--*pRangeCount>0) {
   1.515 +                uprv_memmove(ranges, ranges+1, *pRangeCount*sizeof(WeightRange));
   1.516 +                ranges[0].count=maxByte; /* keep maxByte in ranges[0] */
   1.517 +            }
   1.518 +        } else {
   1.519 +            /* increment the weight for the next value */
   1.520 +            ranges[0].start=incWeight(weight, ranges[0].length2, maxByte);
   1.521 +        }
   1.522 +
   1.523 +        return weight;
   1.524 +    }
   1.525 +}
   1.526 +
   1.527 +#if 0 // #ifdef UCOL_DEBUG
   1.528 +
   1.529 +static void
   1.530 +testAlloc(uint32_t lowerLimit, uint32_t upperLimit, uint32_t n, UBool enumerate) {
   1.531 +    WeightRange ranges[8];
   1.532 +    int32_t rangeCount;
   1.533 +
   1.534 +    rangeCount=ucol_allocWeights(lowerLimit, upperLimit, n, ranges);
   1.535 +    if(enumerate) {
   1.536 +        uint32_t weight;
   1.537 +
   1.538 +        while(n>0) {
   1.539 +            weight=ucol_nextWeight(ranges, &rangeCount);
   1.540 +            if(weight==0xffffffff) {
   1.541 +                printf("error: 0xffffffff with %lu more weights to go\n", n);
   1.542 +                break;
   1.543 +            }
   1.544 +            printf("    0x%08lx\n", weight);
   1.545 +            --n;
   1.546 +        }
   1.547 +    }
   1.548 +}
   1.549 +
   1.550 +extern int
   1.551 +main(int argc, const char *argv[]) {
   1.552 +#if 0
   1.553 +#endif
   1.554 +    testAlloc(0x364214fc, 0x44b87d23, 5, FALSE);
   1.555 +    testAlloc(0x36421500, 0x44b87d23, 5, FALSE);
   1.556 +    testAlloc(0x36421500, 0x44b87d23, 20, FALSE);
   1.557 +    testAlloc(0x36421500, 0x44b87d23, 13700, FALSE);
   1.558 +    testAlloc(0x36421500, 0x38b87d23, 1, FALSE);
   1.559 +    testAlloc(0x36421500, 0x38b87d23, 20, FALSE);
   1.560 +    testAlloc(0x36421500, 0x38b87d23, 200, TRUE);
   1.561 +    testAlloc(0x36421500, 0x38b87d23, 13700, FALSE);
   1.562 +    testAlloc(0x36421500, 0x37b87d23, 13700, FALSE);
   1.563 +    testAlloc(0x36ef1500, 0x37b87d23, 13700, FALSE);
   1.564 +    testAlloc(0x36421500, 0x36b87d23, 13700, FALSE);
   1.565 +    testAlloc(0x36b87122, 0x36b87d23, 13700, FALSE);
   1.566 +    testAlloc(0x49000000, 0x4a600000, 13700, FALSE);
   1.567 +    testAlloc(0x9fffffff, 0xd0000000, 13700, FALSE);
   1.568 +    testAlloc(0x9fffffff, 0xd0000000, 67400, FALSE);
   1.569 +    testAlloc(0x9fffffff, 0xa0030000, 67400, FALSE);
   1.570 +    testAlloc(0x9fffffff, 0xa0030000, 40000, FALSE);
   1.571 +    testAlloc(0xa0000000, 0xa0030000, 40000, FALSE);
   1.572 +    testAlloc(0xa0031100, 0xa0030000, 40000, FALSE);
   1.573 +#if 0
   1.574 +#endif
   1.575 +    return 0;
   1.576 +}
   1.577 +
   1.578 +#endif
   1.579 +
   1.580 +#endif /* #if !UCONFIG_NO_COLLATION */

mercurial