|
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 |