/*
*******************************************************************************
*
-* Copyright (C) 2000-2003, International Business Machines
+* Copyright (C) 2000-2006, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
*/
#include <assert.h>
+#include <stdio.h>
#include "reslist.h"
#include "unewdata.h"
#include "unicode/ures.h"
+#include "unicode/putil.h"
#include "errmsg.h"
#define BIN_ALIGNMENT 16
0,
{0x52, 0x65, 0x73, 0x42}, /* dataFormat="resb" */
- {1, 0, 0, 0}, /* formatVersion */
+ {1, 2, 0, 0}, /* formatVersion */
{1, 4, 0, 0} /* dataVersion take a look at version inside parsed resb*/
};
uint32_t usedOffset, UErrorCode *status) {
uint8_t pad = 0;
uint32_t i = 0;
- uint16_t *keys = NULL;
+ uint16_t *keys16 = NULL;
+ int32_t *keys32 = NULL;
uint32_t *resources = NULL;
struct SResource *current = NULL;
pad = calcPadding(res->fSize);
if (res->u.fTable.fCount > 0) {
- keys = (uint16_t *) uprv_malloc(sizeof(uint16_t) * res->u.fTable.fCount);
-
- if (keys == NULL) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
+ if(res->fType == URES_TABLE) {
+ keys16 = (uint16_t *) uprv_malloc(sizeof(uint16_t) * res->u.fTable.fCount);
+ if (keys16 == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return 0;
+ }
+ } else {
+ keys32 = (int32_t *) uprv_malloc(sizeof(int32_t) * res->u.fTable.fCount);
+ if (keys32 == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return 0;
+ }
}
resources = (uint32_t *) uprv_malloc(sizeof(uint32_t) * res->u.fTable.fCount);
if (resources == NULL) {
- uprv_free(keys);
+ uprv_free(keys16);
+ uprv_free(keys32);
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
while (current != NULL) {
assert(i < res->u.fTable.fCount);
- /* where the key is plus root pointer */
- keys[i] = (uint16_t) (current->fKey + sizeof(uint32_t));
+ /* where the key is */
+ if(res->fType == URES_TABLE) {
+ keys16[i] = (uint16_t) current->fKey;
+ } else {
+ keys32[i] = current->fKey;
+ }
if (current->fType == URES_INT) {
resources[i] = (current->fType << 28) | (current->u.fIntValue.fValue & 0xFFFFFFF);
current = current->fNext;
}
- udata_write16(mem, res->u.fTable.fCount);
+ if(res->fType == URES_TABLE) {
+ udata_write16(mem, (uint16_t)res->u.fTable.fCount);
+
+ udata_writeBlock(mem, keys16, sizeof(uint16_t) * res->u.fTable.fCount);
+ udata_writePadding(mem, pad);
+ } else {
+ udata_write32(mem, res->u.fTable.fCount);
+
+ udata_writeBlock(mem, keys32, sizeof(int32_t) * res->u.fTable.fCount);
+ }
- udata_writeBlock(mem, keys, sizeof(uint16_t) * res->u.fTable.fCount);
- udata_writePadding(mem, pad);
udata_writeBlock(mem, resources, sizeof(uint32_t) * res->u.fTable.fCount);
- uprv_free(keys);
+ uprv_free(keys16);
+ uprv_free(keys32);
uprv_free(resources);
} else {
/* table is empty */
- udata_write16(mem, 0);
- udata_writePadding(mem, pad);
+ if(res->fType == URES_TABLE) {
+ udata_write16(mem, 0);
+ udata_writePadding(mem, pad);
+ } else {
+ udata_write32(mem, 0);
+ }
}
return usedOffset;
case URES_ARRAY:
return array_write (mem, res, usedOffset, status);
case URES_TABLE:
+ case URES_TABLE32:
return table_write (mem, res, usedOffset, status);
default:
uint8_t pad = 0;
uint32_t root = 0;
uint32_t usedOffset = 0;
+ uint32_t top, size;
char dataName[1024];
+ int32_t indexes[URES_INDEX_TOP];
if (writtenFilename && writtenFilenameLen) {
*writtenFilename = 0;
if(outputPkg != NULL)
{
uprv_strcpy(writtenFilename+off, outputPkg);
- off += uprv_strlen(outputPkg);
+ off += (int32_t)uprv_strlen(outputPkg);
writtenFilename[off] = '_';
++off;
}
}
pad = calcPadding(bundle->fKeyPoint);
- usedOffset = sizeof(uint32_t) + bundle->fKeyPoint + pad ; /*this is how much root and keys are taking up*/
+ usedOffset = bundle->fKeyPoint + pad ; /* top of the strings */
- root = ((usedOffset + bundle->fRoot->u.fTable.fChildrenSize) >> 2) | (URES_TABLE << 28); /* we're gonna put the main table at the end */
+ /* we're gonna put the main table at the end */
+ top = usedOffset + bundle->fRoot->u.fTable.fChildrenSize;
+ root = (top) >> 2 | (bundle->fRoot->fType << 28);
+ /* write the root item */
udata_write32(mem, root);
- udata_writeBlock(mem, bundle->fKeys, bundle->fKeyPoint);
-
+ /* add to top the size of the root item */
+ top += bundle->fRoot->fSize;
+ top += calcPadding(top);
+
+ /*
+ * formatVersion 1.1 (ICU 2.8):
+ * write int32_t indexes[] after root and before the strings
+ * to make it easier to parse resource bundles in icuswap or from Java etc.
+ */
+ uprv_memset(indexes, 0, sizeof(indexes));
+ indexes[URES_INDEX_LENGTH]= URES_INDEX_TOP;
+ indexes[URES_INDEX_STRINGS_TOP]= (int32_t)(usedOffset>>2);
+ indexes[URES_INDEX_RESOURCES_TOP]= (int32_t)(top>>2);
+ indexes[URES_INDEX_BUNDLE_TOP]= indexes[URES_INDEX_RESOURCES_TOP];
+ indexes[URES_INDEX_MAX_TABLE_LENGTH]= bundle->fMaxTableLength;
+
+ /*
+ * formatVersion 1.2 (ICU 3.6):
+ * write indexes[URES_INDEX_ATTRIBUTES] with URES_ATT_NO_FALLBACK set or not set
+ * the memset() above initialized all indexes[] to 0
+ */
+ if(bundle->noFallback) {
+ indexes[URES_INDEX_ATTRIBUTES]=URES_ATT_NO_FALLBACK;
+ }
+
+ /* write the indexes[] */
+ udata_writeBlock(mem, indexes, sizeof(indexes));
+
+ /* write the table key strings */
+ udata_writeBlock(mem, bundle->fKeys+URES_STRINGS_BOTTOM,
+ bundle->fKeyPoint-URES_STRINGS_BOTTOM);
+
+ /* write the padding bytes after the table key strings */
udata_writePadding(mem, pad);
+ /* write all of the bundle contents: the root item and its children */
usedOffset = res_write(mem, bundle->fRoot, usedOffset, status);
- udata_finish(mem, status);
+ size = udata_finish(mem, status);
+ if(top != size) {
+ fprintf(stderr, "genrb error: wrote %u bytes but counted %u\n",
+ (int)size, (int)top);
+ *status = U_INTERNAL_PROGRAM_ERROR;
+ }
}
/* Opening Functions */
-struct SResource* table_open(struct SRBRoot *bundle, char *tag, UErrorCode *status) {
+struct SResource* res_open(const struct UString* comment, UErrorCode* status){
struct SResource *res;
if (U_FAILURE(*status)) {
*status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
+ uprv_memset(res, 0, sizeof(struct SResource));
+
+ res->fComment = NULL;
+ if(comment != NULL){
+ res->fComment = (struct UString *) uprv_malloc(sizeof(struct UString));
+ if(res->fComment == NULL){
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ uprv_free(res);
+ return NULL;
+ }
+ ustr_init(res->fComment);
+ ustr_cpy(res->fComment, comment, status);
+ }
+ return res;
+
+}
+struct SResource* table_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status) {
+
+ struct SResource *res = res_open(comment, status);
- res->fType = URES_TABLE;
res->fKey = bundle_addtag(bundle, tag, status);
if (U_FAILURE(*status)) {
+ uprv_free(res->fComment);
uprv_free(res);
return NULL;
}
res->fNext = NULL;
+
+ /*
+ * always open a table not a table32 in case it remains empty -
+ * try to use table32 only when necessary
+ */
+ res->fType = URES_TABLE;
res->fSize = sizeof(uint16_t);
res->u.fTable.fCount = 0;
return res;
}
-struct SResource* array_open(struct SRBRoot *bundle, char *tag, UErrorCode *status) {
- struct SResource *res;
+struct SResource* array_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status) {
- if (U_FAILURE(*status)) {
- return NULL;
- }
-
- res = (struct SResource *) uprv_malloc(sizeof(struct SResource));
+ struct SResource *res = res_open(comment, status);
- if (res == NULL) {
- *status = U_MEMORY_ALLOCATION_ERROR;
+ if (U_FAILURE(*status)) {
return NULL;
}
res->fKey = bundle_addtag(bundle, tag, status);
if (U_FAILURE(*status)) {
+ uprv_free(res->fComment);
uprv_free(res);
return NULL;
}
return res;
}
-struct SResource *string_open(struct SRBRoot *bundle, char *tag, const UChar *value, int32_t len, UErrorCode *status) {
- struct SResource *res;
+struct SResource *string_open(struct SRBRoot *bundle, char *tag, const UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) {
+ struct SResource *res = res_open(comment, status);
if (U_FAILURE(*status)) {
return NULL;
}
- res = (struct SResource *) uprv_malloc(sizeof(struct SResource));
-
- if (res == NULL) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
-
res->fType = URES_STRING;
res->fKey = bundle_addtag(bundle, tag, status);
if (U_FAILURE(*status)) {
+ uprv_free(res->fComment);
uprv_free(res);
return NULL;
}
}
/* TODO: make alias_open and string_open use the same code */
-struct SResource *alias_open(struct SRBRoot *bundle, char *tag, UChar *value, int32_t len, UErrorCode *status) {
- struct SResource *res;
+struct SResource *alias_open(struct SRBRoot *bundle, char *tag, UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) {
+ struct SResource *res = res_open(comment, status);
if (U_FAILURE(*status)) {
return NULL;
}
- res = (struct SResource *) uprv_malloc(sizeof(struct SResource));
-
- if (res == NULL) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
-
res->fType = URES_ALIAS;
res->fKey = bundle_addtag(bundle, tag, status);
if (U_FAILURE(*status)) {
+ uprv_free(res->fComment);
uprv_free(res);
return NULL;
}
}
-struct SResource* intvector_open(struct SRBRoot *bundle, char *tag, UErrorCode *status) {
- struct SResource *res;
+struct SResource* intvector_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status) {
+ struct SResource *res = res_open(comment, status);
if (U_FAILURE(*status)) {
return NULL;
}
- res = (struct SResource *) uprv_malloc(sizeof(struct SResource));
-
- if (res == NULL) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
-
res->fType = URES_INT_VECTOR;
res->fKey = bundle_addtag(bundle, tag, status);
if (U_FAILURE(*status)) {
+ uprv_free(res->fComment);
uprv_free(res);
return NULL;
}
return res;
}
-struct SResource *int_open(struct SRBRoot *bundle, char *tag, int32_t value, UErrorCode *status) {
- struct SResource *res;
+struct SResource *int_open(struct SRBRoot *bundle, char *tag, int32_t value, const struct UString* comment, UErrorCode *status) {
+ struct SResource *res = res_open(comment, status);
if (U_FAILURE(*status)) {
return NULL;
}
- res = (struct SResource *) uprv_malloc(sizeof(struct SResource));
-
- if (res == NULL) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
-
res->fType = URES_INT;
res->fKey = bundle_addtag(bundle, tag, status);
if (U_FAILURE(*status)) {
+ uprv_free(res->fComment);
uprv_free(res);
return NULL;
}
return res;
}
-struct SResource *bin_open(struct SRBRoot *bundle, const char *tag, uint32_t length, uint8_t *data,const char* fileName,UErrorCode *status) {
- struct SResource *res;
+struct SResource *bin_open(struct SRBRoot *bundle, const char *tag, uint32_t length, uint8_t *data, const char* fileName, const struct UString* comment, UErrorCode *status) {
+ struct SResource *res = res_open(comment, status);
if (U_FAILURE(*status)) {
return NULL;
}
- res = (struct SResource *) uprv_malloc(sizeof(struct SResource));
-
- if (res == NULL) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
-
res->fType = URES_BINARY;
res->fKey = bundle_addtag(bundle, tag, status);
if (U_FAILURE(*status)) {
+ uprv_free(res->fComment);
uprv_free(res);
return NULL;
}
-
+
res->fNext = NULL;
res->u.fBinaryValue.fLength = length;
return res;
}
-struct SRBRoot *bundle_open(UErrorCode *status) {
+struct SRBRoot *bundle_open(const struct UString* comment, UErrorCode *status) {
struct SRBRoot *bundle = NULL;
if (U_FAILURE(*status)) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
+ uprv_memset(bundle, 0, sizeof(struct SRBRoot));
bundle->fLocale = NULL;
- bundle->fKeyPoint = 0;
+
bundle->fKeys = (char *) uprv_malloc(sizeof(char) * KEY_SPACE_SIZE);
+ bundle->fKeysCapacity = KEY_SPACE_SIZE;
+
+ if(comment != NULL){
+
+ }
if (bundle->fKeys == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
+ /* formatVersion 1.1: start fKeyPoint after the root item and indexes[] */
+ bundle->fKeyPoint = URES_STRINGS_BOTTOM;
+ uprv_memset(bundle->fKeys, 0, URES_STRINGS_BOTTOM);
+
bundle->fCount = 0;
- bundle->fRoot = table_open(bundle, NULL, status);
+ bundle->fRoot = table_open(bundle, NULL, comment, status);
if (bundle->fRoot == NULL || U_FAILURE(*status)) {
- *status = U_MEMORY_ALLOCATION_ERROR;
+ if (U_SUCCESS(*status)) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ }
uprv_free(bundle->fKeys);
uprv_free(bundle);
void array_close(struct SResource *array, UErrorCode *status) {
struct SResource *current = NULL;
struct SResource *prev = NULL;
-
+
+ if(array==NULL){
+ return;
+ }
current = array->u.fArray.fFirst;
-
+
while (current != NULL) {
prev = current;
current = current->fNext;
case URES_ARRAY:
array_close(res, status);
break;
- case URES_TABLE :
+ case URES_TABLE:
+ case URES_TABLE32:
table_close(res, status);
break;
default:
/* here we need to traverse the list */
list = &(table->u.fTable);
+ if(table->fType == URES_TABLE && res->fKey > 0xffff) {
+ /* this table straddles the 64k strings boundary, update to a table32 */
+ table->fType = URES_TABLE32;
+
+ /*
+ * increase the size because count and each string offset
+ * increase from uint16_t to int32_t
+ */
+ table->fSize += (1 + list->fCount) * 2;
+ }
+
++(list->fCount);
- table->fSize += sizeof(uint32_t) + sizeof(uint16_t);
+ if(list->fCount > (uint32_t)list->fRoot->fMaxTableLength) {
+ list->fRoot->fMaxTableLength = list->fCount;
+ }
+
+ /*
+ * URES_TABLE: 6 bytes = 1 uint16_t key string offset + 1 uint32_t Resource
+ * URES_TABLE32: 8 bytes = 1 int32_t key string offset + 1 uint32_t Resource
+ */
+ table->fSize += table->fType == URES_TABLE ? 6 : 8;
table->u.fTable.fChildrenSize += res->fSize + calcPadding(res->fSize);
- if (res->fType == URES_TABLE) {
+ if (res->fType == URES_TABLE || res->fType == URES_TABLE32) {
table->u.fTable.fChildrenSize += res->u.fTable.fChildrenSize;
} else if (res->fType == URES_ARRAY) {
table->u.fTable.fChildrenSize += res->u.fArray.fChildrenSize;
array->fSize += sizeof(uint32_t);
array->u.fArray.fChildrenSize += res->fSize + calcPadding(res->fSize);
- if (res->fType == URES_TABLE) {
+ if (res->fType == URES_TABLE || res->fType == URES_TABLE32) {
array->u.fArray.fChildrenSize += res->u.fTable.fChildrenSize;
} else if (res->fType == URES_ARRAY) {
array->u.fArray.fChildrenSize += res->u.fArray.fChildrenSize;
}
-uint16_t bundle_addtag(struct SRBRoot *bundle, const char *tag, UErrorCode *status) {
- uint16_t keypos;
+
+int32_t
+bundle_addtag(struct SRBRoot *bundle, const char *tag, UErrorCode *status) {
+ int32_t keypos, length;
if (U_FAILURE(*status)) {
- return (uint16_t) - 1;
+ return -1;
}
if (tag == NULL) {
- return (uint16_t) - 1;
+ /* do not set an error: the root table has a NULL tag */
+ return -1;
}
- keypos = (uint16_t)bundle->fKeyPoint;
+ keypos = bundle->fKeyPoint;
- bundle->fKeyPoint += (uint16_t) (uprv_strlen(tag) + 1);
+ bundle->fKeyPoint += length = (int32_t) (uprv_strlen(tag) + 1);
- if (bundle->fKeyPoint > KEY_SPACE_SIZE) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return (uint16_t) - 1;
+ if (bundle->fKeyPoint >= bundle->fKeysCapacity) {
+ /* overflow - resize the keys buffer */
+ bundle->fKeysCapacity += KEY_SPACE_SIZE;
+ bundle->fKeys = uprv_realloc(bundle->fKeys, bundle->fKeysCapacity);
+ if(bundle->fKeys == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return -1;
+ }
}
- uprv_strcpy(bundle->fKeys + keypos, tag);
+ uprv_memcpy(bundle->fKeys + keypos, tag, length);
return keypos;
}