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