#include "ucmp8.h"
#include "cmemory.h"
U_CAPI int32_t U_EXPORT2
ucmp8_getkUnicodeCount() { return UCMP8_kUnicodeCount;}
U_CAPI int32_t U_EXPORT2
ucmp8_getkBlockCount() { return UCMP8_kBlockCount;}
U_CAPI void U_EXPORT2
ucmp8_initBogus(CompactByteArray* array)
{
CompactByteArray* this_obj = array;
if (this_obj == NULL) return;
this_obj->fStructSize = sizeof(CompactByteArray);
this_obj->fArray = NULL;
this_obj->fIndex = NULL;
this_obj->fCount = UCMP8_kUnicodeCount;
this_obj->fCompact = FALSE;
this_obj->fBogus = TRUE;
this_obj->fAlias = FALSE;
this_obj->fIAmOwned = TRUE;
}
U_CAPI void U_EXPORT2
ucmp8_init(CompactByteArray* array, int8_t defaultValue)
{
CompactByteArray* this_obj = array;
int32_t i;
if (this_obj == NULL) return;
this_obj->fStructSize = sizeof(CompactByteArray);
this_obj->fArray = NULL;
this_obj->fIndex = NULL;
this_obj->fCount = UCMP8_kUnicodeCount;
this_obj->fCompact = FALSE;
this_obj->fBogus = FALSE;
this_obj->fAlias = FALSE;
this_obj->fIAmOwned = TRUE;
this_obj->fArray = (int8_t*) uprv_malloc(sizeof(int8_t) * UCMP8_kUnicodeCount);
if (!this_obj->fArray)
{
this_obj->fBogus = TRUE;
return;
}
this_obj->fIndex = (uint16_t*) uprv_malloc(sizeof(uint16_t) * UCMP8_kIndexCount);
if (!this_obj->fIndex)
{
uprv_free(this_obj->fArray);
this_obj->fArray = NULL;
this_obj->fBogus = TRUE;
return;
}
for (i = 0; i < UCMP8_kUnicodeCount; ++i)
{
this_obj->fArray[i] = defaultValue;
}
for (i = 0; i < UCMP8_kIndexCount; ++i)
{
this_obj->fIndex[i] = (uint16_t)(i << UCMP8_kBlockShift);
}
}
U_CAPI CompactByteArray* U_EXPORT2
ucmp8_open(int8_t defaultValue)
{
CompactByteArray* this_obj = (CompactByteArray*) uprv_malloc(sizeof(CompactByteArray));
int32_t i;
if (this_obj == NULL) return NULL;
this_obj->fStructSize = sizeof(CompactByteArray);
this_obj->fArray = NULL;
this_obj->fIndex = NULL;
this_obj->fCount = UCMP8_kUnicodeCount;
this_obj->fCompact = FALSE;
this_obj->fBogus = FALSE;
this_obj->fAlias = FALSE;
this_obj->fIAmOwned = FALSE;
this_obj->fArray = (int8_t*) uprv_malloc(sizeof(int8_t) * UCMP8_kUnicodeCount);
if (!this_obj->fArray)
{
this_obj->fBogus = TRUE;
return NULL;
}
this_obj->fIndex = (uint16_t*) uprv_malloc(sizeof(uint16_t) * UCMP8_kIndexCount);
if (!this_obj->fIndex)
{
uprv_free(this_obj->fArray);
this_obj->fArray = NULL;
this_obj->fBogus = TRUE;
return NULL;
}
for (i = 0; i < UCMP8_kUnicodeCount; ++i)
{
this_obj->fArray[i] = defaultValue;
}
for (i = 0; i < UCMP8_kIndexCount; ++i)
{
this_obj->fIndex[i] = (uint16_t)(i << UCMP8_kBlockShift);
}
return this_obj;
}
U_CAPI CompactByteArray* U_EXPORT2
ucmp8_openAdopt(uint16_t *indexArray,
int8_t *newValues,
int32_t count)
{
CompactByteArray* this_obj = (CompactByteArray*) uprv_malloc(sizeof(CompactByteArray));
if(this_obj == NULL)
return NULL;
ucmp8_initAdopt(this_obj, indexArray, newValues, count);
this_obj->fIAmOwned = FALSE;
return this_obj;
}
U_CAPI CompactByteArray* U_EXPORT2
ucmp8_openAlias(uint16_t *indexArray,
int8_t *newValues,
int32_t count)
{
CompactByteArray* this_obj = (CompactByteArray*) uprv_malloc(sizeof(CompactByteArray));
if(this_obj == NULL)
return NULL;
ucmp8_initAlias(this_obj, indexArray, newValues, count);
this_obj->fIAmOwned = FALSE;
return this_obj;
}
U_CAPI CompactByteArray* U_EXPORT2
ucmp8_initAdopt(CompactByteArray *this_obj,
uint16_t *indexArray,
int8_t *newValues,
int32_t count)
{
if (this_obj) {
this_obj->fCount = count;
this_obj->fBogus = FALSE;
this_obj->fStructSize = sizeof(CompactByteArray);
this_obj->fArray = newValues;
this_obj->fIndex = indexArray;
this_obj->fCompact = (UBool)((count < UCMP8_kUnicodeCount) ? TRUE : FALSE);
this_obj->fAlias = FALSE;
this_obj->fIAmOwned = TRUE;
}
return this_obj;
}
U_CAPI CompactByteArray* U_EXPORT2
ucmp8_initAlias(CompactByteArray *this_obj,
uint16_t *indexArray,
int8_t *newValues,
int32_t count)
{
if (this_obj) {
this_obj->fArray = NULL;
this_obj->fIndex = NULL;
this_obj->fCount = count;
this_obj->fBogus = FALSE;
this_obj->fStructSize = sizeof(CompactByteArray);
this_obj->fArray = newValues;
this_obj->fIndex = indexArray;
this_obj->fCompact = (UBool)((count < UCMP8_kUnicodeCount) ? TRUE : FALSE);
this_obj->fAlias = TRUE;
this_obj->fIAmOwned = TRUE;
}
return this_obj;
}
U_CAPI void U_EXPORT2
ucmp8_close(CompactByteArray* this_obj)
{
if(this_obj != NULL) {
if(!this_obj->fAlias) {
if(this_obj->fArray != NULL) {
uprv_free(this_obj->fArray);
}
if(this_obj->fIndex != NULL) {
uprv_free(this_obj->fIndex);
}
}
if(!this_obj->fIAmOwned)
{
uprv_free(this_obj);
}
}
}
U_CAPI void U_EXPORT2
ucmp8_expand(CompactByteArray* this_obj)
{
int32_t i;
if (this_obj->fCompact)
{
int8_t* tempArray;
tempArray = (int8_t*) uprv_malloc(sizeof(int8_t) * UCMP8_kUnicodeCount);
if (!tempArray)
{
this_obj->fBogus = TRUE;
return;
}
for (i = 0; i < UCMP8_kUnicodeCount; ++i)
{
tempArray[i] = ucmp8_get(this_obj,(UChar)i);
}
for (i = 0; i < UCMP8_kIndexCount; ++i)
{
this_obj->fIndex[i] = (uint16_t)(i<< UCMP8_kBlockShift);
}
uprv_free(this_obj->fArray);
this_obj->fArray = tempArray;
this_obj->fCompact = FALSE;
this_obj->fAlias = FALSE;
}
}
static int32_t
findOverlappingPosition(CompactByteArray* this_obj,
uint32_t start,
const UChar* tempIndex,
int32_t tempIndexCount,
uint32_t cycle)
{
int32_t i;
int32_t j;
int32_t currentCount;
for (i = 0; i < tempIndexCount; i += cycle)
{
currentCount = UCMP8_kBlockCount;
if (i + UCMP8_kBlockCount > tempIndexCount)
{
currentCount = tempIndexCount - i;
}
for (j = 0; j < currentCount; ++j)
{
if (this_obj->fArray[start + j] != this_obj->fArray[tempIndex[i + j]])
break;
}
if (j == currentCount)
break;
}
return i;
}
U_CAPI UBool U_EXPORT2
ucmp8_isBogus(const CompactByteArray* this_obj)
{
return (UBool)(this_obj == NULL || this_obj->fBogus);
}
U_CAPI const int8_t* U_EXPORT2
ucmp8_getArray(const CompactByteArray* this_obj)
{
return this_obj->fArray;
}
U_CAPI const uint16_t* U_EXPORT2
ucmp8_getIndex(const CompactByteArray* this_obj)
{
return this_obj->fIndex;
}
U_CAPI int32_t U_EXPORT2
ucmp8_getCount(const CompactByteArray* this_obj)
{
return this_obj->fCount;
}
U_CAPI void U_EXPORT2
ucmp8_set(CompactByteArray* this_obj,
UChar c,
int8_t value)
{
if (this_obj->fCompact == TRUE)
{
ucmp8_expand(this_obj);
if (this_obj->fBogus) return;
}
this_obj->fArray[(int32_t)c] = value;
}
U_CAPI void U_EXPORT2
ucmp8_setRange(CompactByteArray* this_obj,
UChar start,
UChar end,
int8_t value)
{
int32_t i;
if (this_obj->fCompact == TRUE)
{
ucmp8_expand(this_obj);
if (this_obj->fBogus)
return;
}
for (i = start; i <= end; ++i)
{
this_obj->fArray[i] = value;
}
}
U_CAPI void U_EXPORT2
ucmp8_compact(CompactByteArray* this_obj,
uint32_t cycle)
{
if (!this_obj->fCompact)
{
UChar* tempIndex;
int32_t tempIndexCount;
int8_t* tempArray;
int32_t iBlock, iIndex;
if (cycle <= 0)
cycle = 1;
else if (cycle > (uint32_t)UCMP8_kBlockCount)
cycle = UCMP8_kBlockCount;
tempIndex = (UChar*) uprv_malloc(sizeof(UChar)* UCMP8_kUnicodeCount);
if (!tempIndex)
{
this_obj->fBogus = TRUE;
return;
}
tempIndexCount = UCMP8_kBlockCount;
for (iIndex = 0; iIndex < UCMP8_kBlockCount; ++iIndex)
{
tempIndex[iIndex] = (uint16_t)iIndex;
}
this_obj->fIndex[0] = 0;
for (iBlock = 1; iBlock < UCMP8_kIndexCount; ++iBlock)
{
int32_t newCount, firstPosition, block;
block = iBlock << UCMP8_kBlockShift;
firstPosition = findOverlappingPosition(this_obj,
block,
tempIndex,
tempIndexCount,
cycle);
newCount = firstPosition + UCMP8_kBlockCount;
if (newCount > tempIndexCount)
{
for (iIndex = tempIndexCount; iIndex < newCount; ++iIndex)
{
tempIndex[iIndex] = (uint16_t)(iIndex - firstPosition + block);
}
tempIndexCount = newCount;
}
this_obj->fIndex[iBlock] = (uint16_t)firstPosition;
}
tempArray = (int8_t*) uprv_malloc(tempIndexCount * sizeof(int8_t));
if (!tempArray)
{
this_obj->fBogus = TRUE;
uprv_free(tempIndex);
return;
}
for (iIndex = 0; iIndex < tempIndexCount; ++iIndex)
{
tempArray[iIndex] = this_obj->fArray[tempIndex[iIndex]];
}
uprv_free(this_obj->fArray);
this_obj->fArray = tempArray;
this_obj->fCount = tempIndexCount;
uprv_free(tempIndex);
this_obj->fCompact = TRUE;
}
}
#define MEMORY_WRITE(destAddr, source, sizeSoFar, len) \
if (destAddr) {\
uprv_memcpy(destAddr+sizeSoFar, source, len);\
}\
sizeSoFar += (len)
U_CAPI uint32_t U_EXPORT2 ucmp8_flattenMem (const CompactByteArray* array, uint8_t *MS)
{
int32_t size = 0;
static const int32_t version = ICU_UCMP8_VERSION;
MEMORY_WRITE(MS, &version, size, 4);
MEMORY_WRITE(MS, &array->fCount, size, 4);
MEMORY_WRITE(MS, array->fIndex, size, sizeof(array->fIndex[0])*UCMP8_kIndexCount);
MEMORY_WRITE(MS, array->fArray, size, sizeof(array->fArray[0])*array->fCount);
while(size%4)
{
uint8_t pad = 0;
MEMORY_WRITE(MS, &pad, size, 1);
}
return size;
}
U_CAPI void U_EXPORT2 ucmp8_initFromData(CompactByteArray *this_obj, const uint8_t **source, UErrorCode *status)
{
uint32_t i;
const uint8_t *oldSource = *source;
if(U_FAILURE(*status))
return;
this_obj->fArray = NULL;
this_obj->fIndex = NULL;
this_obj->fBogus = FALSE;
this_obj->fStructSize = sizeof(CompactByteArray);
this_obj->fCompact = TRUE;
this_obj->fAlias = TRUE;
this_obj->fIAmOwned = TRUE;
i = * ((const uint32_t*) *source);
(*source) += 4;
if(i != ICU_UCMP8_VERSION)
{
*status = U_INVALID_FORMAT_ERROR;
return;
}
this_obj->fCount = * ((const uint32_t*)*source);
(*source) += 4;
this_obj->fIndex = (uint16_t*) *source;
(*source) += sizeof(this_obj->fIndex[0])*UCMP8_kIndexCount;
this_obj->fArray = (int8_t*) *source;
(*source) += sizeof(this_obj->fArray[0])*this_obj->fCount;
while((*source-(oldSource))%4)
(*source)++;
}