1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 1999,2008, International Business Machines 5 * Corporation and others. All Rights Reserved. 6 * 7 ******************************************************************************* 8 * file name: unewdata.c 9 * encoding: US-ASCII 10 * tab size: 8 (not used) 11 * indentation:4 12 * 13 * created on: 1999oct25 14 * created by: Markus W. Scherer 15 */ 16 17 #include "unicode/utypes.h" 18 #include "unicode/putil.h" 19 #include "unicode/ustring.h" 20 #include "cmemory.h" 21 #include "cstring.h" 22 #include "filestrm.h" 23 #include "unicode/udata.h" 24 #include "unewdata.h" 25 26 struct UNewDataMemory { 27 FileStream *file; 28 uint16_t headerSize; 29 uint8_t magic1, magic2; 30 }; 31 32 U_CAPI UNewDataMemory * U_EXPORT2 33 udata_create(const char *dir, const char *type, const char *name, 34 const UDataInfo *pInfo, 35 const char *comment, 36 UErrorCode *pErrorCode) { 37 UNewDataMemory *pData; 38 uint16_t headerSize, commentLength; 39 char filename[512]; 40 uint8_t bytes[16]; 41 int length; 42 43 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 44 return NULL; 45 } else if(name==NULL || *name==0 || pInfo==NULL) { 46 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 47 return NULL; 48 } 49 50 /* allocate the data structure */ 51 pData=(UNewDataMemory *)uprv_malloc(sizeof(UNewDataMemory)); 52 if(pData==NULL) { 53 *pErrorCode=U_MEMORY_ALLOCATION_ERROR; 54 return NULL; 55 } 56 57 /* Check that the full path won't be too long */ 58 length = 0; /* Start with nothing */ 59 if(dir != NULL && *dir !=0) /* Add directory length if one was given */ 60 { 61 length += strlen(dir); 62 63 /* Add 1 if dir doesn't end with path sep */ 64 if (dir[strlen(dir) - 1]!= U_FILE_SEP_CHAR) { 65 length++; 66 } 67 } 68 length += strlen(name); /* Add the filename length */ 69 70 if(type != NULL && *type !=0) { /* Add directory length if given */ 71 length += strlen(type); 72 } 73 74 75 /* LDH buffer Length error check */ 76 if(length > (sizeof(filename) - 1)) 77 { 78 *pErrorCode = U_BUFFER_OVERFLOW_ERROR; 79 uprv_free(pData); 80 return NULL; 81 } 82 83 /* open the output file */ 84 if(dir!=NULL && *dir!=0) { /* if dir has a value, we prepend it to the filename */ 85 char *p=filename+strlen(dir); 86 uprv_strcpy(filename, dir); 87 if (*(p-1)!=U_FILE_SEP_CHAR) { 88 *p++=U_FILE_SEP_CHAR; 89 *p=0; 90 } 91 } else { /* otherwise, we'll output to the current dir */ 92 filename[0]=0; 93 } 94 uprv_strcat(filename, name); 95 if(type!=NULL && *type!=0) { 96 uprv_strcat(filename, "."); 97 uprv_strcat(filename, type); 98 } 99 pData->file=T_FileStream_open(filename, "wb"); 100 if(pData->file==NULL) { 101 uprv_free(pData); 102 *pErrorCode=U_FILE_ACCESS_ERROR; 103 return NULL; 104 } 105 106 /* write the header information */ 107 headerSize=(uint16_t)(pInfo->size+4); 108 if(comment!=NULL && *comment!=0) { 109 commentLength=(uint16_t)(uprv_strlen(comment)+1); 110 headerSize+=commentLength; 111 } else { 112 commentLength=0; 113 } 114 115 /* write the size of the header, take padding into account */ 116 pData->headerSize=(uint16_t)((headerSize+15)&~0xf); 117 pData->magic1=0xda; 118 pData->magic2=0x27; 119 T_FileStream_write(pData->file, &pData->headerSize, 4); 120 121 /* write the information data */ 122 T_FileStream_write(pData->file, pInfo, pInfo->size); 123 124 /* write the comment */ 125 if(commentLength>0) { 126 T_FileStream_write(pData->file, comment, commentLength); 127 } 128 129 /* write padding bytes to align the data section to 16 bytes */ 130 headerSize&=0xf; 131 if(headerSize!=0) { 132 headerSize=(uint16_t)(16-headerSize); 133 uprv_memset(bytes, 0, headerSize); 134 T_FileStream_write(pData->file, bytes, headerSize); 135 } 136 137 return pData; 138 } 139 140 U_CAPI uint32_t U_EXPORT2 141 udata_finish(UNewDataMemory *pData, UErrorCode *pErrorCode) { 142 uint32_t fileLength=0; 143 144 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 145 return 0; 146 } 147 148 if(pData!=NULL) { 149 if(pData->file!=NULL) { 150 /* fflush(pData->file);*/ 151 fileLength=T_FileStream_size(pData->file); 152 if(T_FileStream_error(pData->file)) { 153 *pErrorCode=U_FILE_ACCESS_ERROR; 154 } else { 155 fileLength-=pData->headerSize; 156 } 157 T_FileStream_close(pData->file); 158 } 159 uprv_free(pData); 160 } 161 162 return fileLength; 163 } 164 165 U_CAPI void U_EXPORT2 166 udata_write8(UNewDataMemory *pData, uint8_t byte) { 167 if(pData!=NULL && pData->file!=NULL) { 168 T_FileStream_write(pData->file, &byte, 1); 169 } 170 } 171 172 U_CAPI void U_EXPORT2 173 udata_write16(UNewDataMemory *pData, uint16_t word) { 174 if(pData!=NULL && pData->file!=NULL) { 175 T_FileStream_write(pData->file, &word, 2); 176 } 177 } 178 179 U_CAPI void U_EXPORT2 180 udata_write32(UNewDataMemory *pData, uint32_t wyde) { 181 if(pData!=NULL && pData->file!=NULL) { 182 T_FileStream_write(pData->file, &wyde, 4); 183 } 184 } 185 186 U_CAPI void U_EXPORT2 187 udata_writeBlock(UNewDataMemory *pData, const void *s, int32_t length) { 188 if(pData!=NULL && pData->file!=NULL) { 189 if(length>0) { 190 T_FileStream_write(pData->file, s, length); 191 } 192 } 193 } 194 195 U_CAPI void U_EXPORT2 196 udata_writePadding(UNewDataMemory *pData, int32_t length) { 197 static const uint8_t padding[16]={ 198 0xaa, 0xaa, 0xaa, 0xaa, 199 0xaa, 0xaa, 0xaa, 0xaa, 200 0xaa, 0xaa, 0xaa, 0xaa, 201 0xaa, 0xaa, 0xaa, 0xaa 202 }; 203 if(pData!=NULL && pData->file!=NULL) { 204 while(length>=16) { 205 T_FileStream_write(pData->file, padding, 16); 206 length-=16; 207 } 208 if(length>0) { 209 T_FileStream_write(pData->file, padding, length); 210 } 211 } 212 } 213 214 U_CAPI void U_EXPORT2 215 udata_writeString(UNewDataMemory *pData, const char *s, int32_t length) { 216 if(pData!=NULL && pData->file!=NULL) { 217 if(length==-1) { 218 length=(int32_t)uprv_strlen(s); 219 } 220 if(length>0) { 221 T_FileStream_write(pData->file, s, length); 222 } 223 } 224 } 225 226 U_CAPI void U_EXPORT2 227 udata_writeUString(UNewDataMemory *pData, const UChar *s, int32_t length) { 228 if(pData!=NULL && pData->file!=NULL) { 229 if(length==-1) { 230 length=u_strlen(s); 231 } 232 if(length>0) { 233 T_FileStream_write(pData->file, s, length*sizeof(UChar)); 234 } 235 } 236 } 237 238 /* 239 * Hey, Emacs, please set the following: 240 * 241 * Local Variables: 242 * indent-tabs-mode: nil 243 * End: 244 * 245 */ 246 247