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