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