1b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/*
2b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*******************************************************************************
3b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*
4b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*   Copyright (C) 2002-2009, International Business Machines
5b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*
7b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*******************************************************************************
8b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*   file name:  propsvec.c
9b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*   encoding:   US-ASCII
10b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*   tab size:   8 (not used)
11b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*   indentation:4
12b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*
13b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*   created on: 2002feb22
14b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*   created by: Markus W. Scherer
15b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*
16b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*   Store bits (Unicode character properties) in bit set vectors.
17b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/
18b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
19b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include <stdlib.h>
20b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/utypes.h"
21b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "cmemory.h"
22b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "utrie.h"
23b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "utrie2.h"
24b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "uarrsort.h"
25b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "propsvec.h"
26b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
27b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustruct UPropsVectors {
28b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uint32_t *v;
29b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t columns;  /* number of columns, plus two for start & limit values */
30b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t maxRows;
31b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t rows;
32b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t prevRow;  /* search optimization: remember last row seen */
33b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UBool isCompacted;
34b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru};
35b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define UPVEC_INITIAL_ROWS (1<<12)
37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define UPVEC_MEDIUM_ROWS ((int32_t)1<<16)
38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define UPVEC_MAX_ROWS (UPVEC_MAX_CP+1)
39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
40b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI UPropsVectors * U_EXPORT2
41b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_open(int32_t columns, UErrorCode *pErrorCode) {
42b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UPropsVectors *pv;
43b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uint32_t *v, *row;
44b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uint32_t cp;
45b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
46b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
47b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
49b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(columns<1) {
50b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
52b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
53b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    columns+=2; /* count range start and limit columns */
54b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
55b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    pv=(UPropsVectors *)uprv_malloc(sizeof(UPropsVectors));
56b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    v=(uint32_t *)uprv_malloc(UPVEC_INITIAL_ROWS*columns*4);
57b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pv==NULL || v==NULL) {
58b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uprv_free(pv);
59b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uprv_free(v);
60b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
61b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
62b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_memset(pv, 0, sizeof(UPropsVectors));
64b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    pv->v=v;
65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    pv->columns=columns;
66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    pv->maxRows=UPVEC_INITIAL_ROWS;
67b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    pv->rows=2+(UPVEC_MAX_CP-UPVEC_FIRST_SPECIAL_CP);
68b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
69b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* set the all-Unicode row and the special-value rows */
70b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    row=pv->v;
71b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_memset(row, 0, pv->rows*columns*4);
72b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    row[0]=0;
73b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    row[1]=0x110000;
74b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    row+=columns;
75b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for(cp=UPVEC_FIRST_SPECIAL_CP; cp<=UPVEC_MAX_CP; ++cp) {
76b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        row[0]=cp;
77b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        row[1]=cp+1;
78b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        row+=columns;
79b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
80b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return pv;
81b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
82b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
83b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI void U_EXPORT2
84b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_close(UPropsVectors *pv) {
85b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pv!=NULL) {
86b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uprv_free(pv->v);
87b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uprv_free(pv);
88b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic uint32_t *
92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru_findRow(UPropsVectors *pv, UChar32 rangeStart) {
93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uint32_t *row;
94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t columns, i, start, limit, prevRow, rows;
95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    columns=pv->columns;
97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    rows=limit=pv->rows;
98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    prevRow=pv->prevRow;
99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* check the vicinity of the last-seen row (start searching with an unrolled loop) */
101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    row=pv->v+prevRow*columns;
102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(rangeStart>=(UChar32)row[0]) {
103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(rangeStart<(UChar32)row[1]) {
104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /* same row as last seen */
105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return row;
106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else if(rangeStart<(UChar32)(row+=columns)[1]) {
107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /* next row after the last one */
108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pv->prevRow=prevRow+1;
109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return row;
110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else if(rangeStart<(UChar32)(row+=columns)[1]) {
111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /* second row after the last one */
112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pv->prevRow=prevRow+2;
113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return row;
114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else if((rangeStart-(UChar32)row[1])<10) {
115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /* we are close, continue looping */
116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            prevRow+=2;
117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            do {
118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ++prevRow;
119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                row+=columns;
120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } while(rangeStart>=(UChar32)row[1]);
121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pv->prevRow=prevRow;
122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return row;
123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else if(rangeStart<(UChar32)pv->v[1]) {
125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /* the very first row */
126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        pv->prevRow=0;
127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return pv->v;
128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* do a binary search for the start of the range */
131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    start=0;
132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    while(start<limit-1) {
133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        i=(start+limit)/2;
134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        row=pv->v+i*columns;
135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(rangeStart<(UChar32)row[0]) {
136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            limit=i;
137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else if(rangeStart<(UChar32)row[1]) {
138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pv->prevRow=i;
139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return row;
140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else {
141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            start=i;
142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* must be found because all ranges together always cover all of Unicode */
146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    pv->prevRow=start;
147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return pv->v+start*columns;
148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI void U_EXPORT2
151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_setValue(UPropsVectors *pv,
152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               UChar32 start, UChar32 end,
153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               int32_t column,
154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               uint32_t value, uint32_t mask,
155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               UErrorCode *pErrorCode) {
156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uint32_t *firstRow, *lastRow;
157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t columns;
158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar32 limit;
159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UBool splitFirstRow, splitLastRow;
160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* argument checking */
162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if( pv==NULL ||
166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        start<0 || start>end || end>UPVEC_MAX_CP ||
167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        column<0 || column>=(pv->columns-2)
168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ) {
169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pv->isCompacted) {
173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pErrorCode=U_NO_WRITE_PERMISSION;
174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    limit=end+1;
177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* initialize */
179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    columns=pv->columns;
180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    column+=2; /* skip range start and limit columns */
181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    value&=mask;
182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* find the rows whose ranges overlap with the input range */
184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* find the first and last rows, always successful */
186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    firstRow=_findRow(pv, start);
187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    lastRow=_findRow(pv, end);
188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /*
190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * Rows need to be split if they partially overlap with the
191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * input range (only possible for the first and last rows)
192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * and if their value differs from the input value.
193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     */
194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    splitFirstRow= (UBool)(start!=(UChar32)firstRow[0] && value!=(firstRow[column]&mask));
195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    splitLastRow= (UBool)(limit!=(UChar32)lastRow[1] && value!=(lastRow[column]&mask));
196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* split first/last rows if necessary */
198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(splitFirstRow || splitLastRow) {
199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t count, rows;
200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        rows=pv->rows;
202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if((rows+splitFirstRow+splitLastRow)>pv->maxRows) {
203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uint32_t *newVectors;
204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t newMaxRows;
205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if(pv->maxRows<UPVEC_MEDIUM_ROWS) {
207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                newMaxRows=UPVEC_MEDIUM_ROWS;
208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else if(pv->maxRows<UPVEC_MAX_ROWS) {
209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                newMaxRows=UPVEC_MAX_ROWS;
210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                /* Implementation bug, or UPVEC_MAX_ROWS too low. */
212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                return;
214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            newVectors=(uint32_t *)uprv_malloc(newMaxRows*columns*4);
216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if(newVectors==NULL) {
217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                return;
219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_memcpy(newVectors, pv->v, rows*columns*4);
221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            firstRow=newVectors+(firstRow-pv->v);
222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            lastRow=newVectors+(lastRow-pv->v);
223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_free(pv->v);
224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pv->v=newVectors;
225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pv->maxRows=newMaxRows;
226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /* count the number of row cells to move after the last row, and move them */
229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        count = (int32_t)((pv->v+rows*columns)-(lastRow+columns));
230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(count>0) {
231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_memmove(
232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                lastRow+(1+splitFirstRow+splitLastRow)*columns,
233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                lastRow+columns,
234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                count*4);
235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        pv->rows=rows+splitFirstRow+splitLastRow;
237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /* split the first row, and move the firstRow pointer to the second part */
239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(splitFirstRow) {
240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /* copy all affected rows up one and move the lastRow pointer */
241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            count = (int32_t)((lastRow-firstRow)+columns);
242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_memmove(firstRow+columns, firstRow, count*4);
243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            lastRow+=columns;
244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /* split the range and move the firstRow pointer */
246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            firstRow[1]=firstRow[columns]=(uint32_t)start;
247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            firstRow+=columns;
248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /* split the last row */
251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(splitLastRow) {
252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /* copy the last row data */
253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_memcpy(lastRow+columns, lastRow, columns*4);
254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /* split the range and move the firstRow pointer */
256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            lastRow[1]=lastRow[columns]=(uint32_t)limit;
257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* set the "row last seen" to the last row for the range */
261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    pv->prevRow=(int32_t)((lastRow-(pv->v))/columns);
262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* set the input value in all remaining rows */
264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    firstRow+=column;
265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    lastRow+=column;
266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    mask=~mask;
267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for(;;) {
268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *firstRow=(*firstRow&mask)|value;
269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(firstRow==lastRow) {
270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        firstRow+=columns;
273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI uint32_t U_EXPORT2
277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_getValue(const UPropsVectors *pv, UChar32 c, int32_t column) {
278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uint32_t *row;
27950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UPropsVectors *ncpv;
280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pv->isCompacted || c<0 || c>UPVEC_MAX_CP || column<0 || column>=(pv->columns-2)) {
282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return 0;
283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
28450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ncpv=(UPropsVectors *)pv;
28550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    row=_findRow(ncpv, c);
286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return row[2+column];
287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI uint32_t * U_EXPORT2
290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_getRow(const UPropsVectors *pv, int32_t rowIndex,
291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             UChar32 *pRangeStart, UChar32 *pRangeEnd) {
292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uint32_t *row;
293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t columns;
294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pv->isCompacted || rowIndex<0 || rowIndex>=pv->rows) {
296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    columns=pv->columns;
300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    row=pv->v+rowIndex*columns;
301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pRangeStart!=NULL) {
302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pRangeStart=(UChar32)row[0];
303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pRangeEnd!=NULL) {
305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pRangeEnd=(UChar32)row[1]-1;
306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return row+2;
308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t U_CALLCONV
311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_compareRows(const void *context, const void *l, const void *r) {
312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint32_t *left=(const uint32_t *)l, *right=(const uint32_t *)r;
313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const UPropsVectors *pv=(const UPropsVectors *)context;
314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t i, count, columns;
315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    count=columns=pv->columns; /* includes start/limit columns */
317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* start comparing after start/limit but wrap around to them */
319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    i=2;
320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    do {
321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(left[i]!=right[i]) {
322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return left[i]<right[i] ? -1 : 1;
323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(++i==columns) {
325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            i=0;
326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } while(--count>0);
328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return 0;
330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI void U_EXPORT2
333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_compact(UPropsVectors *pv, UPVecCompactHandler *handler, void *context, UErrorCode *pErrorCode) {
334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uint32_t *row;
335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t i, columns, valueColumns, rows, count;
336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar32 start, limit;
337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* argument checking */
339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(handler==NULL) {
343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pv->isCompacted) {
347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* Set the flag now: Sorting and compacting destroys the builder data structure. */
351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    pv->isCompacted=TRUE;
352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    rows=pv->rows;
354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    columns=pv->columns;
355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    valueColumns=columns-2; /* not counting start & limit */
356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* sort the properties vectors to find unique vector values */
358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_sortArray(pv->v, rows, columns*4,
359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   upvec_compareRows, pv, FALSE, pErrorCode);
360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /*
365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * Find and set the special values.
366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * This has to do almost the same work as the compaction below,
367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * to find the indexes where the special-value rows will move.
368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     */
369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    row=pv->v;
370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    count=-valueColumns;
371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for(i=0; i<rows; ++i) {
372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        start=(UChar32)row[0];
373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /* count a new values vector if it is different from the current one */
375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(count<0 || 0!=uprv_memcmp(row+2, row-valueColumns, valueColumns*4)) {
376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            count+=valueColumns;
377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(start>=UPVEC_FIRST_SPECIAL_CP) {
380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            handler(context, start, start, count, row+2, valueColumns, pErrorCode);
381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if(U_FAILURE(*pErrorCode)) {
382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                return;
383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        row+=columns;
387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
389b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* count is at the beginning of the last vector, add valueColumns to include that last vector */
390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    count+=valueColumns;
391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* Call the handler once more to signal the start of delivering real values. */
393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    handler(context, UPVEC_START_REAL_VALUES_CP, UPVEC_START_REAL_VALUES_CP,
394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            count, row-valueColumns, valueColumns, pErrorCode);
395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
398b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
399b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /*
400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * Move vector contents up to a contiguous array with only unique
401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * vector values, and call the handler function for each vector.
402b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     *
403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * This destroys the Properties Vector structure and replaces it
404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * with an array of just vector values.
405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     */
406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    row=pv->v;
407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    count=-valueColumns;
408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for(i=0; i<rows; ++i) {
409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /* fetch these first before memmove() may overwrite them */
410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        start=(UChar32)row[0];
411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        limit=(UChar32)row[1];
412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /* add a new values vector if it is different from the current one */
414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(count<0 || 0!=uprv_memcmp(row+2, pv->v+count, valueColumns*4)) {
415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            count+=valueColumns;
416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_memmove(pv->v+count, row+2, valueColumns*4);
417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(start<UPVEC_FIRST_SPECIAL_CP) {
420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            handler(context, start, limit-1, count, pv->v+count, valueColumns, pErrorCode);
421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if(U_FAILURE(*pErrorCode)) {
422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                return;
423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        row+=columns;
427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /* count is at the beginning of the last vector, add one to include that last vector */
430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    pv->rows=count/valueColumns+1;
431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI const uint32_t * U_EXPORT2
434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_getArray(const UPropsVectors *pv, int32_t *pRows, int32_t *pColumns) {
435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(!pv->isCompacted) {
436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pRows!=NULL) {
439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pRows=pv->rows;
440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pColumns!=NULL) {
442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pColumns=pv->columns-2;
443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return pv->v;
445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
446b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI uint32_t * U_EXPORT2
448b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_cloneArray(const UPropsVectors *pv,
449b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                 int32_t *pRows, int32_t *pColumns, UErrorCode *pErrorCode) {
450b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uint32_t *clonedArray;
451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t byteLength;
452b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
454b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(!pv->isCompacted) {
457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    byteLength=pv->rows*(pv->columns-2)*4;
461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    clonedArray=(uint32_t *)uprv_malloc(byteLength);
462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(clonedArray==NULL) {
463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
464b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
465b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
466b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_memcpy(clonedArray, pv->v, byteLength);
467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pRows!=NULL) {
468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pRows=pv->rows;
469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(pColumns!=NULL) {
471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *pColumns=pv->columns-2;
472b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
473b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return clonedArray;
474b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
475b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
476b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI UTrie2 * U_EXPORT2
477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_compactToUTrie2WithRowIndexes(UPropsVectors *pv, UErrorCode *pErrorCode) {
478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UPVecToUTrie2Context toUTrie2={ NULL };
479b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    upvec_compact(pv, upvec_compactToUTrie2Handler, &toUTrie2, pErrorCode);
480b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    utrie2_freeze(toUTrie2.trie, UTRIE2_16_VALUE_BITS, pErrorCode);
481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        utrie2_close(toUTrie2.trie);
483b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        toUTrie2.trie=NULL;
484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
485b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return toUTrie2.trie;
486b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
487b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
488b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/*
489b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * TODO(markus): Add upvec_16BitsToUTrie2() function that enumerates all rows, extracts
490b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * some 16-bit field and builds and returns a UTrie2.
491b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */
492b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI void U_CALLCONV
494b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_compactToUTrieHandler(void *context,
495b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            UChar32 start, UChar32 end,
496b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            int32_t rowIndex, uint32_t *row, int32_t columns,
497b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            UErrorCode *pErrorCode) {
498b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UPVecToUTrieContext *toUTrie=(UPVecToUTrieContext *)context;
499b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(start<UPVEC_FIRST_SPECIAL_CP) {
500b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(!utrie_setRange32(toUTrie->newTrie, start, end+1, (uint32_t)rowIndex, TRUE)) {
501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
502b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else {
504b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        switch(start) {
505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        case UPVEC_INITIAL_VALUE_CP:
506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            toUTrie->initialValue=rowIndex;
507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        case UPVEC_START_REAL_VALUES_CP:
509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if(rowIndex>0xffff) {
510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                /* too many rows for a 16-bit trie */
511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                toUTrie->newTrie=utrie_open(NULL, NULL, toUTrie->capacity,
514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                            toUTrie->initialValue, toUTrie->initialValue,
515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                            toUTrie->latin1Linear);
516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if(toUTrie->newTrie==NULL) {
517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        default:
522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
524b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
525b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
526b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI void U_CALLCONV
528b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruupvec_compactToUTrie2Handler(void *context,
529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                             UChar32 start, UChar32 end,
530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                             int32_t rowIndex, uint32_t *row, int32_t columns,
531b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                             UErrorCode *pErrorCode) {
532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UPVecToUTrie2Context *toUTrie2=(UPVecToUTrie2Context *)context;
533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(start<UPVEC_FIRST_SPECIAL_CP) {
534b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        utrie2_setRange32(toUTrie2->trie, start, end, (uint32_t)rowIndex, TRUE, pErrorCode);
535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else {
536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        switch(start) {
537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        case UPVEC_INITIAL_VALUE_CP:
538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            toUTrie2->initialValue=rowIndex;
539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        case UPVEC_ERROR_VALUE_CP:
541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            toUTrie2->errorValue=rowIndex;
542b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        case UPVEC_START_REAL_VALUES_CP:
544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            toUTrie2->maxValue=rowIndex;
545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if(rowIndex>0xffff) {
546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                /* too many rows for a 16-bit trie */
547b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
549b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                toUTrie2->trie=utrie2_open(toUTrie2->initialValue,
550b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                           toUTrie2->errorValue, pErrorCode);
551b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
552b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
553b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        default:
554b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
555b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
556b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
557b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
558