1999-08-16 21:50:52 +00:00
|
|
|
/*
|
1999-12-09 23:27:55 +00:00
|
|
|
**********************************************************************
|
|
|
|
* Copyright (C) 1998-1999, International Business Machines
|
|
|
|
* Corporation and others. All Rights Reserved.
|
|
|
|
**********************************************************************
|
1999-08-16 21:50:52 +00:00
|
|
|
*
|
|
|
|
* 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"
|
1999-12-28 23:39:02 +00:00
|
|
|
#include "unicode/ustring.h"
|
1999-08-16 21:50:52 +00:00
|
|
|
#include "rbdata.h"
|
|
|
|
|
1999-12-28 23:39:02 +00:00
|
|
|
#include "unicode/unistr.h"
|
1999-08-16 21:50:52 +00:00
|
|
|
#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);
|
1999-11-16 01:05:10 +00:00
|
|
|
static void U_CALLCONV RBHashtable_valueDeleter(void *value);
|
1999-08-16 21:50:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* 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];
|
|
|
|
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) return;
|
1999-08-16 21:50:52 +00:00
|
|
|
|
|
|
|
/* 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 */
|
1999-12-28 23:39:02 +00:00
|
|
|
readLen = uprv_min(BUF_SIZE, remain);
|
|
|
|
uprv_memset(buf, 0, readLen*sizeof(UChar));
|
1999-08-16 21:50:52 +00:00
|
|
|
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;
|
|
|
|
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) return 0;
|
1999-08-16 21:50:52 +00:00
|
|
|
|
|
|
|
/* Setup the string list */
|
|
|
|
retval = new StringList();
|
|
|
|
if(retval == 0) {
|
1999-10-07 00:07:53 +00:00
|
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
1999-08-16 21:50:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the name of this string list */
|
|
|
|
read_ustring(rb, listname, status);
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
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) {
|
1999-10-07 00:07:53 +00:00
|
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
1999-08-16 21:50:52 +00:00
|
|
|
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 */
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
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;
|
|
|
|
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) return 0;
|
1999-08-16 21:50:52 +00:00
|
|
|
|
|
|
|
/* Setup the 2-d string list */
|
|
|
|
retval = new String2dList();
|
|
|
|
if(retval == 0) {
|
1999-10-07 00:07:53 +00:00
|
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
1999-08-16 21:50:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the name of this 2-d string list */
|
|
|
|
read_ustring(rb, listname, status);
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
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) {
|
1999-10-07 00:07:53 +00:00
|
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
1999-08-16 21:50:52 +00:00
|
|
|
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) {
|
1999-10-07 00:07:53 +00:00
|
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
1999-08-16 21:50:52 +00:00
|
|
|
/* 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 */
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
/* 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;
|
|
|
|
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) return 0;
|
1999-08-16 21:50:52 +00:00
|
|
|
|
|
|
|
/* Setup the tagged list */
|
|
|
|
retval = new TaggedList();
|
|
|
|
if(retval == 0) {
|
1999-10-07 00:07:53 +00:00
|
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
1999-08-16 21:50:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the name of this tagged list */
|
|
|
|
read_ustring(rb, listname, status);
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
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 */
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
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;
|
|
|
|
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) return 0;
|
1999-08-16 21:50:52 +00:00
|
|
|
|
|
|
|
/* Open the hashtable for saving data */
|
|
|
|
retval = uhash_open((UHashFunction)uhash_hashUString, &status);
|
1999-10-18 22:48:32 +00:00
|
|
|
if(retval == 0 || U_FAILURE(status)) {
|
1999-10-07 00:07:53 +00:00
|
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
1999-08-16 21:50:52 +00:00
|
|
|
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);
|
1999-10-07 00:07:53 +00:00
|
|
|
status = U_INVALID_FORMAT_ERROR;
|
1999-08-16 21:50:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the locale name from the file */
|
|
|
|
read_ustring(f, localename, status);
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
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);
|
1999-12-28 20:25:22 +00:00
|
|
|
if (listname == "%%ALIAS") {
|
|
|
|
localename = strlist->fStrings[0];
|
|
|
|
uhash_close(retval);
|
|
|
|
return 0;
|
|
|
|
}
|
1999-08-16 21:50:52 +00:00
|
|
|
uhash_putKey(retval, listname.hashCode() & 0x7FFFFFFF,
|
|
|
|
strlist, &status);
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
uhash_close(retval);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case sSTRINGLIST2D:
|
|
|
|
strlist2d = read_strlist2d(f, listname, status);
|
|
|
|
uhash_putKey(retval, listname.hashCode() & 0x7FFFFFFF,
|
|
|
|
strlist2d, &status);
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
uhash_close(retval);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case sTAGGEDLIST:
|
|
|
|
taglist = read_taglist(f, listname, status);
|
|
|
|
uhash_putKey(retval, listname.hashCode() & 0x7FFFFFFF,
|
|
|
|
taglist, &status);
|
1999-10-18 22:48:32 +00:00
|
|
|
if(U_FAILURE(status)) {
|
1999-08-16 21:50:52 +00:00
|
|
|
uhash_close(retval);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if any errors occurred during reading */
|
|
|
|
if(T_FileStream_error(f) != 0) {
|
1999-10-07 00:07:53 +00:00
|
|
|
status = U_FILE_ACCESS_ERROR;
|
1999-08-16 21:50:52 +00:00
|
|
|
delete retval;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RBHashtable_valueDeleter(void *value)
|
|
|
|
{
|
|
|
|
delete (ResourceBundleData*)value;
|
|
|
|
}
|