1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 1999-2010, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
10 * file name: unewdata.c
12 * tab size: 8 (not used)
15 * created on: 1999oct25
16 * created by: Markus W. Scherer
20 #include "unicode/utypes.h"
21 #include "unicode/putil.h"
22 #include "unicode/ustring.h"
26 #include "unicode/udata.h"
29 struct UNewDataMemory
{
32 uint8_t magic1
, magic2
;
35 U_CAPI UNewDataMemory
* U_EXPORT2
36 udata_create(const char *dir
, const char *type
, const char *name
,
37 const UDataInfo
*pInfo
,
39 UErrorCode
*pErrorCode
) {
40 UNewDataMemory
*pData
;
41 uint16_t headerSize
, commentLength
;
46 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
48 } else if(name
==NULL
|| *name
==0 || pInfo
==NULL
) {
49 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
53 /* allocate the data structure */
54 pData
=(UNewDataMemory
*)uprv_malloc(sizeof(UNewDataMemory
));
56 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
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 */
64 length
+= static_cast<int32_t>(strlen(dir
));
66 /* Add 1 if dir doesn't end with path sep */
67 if (dir
[strlen(dir
) - 1]!= U_FILE_SEP_CHAR
) {
71 length
+= static_cast<int32_t>(strlen(name
)); /* Add the filename length */
73 if(type
!= NULL
&& *type
!=0) { /* Add directory length if given */
74 length
+= static_cast<int32_t>(strlen(type
));
78 /* LDH buffer Length error check */
79 if(length
> ((int32_t)sizeof(filename
) - 1))
81 *pErrorCode
= U_BUFFER_OVERFLOW_ERROR
;
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
) {
94 } else { /* otherwise, we'll output to the current dir */
97 uprv_strcat(filename
, name
);
98 if(type
!=NULL
&& *type
!=0) {
99 uprv_strcat(filename
, ".");
100 uprv_strcat(filename
, type
);
102 pData
->file
=T_FileStream_open(filename
, "wb");
103 if(pData
->file
==NULL
) {
105 *pErrorCode
=U_FILE_ACCESS_ERROR
;
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
;
118 /* write the size of the header, take padding into account */
119 pData
->headerSize
=(uint16_t)((headerSize
+15)&~0xf);
122 T_FileStream_write(pData
->file
, &pData
->headerSize
, 4);
124 /* write the information data */
125 T_FileStream_write(pData
->file
, pInfo
, pInfo
->size
);
127 /* write the comment */
128 if(commentLength
>0) {
129 T_FileStream_write(pData
->file
, comment
, commentLength
);
132 /* write padding bytes to align the data section to 16 bytes */
135 headerSize
=(uint16_t)(16-headerSize
);
136 uprv_memset(bytes
, 0, headerSize
);
137 T_FileStream_write(pData
->file
, bytes
, headerSize
);
143 U_CAPI
uint32_t U_EXPORT2
144 udata_finish(UNewDataMemory
*pData
, UErrorCode
*pErrorCode
) {
145 uint32_t fileLength
=0;
147 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
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
;
158 fileLength
-=pData
->headerSize
;
160 T_FileStream_close(pData
->file
);
168 /* dummy UDataInfo cf. udata.h */
169 static const UDataInfo dummyDataInfo
= {
178 { 0, 0, 0, 0 }, /* dummy dataFormat */
179 { 0, 0, 0, 0 }, /* dummy formatVersion */
180 { 0, 0, 0, 0 } /* dummy dataVersion */
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
);
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);
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);
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);
216 U_CAPI
void U_EXPORT2
217 udata_writeBlock(UNewDataMemory
*pData
, const void *s
, int32_t length
) {
218 if(pData
!=NULL
&& pData
->file
!=NULL
) {
220 T_FileStream_write(pData
->file
, s
, length
);
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
233 if(pData
!=NULL
&& pData
->file
!=NULL
) {
235 T_FileStream_write(pData
->file
, padding
, 16);
239 T_FileStream_write(pData
->file
, padding
, length
);
244 U_CAPI
void U_EXPORT2
245 udata_writeString(UNewDataMemory
*pData
, const char *s
, int32_t length
) {
246 if(pData
!=NULL
&& pData
->file
!=NULL
) {
248 length
=(int32_t)uprv_strlen(s
);
251 T_FileStream_write(pData
->file
, s
, length
);
256 U_CAPI
void U_EXPORT2
257 udata_writeUString(UNewDataMemory
*pData
, const UChar
*s
, int32_t length
) {
258 if(pData
!=NULL
&& pData
->file
!=NULL
) {
263 T_FileStream_write(pData
->file
, s
, length
*sizeof(UChar
));
269 * Hey, Emacs, please set the following:
272 * indent-tabs-mode: nil