home *** CD-ROM | disk | FTP | other *** search
- /*
- *****************************************************************************************
- * *
- * COPYRIGHT: *
- * (C) Copyright Taligent, Inc., 1997 *
- * (C) Copyright International Business Machines Corporation, 1997-1998 *
- * Licensed Material - Program-Property of IBM - All Rights Reserved. *
- * US Government Users Restricted Rights - Use, duplication, or disclosure *
- * restricted by GSA ADP Schedule Contract with IBM Corp. *
- * *
- *****************************************************************************************
- */
- /*===============================================================================
- *
- * File cmpshrta.cpp
- *
- * Modification History:
- *
- * Date Name Description
- * 2/5/97 aliu Added CompactIntArray streamIn and streamOut methods.
- * 3/4/97 aliu Tuned performance of CompactIntArray constructor,
- * 05/07/97 helena Added isBogus()
- * based on performance data indicating that this was slow.
- * 07/15/98 erm Synched with Java 1.2 CompactShortArray.java.
- * 07/30/98 erm Added changes from 07/29/98 code review.
- *===============================================================================
- */
- #include "ucmp16.h"
- #include "cmemory.h"
-
-
-
-
-
- #define arrayRegionMatches(source, sourceStart, target, targetStart, len) (icu_memcmp(&source[sourceStart], &target[targetStart], len * sizeof(int16_t)) != 0)
-
- /* internal constants*/
- #define UCMP16_kMaxUnicode_int 65535
- #define UCMP16_kUnicodeCount_int (UCMP16_kMaxUnicode_int + 1)
- #define UCMP16_kBlockShift_int 7
- #define UCMP16_kBlockCount_int (1 << UCMP16_kBlockShift_int)
- #define UCMP16_kBlockBytes_int (UCMP16_kBlockCount_int * sizeof(int16_t))
- #define UCMP16_kIndexShift_int (16 - UCMP16_kBlockShift_int)
- #define UCMP16_kIndexCount_int (1 << UCMP16_kIndexShift_int)
- #define UCMP16_kBlockMask_int (UCMP16_kBlockCount_int - 1)
-
-
- const int32_t UCMP16_kMaxUnicode = UCMP16_kMaxUnicode_int;
- const int32_t UCMP16_kUnicodeCount = UCMP16_kUnicodeCount_int;
- const int32_t UCMP16_kBlockShift = UCMP16_kBlockShift_int;
- const int32_t UCMP16_kBlockCount = UCMP16_kBlockCount_int;
- const int32_t UCMP16_kBlockBytes = UCMP16_kBlockBytes_int;
- const int32_t UCMP16_kIndexShift = UCMP16_kIndexShift_int;
- const int32_t UCMP16_kIndexCount = UCMP16_kIndexCount_int;
- const uint32_t UCMP16_kBlockMask = UCMP16_kBlockMask_int;
-
- /**
- * Sets the array to the invalid memory state.
- */
- static CompactShortArray* setToBogus(CompactShortArray* array);
- static void touchBlock(CompactShortArray* this,
- int32_t i,
- int16_t value);
- static bool_t blockTouched(const CompactShortArray* this,
- int32_t i);
-
-
- /* debug flags*/
- /*=======================================================*/
-
- int32_t ucmp16_getkUnicodeCount()
- {return UCMP16_kUnicodeCount;}
-
- int32_t ucmp16_getkBlockCount()
- {return UCMP16_kBlockCount;}
-
- int32_t ucmp16_getkIndexCount()
- { return UCMP16_kIndexCount;}
-
- CompactShortArray* ucmp16_open(int16_t defaultValue)
- {
- int32_t i;
- CompactShortArray* this = (CompactShortArray*) icu_malloc(sizeof(CompactShortArray));
- if (this == NULL) return NULL;
-
- this->fCount = UCMP16_kUnicodeCount;
- this->fCompact = FALSE;
- this->fBogus = FALSE;
- this->fArray = NULL;
- this->fIndex = NULL;
- this->fHashes = NULL;
- this->fDefaultValue = defaultValue;
-
- this->fArray = (int16_t*)icu_malloc(UCMP16_kUnicodeCount * sizeof(int16_t));
- if (this->fArray == NULL)
- {
- this->fBogus = TRUE;
- return NULL;
- }
-
- this->fIndex = (uint16_t*)icu_malloc(UCMP16_kIndexCount * sizeof(uint16_t));
- if (this->fIndex == NULL)
- {
- icu_free(this->fArray);
- this->fArray = NULL;
-
- this->fBogus = TRUE;
- return NULL;
- }
-
- this->kBlockShift = UCMP16_kBlockShift;
- this->kBlockMask = UCMP16_kBlockMask;
- for (i = 0; i < UCMP16_kUnicodeCount; i += 1)
- {
- this->fArray[i] = defaultValue;
- }
-
- this->fHashes =(int32_t*)icu_malloc(UCMP16_kIndexCount * sizeof(int32_t));
- if (this->fHashes == NULL)
- {
- icu_free(this->fArray);
- icu_free(this->fIndex);
- this->fBogus = TRUE;
- return NULL;
- }
-
- for (i = 0; i < UCMP16_kIndexCount; i += 1)
- {
- this->fIndex[i] = (uint16_t)(i << UCMP16_kBlockShift);
- this->fHashes[i] = 0;
- }
-
- return this;
- }
-
- CompactShortArray* ucmp16_openAdopt(uint16_t *indexArray,
- int16_t *newValues,
- int32_t count,
- int16_t defaultValue)
- {
- CompactShortArray* this = (CompactShortArray*) icu_malloc(sizeof(CompactShortArray));
- if (this == NULL) return NULL;
- this->fHashes = NULL;
- this->fCount = count;
- this->fDefaultValue = defaultValue;
- this->fBogus = FALSE;
- this->fArray = newValues;
- this->fIndex = indexArray;
- this->fCompact = count < UCMP16_kUnicodeCount;
- this->kBlockShift = UCMP16_kBlockShift;
- this->kBlockMask = UCMP16_kBlockMask;
-
- return this;
- }
-
- CompactShortArray* ucmp16_openAdoptWithBlockShift(uint16_t *indexArray,
- int16_t *newValues,
- int32_t count,
- int16_t defaultValue,
- int32_t blockShift)
- {
- CompactShortArray* this = ucmp16_openAdopt(indexArray,
- newValues,
- count,
- defaultValue);
- if (this == NULL) return NULL;
-
- this->kBlockShift = blockShift;
- this->kBlockMask = (uint32_t) (((uint32_t)1 << (uint32_t)blockShift) - (uint32_t)1);
-
- return this;
- }
-
- /*=======================================================*/
-
- void ucmp16_close(CompactShortArray* this)
- {
- icu_free(this->fArray);
- icu_free(this->fIndex);
- icu_free(this->fHashes);
- icu_free(this);
-
- return;
- }
-
- CompactShortArray* setToBogus(CompactShortArray* this)
- {
- icu_free(this->fArray);
- this->fArray = NULL;
-
- icu_free(this->fIndex);
- this->fIndex = NULL;
-
- icu_free(this->fHashes);
- this->fHashes = NULL;
-
- this->fCount = 0;
- this->fCompact = FALSE;
- this->fBogus = TRUE;
-
- return this;
- }
-
-
- void ucmp16_expand(CompactShortArray* this)
- {
- if (this->fCompact)
- {
- int32_t i;
- int16_t *tempArray = (int16_t*)icu_malloc(UCMP16_kUnicodeCount * sizeof(int16_t));
-
- if (tempArray == NULL)
- {
- this->fBogus = TRUE;
- return;
- }
-
- for (i = 0; i < UCMP16_kUnicodeCount; i += 1)
- {
- tempArray[i] = ucmp16_get(this, (UChar)i); /* HSYS : How expand?*/
- }
-
- for (i = 0; i < (1 << (16 - this->kBlockShift)); i += 1)
- {
- this->fIndex[i] = (uint16_t)(i<<this->kBlockShift);
- }
-
- icu_free(this->fArray);
- this->fArray = tempArray;
- this->fCompact = FALSE;
- }
- }
-
- void ucmp16_set(CompactShortArray* this,
- UChar c,
- int16_t value)
- {
- if (this->fCompact)
- {
- ucmp16_expand(this);
- if (this->fBogus) return;
- }
-
- this->fArray[(int32_t)c] = value;
-
- if (value != this->fDefaultValue)
- {
- touchBlock(this, c >> this->kBlockShift, value);
- }
- }
-
-
- void ucmp16_setRange(CompactShortArray* this,
- UChar start,
- UChar end,
- int16_t value)
- {
- int32_t i;
- if (this->fCompact)
- {
- ucmp16_expand(this);
- if (this->fBogus) return;
- }
- if (value != this->fDefaultValue)
- {
- for (i = start; i <= end; i += 1)
- {
- this->fArray[i] = value;
- touchBlock(this, i >> this->kBlockShift, value);
- }
- }
- else
- {
- for (i = start; i <= end; i += 1) this->fArray[i] = value;
- }
- }
-
-
- /*=======================================================*/
- void ucmp16_compact(CompactShortArray* this)
- {
- if (!this->fCompact)
- {
- int32_t limitCompacted = 0;
- int32_t i, iBlockStart;
- int16_t iUntouched = -1;
-
- for (i = 0, iBlockStart = 0; i < (1 << (16 - this->kBlockShift)); i += 1, iBlockStart += (1 << this->kBlockShift))
- {
- bool_t touched = blockTouched(this, i);
-
- this->fIndex[i] = 0xFFFF;
-
- if (!touched && iUntouched != -1)
- {
- /* If no values in this block were set, we can just set its
- * index to be the same as some other block with no values
- * set, assuming we've seen one yet.
- */
- this->fIndex[i] = iUntouched;
- }
- else
- {
- int32_t j, jBlockStart;
-
- for (j = 0, jBlockStart = 0;
- j < limitCompacted;
- j += 1, jBlockStart += (1 << this->kBlockShift))
- {
- if (this->fHashes[i] == this->fHashes[j] &&
- arrayRegionMatches(this->fArray,
- iBlockStart,
- this->fArray,
- jBlockStart,
- (1 << this->kBlockShift)))
- {
- this->fIndex[i] = (int16_t)jBlockStart;
- }
- }
-
- /* TODO: verify this is correct*/
- if (this->fIndex[i] == 0xFFFF)
- {
- /* we didn't match, so copy & update*/
- icu_memcpy(&(this->fArray[jBlockStart]),
- &(this->fArray[iBlockStart]),
- (1 << this->kBlockShift)*sizeof(int16_t));
-
- this->fIndex[i] = (int16_t)jBlockStart;
- this->fHashes[j] = this->fHashes[i];
- limitCompacted += 1;
-
- if (!touched)
- {
- /* If this is the first untouched block we've seen,*/
- /* remember its index.*/
- iUntouched = (int16_t)jBlockStart;
- }
- }
- }
- }
-
- /* we are done compacting, so now make the array shorter*/
- {
- int32_t newSize = limitCompacted * (1 << this->kBlockShift);
- int16_t *result = (int16_t*) icu_malloc(sizeof(int16_t) * newSize);
-
- icu_memcpy(result, this->fArray, newSize * sizeof(int16_t));
-
- icu_free(this->fArray);
- this->fArray = result;
- this->fCount = newSize;
- icu_free(this->fHashes);
- this->fHashes = NULL;
-
- this->fCompact = TRUE;
- }
- }
- }
-
- /**
- * Query whether a specified block was "touched", i.e. had a value set.
- * Untouched blocks can be skipped when compacting the array
- */
-
- int16_t ucmp16_getDefaultValue(const CompactShortArray* this)
- {
- return this->fDefaultValue;
- }
-
-
- void touchBlock(CompactShortArray* this,
- int32_t i,
- int16_t value)
- {
- this->fHashes[i] = (this->fHashes[i] + (value << 1)) | 1;
- }
-
- bool_t blockTouched(const CompactShortArray* this, int32_t i)
- {
- return (this->fHashes[i] != 0);
- }
-
-
- const int16_t*
- ucmp16_getArray(const CompactShortArray* this)
- {
- return this->fArray;
- }
-
- const uint16_t*
- ucmp16_getIndex(const CompactShortArray* this)
- {
- return this->fIndex;
- }
-
- uint32_t
- ucmp16_getCount(const CompactShortArray* this)
- {
- return this->fCount;
- }
-
-