diff options
Diffstat (limited to 'Build/source/libs/icu/icu-xetex/tools/toolutil/propsvec.c')
-rw-r--r-- | Build/source/libs/icu/icu-xetex/tools/toolutil/propsvec.c | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/Build/source/libs/icu/icu-xetex/tools/toolutil/propsvec.c b/Build/source/libs/icu/icu-xetex/tools/toolutil/propsvec.c new file mode 100644 index 00000000000..c4cb7b17293 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/tools/toolutil/propsvec.c @@ -0,0 +1,353 @@ +/* +******************************************************************************* +* +* Copyright (C) 2002-2005, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: propsvec.c +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2002feb22 +* created by: Markus W. Scherer +* +* Store additional Unicode character properties in bit set vectors. +*/ + +#include <stdlib.h> +#include "unicode/utypes.h" +#include "cmemory.h" +#include "utrie.h" +#include "uarrsort.h" +#include "propsvec.h" + +static uint32_t * +_findRow(uint32_t *pv, UChar32 rangeStart) { + uint32_t *row; + int32_t *hdr; + int32_t columns, i, start, limit, prevRow, rows; + + hdr=(int32_t *)pv; + columns=hdr[UPVEC_COLUMNS]; + limit=hdr[UPVEC_ROWS]; + prevRow=hdr[UPVEC_PREV_ROW]; + rows=hdr[UPVEC_ROWS]; + pv+=UPVEC_HEADER_LENGTH; + + /* check the vicinity of the last-seen row */ + if(prevRow<rows) { + row=pv+prevRow*columns; + if(rangeStart>=(UChar32)row[0]) { + if(rangeStart<(UChar32)row[1]) { + /* same row as last seen */ + return row; + } else if( + ++prevRow<rows && + rangeStart>=(UChar32)(row+=columns)[0] && rangeStart<(UChar32)row[1] + ) { + /* next row after the last one */ + hdr[UPVEC_PREV_ROW]=prevRow; + return row; + } + } + } + + /* do a binary search for the start of the range */ + start=0; + while(start<limit-1) { + i=(start+limit)/2; + row=pv+i*columns; + if(rangeStart<(UChar32)row[0]) { + limit=i; + } else if(rangeStart<(UChar32)row[1]) { + hdr[UPVEC_PREV_ROW]=i; + return row; + } else { + start=i; + } + } + + /* must be found because all ranges together always cover all of Unicode */ + hdr[UPVEC_PREV_ROW]=start; + return pv+start*columns; +} + +U_CAPI uint32_t * U_EXPORT2 +upvec_open(int32_t columns, int32_t maxRows) { + uint32_t *pv, *row; + int32_t length; + + if(columns<1 || maxRows<1) { + return NULL; + } + + columns+=2; /* count range start and limit columns */ + length=UPVEC_HEADER_LENGTH+maxRows*columns; + pv=(uint32_t *)uprv_malloc(length*4); + if(pv!=NULL) { + /* set header */ + pv[UPVEC_COLUMNS]=(uint32_t)columns; + pv[UPVEC_MAXROWS]=(uint32_t)maxRows; + pv[UPVEC_ROWS]=1; + pv[UPVEC_PREV_ROW]=0; + + /* set initial row */ + row=pv+UPVEC_HEADER_LENGTH; + *row++=0; + *row++=0x110000; + columns-=2; + do { + *row++=0; + } while(--columns>0); + } + return pv; +} + +U_CAPI void U_EXPORT2 +upvec_close(uint32_t *pv) { + if(pv!=NULL) { + uprv_free(pv); + } +} + +U_CAPI UBool U_EXPORT2 +upvec_setValue(uint32_t *pv, + UChar32 start, UChar32 limit, + int32_t column, + uint32_t value, uint32_t mask, + UErrorCode *pErrorCode) { + uint32_t *firstRow, *lastRow; + int32_t columns; + UBool splitFirstRow, splitLastRow; + + /* argument checking */ + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { + return FALSE; + } + + if( pv==NULL || + start<0 || start>limit || limit>0x110000 || + column<0 || (uint32_t)(column+1)>=pv[UPVEC_COLUMNS] + ) { + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; + return FALSE; + } + if(start==limit) { + /* empty range, nothing to do */ + return TRUE; + } + + /* initialize */ + columns=(int32_t)pv[UPVEC_COLUMNS]; + column+=2; /* skip range start and limit columns */ + value&=mask; + + /* find the rows whose ranges overlap with the input range */ + + /* find the first row, always successful */ + firstRow=_findRow(pv, start); + + /* find the last row, always successful */ + lastRow=firstRow; + while(limit>(UChar32)lastRow[1]) { + lastRow+=columns; + } + + /* + * Rows need to be split if they partially overlap with the + * input range (only possible for the first and last rows) + * and if their value differs from the input value. + */ + splitFirstRow= (UBool)(start!=(UChar32)firstRow[0] && value!=(firstRow[column]&mask)); + splitLastRow= (UBool)(limit!=(UChar32)lastRow[1] && value!=(lastRow[column]&mask)); + + /* split first/last rows if necessary */ + if(splitFirstRow || splitLastRow) { + int32_t count, rows; + + rows=(int32_t)pv[UPVEC_ROWS]; + if((rows+splitFirstRow+splitLastRow)>(int32_t)pv[UPVEC_MAXROWS]) { + *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; + return FALSE; + } + + /* count the number of row cells to move after the last row, and move them */ + count = (int32_t)((pv+UPVEC_HEADER_LENGTH+rows*columns)-(lastRow+columns)); + if(count>0) { + uprv_memmove( + lastRow+(1+splitFirstRow+splitLastRow)*columns, + lastRow+columns, + count*4); + } + pv[UPVEC_ROWS]=rows+splitFirstRow+splitLastRow; + + /* split the first row, and move the firstRow pointer to the second part */ + if(splitFirstRow) { + /* copy all affected rows up one and move the lastRow pointer */ + count = (int32_t)((lastRow-firstRow)+columns); + uprv_memmove(firstRow+columns, firstRow, count*4); + lastRow+=columns; + + /* split the range and move the firstRow pointer */ + firstRow[1]=firstRow[columns]=(uint32_t)start; + firstRow+=columns; + } + + /* split the last row */ + if(splitLastRow) { + /* copy the last row data */ + uprv_memcpy(lastRow+columns, lastRow, columns*4); + + /* split the range and move the firstRow pointer */ + lastRow[1]=lastRow[columns]=(uint32_t)limit; + } + } + + /* set the "row last seen" to the last row for the range */ + pv[UPVEC_PREV_ROW]=(uint32_t)((lastRow-(pv+UPVEC_HEADER_LENGTH))/columns); + + /* set the input value in all remaining rows */ + firstRow+=column; + lastRow+=column; + mask=~mask; + for(;;) { + *firstRow=(*firstRow&mask)|value; + if(firstRow==lastRow) { + break; + } + firstRow+=columns; + } + return TRUE; +} + +U_CAPI uint32_t U_EXPORT2 +upvec_getValue(uint32_t *pv, UChar32 c, int32_t column) { + uint32_t *row; + + if(pv==NULL || c<0 || c>=0x110000) { + return 0; + } + row=_findRow(pv, c); + return row[2+column]; +} + +U_CAPI uint32_t * U_EXPORT2 +upvec_getRow(uint32_t *pv, int32_t rowIndex, + UChar32 *pRangeStart, UChar32 *pRangeLimit) { + uint32_t *row; + int32_t columns; + + if(pv==NULL || rowIndex<0 || rowIndex>=(int32_t)pv[UPVEC_ROWS]) { + return NULL; + } + + columns=(int32_t)pv[UPVEC_COLUMNS]; + row=pv+UPVEC_HEADER_LENGTH+rowIndex*columns; + if(pRangeStart!=NULL) { + *pRangeStart=row[0]; + } + if(pRangeLimit!=NULL) { + *pRangeLimit=row[1]; + } + return row+2; +} + +static int32_t U_CALLCONV +upvec_compareRows(const void *context, const void *l, const void *r) { + const uint32_t *left=(const uint32_t *)l, *right=(const uint32_t *)r; + const uint32_t *pv=(const uint32_t *)context; + int32_t i, count, columns; + + count=columns=(int32_t)pv[UPVEC_COLUMNS]; /* includes start/limit columns */ + + /* start comparing after start/limit but wrap around to them */ + i=2; + do { + if(left[i]!=right[i]) { + return left[i]<right[i] ? -1 : 1; + } + if(++i==columns) { + i=0; + } + } while(--count>0); + + return 0; +} + +U_CAPI int32_t U_EXPORT2 +upvec_compact(uint32_t *pv, UPVecCompactHandler *handler, void *context, UErrorCode *pErrorCode) { + uint32_t *row; + int32_t columns, valueColumns, rows, count; + UChar32 start, limit; + + /* argument checking */ + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { + return 0; + } + + if(pv==NULL || handler==NULL) { + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + row=pv+UPVEC_HEADER_LENGTH; + columns=(int32_t)pv[UPVEC_COLUMNS]; + rows=(int32_t)pv[UPVEC_ROWS]; + + if(rows==0) { + return 0; + } + + /* sort the properties vectors to find unique vector values */ + if(rows>1) { + uprv_sortArray(pv+UPVEC_HEADER_LENGTH, rows, columns*4, + upvec_compareRows, pv, FALSE, pErrorCode); + } + if(U_FAILURE(*pErrorCode)) { + return 0; + } + + /* + * Move vector contents up to a contiguous array with only unique + * vector values, and call the handler function for each vector. + * + * This destroys the Properties Vector structure and replaces it + * with an array of just vector values. + */ + valueColumns=columns-2; /* not counting start & limit */ + count=-valueColumns; + + do { + /* fetch these first before memmove() may overwrite them */ + start=(UChar32)row[0]; + limit=(UChar32)row[1]; + + /* add a new values vector if it is different from the current one */ + if(count<0 || 0!=uprv_memcmp(row+2, pv+count, valueColumns*4)) { + count+=valueColumns; + uprv_memmove(pv+count, row+2, valueColumns*4); + } + + handler(context, start, limit, count, pv+count, valueColumns, pErrorCode); + if(U_FAILURE(*pErrorCode)) { + return 0; + } + + row+=columns; + } while(--rows>0); + + /* count is at the beginning of the last vector, add valueColumns to include that last vector */ + return count+valueColumns; +} + +U_CAPI void U_CALLCONV +upvec_compactToTrieHandler(void *context, + UChar32 start, UChar32 limit, + int32_t rowIndex, uint32_t *row, int32_t columns, + UErrorCode *pErrorCode) { + if(!utrie_setRange32((UNewTrie *)context, start, limit, (uint32_t)rowIndex, FALSE)) { + *pErrorCode=U_BUFFER_OVERFLOW_ERROR; + } +} |