1/* 2******************************************************************************* 3* 4* Copyright (C) 2000-2008, International Business Machines 5* Corporation and others. All Rights Reserved. 6* 7******************************************************************************* 8* 9* File reslist.c 10* 11* Modification History: 12* 13* Date Name Description 14* 02/21/00 weiv Creation. 15******************************************************************************* 16*/ 17 18#include <assert.h> 19#include <stdio.h> 20#include "reslist.h" 21#include "unewdata.h" 22#include "unicode/ures.h" 23#include "unicode/putil.h" 24#include "errmsg.h" 25 26#define BIN_ALIGNMENT 16 27 28static UBool gIncludeCopyright = FALSE; 29 30/* 31 * res_none() returns the address of kNoResource, 32 * for use in non-error cases when no resource is to be added to the bundle. 33 * (NULL is used in error cases.) 34 */ 35static struct SResource kNoResource = { RES_NONE }; 36 37uint32_t res_write(UNewDataMemory *mem, struct SResource *res, 38 uint32_t usedOffset, UErrorCode *status); 39 40static const UDataInfo dataInfo= { 41 sizeof(UDataInfo), 42 0, 43 44 U_IS_BIG_ENDIAN, 45 U_CHARSET_FAMILY, 46 sizeof(UChar), 47 0, 48 49 {0x52, 0x65, 0x73, 0x42}, /* dataFormat="resb" */ 50 {1, 2, 0, 0}, /* formatVersion */ 51 {1, 4, 0, 0} /* dataVersion take a look at version inside parsed resb*/ 52}; 53 54static uint8_t calcPadding(uint32_t size) { 55 /* returns space we need to pad */ 56 return (uint8_t) ((size % sizeof(uint32_t)) ? (sizeof(uint32_t) - (size % sizeof(uint32_t))) : 0); 57 58} 59 60void setIncludeCopyright(UBool val){ 61 gIncludeCopyright=val; 62} 63 64UBool getIncludeCopyright(void){ 65 return gIncludeCopyright; 66} 67 68/* Writing Functions */ 69static uint32_t string_write(UNewDataMemory *mem, struct SResource *res, 70 uint32_t usedOffset, UErrorCode *status) { 71 udata_write32(mem, res->u.fString.fLength); 72 udata_writeUString(mem, res->u.fString.fChars, res->u.fString.fLength + 1); 73 udata_writePadding(mem, calcPadding(res->fSize)); 74 75 return usedOffset; 76} 77 78/* Writing Functions */ 79static uint32_t alias_write(UNewDataMemory *mem, struct SResource *res, 80 uint32_t usedOffset, UErrorCode *status) { 81 udata_write32(mem, res->u.fString.fLength); 82 udata_writeUString(mem, res->u.fString.fChars, res->u.fString.fLength + 1); 83 udata_writePadding(mem, calcPadding(res->fSize)); 84 85 return usedOffset; 86} 87 88static uint32_t array_write(UNewDataMemory *mem, struct SResource *res, 89 uint32_t usedOffset, UErrorCode *status) { 90 uint32_t *resources = NULL; 91 uint32_t i = 0; 92 93 struct SResource *current = NULL; 94 95 if (U_FAILURE(*status)) { 96 return 0; 97 } 98 99 if (res->u.fArray.fCount > 0) { 100 resources = (uint32_t *) uprv_malloc(sizeof(uint32_t) * res->u.fArray.fCount); 101 102 if (resources == NULL) { 103 *status = U_MEMORY_ALLOCATION_ERROR; 104 return 0; 105 } 106 107 current = res->u.fArray.fFirst; 108 i = 0; 109 110 while (current != NULL) { 111 if (current->fType == URES_INT) { 112 resources[i] = (current->fType << 28) | (current->u.fIntValue.fValue & 0xFFFFFFF); 113 } else if (current->fType == URES_BINARY) { 114 uint32_t uo = usedOffset; 115 116 usedOffset = res_write(mem, current, usedOffset, status); 117 resources[i] = (current->fType << 28) | (usedOffset >> 2); 118 usedOffset += current->fSize + calcPadding(current->fSize) - (usedOffset - uo); 119 } else { 120 usedOffset = res_write(mem, current, usedOffset, status); 121 resources[i] = (current->fType << 28) | (usedOffset >> 2); 122 usedOffset += current->fSize + calcPadding(current->fSize); 123 } 124 125 i++; 126 current = current->fNext; 127 } 128 129 /* usedOffset += res->fSize + pad; */ 130 131 udata_write32(mem, res->u.fArray.fCount); 132 udata_writeBlock(mem, resources, sizeof(uint32_t) * res->u.fArray.fCount); 133 uprv_free(resources); 134 } else { 135 /* array is empty */ 136 udata_write32(mem, 0); 137 } 138 139 return usedOffset; 140} 141 142static uint32_t intvector_write(UNewDataMemory *mem, struct SResource *res, 143 uint32_t usedOffset, UErrorCode *status) { 144 uint32_t i = 0; 145 udata_write32(mem, res->u.fIntVector.fCount); 146 for(i = 0; i<res->u.fIntVector.fCount; i++) { 147 udata_write32(mem, res->u.fIntVector.fArray[i]); 148 } 149 150 return usedOffset; 151} 152 153static uint32_t bin_write(UNewDataMemory *mem, struct SResource *res, 154 uint32_t usedOffset, UErrorCode *status) { 155 uint32_t pad = 0; 156 uint32_t extrapad = calcPadding(res->fSize); 157 uint32_t dataStart = usedOffset + sizeof(res->u.fBinaryValue.fLength); 158 159 if (dataStart % BIN_ALIGNMENT) { 160 pad = (BIN_ALIGNMENT - dataStart % BIN_ALIGNMENT); 161 udata_writePadding(mem, pad); 162 usedOffset += pad; 163 } 164 165 udata_write32(mem, res->u.fBinaryValue.fLength); 166 if (res->u.fBinaryValue.fLength > 0) { 167 udata_writeBlock(mem, res->u.fBinaryValue.fData, res->u.fBinaryValue.fLength); 168 } 169 udata_writePadding(mem, (BIN_ALIGNMENT - pad + extrapad)); 170 171 return usedOffset; 172} 173 174static uint32_t int_write(UNewDataMemory *mem, struct SResource *res, 175 uint32_t usedOffset, UErrorCode *status) { 176 return usedOffset; 177} 178 179static uint32_t table_write(UNewDataMemory *mem, struct SResource *res, 180 uint32_t usedOffset, UErrorCode *status) { 181 uint8_t pad = 0; 182 uint32_t i = 0; 183 uint16_t *keys16 = NULL; 184 int32_t *keys32 = NULL; 185 uint32_t *resources = NULL; 186 187 struct SResource *current = NULL; 188 189 if (U_FAILURE(*status)) { 190 return 0; 191 } 192 193 pad = calcPadding(res->fSize); 194 195 if (res->u.fTable.fCount > 0) { 196 if(res->fType == URES_TABLE) { 197 keys16 = (uint16_t *) uprv_malloc(sizeof(uint16_t) * res->u.fTable.fCount); 198 if (keys16 == NULL) { 199 *status = U_MEMORY_ALLOCATION_ERROR; 200 return 0; 201 } 202 } else { 203 keys32 = (int32_t *) uprv_malloc(sizeof(int32_t) * res->u.fTable.fCount); 204 if (keys32 == NULL) { 205 *status = U_MEMORY_ALLOCATION_ERROR; 206 return 0; 207 } 208 } 209 210 resources = (uint32_t *) uprv_malloc(sizeof(uint32_t) * res->u.fTable.fCount); 211 212 if (resources == NULL) { 213 uprv_free(keys16); 214 uprv_free(keys32); 215 *status = U_MEMORY_ALLOCATION_ERROR; 216 return 0; 217 } 218 219 current = res->u.fTable.fFirst; 220 i = 0; 221 222 while (current != NULL) { 223 assert(i < res->u.fTable.fCount); 224 225 /* where the key is */ 226 if(res->fType == URES_TABLE) { 227 keys16[i] = (uint16_t) current->fKey; 228 } else { 229 keys32[i] = current->fKey; 230 } 231 232 if (current->fType == URES_INT) { 233 resources[i] = (current->fType << 28) | (current->u.fIntValue.fValue & 0xFFFFFFF); 234 } else if (current->fType == URES_BINARY) { 235 uint32_t uo = usedOffset; 236 237 usedOffset = res_write(mem, current, usedOffset, status); 238 resources[i] = (current->fType << 28) | (usedOffset >> 2); 239 usedOffset += current->fSize + calcPadding(current->fSize) - (usedOffset - uo); 240 } else { 241 usedOffset = res_write(mem, current, usedOffset, status); 242 resources[i] = (current->fType << 28) | (usedOffset >> 2); 243 usedOffset += current->fSize + calcPadding(current->fSize); 244 } 245 246 i++; 247 current = current->fNext; 248 } 249 250 if(res->fType == URES_TABLE) { 251 udata_write16(mem, (uint16_t)res->u.fTable.fCount); 252 253 udata_writeBlock(mem, keys16, sizeof(uint16_t) * res->u.fTable.fCount); 254 udata_writePadding(mem, pad); 255 } else { 256 udata_write32(mem, res->u.fTable.fCount); 257 258 udata_writeBlock(mem, keys32, sizeof(int32_t) * res->u.fTable.fCount); 259 } 260 261 udata_writeBlock(mem, resources, sizeof(uint32_t) * res->u.fTable.fCount); 262 263 uprv_free(keys16); 264 uprv_free(keys32); 265 uprv_free(resources); 266 } else { 267 /* table is empty */ 268 if(res->fType == URES_TABLE) { 269 udata_write16(mem, 0); 270 udata_writePadding(mem, pad); 271 } else { 272 udata_write32(mem, 0); 273 } 274 } 275 276 return usedOffset; 277} 278 279uint32_t res_write(UNewDataMemory *mem, struct SResource *res, 280 uint32_t usedOffset, UErrorCode *status) { 281 if (U_FAILURE(*status)) { 282 return 0; 283 } 284 285 if (res != NULL) { 286 switch (res->fType) { 287 case URES_STRING: 288 return string_write (mem, res, usedOffset, status); 289 case URES_ALIAS: 290 return alias_write (mem, res, usedOffset, status); 291 case URES_INT_VECTOR: 292 return intvector_write (mem, res, usedOffset, status); 293 case URES_BINARY: 294 return bin_write (mem, res, usedOffset, status); 295 case URES_INT: 296 return int_write (mem, res, usedOffset, status); 297 case URES_ARRAY: 298 return array_write (mem, res, usedOffset, status); 299 case URES_TABLE: 300 case URES_TABLE32: 301 return table_write (mem, res, usedOffset, status); 302 303 default: 304 break; 305 } 306 } 307 308 *status = U_INTERNAL_PROGRAM_ERROR; 309 return 0; 310} 311 312void bundle_write(struct SRBRoot *bundle, const char *outputDir, const char *outputPkg, char *writtenFilename, int writtenFilenameLen, UErrorCode *status) { 313 UNewDataMemory *mem = NULL; 314 uint8_t pad = 0; 315 uint32_t root = 0; 316 uint32_t usedOffset = 0; 317 uint32_t top, size; 318 char dataName[1024]; 319 int32_t indexes[URES_INDEX_TOP]; 320 321 if (writtenFilename && writtenFilenameLen) { 322 *writtenFilename = 0; 323 } 324 325 if (U_FAILURE(*status)) { 326 return; 327 } 328 329 if (writtenFilename) { 330 int32_t off = 0, len = 0; 331 if (outputDir) { 332 len = (int32_t)uprv_strlen(outputDir); 333 if (len > writtenFilenameLen) { 334 len = writtenFilenameLen; 335 } 336 uprv_strncpy(writtenFilename, outputDir, len); 337 } 338 if (writtenFilenameLen -= len) { 339 off += len; 340 writtenFilename[off] = U_FILE_SEP_CHAR; 341 if (--writtenFilenameLen) { 342 ++off; 343 if(outputPkg != NULL) 344 { 345 uprv_strcpy(writtenFilename+off, outputPkg); 346 off += (int32_t)uprv_strlen(outputPkg); 347 writtenFilename[off] = '_'; 348 ++off; 349 } 350 351 len = (int32_t)uprv_strlen(bundle->fLocale); 352 if (len > writtenFilenameLen) { 353 len = writtenFilenameLen; 354 } 355 uprv_strncpy(writtenFilename + off, bundle->fLocale, len); 356 if (writtenFilenameLen -= len) { 357 off += len; 358 len = 5; 359 if (len > writtenFilenameLen) { 360 len = writtenFilenameLen; 361 } 362 uprv_strncpy(writtenFilename + off, ".res", len); 363 } 364 } 365 } 366 } 367 368 if(outputPkg) 369 { 370 uprv_strcpy(dataName, outputPkg); 371 uprv_strcat(dataName, "_"); 372 uprv_strcat(dataName, bundle->fLocale); 373 } 374 else 375 { 376 uprv_strcpy(dataName, bundle->fLocale); 377 } 378 379 mem = udata_create(outputDir, "res", dataName, &dataInfo, (gIncludeCopyright==TRUE)? U_COPYRIGHT_STRING:NULL, status); 380 if(U_FAILURE(*status)){ 381 return; 382 } 383 pad = calcPadding(bundle->fKeyPoint); 384 385 usedOffset = bundle->fKeyPoint + pad ; /* top of the strings */ 386 387 /* we're gonna put the main table at the end */ 388 top = usedOffset + bundle->fRoot->u.fTable.fChildrenSize; 389 root = (top) >> 2 | (bundle->fRoot->fType << 28); 390 391 /* write the root item */ 392 udata_write32(mem, root); 393 394 /* add to top the size of the root item */ 395 top += bundle->fRoot->fSize; 396 top += calcPadding(top); 397 398 /* 399 * formatVersion 1.1 (ICU 2.8): 400 * write int32_t indexes[] after root and before the strings 401 * to make it easier to parse resource bundles in icuswap or from Java etc. 402 */ 403 uprv_memset(indexes, 0, sizeof(indexes)); 404 indexes[URES_INDEX_LENGTH]= URES_INDEX_TOP; 405 indexes[URES_INDEX_STRINGS_TOP]= (int32_t)(usedOffset>>2); 406 indexes[URES_INDEX_RESOURCES_TOP]= (int32_t)(top>>2); 407 indexes[URES_INDEX_BUNDLE_TOP]= indexes[URES_INDEX_RESOURCES_TOP]; 408 indexes[URES_INDEX_MAX_TABLE_LENGTH]= bundle->fMaxTableLength; 409 410 /* 411 * formatVersion 1.2 (ICU 3.6): 412 * write indexes[URES_INDEX_ATTRIBUTES] with URES_ATT_NO_FALLBACK set or not set 413 * the memset() above initialized all indexes[] to 0 414 */ 415 if(bundle->noFallback) { 416 indexes[URES_INDEX_ATTRIBUTES]=URES_ATT_NO_FALLBACK; 417 } 418 419 /* write the indexes[] */ 420 udata_writeBlock(mem, indexes, sizeof(indexes)); 421 422 /* write the table key strings */ 423 udata_writeBlock(mem, bundle->fKeys+URES_STRINGS_BOTTOM, 424 bundle->fKeyPoint-URES_STRINGS_BOTTOM); 425 426 /* write the padding bytes after the table key strings */ 427 udata_writePadding(mem, pad); 428 429 /* write all of the bundle contents: the root item and its children */ 430 usedOffset = res_write(mem, bundle->fRoot, usedOffset, status); 431 432 size = udata_finish(mem, status); 433 if(top != size) { 434 fprintf(stderr, "genrb error: wrote %u bytes but counted %u\n", 435 (int)size, (int)top); 436 *status = U_INTERNAL_PROGRAM_ERROR; 437 } 438} 439 440/* Opening Functions */ 441struct SResource* res_open(const struct UString* comment, UErrorCode* status){ 442 struct SResource *res; 443 444 if (U_FAILURE(*status)) { 445 return NULL; 446 } 447 448 res = (struct SResource *) uprv_malloc(sizeof(struct SResource)); 449 450 if (res == NULL) { 451 *status = U_MEMORY_ALLOCATION_ERROR; 452 return NULL; 453 } 454 uprv_memset(res, 0, sizeof(struct SResource)); 455 456 ustr_init(&res->fComment); 457 if(comment != NULL){ 458 ustr_cpy(&res->fComment, comment, status); 459 } 460 return res; 461 462} 463 464struct SResource* res_none() { 465 return &kNoResource; 466} 467 468struct SResource* table_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status) { 469 470 struct SResource *res = res_open(comment, status); 471 472 res->fKey = bundle_addtag(bundle, tag, status); 473 474 if (U_FAILURE(*status)) { 475 res_close(res); 476 return NULL; 477 } 478 479 res->fNext = NULL; 480 481 /* 482 * always open a table not a table32 in case it remains empty - 483 * try to use table32 only when necessary 484 */ 485 res->fType = URES_TABLE; 486 res->fSize = sizeof(uint16_t); 487 488 res->u.fTable.fCount = 0; 489 res->u.fTable.fChildrenSize = 0; 490 res->u.fTable.fFirst = NULL; 491 res->u.fTable.fRoot = bundle; 492 493 return res; 494} 495 496struct SResource* array_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status) { 497 498 struct SResource *res = res_open(comment, status); 499 500 if (U_FAILURE(*status)) { 501 return NULL; 502 } 503 504 res->fType = URES_ARRAY; 505 res->fKey = bundle_addtag(bundle, tag, status); 506 507 if (U_FAILURE(*status)) { 508 uprv_free(res); 509 return NULL; 510 } 511 512 res->fNext = NULL; 513 res->fSize = sizeof(int32_t); 514 515 res->u.fArray.fCount = 0; 516 res->u.fArray.fChildrenSize = 0; 517 res->u.fArray.fFirst = NULL; 518 res->u.fArray.fLast = NULL; 519 520 return res; 521} 522 523struct SResource *string_open(struct SRBRoot *bundle, char *tag, const UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) { 524 struct SResource *res = res_open(comment, status); 525 526 if (U_FAILURE(*status)) { 527 return NULL; 528 } 529 530 res->fType = URES_STRING; 531 res->fKey = bundle_addtag(bundle, tag, status); 532 533 if (U_FAILURE(*status)) { 534 uprv_free(res); 535 return NULL; 536 } 537 538 res->fNext = NULL; 539 540 res->u.fString.fLength = len; 541 res->u.fString.fChars = (UChar *) uprv_malloc(sizeof(UChar) * (len + 1)); 542 543 if (res->u.fString.fChars == NULL) { 544 *status = U_MEMORY_ALLOCATION_ERROR; 545 uprv_free(res); 546 return NULL; 547 } 548 549 uprv_memcpy(res->u.fString.fChars, value, sizeof(UChar) * (len + 1)); 550 res->fSize = sizeof(int32_t) + sizeof(UChar) * (len+1); 551 552 return res; 553} 554 555/* TODO: make alias_open and string_open use the same code */ 556struct SResource *alias_open(struct SRBRoot *bundle, char *tag, UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) { 557 struct SResource *res = res_open(comment, status); 558 559 if (U_FAILURE(*status)) { 560 return NULL; 561 } 562 563 res->fType = URES_ALIAS; 564 res->fKey = bundle_addtag(bundle, tag, status); 565 566 if (U_FAILURE(*status)) { 567 uprv_free(res); 568 return NULL; 569 } 570 571 res->fNext = NULL; 572 573 res->u.fString.fLength = len; 574 res->u.fString.fChars = (UChar *) uprv_malloc(sizeof(UChar) * (len + 1)); 575 576 if (res->u.fString.fChars == NULL) { 577 *status = U_MEMORY_ALLOCATION_ERROR; 578 uprv_free(res); 579 return NULL; 580 } 581 582 uprv_memcpy(res->u.fString.fChars, value, sizeof(UChar) * (len + 1)); 583 res->fSize = sizeof(int32_t) + sizeof(UChar) * (len + 1); 584 585 return res; 586} 587 588 589struct SResource* intvector_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status) { 590 struct SResource *res = res_open(comment, status); 591 592 if (U_FAILURE(*status)) { 593 return NULL; 594 } 595 596 res->fType = URES_INT_VECTOR; 597 res->fKey = bundle_addtag(bundle, tag, status); 598 599 if (U_FAILURE(*status)) { 600 uprv_free(res); 601 return NULL; 602 } 603 604 res->fNext = NULL; 605 res->fSize = sizeof(int32_t); 606 607 res->u.fIntVector.fCount = 0; 608 res->u.fIntVector.fArray = (uint32_t *) uprv_malloc(sizeof(uint32_t) * RESLIST_MAX_INT_VECTOR); 609 610 if (res->u.fIntVector.fArray == NULL) { 611 *status = U_MEMORY_ALLOCATION_ERROR; 612 uprv_free(res); 613 return NULL; 614 } 615 616 return res; 617} 618 619struct SResource *int_open(struct SRBRoot *bundle, char *tag, int32_t value, const struct UString* comment, UErrorCode *status) { 620 struct SResource *res = res_open(comment, status); 621 622 if (U_FAILURE(*status)) { 623 return NULL; 624 } 625 626 res->fType = URES_INT; 627 res->fKey = bundle_addtag(bundle, tag, status); 628 629 if (U_FAILURE(*status)) { 630 uprv_free(res); 631 return NULL; 632 } 633 634 res->fSize = 0; 635 res->fNext = NULL; 636 res->u.fIntValue.fValue = value; 637 638 return res; 639} 640 641struct SResource *bin_open(struct SRBRoot *bundle, const char *tag, uint32_t length, uint8_t *data, const char* fileName, const struct UString* comment, UErrorCode *status) { 642 struct SResource *res = res_open(comment, status); 643 644 if (U_FAILURE(*status)) { 645 return NULL; 646 } 647 648 res->fType = URES_BINARY; 649 res->fKey = bundle_addtag(bundle, tag, status); 650 651 if (U_FAILURE(*status)) { 652 uprv_free(res); 653 return NULL; 654 } 655 656 res->fNext = NULL; 657 658 res->u.fBinaryValue.fLength = length; 659 res->u.fBinaryValue.fFileName = NULL; 660 if(fileName!=NULL && uprv_strcmp(fileName, "") !=0){ 661 res->u.fBinaryValue.fFileName = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(fileName)+1)); 662 uprv_strcpy(res->u.fBinaryValue.fFileName,fileName); 663 } 664 if (length > 0) { 665 res->u.fBinaryValue.fData = (uint8_t *) uprv_malloc(sizeof(uint8_t) * length); 666 667 if (res->u.fBinaryValue.fData == NULL) { 668 *status = U_MEMORY_ALLOCATION_ERROR; 669 uprv_free(res); 670 return NULL; 671 } 672 673 uprv_memcpy(res->u.fBinaryValue.fData, data, length); 674 } 675 else { 676 res->u.fBinaryValue.fData = NULL; 677 } 678 679 res->fSize = sizeof(int32_t) + sizeof(uint8_t) * length + BIN_ALIGNMENT; 680 681 return res; 682} 683 684struct SRBRoot *bundle_open(const struct UString* comment, UErrorCode *status) { 685 struct SRBRoot *bundle = NULL; 686 687 if (U_FAILURE(*status)) { 688 return NULL; 689 } 690 691 bundle = (struct SRBRoot *) uprv_malloc(sizeof(struct SRBRoot)); 692 693 if (bundle == NULL) { 694 *status = U_MEMORY_ALLOCATION_ERROR; 695 return 0; 696 } 697 uprv_memset(bundle, 0, sizeof(struct SRBRoot)); 698 699 bundle->fLocale = NULL; 700 701 bundle->fKeys = (char *) uprv_malloc(sizeof(char) * KEY_SPACE_SIZE); 702 bundle->fKeysCapacity = KEY_SPACE_SIZE; 703 704 if(comment != NULL){ 705 706 } 707 708 if (bundle->fKeys == NULL) { 709 *status = U_MEMORY_ALLOCATION_ERROR; 710 uprv_free(bundle); 711 return NULL; 712 } 713 714 /* formatVersion 1.1: start fKeyPoint after the root item and indexes[] */ 715 bundle->fKeyPoint = URES_STRINGS_BOTTOM; 716 uprv_memset(bundle->fKeys, 0, URES_STRINGS_BOTTOM); 717 718 bundle->fCount = 0; 719 bundle->fRoot = table_open(bundle, NULL, comment, status); 720 721 if (bundle->fRoot == NULL || U_FAILURE(*status)) { 722 if (U_SUCCESS(*status)) { 723 *status = U_MEMORY_ALLOCATION_ERROR; 724 } 725 726 uprv_free(bundle->fKeys); 727 uprv_free(bundle); 728 729 return NULL; 730 } 731 732 return bundle; 733} 734 735/* Closing Functions */ 736static void table_close(struct SResource *table) { 737 struct SResource *current = NULL; 738 struct SResource *prev = NULL; 739 740 current = table->u.fTable.fFirst; 741 742 while (current != NULL) { 743 prev = current; 744 current = current->fNext; 745 746 res_close(prev); 747 } 748 749 table->u.fTable.fFirst = NULL; 750} 751 752static void array_close(struct SResource *array) { 753 struct SResource *current = NULL; 754 struct SResource *prev = NULL; 755 756 if(array==NULL){ 757 return; 758 } 759 current = array->u.fArray.fFirst; 760 761 while (current != NULL) { 762 prev = current; 763 current = current->fNext; 764 765 res_close(prev); 766 } 767 array->u.fArray.fFirst = NULL; 768} 769 770static void string_close(struct SResource *string) { 771 if (string->u.fString.fChars != NULL) { 772 uprv_free(string->u.fString.fChars); 773 string->u.fString.fChars =NULL; 774 } 775} 776 777static void alias_close(struct SResource *alias) { 778 if (alias->u.fString.fChars != NULL) { 779 uprv_free(alias->u.fString.fChars); 780 alias->u.fString.fChars =NULL; 781 } 782} 783 784static void intvector_close(struct SResource *intvector) { 785 if (intvector->u.fIntVector.fArray != NULL) { 786 uprv_free(intvector->u.fIntVector.fArray); 787 intvector->u.fIntVector.fArray =NULL; 788 } 789} 790 791static void int_close(struct SResource *intres) { 792 /* Intentionally left blank */ 793} 794 795static void bin_close(struct SResource *binres) { 796 if (binres->u.fBinaryValue.fData != NULL) { 797 uprv_free(binres->u.fBinaryValue.fData); 798 binres->u.fBinaryValue.fData = NULL; 799 } 800} 801 802void res_close(struct SResource *res) { 803 if (res != NULL) { 804 switch(res->fType) { 805 case URES_STRING: 806 string_close(res); 807 break; 808 case URES_ALIAS: 809 alias_close(res); 810 break; 811 case URES_INT_VECTOR: 812 intvector_close(res); 813 break; 814 case URES_BINARY: 815 bin_close(res); 816 break; 817 case URES_INT: 818 int_close(res); 819 break; 820 case URES_ARRAY: 821 array_close(res); 822 break; 823 case URES_TABLE: 824 case URES_TABLE32: 825 table_close(res); 826 break; 827 default: 828 /* Shouldn't happen */ 829 break; 830 } 831 832 ustr_deinit(&res->fComment); 833 uprv_free(res); 834 } 835} 836 837void bundle_close(struct SRBRoot *bundle, UErrorCode *status) { 838 if (bundle->fRoot != NULL) { 839 res_close(bundle->fRoot); 840 } 841 842 if (bundle->fLocale != NULL) { 843 uprv_free(bundle->fLocale); 844 } 845 846 if (bundle->fKeys != NULL) { 847 uprv_free(bundle->fKeys); 848 } 849 850 uprv_free(bundle); 851} 852 853/* Adding Functions */ 854void table_add(struct SResource *table, struct SResource *res, int linenumber, UErrorCode *status) { 855 struct SResource *current = NULL; 856 struct SResource *prev = NULL; 857 struct SResTable *list; 858 859 if (U_FAILURE(*status)) { 860 return; 861 } 862 if (res == &kNoResource) { 863 return; 864 } 865 866 /* remember this linenumber to report to the user if there is a duplicate key */ 867 res->line = linenumber; 868 869 /* here we need to traverse the list */ 870 list = &(table->u.fTable); 871 872 if(table->fType == URES_TABLE && res->fKey > 0xffff) { 873 /* this table straddles the 64k strings boundary, update to a table32 */ 874 table->fType = URES_TABLE32; 875 876 /* 877 * increase the size because count and each string offset 878 * increase from uint16_t to int32_t 879 */ 880 table->fSize += (1 + list->fCount) * 2; 881 } 882 883 ++(list->fCount); 884 if(list->fCount > (uint32_t)list->fRoot->fMaxTableLength) { 885 list->fRoot->fMaxTableLength = list->fCount; 886 } 887 888 /* 889 * URES_TABLE: 6 bytes = 1 uint16_t key string offset + 1 uint32_t Resource 890 * URES_TABLE32: 8 bytes = 1 int32_t key string offset + 1 uint32_t Resource 891 */ 892 table->fSize += table->fType == URES_TABLE ? 6 : 8; 893 894 table->u.fTable.fChildrenSize += res->fSize + calcPadding(res->fSize); 895 896 if (res->fType == URES_TABLE || res->fType == URES_TABLE32) { 897 table->u.fTable.fChildrenSize += res->u.fTable.fChildrenSize; 898 } else if (res->fType == URES_ARRAY) { 899 table->u.fTable.fChildrenSize += res->u.fArray.fChildrenSize; 900 } 901 902 /* is list still empty? */ 903 if (list->fFirst == NULL) { 904 list->fFirst = res; 905 res->fNext = NULL; 906 return; 907 } 908 909 current = list->fFirst; 910 911 while (current != NULL) { 912 if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), ((list->fRoot->fKeys) + (res->fKey))) < 0) { 913 prev = current; 914 current = current->fNext; 915 } else if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), ((list->fRoot->fKeys) + (res->fKey))) > 0) { 916 /* we're either in front of list, or in middle */ 917 if (prev == NULL) { 918 /* front of the list */ 919 list->fFirst = res; 920 } else { 921 /* middle of the list */ 922 prev->fNext = res; 923 } 924 925 res->fNext = current; 926 return; 927 } else { 928 /* Key already exists! ERROR! */ 929 error(linenumber, "duplicate key '%s' in table, first appeared at line %d", list->fRoot->fKeys + current->fKey, current->line); 930 *status = U_UNSUPPORTED_ERROR; 931 return; 932 } 933 } 934 935 /* end of list */ 936 prev->fNext = res; 937 res->fNext = NULL; 938} 939 940void array_add(struct SResource *array, struct SResource *res, UErrorCode *status) { 941 if (U_FAILURE(*status)) { 942 return; 943 } 944 945 if (array->u.fArray.fFirst == NULL) { 946 array->u.fArray.fFirst = res; 947 array->u.fArray.fLast = res; 948 } else { 949 array->u.fArray.fLast->fNext = res; 950 array->u.fArray.fLast = res; 951 } 952 953 (array->u.fArray.fCount)++; 954 955 array->fSize += sizeof(uint32_t); 956 array->u.fArray.fChildrenSize += res->fSize + calcPadding(res->fSize); 957 958 if (res->fType == URES_TABLE || res->fType == URES_TABLE32) { 959 array->u.fArray.fChildrenSize += res->u.fTable.fChildrenSize; 960 } else if (res->fType == URES_ARRAY) { 961 array->u.fArray.fChildrenSize += res->u.fArray.fChildrenSize; 962 } 963} 964 965void intvector_add(struct SResource *intvector, int32_t value, UErrorCode *status) { 966 if (U_FAILURE(*status)) { 967 return; 968 } 969 970 *(intvector->u.fIntVector.fArray + intvector->u.fIntVector.fCount) = value; 971 intvector->u.fIntVector.fCount++; 972 973 intvector->fSize += sizeof(uint32_t); 974} 975 976/* Misc Functions */ 977 978void bundle_setlocale(struct SRBRoot *bundle, UChar *locale, UErrorCode *status) { 979 980 if(U_FAILURE(*status)) { 981 return; 982 } 983 984 if (bundle->fLocale!=NULL) { 985 uprv_free(bundle->fLocale); 986 } 987 988 bundle->fLocale= (char*) uprv_malloc(sizeof(char) * (u_strlen(locale)+1)); 989 990 if(bundle->fLocale == NULL) { 991 *status = U_MEMORY_ALLOCATION_ERROR; 992 return; 993 } 994 995 /*u_strcpy(bundle->fLocale, locale);*/ 996 u_UCharsToChars(locale, bundle->fLocale, u_strlen(locale)+1); 997 998} 999 1000 1001int32_t 1002bundle_addtag(struct SRBRoot *bundle, const char *tag, UErrorCode *status) { 1003 int32_t keypos, length; 1004 1005 if (U_FAILURE(*status)) { 1006 return -1; 1007 } 1008 1009 if (tag == NULL) { 1010 /* do not set an error: the root table has a NULL tag */ 1011 return -1; 1012 } 1013 1014 keypos = bundle->fKeyPoint; 1015 1016 bundle->fKeyPoint += length = (int32_t) (uprv_strlen(tag) + 1); 1017 1018 if (bundle->fKeyPoint >= bundle->fKeysCapacity) { 1019 /* overflow - resize the keys buffer */ 1020 bundle->fKeysCapacity += KEY_SPACE_SIZE; 1021 bundle->fKeys = uprv_realloc(bundle->fKeys, bundle->fKeysCapacity); 1022 if(bundle->fKeys == NULL) { 1023 *status = U_MEMORY_ALLOCATION_ERROR; 1024 return -1; 1025 } 1026 } 1027 1028 uprv_memcpy(bundle->fKeys + keypos, tag, length); 1029 1030 return keypos; 1031} 1032