michael@0: /* michael@0: ******************************************************************************* michael@0: * michael@0: * Copyright (C) 1999-2010, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: * michael@0: ******************************************************************************* michael@0: * file name: unewdata.c michael@0: * encoding: US-ASCII michael@0: * tab size: 8 (not used) michael@0: * indentation:4 michael@0: * michael@0: * created on: 1999oct25 michael@0: * created by: Markus W. Scherer michael@0: */ michael@0: michael@0: #include michael@0: #include "unicode/utypes.h" michael@0: #include "unicode/putil.h" michael@0: #include "unicode/ustring.h" michael@0: #include "cmemory.h" michael@0: #include "cstring.h" michael@0: #include "filestrm.h" michael@0: #include "unicode/udata.h" michael@0: #include "unewdata.h" michael@0: michael@0: struct UNewDataMemory { michael@0: FileStream *file; michael@0: uint16_t headerSize; michael@0: uint8_t magic1, magic2; michael@0: }; michael@0: michael@0: U_CAPI UNewDataMemory * U_EXPORT2 michael@0: udata_create(const char *dir, const char *type, const char *name, michael@0: const UDataInfo *pInfo, michael@0: const char *comment, michael@0: UErrorCode *pErrorCode) { michael@0: UNewDataMemory *pData; michael@0: uint16_t headerSize, commentLength; michael@0: char filename[512]; michael@0: uint8_t bytes[16]; michael@0: int length; michael@0: michael@0: if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { michael@0: return NULL; michael@0: } else if(name==NULL || *name==0 || pInfo==NULL) { michael@0: *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; michael@0: return NULL; michael@0: } michael@0: michael@0: /* allocate the data structure */ michael@0: pData=(UNewDataMemory *)uprv_malloc(sizeof(UNewDataMemory)); michael@0: if(pData==NULL) { michael@0: *pErrorCode=U_MEMORY_ALLOCATION_ERROR; michael@0: return NULL; michael@0: } michael@0: michael@0: /* Check that the full path won't be too long */ michael@0: length = 0; /* Start with nothing */ michael@0: if(dir != NULL && *dir !=0) /* Add directory length if one was given */ michael@0: { michael@0: length += strlen(dir); michael@0: michael@0: /* Add 1 if dir doesn't end with path sep */ michael@0: if (dir[strlen(dir) - 1]!= U_FILE_SEP_CHAR) { michael@0: length++; michael@0: } michael@0: } michael@0: length += strlen(name); /* Add the filename length */ michael@0: michael@0: if(type != NULL && *type !=0) { /* Add directory length if given */ michael@0: length += strlen(type); michael@0: } michael@0: michael@0: michael@0: /* LDH buffer Length error check */ michael@0: if(length > (sizeof(filename) - 1)) michael@0: { michael@0: *pErrorCode = U_BUFFER_OVERFLOW_ERROR; michael@0: uprv_free(pData); michael@0: return NULL; michael@0: } michael@0: michael@0: /* open the output file */ michael@0: if(dir!=NULL && *dir!=0) { /* if dir has a value, we prepend it to the filename */ michael@0: char *p=filename+strlen(dir); michael@0: uprv_strcpy(filename, dir); michael@0: if (*(p-1)!=U_FILE_SEP_CHAR) { michael@0: *p++=U_FILE_SEP_CHAR; michael@0: *p=0; michael@0: } michael@0: } else { /* otherwise, we'll output to the current dir */ michael@0: filename[0]=0; michael@0: } michael@0: uprv_strcat(filename, name); michael@0: if(type!=NULL && *type!=0) { michael@0: uprv_strcat(filename, "."); michael@0: uprv_strcat(filename, type); michael@0: } michael@0: pData->file=T_FileStream_open(filename, "wb"); michael@0: if(pData->file==NULL) { michael@0: uprv_free(pData); michael@0: *pErrorCode=U_FILE_ACCESS_ERROR; michael@0: return NULL; michael@0: } michael@0: michael@0: /* write the header information */ michael@0: headerSize=(uint16_t)(pInfo->size+4); michael@0: if(comment!=NULL && *comment!=0) { michael@0: commentLength=(uint16_t)(uprv_strlen(comment)+1); michael@0: headerSize+=commentLength; michael@0: } else { michael@0: commentLength=0; michael@0: } michael@0: michael@0: /* write the size of the header, take padding into account */ michael@0: pData->headerSize=(uint16_t)((headerSize+15)&~0xf); michael@0: pData->magic1=0xda; michael@0: pData->magic2=0x27; michael@0: T_FileStream_write(pData->file, &pData->headerSize, 4); michael@0: michael@0: /* write the information data */ michael@0: T_FileStream_write(pData->file, pInfo, pInfo->size); michael@0: michael@0: /* write the comment */ michael@0: if(commentLength>0) { michael@0: T_FileStream_write(pData->file, comment, commentLength); michael@0: } michael@0: michael@0: /* write padding bytes to align the data section to 16 bytes */ michael@0: headerSize&=0xf; michael@0: if(headerSize!=0) { michael@0: headerSize=(uint16_t)(16-headerSize); michael@0: uprv_memset(bytes, 0, headerSize); michael@0: T_FileStream_write(pData->file, bytes, headerSize); michael@0: } michael@0: michael@0: return pData; michael@0: } michael@0: michael@0: U_CAPI uint32_t U_EXPORT2 michael@0: udata_finish(UNewDataMemory *pData, UErrorCode *pErrorCode) { michael@0: uint32_t fileLength=0; michael@0: michael@0: if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { michael@0: return 0; michael@0: } michael@0: michael@0: if(pData!=NULL) { michael@0: if(pData->file!=NULL) { michael@0: /* fflush(pData->file);*/ michael@0: fileLength=T_FileStream_size(pData->file); michael@0: if(T_FileStream_error(pData->file)) { michael@0: *pErrorCode=U_FILE_ACCESS_ERROR; michael@0: } else { michael@0: fileLength-=pData->headerSize; michael@0: } michael@0: T_FileStream_close(pData->file); michael@0: } michael@0: uprv_free(pData); michael@0: } michael@0: michael@0: return fileLength; michael@0: } michael@0: michael@0: /* dummy UDataInfo cf. udata.h */ michael@0: static const UDataInfo dummyDataInfo = { michael@0: sizeof(UDataInfo), michael@0: 0, michael@0: michael@0: U_IS_BIG_ENDIAN, michael@0: U_CHARSET_FAMILY, michael@0: U_SIZEOF_UCHAR, michael@0: 0, michael@0: michael@0: { 0, 0, 0, 0 }, /* dummy dataFormat */ michael@0: { 0, 0, 0, 0 }, /* dummy formatVersion */ michael@0: { 0, 0, 0, 0 } /* dummy dataVersion */ michael@0: }; michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udata_createDummy(const char *dir, const char *type, const char *name, UErrorCode *pErrorCode) { michael@0: if(U_SUCCESS(*pErrorCode)) { michael@0: udata_finish(udata_create(dir, type, name, &dummyDataInfo, NULL, pErrorCode), pErrorCode); michael@0: if(U_FAILURE(*pErrorCode)) { michael@0: fprintf(stderr, "error %s writing dummy data file %s" U_FILE_SEP_STRING "%s.%s\n", michael@0: u_errorName(*pErrorCode), dir, name, type); michael@0: exit(*pErrorCode); michael@0: } michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udata_write8(UNewDataMemory *pData, uint8_t byte) { michael@0: if(pData!=NULL && pData->file!=NULL) { michael@0: T_FileStream_write(pData->file, &byte, 1); michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udata_write16(UNewDataMemory *pData, uint16_t word) { michael@0: if(pData!=NULL && pData->file!=NULL) { michael@0: T_FileStream_write(pData->file, &word, 2); michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udata_write32(UNewDataMemory *pData, uint32_t wyde) { michael@0: if(pData!=NULL && pData->file!=NULL) { michael@0: T_FileStream_write(pData->file, &wyde, 4); michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udata_writeBlock(UNewDataMemory *pData, const void *s, int32_t length) { michael@0: if(pData!=NULL && pData->file!=NULL) { michael@0: if(length>0) { michael@0: T_FileStream_write(pData->file, s, length); michael@0: } michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udata_writePadding(UNewDataMemory *pData, int32_t length) { michael@0: static const uint8_t padding[16]={ michael@0: 0xaa, 0xaa, 0xaa, 0xaa, michael@0: 0xaa, 0xaa, 0xaa, 0xaa, michael@0: 0xaa, 0xaa, 0xaa, 0xaa, michael@0: 0xaa, 0xaa, 0xaa, 0xaa michael@0: }; michael@0: if(pData!=NULL && pData->file!=NULL) { michael@0: while(length>=16) { michael@0: T_FileStream_write(pData->file, padding, 16); michael@0: length-=16; michael@0: } michael@0: if(length>0) { michael@0: T_FileStream_write(pData->file, padding, length); michael@0: } michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udata_writeString(UNewDataMemory *pData, const char *s, int32_t length) { michael@0: if(pData!=NULL && pData->file!=NULL) { michael@0: if(length==-1) { michael@0: length=(int32_t)uprv_strlen(s); michael@0: } michael@0: if(length>0) { michael@0: T_FileStream_write(pData->file, s, length); michael@0: } michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udata_writeUString(UNewDataMemory *pData, const UChar *s, int32_t length) { michael@0: if(pData!=NULL && pData->file!=NULL) { michael@0: if(length==-1) { michael@0: length=u_strlen(s); michael@0: } michael@0: if(length>0) { michael@0: T_FileStream_write(pData->file, s, length*sizeof(UChar)); michael@0: } michael@0: } michael@0: } michael@0: michael@0: /* michael@0: * Hey, Emacs, please set the following: michael@0: * michael@0: * Local Variables: michael@0: * indent-tabs-mode: nil michael@0: * End: michael@0: * michael@0: */ michael@0: