]> git.saurik.com Git - apple/icu.git/blame - icuSources/io/ufile.c
ICU-57131.0.1.tar.gz
[apple/icu.git] / icuSources / io / ufile.c
CommitLineData
b75a7d8f
A
1/*
2******************************************************************************
3*
2ca993e8 4* Copyright (C) 1998-2015, International Business Machines
b75a7d8f
A
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
4388f060 21/*
51004dcb 22 * fileno is not declared when building with GCC in strict mode.
4388f060 23 */
51004dcb
A
24#if defined(__GNUC__) && defined(__STRICT_ANSI__)
25#undef __STRICT_ANSI__
26#endif
374ca955 27
b75a7d8f
A
28#include "locmap.h"
29#include "unicode/ustdio.h"
b331163b
A
30
31#if !UCONFIG_NO_CONVERSION
32
b75a7d8f
A
33#include "ufile.h"
34#include "unicode/uloc.h"
b75a7d8f
A
35#include "unicode/ures.h"
36#include "unicode/ucnv.h"
b331163b 37#include "unicode/ustring.h"
b75a7d8f
A
38#include "cstring.h"
39#include "cmemory.h"
40
4388f060 41#if U_PLATFORM_USES_ONLY_WIN32_API && !defined(fileno)
374ca955
A
42/* Windows likes to rename Unix-like functions */
43#define fileno _fileno
44#endif
b75a7d8f 45
729e4ab9
A
46static UFILE*
47finit_owner(FILE *f,
48 const char *locale,
49 const char *codepage,
50 UBool takeOwnership
51 )
374ca955 52{
73c04bcf
A
53 UErrorCode status = U_ZERO_ERROR;
54 UFILE *result;
55 if(f == NULL) {
56 return 0;
57 }
58 result = (UFILE*) uprv_malloc(sizeof(UFILE));
59 if(result == NULL) {
374ca955
A
60 return 0;
61 }
b75a7d8f 62
374ca955
A
63 uprv_memset(result, 0, sizeof(UFILE));
64 result->fFileno = fileno(f);
65
2ca993e8
A
66#if U_PLATFORM_USES_ONLY_WIN32_API && _MSC_VER < 1900
67 /*
68 * Below is a very old workaround (ICU ticket:231).
69 *
70 * Previously, 'FILE*' from inside and outside ICU's DLL
71 * were different, because they pointed into local copies
72 * of the io block. At least by VS 2015 the implementation
73 * is something like:
74 * stdio = _acrt_iob_func(0)
75 * .. which is a function call, so should return the same pointer
76 * regardless of call site.
77 * As of _MSC_VER 1900 this patch is retired, at 16 years old.
78 */
374ca955
A
79 if (0 <= result->fFileno && result->fFileno <= 2) {
80 /* stdin, stdout and stderr need to be special cased for Windows 98 */
73c04bcf
A
81#if _MSC_VER >= 1400
82 result->fFile = &__iob_func()[_fileno(f)];
83#else
374ca955 84 result->fFile = &_iob[_fileno(f)];
73c04bcf 85#endif
b75a7d8f 86 }
374ca955 87 else
b75a7d8f 88#endif
374ca955
A
89 {
90 result->fFile = f;
b75a7d8f
A
91 }
92
374ca955
A
93 result->str.fBuffer = result->fUCBuffer;
94 result->str.fPos = result->fUCBuffer;
95 result->str.fLimit = result->fUCBuffer;
b75a7d8f 96
374ca955
A
97#if !UCONFIG_NO_FORMATTING
98 /* if locale is 0, use the default */
374ca955
A
99 if(u_locbund_init(&result->str.fBundle, locale) == 0) {
100 /* DO NOT FCLOSE HERE! */
101 uprv_free(result);
102 return 0;
103 }
104#endif
105
106 /* If the codepage is not "" use the ucnv_open default behavior */
107 if(codepage == NULL || *codepage != '\0') {
108 result->fConverter = ucnv_open(codepage, &status);
109 }
110 /* else result->fConverter is already memset'd to NULL. */
111
729e4ab9
A
112 if(U_SUCCESS(status)) {
113 result->fOwnFile = takeOwnership;
114 }
115 else {
374ca955
A
116#if !UCONFIG_NO_FORMATTING
117 u_locbund_close(&result->str.fBundle);
118#endif
119 /* DO NOT fclose here!!!!!! */
120 uprv_free(result);
121 result = NULL;
122 }
123
124 return result;
125}
b75a7d8f 126
729e4ab9
A
127U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
128u_finit(FILE *f,
129 const char *locale,
130 const char *codepage)
131{
132 return finit_owner(f, locale, codepage, FALSE);
133}
134
135U_CAPI UFILE* U_EXPORT2
136u_fadopt(FILE *f,
137 const char *locale,
138 const char *codepage)
139{
140 return finit_owner(f, locale, codepage, TRUE);
141}
142
b75a7d8f
A
143U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
144u_fopen(const char *filename,
145 const char *perm,
146 const char *locale,
147 const char *codepage)
148{
149 UFILE *result;
150 FILE *systemFile = fopen(filename, perm);
151 if(systemFile == 0) {
152 return 0;
153 }
154
729e4ab9 155 result = finit_owner(systemFile, locale, codepage, TRUE);
b75a7d8f 156
729e4ab9 157 if (!result) {
374ca955
A
158 /* Something bad happened.
159 Maybe the converter couldn't be opened. */
160 fclose(systemFile);
161 }
b75a7d8f 162
4388f060 163 return result; /* not a file leak */
b75a7d8f
A
164}
165
b331163b
A
166U_CAPI UFILE* U_EXPORT2
167u_fopen_u(const UChar *filename,
168 const char *perm,
169 const char *locale,
170 const char *codepage)
171{
172 UFILE *result;
173 char buffer[256];
174
175 u_austrcpy(buffer, filename);
176
177 result = u_fopen(buffer, perm, locale, codepage);
178#if U_PLATFORM_USES_ONLY_WIN32_API
179 /* Try Windows API _wfopen if the above fails. */
180 if (!result) {
181 FILE *systemFile = _wfopen(filename, (UChar*)perm);
182 if (systemFile) {
183 result = finit_owner(systemFile, locale, codepage, TRUE);
184 }
185 if (!result) {
186 /* Something bad happened.
187 Maybe the converter couldn't be opened. */
188 fclose(systemFile);
189 }
190 }
191#endif
192 return result; /* not a file leak */
193}
194
374ca955
A
195U_CAPI UFILE* U_EXPORT2
196u_fstropen(UChar *stringBuf,
197 int32_t capacity,
198 const char *locale)
b75a7d8f 199{
374ca955
A
200 UFILE *result;
201
202 if (capacity < 0) {
203 return NULL;
b75a7d8f
A
204 }
205
374ca955 206 result = (UFILE*) uprv_malloc(sizeof(UFILE));
46f4442e
A
207 /* Null pointer test */
208 if (result == NULL) {
209 return NULL; /* Just get out. */
210 }
b75a7d8f 211 uprv_memset(result, 0, sizeof(UFILE));
374ca955
A
212 result->str.fBuffer = stringBuf;
213 result->str.fPos = stringBuf;
214 result->str.fLimit = stringBuf+capacity;
b75a7d8f 215
b75a7d8f 216#if !UCONFIG_NO_FORMATTING
374ca955 217 /* if locale is 0, use the default */
374ca955
A
218 if(u_locbund_init(&result->str.fBundle, locale) == 0) {
219 /* DO NOT FCLOSE HERE! */
220 uprv_free(result);
221 return 0;
b75a7d8f 222 }
374ca955
A
223#endif
224
b75a7d8f
A
225 return result;
226}
227
374ca955
A
228U_CAPI UBool U_EXPORT2
229u_feof(UFILE *f)
230{
231 UBool endOfBuffer;
232 if (f == NULL) {
233 return TRUE;
234 }
235 endOfBuffer = (UBool)(f->str.fPos >= f->str.fLimit);
236 if (f->fFile != NULL) {
237 return endOfBuffer && feof(f->fFile);
238 }
239 return endOfBuffer;
240}
b75a7d8f
A
241
242U_CAPI void U_EXPORT2
243u_fflush(UFILE *file)
244{
374ca955 245 ufile_flush_translit(file);
729e4ab9 246 ufile_flush_io(file);
374ca955
A
247 if (file->fFile) {
248 fflush(file->fFile);
249 }
250 else if (file->str.fPos < file->str.fLimit) {
251 *(file->str.fPos++) = 0;
252 }
253 /* TODO: flush input */
254}
255
256U_CAPI void
257u_frewind(UFILE *file)
258{
259 u_fflush(file);
260 ucnv_reset(file->fConverter);
261 if (file->fFile) {
262 rewind(file->fFile);
263 file->str.fLimit = file->fUCBuffer;
264 file->str.fPos = file->fUCBuffer;
265 }
266 else {
267 file->str.fPos = file->str.fBuffer;
268 }
b75a7d8f
A
269}
270
271U_CAPI void U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
272u_fclose(UFILE *file)
273{
729e4ab9
A
274 if (file) {
275 u_fflush(file);
276 ufile_close_translit(file);
b75a7d8f 277
729e4ab9
A
278 if(file->fOwnFile)
279 fclose(file->fFile);
b75a7d8f
A
280
281#if !UCONFIG_NO_FORMATTING
729e4ab9 282 u_locbund_close(&file->str.fBundle);
b75a7d8f
A
283#endif
284
729e4ab9
A
285 ucnv_close(file->fConverter);
286 uprv_free(file);
287 }
b75a7d8f
A
288}
289
290U_CAPI FILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
291u_fgetfile( UFILE *f)
292{
293 return f->fFile;
294}
295
296#if !UCONFIG_NO_FORMATTING
297
298U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
299u_fgetlocale( UFILE *file)
300{
374ca955 301 return file->str.fBundle.fLocale;
b75a7d8f
A
302}
303
304U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
374ca955
A
305u_fsetlocale(UFILE *file,
306 const char *locale)
b75a7d8f 307{
374ca955 308 u_locbund_close(&file->str.fBundle);
b75a7d8f 309
374ca955 310 return u_locbund_init(&file->str.fBundle, locale) == 0 ? -1 : 0;
b75a7d8f
A
311}
312
313#endif
314
315U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
316u_fgetcodepage(UFILE *file)
317{
318 UErrorCode status = U_ZERO_ERROR;
319 const char *codepage = NULL;
320
321 if (file->fConverter) {
322 codepage = ucnv_getName(file->fConverter, &status);
323 if(U_FAILURE(status))
324 return 0;
325 }
326 return codepage;
327}
328
329U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
330u_fsetcodepage( const char *codepage,
331 UFILE *file)
332{
333 UErrorCode status = U_ZERO_ERROR;
374ca955
A
334 int32_t retVal = -1;
335
336 /* We use the normal default codepage for this system, and not the one for the locale. */
337 if ((file->str.fPos == file->str.fBuffer) && (file->str.fLimit == file->str.fBuffer)) {
338 ucnv_close(file->fConverter);
339 file->fConverter = ucnv_open(codepage, &status);
340 if(U_SUCCESS(status)) {
341 retVal = 0;
342 }
b75a7d8f 343 }
374ca955 344 return retVal;
b75a7d8f
A
345}
346
347
348U_CAPI UConverter * U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
349u_fgetConverter(UFILE *file)
350{
351 return file->fConverter;
352}
51004dcb
A
353#if !UCONFIG_NO_FORMATTING
354U_CAPI const UNumberFormat* U_EXPORT2 u_fgetNumberFormat(UFILE *file)
355{
356 return u_locbund_getNumberFormat(&file->str.fBundle, UNUM_DECIMAL);
357}
358#endif
374ca955 359
b331163b 360#endif