| /* |
| ******************************************************************************* |
| * * |
| * COPYRIGHT: * |
| * (C) Copyright International Business Machines Corporation, 1998, 1999 * |
| * 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 rbread.cpp |
| * |
| * Modification History: |
| * |
| * Date Name Description |
| * 06/11/99 stephen Creation. |
| ******************************************************************************* |
| */ |
| |
| #include <stdio.h> |
| |
| #include "rbread.h" |
| #include "cmemory.h" |
| #include "cstring.h" |
| #include "filestrm.h" |
| #include "ustring.h" |
| #include "rbdata.h" |
| |
| #include "unistr.h" |
| #include "rbdata.h" |
| |
| |
| /* Protos */ |
| static void read_ustring(FileStream *rb, UnicodeString& val, |
| UErrorCode& status); |
| static StringList* read_strlist(FileStream *rb, UnicodeString& listname, |
| UErrorCode& status); |
| static String2dList* read_strlist2d(FileStream *rb, UnicodeString& listname, |
| UErrorCode& status); |
| static TaggedList* read_taglist(FileStream *rb, UnicodeString& listname, |
| UErrorCode& status); |
| static void RBHashtable_valueDeleter(void *value); |
| |
| |
| /* Read a string from a compiled resource file */ |
| #define BUF_SIZE 128 |
| void |
| read_ustring(FileStream *rb, |
| UnicodeString& val, |
| UErrorCode& status) |
| { |
| int32_t len = 0, readLen = 0, remain = 0; |
| UChar buf [BUF_SIZE]; |
| |
| if(FAILURE(status)) return; |
| |
| /* Read the string's length */ |
| T_FileStream_read(rb, &len, sizeof(len)); |
| |
| /* Truncate the output string */ |
| val.remove(); |
| |
| remain = len; |
| |
| /* Successively read the string's data from the file */ |
| while(remain != 0) { |
| |
| /* Read the next chunk of data */ |
| readLen = icu_min(BUF_SIZE, remain); |
| memset(buf, 0, readLen*sizeof(UChar)); |
| T_FileStream_read(rb, buf, sizeof(UChar) * readLen); |
| |
| /* Append the chunk to the string */ |
| val.append(buf, readLen); |
| |
| remain -= readLen; |
| } |
| |
| } |
| |
| /* Read a string list */ |
| StringList* |
| read_strlist(FileStream *rb, |
| UnicodeString& listname, |
| UErrorCode& status) |
| { |
| int32_t i, count = 0; |
| StringList *retval; |
| |
| if(FAILURE(status)) return 0; |
| |
| /* Setup the string list */ |
| retval = new StringList(); |
| if(retval == 0) { |
| status = MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| |
| /* Read the name of this string list */ |
| read_ustring(rb, listname, status); |
| if(FAILURE(status)) { |
| delete retval; |
| return 0; |
| } |
| |
| /* Read the number of items in this string list */ |
| T_FileStream_read(rb, &count, sizeof(count)); |
| retval->fCount = count; |
| |
| /* Allocate space for the array of strings */ |
| retval->fStrings = new UnicodeString [ retval->fCount ]; |
| if(retval->fStrings == 0) { |
| status = MEMORY_ALLOCATION_ERROR; |
| delete retval; |
| return 0; |
| } |
| |
| /* Successively read strings in the list */ |
| for(i = 0; i < count; ++i) { |
| read_ustring(rb, retval->fStrings[i], status); |
| |
| /* handle error */ |
| if(FAILURE(status)) { |
| delete [] retval->fStrings; |
| delete retval; |
| return 0; |
| } |
| } |
| |
| return retval; |
| } |
| |
| /* Read a 2-d string list */ |
| String2dList* |
| read_strlist2d(FileStream *rb, |
| UnicodeString& listname, |
| UErrorCode& status) |
| { |
| int32_t i, j; |
| int32_t rows, itemcount; |
| String2dList *retval; |
| |
| if(FAILURE(status)) return 0; |
| |
| /* Setup the 2-d string list */ |
| retval = new String2dList(); |
| if(retval == 0) { |
| status = MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| |
| /* Read the name of this 2-d string list */ |
| read_ustring(rb, listname, status); |
| if(FAILURE(status)) { |
| delete retval; |
| return 0; |
| } |
| |
| /* Read the number of rows in this 2-d string list */ |
| T_FileStream_read(rb, &rows, sizeof(rows)); |
| retval->fRowCount = rows; |
| |
| /* Allocate space for the array of strings */ |
| retval->fStrings = new UnicodeString* [ retval->fRowCount ]; |
| if(retval->fStrings == 0) { |
| status = MEMORY_ALLOCATION_ERROR; |
| delete retval; |
| return 0; |
| } |
| |
| /* Read each row */ |
| for(i = 0; i < rows; ++i) { |
| |
| /* Read the number of items in this row */ |
| T_FileStream_read(rb, &itemcount, sizeof(itemcount)); |
| |
| /* Hack for now - assume all rows are the same length */ |
| retval->fColCount = itemcount; |
| |
| /* Allocate enough space for each item */ |
| retval->fStrings[i] = new UnicodeString[itemcount]; |
| if(retval->fStrings[i] == 0) { |
| status = MEMORY_ALLOCATION_ERROR; |
| /* Complicated cleanup later */ |
| delete retval; |
| return 0; |
| } |
| |
| /* Read each item */ |
| for(j = 0; j < itemcount; ++j) { |
| read_ustring(rb, retval->fStrings[i][j], status); |
| |
| /* handle error */ |
| if(FAILURE(status)) { |
| /* Complicated cleanup later */ |
| delete retval; |
| return 0; |
| } |
| } |
| } |
| |
| return retval; |
| } |
| |
| /* Read a tagged list */ |
| TaggedList* |
| read_taglist(FileStream *rb, |
| UnicodeString& listname, |
| UErrorCode& status) |
| { |
| TaggedList *retval; |
| int32_t i, count = 0; |
| UnicodeString tag, value; |
| |
| if(FAILURE(status)) return 0; |
| |
| /* Setup the tagged list */ |
| retval = new TaggedList(); |
| if(retval == 0) { |
| status = MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| |
| /* Read the name of this tagged list */ |
| read_ustring(rb, listname, status); |
| if(FAILURE(status)) { |
| delete retval; |
| return 0; |
| } |
| |
| /* Read the number of items in this tagged list */ |
| T_FileStream_read(rb, &count, sizeof(count)); |
| |
| /* Successively read strings in the list */ |
| for(i = 0; i < count; ++i) { |
| read_ustring(rb, tag, status); |
| read_ustring(rb, value, status); |
| |
| /* handle error */ |
| if(FAILURE(status)) { |
| delete retval; |
| return 0; |
| } |
| |
| /* put the tag/value in the list */ |
| retval->put(tag, value); |
| } |
| |
| return retval; |
| } |
| |
| /* Parse a compiled rb file */ |
| UHashtable* |
| rb_parse(FileStream *f, |
| UnicodeString& localename, |
| UErrorCode& status) |
| { |
| UHashtable *retval; |
| int32_t bom; |
| int32_t itemtype; |
| UnicodeString listname; |
| StringList *strlist; |
| String2dList *strlist2d; |
| TaggedList *taglist; |
| |
| if(FAILURE(status)) return 0; |
| |
| /* Open the hashtable for saving data */ |
| retval = uhash_open((UHashFunction)uhash_hashUString, &status); |
| if(retval == 0 || FAILURE(status)) { |
| status = MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| uhash_setValueDeleter(retval, RBHashtable_valueDeleter); |
| |
| /* Read the byte order mark from the file */ |
| T_FileStream_read(f, &bom, sizeof(bom)); |
| |
| /* Verify the byte ordering matches */ |
| if(bom != sBOM) { |
| uhash_close(retval); |
| status = INVALID_FORMAT_ERROR; |
| return 0; |
| } |
| |
| /* Read the locale name from the file */ |
| read_ustring(f, localename, status); |
| if(FAILURE(status)) { |
| uhash_close(retval); |
| return 0; |
| } |
| |
| /* Successively read each list item */ |
| for(;;) { |
| |
| /* Read the next item type */ |
| T_FileStream_read(f, &itemtype, sizeof(itemtype)); |
| |
| /* If we're at EOF, break */ |
| if(itemtype == sEOF) { |
| break; |
| } |
| |
| /* Parse each item and add it to the hashtable */ |
| switch(itemtype) { |
| case sSTRINGLIST: |
| strlist = read_strlist(f, listname, status); |
| uhash_putKey(retval, listname.hashCode() & 0x7FFFFFFF, |
| strlist, &status); |
| if(FAILURE(status)) { |
| uhash_close(retval); |
| return 0; |
| } |
| break; |
| |
| case sSTRINGLIST2D: |
| strlist2d = read_strlist2d(f, listname, status); |
| uhash_putKey(retval, listname.hashCode() & 0x7FFFFFFF, |
| strlist2d, &status); |
| if(FAILURE(status)) { |
| uhash_close(retval); |
| return 0; |
| } |
| break; |
| |
| case sTAGGEDLIST: |
| taglist = read_taglist(f, listname, status); |
| uhash_putKey(retval, listname.hashCode() & 0x7FFFFFFF, |
| taglist, &status); |
| if(FAILURE(status)) { |
| uhash_close(retval); |
| return 0; |
| } |
| break; |
| } |
| } |
| |
| /* Check if any errors occurred during reading */ |
| if(T_FileStream_error(f) != 0) { |
| status = FILE_ACCESS_ERROR; |
| delete retval; |
| return 0; |
| } |
| |
| return retval; |
| } |
| |
| void |
| RBHashtable_valueDeleter(void *value) |
| { |
| delete (ResourceBundleData*)value; |
| } |