|  | /* | 
|  | ******************************************************************************* | 
|  | * | 
|  | *   Copyright (C) 1998-2000, International Business Machines | 
|  | *   Corporation and others.  All Rights Reserved. | 
|  | * | 
|  | ******************************************************************************* | 
|  | * | 
|  | * File write.c | 
|  | * | 
|  | * Modification History: | 
|  | * | 
|  | *   Date        Name        Description | 
|  | *   06/01/99    stephen     Creation. | 
|  | ******************************************************************************* | 
|  | */ | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include "write.h" | 
|  | #include "cmemory.h" | 
|  | #include "cstring.h" | 
|  | #include "filestrm.h" | 
|  | #include "unicode/ustring.h" | 
|  | #include "error.h" | 
|  | #include "list.h" | 
|  |  | 
|  |  | 
|  | /* Protos */ | 
|  | static void write_ustring(FileStream *rb, const UChar *data); | 
|  | static void write_string(FileStream *rb, const char *data); | 
|  | static void write_strlist(FileStream *rb, const char *name, | 
|  | const struct SStringList *list); | 
|  | static void write_strlist2d(FileStream *rb, const char *name, | 
|  | const struct SStringList2d *list); | 
|  | static void write_taglist(FileStream *rb, const char *name, | 
|  | const struct STaggedList *list); | 
|  |  | 
|  | /* Special values */ | 
|  | static const int32_t sBOM = 0x021C; | 
|  |  | 
|  | static const int32_t sEOF = -1; | 
|  |  | 
|  | static const int32_t sSTRINGLIST = 1; | 
|  | static const int32_t sSTRINGLIST2D = 2; | 
|  | static const int32_t sTAGGEDLIST = 3; | 
|  |  | 
|  | static const UChar gCollationElementsTag [] = { | 
|  | /* "CollationElements" */ | 
|  | 0x0043, 0x006f, 0x006c, 0x006c, 0x0061, 0x0074, 0x0069, 0x006f, 0x006e, | 
|  | 0x0045, 0x006c, 0x0065, 0x006d, 0x0065, 0x006e, 0x0074, 0x0073, 0x0000 | 
|  | }; | 
|  |  | 
|  | /* Write a null-terminated UChar array */ | 
|  | static void | 
|  | write_ustring(FileStream *rb, | 
|  | const UChar *data) | 
|  | { | 
|  | int32_t len; | 
|  |  | 
|  | len = u_strlen(data); | 
|  |  | 
|  | /* Write the string's length */ | 
|  | T_FileStream_write(rb, &len, sizeof(len)); | 
|  |  | 
|  | /* Write the string's data */ | 
|  | T_FileStream_write(rb, data, sizeof(UChar) * len); | 
|  | } | 
|  |  | 
|  | static void | 
|  | write_string(FileStream *rb, | 
|  | const char *data) { | 
|  | int32_t len; | 
|  |  | 
|  | len = uprv_strlen(data); | 
|  | T_FileStream_write(rb, &len, sizeof(len)); | 
|  |  | 
|  | T_FileStream_write(rb, data, sizeof(char) * len); | 
|  | } | 
|  |  | 
|  | /* Write a string list */ | 
|  | static void | 
|  | write_strlist(FileStream *rb, | 
|  | const char *name, | 
|  | const struct SStringList *list) | 
|  | { | 
|  | int32_t i; | 
|  |  | 
|  | /* Write out the value indicating this is a string list */ | 
|  | T_FileStream_write(rb, &sSTRINGLIST, sizeof(sSTRINGLIST)); | 
|  |  | 
|  | /* Write the name of this string list */ | 
|  | write_string(rb, name); | 
|  |  | 
|  | /* Write the item count */ | 
|  | T_FileStream_write(rb, &list->fCount, sizeof(list->fCount)); | 
|  |  | 
|  | /* Write each string in the list */ | 
|  | for(i = 0; i < list->fCount; ++i) { | 
|  | write_ustring(rb, list->fData[i]); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Write a 2-d string list */ | 
|  | static void | 
|  | write_strlist2d(FileStream *rb, | 
|  | const char *name, | 
|  | const struct SStringList2d *list) | 
|  | { | 
|  | int32_t i, j; | 
|  | int32_t itemcount; | 
|  |  | 
|  | /* Write out the value indicating this is a 2-d string list */ | 
|  | T_FileStream_write(rb, &sSTRINGLIST2D, sizeof(sSTRINGLIST2D)); | 
|  |  | 
|  | /* Write the name of this 2-d string list */ | 
|  | write_string(rb, name); | 
|  |  | 
|  | /* Write the row count */ | 
|  | T_FileStream_write(rb, &list->fRowCount, sizeof(list->fRowCount)); | 
|  |  | 
|  | /* Write out each row */ | 
|  | for(i = 0; i < list->fRowCount; ++i) { | 
|  | itemcount = (i == list->fRowCount - 1 ? list->fCount: list->fRows[i+1]) | 
|  | - list->fRows[i]; | 
|  |  | 
|  | /* Write out the count of strings in this row */ | 
|  | T_FileStream_write(rb, &itemcount, sizeof(itemcount)); | 
|  |  | 
|  | /* Write out each string in the row */ | 
|  | for(j = 0; j < itemcount; ++j) { | 
|  | write_ustring(rb, list->fData[list->fRows[i] + j]); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Write a tagged list */ | 
|  | static void | 
|  | write_taglist(FileStream *rb, | 
|  | const char *name, | 
|  | const struct STaggedList *list) | 
|  | { | 
|  | /*  int32_t i;   */ | 
|  | struct SStringPair *current; | 
|  |  | 
|  | /* Write out the value indicating this is a tagged list */ | 
|  | T_FileStream_write(rb, &sTAGGEDLIST, sizeof(sTAGGEDLIST)); | 
|  |  | 
|  | /* Write the name of this tagged list */ | 
|  | write_string(rb, name); | 
|  |  | 
|  | /* Write the item count */ | 
|  | T_FileStream_write(rb, &list->fCount, sizeof(list->fCount)); | 
|  |  | 
|  | /* Write out each key/value pair */ | 
|  | current = list->fFirst; | 
|  | while(current != NULL) { | 
|  | write_string(rb, current->fKey); | 
|  | write_ustring(rb, current->fValue); | 
|  | current = current->fNext; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*  for(i = 0; i < list->fCount; ++i) { | 
|  | //    write_ustring(rb, list->fData[i].fKey); | 
|  | //    write_ustring(rb, list->fData[i].fValue); | 
|  | //  } */ | 
|  | } | 
|  |  | 
|  | /* Write a parsed SRBItemList to a file */ | 
|  | void | 
|  | rb_write(FileStream *f, | 
|  | struct SRBItemList *data, | 
|  | UErrorCode *status) | 
|  | { | 
|  | /*  int32_t i; */ | 
|  | struct SRBItem *item; | 
|  |  | 
|  | if(U_FAILURE(*status)) return; | 
|  |  | 
|  | /* Write the byte order mark to the file */ | 
|  | T_FileStream_write(f, &sBOM, sizeof(sBOM)); | 
|  |  | 
|  | /* Write the locale name to the file */ | 
|  | write_ustring(f, data->fLocale); | 
|  |  | 
|  | item = data->fFirst; | 
|  |  | 
|  | /* Successively write each list item */ | 
|  | /*  for(i = 0; i < data->fCount; ++i) {  */ | 
|  | while(item != NULL) { | 
|  |  | 
|  | /*    item = data->fData[i];  */ | 
|  |  | 
|  | switch(item->fData->fType) { | 
|  | case eStringList: | 
|  | /*if(u_strcmp(item->fTag, gCollationElementsTag) == 0) | 
|  | puts("got CollationElements");*/ | 
|  | write_strlist(f, item->fTag, &item->fData->u.fStringList); | 
|  | break; | 
|  |  | 
|  | case eStringList2d: | 
|  | write_strlist2d(f, item->fTag, &item->fData->u.fStringList2d); | 
|  | break; | 
|  |  | 
|  | case eTaggedList: | 
|  | write_taglist(f, item->fTag, &item->fData->u.fTaggedList); | 
|  | break; | 
|  |  | 
|  | case eEmpty: | 
|  | *status = U_INTERNAL_PROGRAM_ERROR; | 
|  | setErrorText("Unexpected empty item found"); | 
|  | goto finish; | 
|  | /*break;*/ | 
|  | } | 
|  | item = item->fNext; | 
|  | } | 
|  |  | 
|  | /* Indicate the end of the data */ | 
|  | T_FileStream_write(f, &sEOF, sizeof(sEOF)); | 
|  |  | 
|  | /* Check if any errors occurred during writing */ | 
|  | if(T_FileStream_error(f) != 0) { | 
|  | *status = U_FILE_ACCESS_ERROR; | 
|  | } | 
|  |  | 
|  | finish: | 
|  | ; | 
|  |  | 
|  | /* clean up */ | 
|  | } |