16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 2002-2011, International Business Machines
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   file name:  propsvec.c
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   encoding:   US-ASCII
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   tab size:   8 (not used)
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   indentation:4
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created on: 2002feb22
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created by: Markus W. Scherer
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Store bits (Unicode character properties) in bit set vectors.
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <stdlib.h>
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "utrie.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "utrie2.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uarrsort.h"
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "propsvec.h"
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstruct UPropsVectors {
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *v;
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t columns;  /* number of columns, plus two for start & limit values */
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t maxRows;
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t rows;
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t prevRow;  /* search optimization: remember last row seen */
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool isCompacted;
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define UPVEC_INITIAL_ROWS (1<<12)
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define UPVEC_MEDIUM_ROWS ((int32_t)1<<16)
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define UPVEC_MAX_ROWS (UPVEC_MAX_CP+1)
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UPropsVectors * U_EXPORT2
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_open(int32_t columns, UErrorCode *pErrorCode) {
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UPropsVectors *pv;
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *v, *row;
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t cp;
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(columns<1) {
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    columns+=2; /* count range start and limit columns */
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pv=(UPropsVectors *)uprv_malloc(sizeof(UPropsVectors));
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    v=(uint32_t *)uprv_malloc(UPVEC_INITIAL_ROWS*columns*4);
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pv==NULL || v==NULL) {
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(pv);
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(v);
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memset(pv, 0, sizeof(UPropsVectors));
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pv->v=v;
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pv->columns=columns;
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pv->maxRows=UPVEC_INITIAL_ROWS;
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pv->rows=2+(UPVEC_MAX_CP-UPVEC_FIRST_SPECIAL_CP);
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set the all-Unicode row and the special-value rows */
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    row=pv->v;
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memset(row, 0, pv->rows*columns*4);
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    row[0]=0;
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    row[1]=0x110000;
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    row+=columns;
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(cp=UPVEC_FIRST_SPECIAL_CP; cp<=UPVEC_MAX_CP; ++cp) {
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        row[0]=cp;
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        row[1]=cp+1;
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        row+=columns;
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return pv;
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_close(UPropsVectors *pv) {
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pv!=NULL) {
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(pv->v);
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(pv);
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic uint32_t *
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org_findRow(UPropsVectors *pv, UChar32 rangeStart) {
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *row;
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t columns, i, start, limit, prevRow;
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    columns=pv->columns;
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    limit=pv->rows;
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    prevRow=pv->prevRow;
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check the vicinity of the last-seen row (start searching with an unrolled loop) */
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    row=pv->v+prevRow*columns;
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(rangeStart>=(UChar32)row[0]) {
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(rangeStart<(UChar32)row[1]) {
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* same row as last seen */
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return row;
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(rangeStart<(UChar32)(row+=columns)[1]) {
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* next row after the last one */
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pv->prevRow=prevRow+1;
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return row;
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(rangeStart<(UChar32)(row+=columns)[1]) {
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* second row after the last one */
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pv->prevRow=prevRow+2;
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return row;
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if((rangeStart-(UChar32)row[1])<10) {
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* we are close, continue looping */
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            prevRow+=2;
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            do {
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ++prevRow;
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                row+=columns;
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } while(rangeStart>=(UChar32)row[1]);
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pv->prevRow=prevRow;
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return row;
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(rangeStart<(UChar32)pv->v[1]) {
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* the very first row */
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pv->prevRow=0;
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return pv->v;
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* do a binary search for the start of the range */
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    start=0;
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(start<limit-1) {
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=(start+limit)/2;
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        row=pv->v+i*columns;
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(rangeStart<(UChar32)row[0]) {
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            limit=i;
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(rangeStart<(UChar32)row[1]) {
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pv->prevRow=i;
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return row;
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start=i;
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* must be found because all ranges together always cover all of Unicode */
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pv->prevRow=start;
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return pv->v+start*columns;
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_setValue(UPropsVectors *pv,
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UChar32 start, UChar32 end,
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               int32_t column,
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               uint32_t value, uint32_t mask,
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UErrorCode *pErrorCode) {
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *firstRow, *lastRow;
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t columns;
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 limit;
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool splitFirstRow, splitLastRow;
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* argument checking */
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( pv==NULL ||
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        start<0 || start>end || end>UPVEC_MAX_CP ||
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        column<0 || column>=(pv->columns-2)
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pv->isCompacted) {
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_NO_WRITE_PERMISSION;
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    limit=end+1;
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* initialize */
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    columns=pv->columns;
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    column+=2; /* skip range start and limit columns */
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    value&=mask;
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* find the rows whose ranges overlap with the input range */
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* find the first and last rows, always successful */
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    firstRow=_findRow(pv, start);
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lastRow=_findRow(pv, end);
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Rows need to be split if they partially overlap with the
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * input range (only possible for the first and last rows)
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * and if their value differs from the input value.
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    splitFirstRow= (UBool)(start!=(UChar32)firstRow[0] && value!=(firstRow[column]&mask));
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    splitLastRow= (UBool)(limit!=(UChar32)lastRow[1] && value!=(lastRow[column]&mask));
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* split first/last rows if necessary */
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(splitFirstRow || splitLastRow) {
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t count, rows;
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        rows=pv->rows;
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((rows+splitFirstRow+splitLastRow)>pv->maxRows) {
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uint32_t *newVectors;
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t newMaxRows;
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(pv->maxRows<UPVEC_MEDIUM_ROWS) {
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                newMaxRows=UPVEC_MEDIUM_ROWS;
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(pv->maxRows<UPVEC_MAX_ROWS) {
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                newMaxRows=UPVEC_MAX_ROWS;
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* Implementation bug, or UPVEC_MAX_ROWS too low. */
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            newVectors=(uint32_t *)uprv_malloc(newMaxRows*columns*4);
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(newVectors==NULL) {
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memcpy(newVectors, pv->v, rows*columns*4);
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            firstRow=newVectors+(firstRow-pv->v);
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lastRow=newVectors+(lastRow-pv->v);
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_free(pv->v);
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pv->v=newVectors;
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pv->maxRows=newMaxRows;
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* count the number of row cells to move after the last row, and move them */
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        count = (int32_t)((pv->v+rows*columns)-(lastRow+columns));
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(count>0) {
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memmove(
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                lastRow+(1+splitFirstRow+splitLastRow)*columns,
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                lastRow+columns,
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                count*4);
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pv->rows=rows+splitFirstRow+splitLastRow;
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* split the first row, and move the firstRow pointer to the second part */
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(splitFirstRow) {
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* copy all affected rows up one and move the lastRow pointer */
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            count = (int32_t)((lastRow-firstRow)+columns);
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memmove(firstRow+columns, firstRow, count*4);
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lastRow+=columns;
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* split the range and move the firstRow pointer */
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            firstRow[1]=firstRow[columns]=(uint32_t)start;
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            firstRow+=columns;
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* split the last row */
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(splitLastRow) {
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* copy the last row data */
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memcpy(lastRow+columns, lastRow, columns*4);
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* split the range and move the firstRow pointer */
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lastRow[1]=lastRow[columns]=(uint32_t)limit;
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set the "row last seen" to the last row for the range */
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pv->prevRow=(int32_t)((lastRow-(pv->v))/columns);
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set the input value in all remaining rows */
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    firstRow+=column;
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lastRow+=column;
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    mask=~mask;
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *firstRow=(*firstRow&mask)|value;
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(firstRow==lastRow) {
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        firstRow+=columns;
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI uint32_t U_EXPORT2
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_getValue(const UPropsVectors *pv, UChar32 c, int32_t column) {
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *row;
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UPropsVectors *ncpv;
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pv->isCompacted || c<0 || c>UPVEC_MAX_CP || column<0 || column>=(pv->columns-2)) {
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ncpv=(UPropsVectors *)pv;
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    row=_findRow(ncpv, c);
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return row[2+column];
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI uint32_t * U_EXPORT2
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_getRow(const UPropsVectors *pv, int32_t rowIndex,
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UChar32 *pRangeStart, UChar32 *pRangeEnd) {
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *row;
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t columns;
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pv->isCompacted || rowIndex<0 || rowIndex>=pv->rows) {
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    columns=pv->columns;
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    row=pv->v+rowIndex*columns;
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pRangeStart!=NULL) {
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pRangeStart=(UChar32)row[0];
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pRangeEnd!=NULL) {
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pRangeEnd=(UChar32)row[1]-1;
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return row+2;
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t U_CALLCONV
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_compareRows(const void *context, const void *l, const void *r) {
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint32_t *left=(const uint32_t *)l, *right=(const uint32_t *)r;
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UPropsVectors *pv=(const UPropsVectors *)context;
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, count, columns;
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    count=columns=pv->columns; /* includes start/limit columns */
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* start comparing after start/limit but wrap around to them */
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    i=2;
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    do {
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(left[i]!=right[i]) {
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return left[i]<right[i] ? -1 : 1;
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(++i==columns) {
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            i=0;
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } while(--count>0);
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return 0;
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_compact(UPropsVectors *pv, UPVecCompactHandler *handler, void *context, UErrorCode *pErrorCode) {
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *row;
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, columns, valueColumns, rows, count;
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 start, limit;
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* argument checking */
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(handler==NULL) {
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pv->isCompacted) {
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Set the flag now: Sorting and compacting destroys the builder data structure. */
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pv->isCompacted=TRUE;
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    rows=pv->rows;
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    columns=pv->columns;
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_ASSERT(columns>=3); /* upvec_open asserts this */
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    valueColumns=columns-2; /* not counting start & limit */
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* sort the properties vectors to find unique vector values */
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_sortArray(pv->v, rows, columns*4,
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   upvec_compareRows, pv, FALSE, pErrorCode);
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Find and set the special values.
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * This has to do almost the same work as the compaction below,
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * to find the indexes where the special-value rows will move.
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    row=pv->v;
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    count=-valueColumns;
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(i=0; i<rows; ++i) {
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        start=(UChar32)row[0];
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* count a new values vector if it is different from the current one */
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(count<0 || 0!=uprv_memcmp(row+2, row-valueColumns, valueColumns*4)) {
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            count+=valueColumns;
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(start>=UPVEC_FIRST_SPECIAL_CP) {
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            handler(context, start, start, count, row+2, valueColumns, pErrorCode);
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_FAILURE(*pErrorCode)) {
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        row+=columns;
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* count is at the beginning of the last vector, add valueColumns to include that last vector */
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    count+=valueColumns;
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Call the handler once more to signal the start of delivering real values. */
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    handler(context, UPVEC_START_REAL_VALUES_CP, UPVEC_START_REAL_VALUES_CP,
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            count, row-valueColumns, valueColumns, pErrorCode);
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Move vector contents up to a contiguous array with only unique
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * vector values, and call the handler function for each vector.
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * This destroys the Properties Vector structure and replaces it
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * with an array of just vector values.
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    row=pv->v;
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    count=-valueColumns;
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(i=0; i<rows; ++i) {
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* fetch these first before memmove() may overwrite them */
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        start=(UChar32)row[0];
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit=(UChar32)row[1];
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* add a new values vector if it is different from the current one */
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(count<0 || 0!=uprv_memcmp(row+2, pv->v+count, valueColumns*4)) {
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            count+=valueColumns;
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memmove(pv->v+count, row+2, valueColumns*4);
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(start<UPVEC_FIRST_SPECIAL_CP) {
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            handler(context, start, limit-1, count, pv->v+count, valueColumns, pErrorCode);
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_FAILURE(*pErrorCode)) {
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        row+=columns;
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* count is at the beginning of the last vector, add one to include that last vector */
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pv->rows=count/valueColumns+1;
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI const uint32_t * U_EXPORT2
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_getArray(const UPropsVectors *pv, int32_t *pRows, int32_t *pColumns) {
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!pv->isCompacted) {
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pRows!=NULL) {
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pRows=pv->rows;
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pColumns!=NULL) {
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pColumns=pv->columns-2;
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return pv->v;
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI uint32_t * U_EXPORT2
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_cloneArray(const UPropsVectors *pv,
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 int32_t *pRows, int32_t *pColumns, UErrorCode *pErrorCode) {
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *clonedArray;
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t byteLength;
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!pv->isCompacted) {
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    byteLength=pv->rows*(pv->columns-2)*4;
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    clonedArray=(uint32_t *)uprv_malloc(byteLength);
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(clonedArray==NULL) {
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memcpy(clonedArray, pv->v, byteLength);
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pRows!=NULL) {
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pRows=pv->rows;
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pColumns!=NULL) {
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pColumns=pv->columns-2;
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return clonedArray;
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UTrie2 * U_EXPORT2
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_compactToUTrie2WithRowIndexes(UPropsVectors *pv, UErrorCode *pErrorCode) {
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UPVecToUTrie2Context toUTrie2={ NULL };
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    upvec_compact(pv, upvec_compactToUTrie2Handler, &toUTrie2, pErrorCode);
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    utrie2_freeze(toUTrie2.trie, UTRIE2_16_VALUE_BITS, pErrorCode);
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        utrie2_close(toUTrie2.trie);
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        toUTrie2.trie=NULL;
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return toUTrie2.trie;
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * TODO(markus): Add upvec_16BitsToUTrie2() function that enumerates all rows, extracts
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * some 16-bit field and builds and returns a UTrie2.
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_CALLCONV
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgupvec_compactToUTrie2Handler(void *context,
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             UChar32 start, UChar32 end,
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             int32_t rowIndex, uint32_t *row, int32_t columns,
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             UErrorCode *pErrorCode) {
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UPVecToUTrie2Context *toUTrie2=(UPVecToUTrie2Context *)context;
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(start<UPVEC_FIRST_SPECIAL_CP) {
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        utrie2_setRange32(toUTrie2->trie, start, end, (uint32_t)rowIndex, TRUE, pErrorCode);
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        switch(start) {
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UPVEC_INITIAL_VALUE_CP:
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            toUTrie2->initialValue=rowIndex;
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UPVEC_ERROR_VALUE_CP:
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            toUTrie2->errorValue=rowIndex;
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UPVEC_START_REAL_VALUES_CP:
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            toUTrie2->maxValue=rowIndex;
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(rowIndex>0xffff) {
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* too many rows for a 16-bit trie */
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                toUTrie2->trie=utrie2_open(toUTrie2->initialValue,
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                           toUTrie2->errorValue, pErrorCode);
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        default:
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
526