00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "ucmp32.h"
00020 #include "cmemory.h"
00021 #include "filestrm.h"
00022 #include <stdlib.h>
00023
00024
00025
00026 static int32_t ucmp32_findOverlappingPosition(CompactIntArray* this_obj, uint32_t start,
00027 const UChar *tempIndex,
00028 int32_t tempIndexCount,
00029 uint32_t cycle);
00030
00031 static UBool debugSmall = FALSE;
00032 static uint32_t debugSmallLimit = 30000;
00033
00038 int32_t ucmp32_getkUnicodeCount() { return UCMP32_kUnicodeCount;}
00039 int32_t ucmp32_getkBlockCount() { return UCMP32_kBlockCount;}
00040
00041 U_CAPI void ucmp32_streamIn(CompactIntArray* this_obj, FileStream* is)
00042 {
00043 int32_t newCount, len;
00044 char c;
00045 if (!T_FileStream_error(is))
00046 {
00047
00048 T_FileStream_read(is, &newCount, sizeof(newCount));
00049 if (this_obj->fCount != newCount)
00050 {
00051 this_obj->fCount = newCount;
00052 uprv_free(this_obj->fArray);
00053 this_obj->fArray = 0;
00054 this_obj->fArray = (int32_t*)uprv_malloc(this_obj->fCount * sizeof(int32_t));
00055 if (!this_obj->fArray) {
00056 this_obj->fBogus = TRUE;
00057 return;
00058 }
00059 }
00060 T_FileStream_read(is, this_obj->fArray, sizeof(*(this_obj->fArray)) * this_obj->fCount);
00061 T_FileStream_read(is, &len, sizeof(len));
00062 if (len == 0)
00063 {
00064 uprv_free(this_obj->fIndex);
00065 this_obj->fIndex = 0;
00066 }
00067 else if (len == UCMP32_kIndexCount)
00068 {
00069 if (this_obj->fIndex == 0)
00070 this_obj->fIndex =(uint16_t*)uprv_malloc(UCMP32_kIndexCount * sizeof(uint16_t));
00071 if (!this_obj->fIndex) {
00072 this_obj->fBogus = TRUE;
00073 uprv_free(this_obj->fArray);
00074 this_obj->fArray = 0;
00075 return;
00076 }
00077 T_FileStream_read(is, this_obj->fIndex, sizeof(*(this_obj->fIndex)) * UCMP32_kIndexCount);
00078 }
00079 else
00080 {
00081 this_obj->fBogus = TRUE;
00082 return;
00083 }
00084
00085 T_FileStream_read(is, (char*)&c, sizeof(c));
00086 this_obj->fCompact = (UBool)(c != 0);
00087 }
00088 }
00089
00090 U_CAPI void ucmp32_streamOut(CompactIntArray* this_obj, FileStream* os)
00091 {
00092 char c;
00093 if (!T_FileStream_error(os))
00094 {
00095 if (this_obj->fCount != 0 && this_obj->fArray != 0)
00096 {
00097 T_FileStream_write(os, &(this_obj->fCount), sizeof(this_obj->fCount));
00098 T_FileStream_write(os, this_obj->fArray, sizeof(*(this_obj->fArray)) * this_obj->fCount);
00099 }
00100 else
00101 {
00102 int32_t zero = 0;
00103 T_FileStream_write(os, &zero, sizeof(zero));
00104 }
00105
00106 if (this_obj->fIndex == 0)
00107 {
00108 int32_t len = 0;
00109 T_FileStream_write(os, &len, sizeof(len));
00110 }
00111 else
00112 {
00113 int32_t len = UCMP32_kIndexCount;
00114 T_FileStream_write(os, &len, sizeof(len));
00115 T_FileStream_write(os, this_obj->fIndex, sizeof(*(this_obj->fIndex)) * UCMP32_kIndexCount);
00116 }
00117 c = (char)(this_obj->fCompact ? 1 : 0);
00118 T_FileStream_write(os, (const char*)&c, sizeof(c));
00119 }
00120 }
00121
00122 U_CAPI void ucmp32_streamMemIn(CompactIntArray* this_obj, UMemoryStream* is)
00123 {
00124 int32_t newCount, len;
00125 char c;
00126 if (!uprv_mstrm_error(is))
00127 {
00128
00129 uprv_mstrm_read(is, &newCount, sizeof(newCount));
00130 if (this_obj->fCount != newCount)
00131 {
00132 this_obj->fCount = newCount;
00133 uprv_free(this_obj->fArray);
00134 this_obj->fArray = 0;
00135 this_obj->fArray = (int32_t*)uprv_malloc(this_obj->fCount * sizeof(int32_t));
00136 if (!this_obj->fArray) {
00137 this_obj->fBogus = TRUE;
00138 return;
00139 }
00140 }
00141 uprv_mstrm_read(is, this_obj->fArray, sizeof(*(this_obj->fArray)) * this_obj->fCount);
00142 uprv_mstrm_read(is, &len, sizeof(len));
00143 if (len == 0)
00144 {
00145 uprv_free(this_obj->fIndex);
00146 this_obj->fIndex = 0;
00147 }
00148 else if (len == UCMP32_kIndexCount)
00149 {
00150 if (this_obj->fIndex == 0)
00151 this_obj->fIndex =(uint16_t*)uprv_malloc(UCMP32_kIndexCount * sizeof(uint16_t));
00152 if (!this_obj->fIndex) {
00153 this_obj->fBogus = TRUE;
00154 uprv_free(this_obj->fArray);
00155 this_obj->fArray = 0;
00156 return;
00157 }
00158 uprv_mstrm_read(is, this_obj->fIndex, sizeof(*(this_obj->fIndex)) * UCMP32_kIndexCount);
00159 }
00160 else
00161 {
00162 this_obj->fBogus = TRUE;
00163 return;
00164 }
00165
00166 uprv_mstrm_read(is, (char*)&c, sizeof(c));
00167 this_obj->fCompact = (UBool)(c != 0);
00168 }
00169 }
00170
00171 U_CAPI void ucmp32_streamMemOut(CompactIntArray* this_obj, UMemoryStream* os)
00172 {
00173 char c;
00174 if (!uprv_mstrm_error(os))
00175 {
00176 if (this_obj->fCount != 0 && this_obj->fArray != 0)
00177 {
00178 uprv_mstrm_write(os, (uint8_t *)&(this_obj->fCount), sizeof(this_obj->fCount));
00179 uprv_mstrm_write(os, (uint8_t *)this_obj->fArray, sizeof(*(this_obj->fArray)) * this_obj->fCount);
00180 }
00181 else
00182 {
00183 int32_t zero = 0;
00184 uprv_mstrm_write(os, (uint8_t *)&zero, sizeof(zero));
00185 }
00186
00187 if (this_obj->fIndex == 0)
00188 {
00189 int32_t len = 0;
00190 uprv_mstrm_write(os, (uint8_t *)&len, sizeof(len));
00191 }
00192 else
00193 {
00194 int32_t len = UCMP32_kIndexCount;
00195 uprv_mstrm_write(os, (uint8_t *)&len, sizeof(len));
00196 uprv_mstrm_write(os, (uint8_t *)this_obj->fIndex, sizeof(*(this_obj->fIndex)) * UCMP32_kIndexCount);
00197 }
00198 c = (char)(this_obj->fCompact ? 1 : 0);
00199 uprv_mstrm_write(os, (uint8_t *)&c, sizeof(c));
00200 }
00201 }
00202
00203 CompactIntArray* ucmp32_open(int32_t defaultValue)
00204 {
00205 uint16_t i;
00206 int32_t *p, *p_end;
00207 uint16_t *q, *q_end;
00208 CompactIntArray* this_obj = (CompactIntArray*) uprv_malloc(sizeof(CompactIntArray));
00209 if (this_obj == NULL) return NULL;
00210
00211 this_obj->fStructSize = sizeof(CompactIntArray);
00212 this_obj->fArray = NULL;
00213 this_obj->fIndex = NULL;
00214 this_obj->fCount = UCMP32_kUnicodeCount;
00215 this_obj->fCompact = FALSE;
00216 this_obj->fBogus = FALSE;
00217 this_obj->fAlias = FALSE;
00218 this_obj->fIAmOwned = FALSE;
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 this_obj->fArray = (int32_t*)uprv_malloc(UCMP32_kUnicodeCount * sizeof(int32_t));
00241 if (this_obj->fArray == NULL) {
00242 this_obj->fBogus = TRUE;
00243 return NULL;
00244 }
00245
00246 this_obj->fIndex = (uint16_t*)uprv_malloc(UCMP32_kIndexCount * sizeof(uint16_t));
00247 if (!this_obj->fIndex) {
00248 uprv_free(this_obj->fArray);
00249 this_obj->fArray = NULL;
00250 this_obj->fBogus = TRUE;
00251 return NULL;
00252 }
00253 p = this_obj->fArray;
00254 p_end = p + UCMP32_kUnicodeCount;
00255 while (p < p_end) *p++ = defaultValue;
00256
00257 q = this_obj->fIndex;
00258 q_end = q + UCMP32_kIndexCount;
00259 i = 0;
00260 while (q < q_end)
00261 {
00262 *q++ = i;
00263 i += (1 << UCMP32_kBlockShift);
00264 }
00265 return this_obj;
00266 }
00267
00268 CompactIntArray* ucmp32_openAdopt(uint16_t *indexArray,
00269 int32_t *newValues,
00270 int32_t count)
00271 {
00272 CompactIntArray* this_obj = (CompactIntArray*) uprv_malloc(sizeof(CompactIntArray));
00273
00274 ucmp32_initAdopt(this_obj, indexArray, newValues, count);
00275 this_obj->fIAmOwned = FALSE;
00276 return this_obj;
00277 }
00278
00279 CompactIntArray* ucmp32_openAlias(uint16_t *indexArray,
00280 int32_t *newValues,
00281 int32_t count)
00282 {
00283 CompactIntArray* this_obj = (CompactIntArray*) uprv_malloc(sizeof(CompactIntArray));
00284
00285 ucmp32_initAlias(this_obj, indexArray, newValues, count);
00286 this_obj->fIAmOwned = FALSE;
00287 return this_obj;
00288 }
00289
00290
00291
00292 CompactIntArray* ucmp32_initAdopt(CompactIntArray* this_obj,
00293 uint16_t *indexArray,
00294 int32_t *newValues,
00295 int32_t count)
00296 {
00297 if (this_obj) {
00298 this_obj->fCount = count;
00299 this_obj->fBogus = FALSE;
00300 this_obj->fStructSize = sizeof(CompactIntArray);
00301
00302 this_obj->fArray = newValues;
00303 this_obj->fIndex = indexArray;
00304 this_obj->fCompact = (UBool)((count < UCMP32_kUnicodeCount) ? TRUE : FALSE);
00305 this_obj->fAlias = FALSE;
00306 this_obj->fIAmOwned = TRUE;
00307 }
00308
00309 return this_obj;
00310 }
00311
00312 CompactIntArray* ucmp32_initAlias(CompactIntArray* this_obj,
00313 uint16_t *indexArray,
00314 int32_t *newValues,
00315 int32_t count)
00316 {
00317 if (this_obj) {
00318 this_obj->fCount = count;
00319 this_obj->fBogus = FALSE;
00320 this_obj->fStructSize = sizeof(CompactIntArray);
00321
00322 this_obj->fArray = newValues;
00323 this_obj->fIndex = indexArray;
00324 this_obj->fCompact = (UBool)((count < UCMP32_kUnicodeCount) ? TRUE : FALSE);
00325 this_obj->fAlias = TRUE;
00326 this_obj->fIAmOwned = TRUE;
00327 }
00328
00329 return this_obj;
00330 }
00331
00332
00333 void ucmp32_close(CompactIntArray* this_obj)
00334 {
00335 if(this_obj != NULL) {
00336 if(!this_obj->fAlias) {
00337 if(this_obj->fArray != NULL) {
00338 uprv_free(this_obj->fArray);
00339 }
00340 if(this_obj->fIndex != NULL) {
00341 uprv_free(this_obj->fIndex);
00342 }
00343 }
00344 if(!this_obj->fIAmOwned) {
00345 uprv_free(this_obj);
00346 }
00347 }
00348 }
00349
00350 UBool ucmp32_isBogus(const CompactIntArray* this_obj)
00351 {
00352 return (UBool)(this_obj == NULL || this_obj->fBogus);
00353 }
00354
00355 void ucmp32_expand(CompactIntArray* this_obj) {
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 int32_t i;
00370 int32_t* tempArray;
00371 if (this_obj->fCompact) {
00372 tempArray = (int32_t*)uprv_malloc(UCMP32_kUnicodeCount * sizeof(int32_t));
00373 if (tempArray == NULL) {
00374 this_obj->fBogus = TRUE;
00375 return;
00376 }
00377 for (i = 0; i < UCMP32_kUnicodeCount; ++i) {
00378 tempArray[i] = ucmp32_get(this_obj, (UChar)i);
00379 }
00380 for (i = 0; i < UCMP32_kIndexCount; ++i) {
00381 this_obj->fIndex[i] = (uint16_t)(i<<UCMP32_kBlockShift);
00382 }
00383 uprv_free(this_obj->fArray);
00384 this_obj->fArray = tempArray;
00385 this_obj->fCompact = FALSE;
00386 }
00387 }
00388
00389 uint32_t ucmp32_getCount(const CompactIntArray* this_obj)
00390 {
00391 return this_obj->fCount;
00392 }
00393
00394 const int32_t* ucmp32_getArray(const CompactIntArray* this_obj)
00395 {
00396 return this_obj->fArray;
00397 }
00398
00399 const uint16_t* ucmp32_getIndex(const CompactIntArray* this_obj)
00400 {
00401 return this_obj->fIndex;
00402 }
00403
00404 void ucmp32_set(CompactIntArray* this_obj, UChar c, int32_t value)
00405 {
00406 if (this_obj->fCompact == TRUE) {
00407 ucmp32_expand(this_obj);
00408 if (this_obj->fBogus) return;
00409 }
00410 this_obj->fArray[(int32_t)c] = value;
00411 }
00412
00413
00414 void ucmp32_setRange(CompactIntArray* this_obj, UChar start, UChar end, int32_t value)
00415 {
00416 int32_t i;
00417 if (this_obj->fCompact == TRUE) {
00418 ucmp32_expand(this_obj);
00419 if (this_obj->fBogus) return;
00420
00421 }
00422 for (i = start; i <= end; ++i) {
00423 this_obj->fArray[i] = value;
00424 }
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434 static int32_t ucmp32_findOverlappingPosition(CompactIntArray* this_obj,
00435 uint32_t start,
00436 const UChar* tempIndex,
00437 int32_t tempIndexCount,
00438 uint32_t cycle) {
00439
00440
00441
00442
00443 int32_t i;
00444 int32_t j;
00445 int32_t currentCount;
00446
00447
00448 for (i = 0; i < tempIndexCount; i += cycle) {
00449 currentCount = UCMP32_kBlockCount;
00450 if (i + UCMP32_kBlockCount > tempIndexCount) {
00451 currentCount = tempIndexCount - i;
00452 }
00453 for (j = 0; j < currentCount; ++j) {
00454 if (this_obj->fArray[start + j] != this_obj->fArray[tempIndex[i + j]]) break;
00455 }
00456 if (j == currentCount) break;
00457 }
00458
00459 return i;
00460 }
00461
00462
00463 void ucmp32_compact(CompactIntArray* this_obj, int32_t cycle) {
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 UChar* tempIndex;
00475 int32_t tempIndexCount;
00476 int32_t* tempArray;
00477 int32_t iBlock, iIndex;
00478 int32_t newCount, firstPosition;
00479 uint32_t block;
00480 if (!this_obj->fCompact) {
00481
00482
00483 if (cycle < 0) cycle = 1;
00484 else if (cycle > UCMP32_kBlockCount)
00485 cycle = UCMP32_kBlockCount;
00486
00487
00488 tempIndex =(UChar*)uprv_malloc(UCMP32_kUnicodeCount * sizeof(uint32_t));
00489 if (tempIndex == NULL) {
00490 this_obj->fBogus = TRUE;
00491 return;
00492 }
00493
00494 tempIndexCount = UCMP32_kBlockCount;
00495 for (iIndex = 0; iIndex < UCMP32_kBlockCount; ++iIndex) {
00496 tempIndex[iIndex] = (uint16_t)iIndex;
00497 };
00498 this_obj->fIndex[0] = 0;
00499
00500
00501 for (iBlock = 1; iBlock < UCMP32_kIndexCount; ++iBlock) {
00502
00503 block = iBlock<<UCMP32_kBlockShift;
00504 if (debugSmall) if (block > debugSmallLimit) break;
00505 firstPosition = ucmp32_findOverlappingPosition(this_obj, block, tempIndex, tempIndexCount, cycle);
00506
00507
00508
00509
00510
00511 newCount = firstPosition + UCMP32_kBlockCount;
00512 if (newCount > tempIndexCount) {
00513 for (iIndex = tempIndexCount; iIndex < newCount; ++iIndex) {
00514 tempIndex[iIndex] = (uint16_t)(iIndex - firstPosition + block);
00515 }
00516 tempIndexCount = newCount;
00517 }
00518 this_obj->fIndex[iBlock] = (uint16_t)firstPosition;
00519 }
00520
00521
00522
00523
00524 tempArray = (int32_t*)uprv_malloc(tempIndexCount * sizeof(uint32_t));
00525 if (tempArray == NULL) {
00526 this_obj->fBogus = TRUE;
00527 uprv_free(tempIndex);
00528 return;
00529 }
00530 for (iIndex = 0; iIndex < tempIndexCount; ++iIndex) {
00531 tempArray[iIndex] = this_obj->fArray[tempIndex[iIndex]];
00532 }
00533 uprv_free(this_obj->fArray);
00534 this_obj->fArray = tempArray;
00535 this_obj->fCount = tempIndexCount;
00536
00537
00538
00539
00540 uprv_free(tempIndex);
00541 this_obj->fCompact = TRUE;
00542
00543 #ifdef _DEBUG
00544
00545
00546 #endif
00547 }
00548 }
00549
00550 U_CAPI uint32_t U_EXPORT2 ucmp32_flattenMem (const CompactIntArray* array, UMemoryStream *MS)
00551 {
00552 int32_t size = 0;
00553
00554 uprv_mstrm_write32(MS, ICU_UCMP32_VERSION);
00555 size += 4;
00556
00557 uprv_mstrm_write32(MS, array->fCount);
00558 size += 4;
00559
00560 uprv_mstrm_writeBlock(MS, array->fIndex, sizeof(array->fIndex[0])*UCMP32_kIndexCount);
00561 size += sizeof(array->fIndex[0])*UCMP32_kIndexCount;
00562
00563 uprv_mstrm_writeBlock(MS, array->fArray, sizeof(array->fArray[0])*array->fCount);
00564 size += sizeof(array->fArray[0])*array->fCount;
00565
00566 while(size%4)
00567 {
00568 uprv_mstrm_writePadding(MS, 1);
00569 size += 1;
00570 }
00571
00572 return size;
00573 }
00574
00575 U_CAPI void U_EXPORT2 ucmp32_initFromData(CompactIntArray *this_obj, const uint8_t **source, UErrorCode *status)
00576 {
00577 uint32_t i;
00578 const uint8_t *oldSource = *source;
00579
00580 if(U_FAILURE(*status))
00581 return;
00582
00583 this_obj->fArray = NULL;
00584 this_obj->fIndex = NULL;
00585 this_obj->fBogus = FALSE;
00586 this_obj->fStructSize = sizeof(CompactIntArray);
00587 this_obj->fCompact = TRUE;
00588 this_obj->fAlias = TRUE;
00589 this_obj->fIAmOwned = TRUE;
00590
00591 i = * ((const uint32_t*) *source);
00592 (*source) += 4;
00593
00594 if(i != ICU_UCMP32_VERSION)
00595 {
00596 *status = U_INVALID_FORMAT_ERROR;
00597 return;
00598 }
00599
00600 this_obj->fCount = * ((const uint32_t*)*source);
00601 (*source) += 4;
00602
00603 this_obj->fIndex = (uint16_t*) *source;
00604 (*source) += sizeof(this_obj->fIndex[0])*UCMP32_kIndexCount;
00605
00606 this_obj->fArray = (int32_t*) *source;
00607 (*source) += sizeof(this_obj->fArray[0])*this_obj->fCount;
00608
00609
00610 while((*source-(oldSource))%4)
00611 (*source)++;
00612 }