summaryrefslogtreecommitdiff
path: root/Build/source/libs/icu/icu-xetex/tools/toolutil/propsvec.c
diff options
context:
space:
mode:
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.c353
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;
+ }
+}