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