]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | ****************************************************************************** | |
3 | * | |
4 | * Copyright (C) 1998-2013, International Business Machines | |
5 | * Corporation and others. All Rights Reserved. | |
6 | * | |
7 | ****************************************************************************** | |
8 | * | |
9 | * File ufile.c | |
10 | * | |
11 | * Modification History: | |
12 | * | |
13 | * Date Name Description | |
14 | * 11/19/98 stephen Creation. | |
15 | * 03/12/99 stephen Modified for new C API. | |
16 | * 06/16/99 stephen Changed T_LocaleBundle to u_locbund | |
17 | * 07/19/99 stephen Fixed to use ucnv's default codepage. | |
18 | ****************************************************************************** | |
19 | */ | |
20 | ||
21 | /* | |
22 | * fileno is not declared when building with GCC in strict mode. | |
23 | */ | |
24 | #if defined(__GNUC__) && defined(__STRICT_ANSI__) | |
25 | #undef __STRICT_ANSI__ | |
26 | #endif | |
27 | ||
28 | #include "locmap.h" | |
29 | #include "unicode/ustdio.h" | |
30 | #include "ufile.h" | |
31 | #include "unicode/uloc.h" | |
32 | #include "unicode/ures.h" | |
33 | #include "unicode/ucnv.h" | |
34 | #include "cstring.h" | |
35 | #include "cmemory.h" | |
36 | ||
37 | #if U_PLATFORM_USES_ONLY_WIN32_API && !defined(fileno) | |
38 | /* Windows likes to rename Unix-like functions */ | |
39 | #define fileno _fileno | |
40 | #endif | |
41 | ||
42 | static UFILE* | |
43 | finit_owner(FILE *f, | |
44 | const char *locale, | |
45 | const char *codepage, | |
46 | UBool takeOwnership | |
47 | ) | |
48 | { | |
49 | UErrorCode status = U_ZERO_ERROR; | |
50 | UFILE *result; | |
51 | if(f == NULL) { | |
52 | return 0; | |
53 | } | |
54 | result = (UFILE*) uprv_malloc(sizeof(UFILE)); | |
55 | if(result == NULL) { | |
56 | return 0; | |
57 | } | |
58 | ||
59 | uprv_memset(result, 0, sizeof(UFILE)); | |
60 | result->fFileno = fileno(f); | |
61 | ||
62 | #if U_PLATFORM_USES_ONLY_WIN32_API | |
63 | if (0 <= result->fFileno && result->fFileno <= 2) { | |
64 | /* stdin, stdout and stderr need to be special cased for Windows 98 */ | |
65 | #if _MSC_VER >= 1400 | |
66 | result->fFile = &__iob_func()[_fileno(f)]; | |
67 | #else | |
68 | result->fFile = &_iob[_fileno(f)]; | |
69 | #endif | |
70 | } | |
71 | else | |
72 | #endif | |
73 | { | |
74 | result->fFile = f; | |
75 | } | |
76 | ||
77 | result->str.fBuffer = result->fUCBuffer; | |
78 | result->str.fPos = result->fUCBuffer; | |
79 | result->str.fLimit = result->fUCBuffer; | |
80 | ||
81 | #if !UCONFIG_NO_FORMATTING | |
82 | /* if locale is 0, use the default */ | |
83 | if(u_locbund_init(&result->str.fBundle, locale) == 0) { | |
84 | /* DO NOT FCLOSE HERE! */ | |
85 | uprv_free(result); | |
86 | return 0; | |
87 | } | |
88 | #endif | |
89 | ||
90 | /* If the codepage is not "" use the ucnv_open default behavior */ | |
91 | if(codepage == NULL || *codepage != '\0') { | |
92 | result->fConverter = ucnv_open(codepage, &status); | |
93 | } | |
94 | /* else result->fConverter is already memset'd to NULL. */ | |
95 | ||
96 | if(U_SUCCESS(status)) { | |
97 | result->fOwnFile = takeOwnership; | |
98 | } | |
99 | else { | |
100 | #if !UCONFIG_NO_FORMATTING | |
101 | u_locbund_close(&result->str.fBundle); | |
102 | #endif | |
103 | /* DO NOT fclose here!!!!!! */ | |
104 | uprv_free(result); | |
105 | result = NULL; | |
106 | } | |
107 | ||
108 | return result; | |
109 | } | |
110 | ||
111 | U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
112 | u_finit(FILE *f, | |
113 | const char *locale, | |
114 | const char *codepage) | |
115 | { | |
116 | return finit_owner(f, locale, codepage, FALSE); | |
117 | } | |
118 | ||
119 | U_CAPI UFILE* U_EXPORT2 | |
120 | u_fadopt(FILE *f, | |
121 | const char *locale, | |
122 | const char *codepage) | |
123 | { | |
124 | return finit_owner(f, locale, codepage, TRUE); | |
125 | } | |
126 | ||
127 | U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
128 | u_fopen(const char *filename, | |
129 | const char *perm, | |
130 | const char *locale, | |
131 | const char *codepage) | |
132 | { | |
133 | UFILE *result; | |
134 | FILE *systemFile = fopen(filename, perm); | |
135 | if(systemFile == 0) { | |
136 | return 0; | |
137 | } | |
138 | ||
139 | result = finit_owner(systemFile, locale, codepage, TRUE); | |
140 | ||
141 | if (!result) { | |
142 | /* Something bad happened. | |
143 | Maybe the converter couldn't be opened. */ | |
144 | fclose(systemFile); | |
145 | } | |
146 | ||
147 | return result; /* not a file leak */ | |
148 | } | |
149 | ||
150 | U_CAPI UFILE* U_EXPORT2 | |
151 | u_fstropen(UChar *stringBuf, | |
152 | int32_t capacity, | |
153 | const char *locale) | |
154 | { | |
155 | UFILE *result; | |
156 | ||
157 | if (capacity < 0) { | |
158 | return NULL; | |
159 | } | |
160 | ||
161 | result = (UFILE*) uprv_malloc(sizeof(UFILE)); | |
162 | /* Null pointer test */ | |
163 | if (result == NULL) { | |
164 | return NULL; /* Just get out. */ | |
165 | } | |
166 | uprv_memset(result, 0, sizeof(UFILE)); | |
167 | result->str.fBuffer = stringBuf; | |
168 | result->str.fPos = stringBuf; | |
169 | result->str.fLimit = stringBuf+capacity; | |
170 | ||
171 | #if !UCONFIG_NO_FORMATTING | |
172 | /* if locale is 0, use the default */ | |
173 | if(u_locbund_init(&result->str.fBundle, locale) == 0) { | |
174 | /* DO NOT FCLOSE HERE! */ | |
175 | uprv_free(result); | |
176 | return 0; | |
177 | } | |
178 | #endif | |
179 | ||
180 | return result; | |
181 | } | |
182 | ||
183 | U_CAPI UBool U_EXPORT2 | |
184 | u_feof(UFILE *f) | |
185 | { | |
186 | UBool endOfBuffer; | |
187 | if (f == NULL) { | |
188 | return TRUE; | |
189 | } | |
190 | endOfBuffer = (UBool)(f->str.fPos >= f->str.fLimit); | |
191 | if (f->fFile != NULL) { | |
192 | return endOfBuffer && feof(f->fFile); | |
193 | } | |
194 | return endOfBuffer; | |
195 | } | |
196 | ||
197 | U_CAPI void U_EXPORT2 | |
198 | u_fflush(UFILE *file) | |
199 | { | |
200 | ufile_flush_translit(file); | |
201 | ufile_flush_io(file); | |
202 | if (file->fFile) { | |
203 | fflush(file->fFile); | |
204 | } | |
205 | else if (file->str.fPos < file->str.fLimit) { | |
206 | *(file->str.fPos++) = 0; | |
207 | } | |
208 | /* TODO: flush input */ | |
209 | } | |
210 | ||
211 | U_CAPI void | |
212 | u_frewind(UFILE *file) | |
213 | { | |
214 | u_fflush(file); | |
215 | ucnv_reset(file->fConverter); | |
216 | if (file->fFile) { | |
217 | rewind(file->fFile); | |
218 | file->str.fLimit = file->fUCBuffer; | |
219 | file->str.fPos = file->fUCBuffer; | |
220 | } | |
221 | else { | |
222 | file->str.fPos = file->str.fBuffer; | |
223 | } | |
224 | } | |
225 | ||
226 | U_CAPI void U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
227 | u_fclose(UFILE *file) | |
228 | { | |
229 | if (file) { | |
230 | u_fflush(file); | |
231 | ufile_close_translit(file); | |
232 | ||
233 | if(file->fOwnFile) | |
234 | fclose(file->fFile); | |
235 | ||
236 | #if !UCONFIG_NO_FORMATTING | |
237 | u_locbund_close(&file->str.fBundle); | |
238 | #endif | |
239 | ||
240 | ucnv_close(file->fConverter); | |
241 | uprv_free(file); | |
242 | } | |
243 | } | |
244 | ||
245 | U_CAPI FILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
246 | u_fgetfile( UFILE *f) | |
247 | { | |
248 | return f->fFile; | |
249 | } | |
250 | ||
251 | #if !UCONFIG_NO_FORMATTING | |
252 | ||
253 | U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
254 | u_fgetlocale( UFILE *file) | |
255 | { | |
256 | return file->str.fBundle.fLocale; | |
257 | } | |
258 | ||
259 | U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
260 | u_fsetlocale(UFILE *file, | |
261 | const char *locale) | |
262 | { | |
263 | u_locbund_close(&file->str.fBundle); | |
264 | ||
265 | return u_locbund_init(&file->str.fBundle, locale) == 0 ? -1 : 0; | |
266 | } | |
267 | ||
268 | #endif | |
269 | ||
270 | U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
271 | u_fgetcodepage(UFILE *file) | |
272 | { | |
273 | UErrorCode status = U_ZERO_ERROR; | |
274 | const char *codepage = NULL; | |
275 | ||
276 | if (file->fConverter) { | |
277 | codepage = ucnv_getName(file->fConverter, &status); | |
278 | if(U_FAILURE(status)) | |
279 | return 0; | |
280 | } | |
281 | return codepage; | |
282 | } | |
283 | ||
284 | U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
285 | u_fsetcodepage( const char *codepage, | |
286 | UFILE *file) | |
287 | { | |
288 | UErrorCode status = U_ZERO_ERROR; | |
289 | int32_t retVal = -1; | |
290 | ||
291 | /* We use the normal default codepage for this system, and not the one for the locale. */ | |
292 | if ((file->str.fPos == file->str.fBuffer) && (file->str.fLimit == file->str.fBuffer)) { | |
293 | ucnv_close(file->fConverter); | |
294 | file->fConverter = ucnv_open(codepage, &status); | |
295 | if(U_SUCCESS(status)) { | |
296 | retVal = 0; | |
297 | } | |
298 | } | |
299 | return retVal; | |
300 | } | |
301 | ||
302 | ||
303 | U_CAPI UConverter * U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
304 | u_fgetConverter(UFILE *file) | |
305 | { | |
306 | return file->fConverter; | |
307 | } | |
308 | #if !UCONFIG_NO_FORMATTING | |
309 | U_CAPI const UNumberFormat* U_EXPORT2 u_fgetNumberFormat(UFILE *file) | |
310 | { | |
311 | return u_locbund_getNumberFormat(&file->str.fBundle, UNUM_DECIMAL); | |
312 | } | |
313 | #endif | |
314 |