blob: 1d8c221cdcbf85026029bf58d31126b89b494bfa [file] [log] [blame]
Jungshik Shin87232d82017-05-13 21:10:13 -07001// © 2016 and later: Unicode, Inc. and others.
Jungshik Shin5feb9ad2016-10-21 12:52:48 -07002// License & terms of use: http://www.unicode.org/copyright.html
jshin@chromium.org6f31ac32014-03-26 22:15:14 +00003/*
4******************************************************************************
5*
Jungshik Shin70f82502016-01-29 00:32:36 -08006* Copyright (C) 1998-2015, International Business Machines
jshin@chromium.org6f31ac32014-03-26 22:15:14 +00007* Corporation and others. All Rights Reserved.
8*
9******************************************************************************
10*
Jungshik Shin87232d82017-05-13 21:10:13 -070011* File ufile.cpp
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000012*
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
Jungshik Shin87232d82017-05-13 21:10:13 -070023#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.
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000028#undef __STRICT_ANSI__
29#endif
30
31#include "locmap.h"
32#include "unicode/ustdio.h"
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080033
34#if !UCONFIG_NO_CONVERSION
35
Jungshik Shin87232d82017-05-13 21:10:13 -070036#include <stdlib.h>
37
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000038#include "ufile.h"
39#include "unicode/uloc.h"
40#include "unicode/ures.h"
41#include "unicode/ucnv.h"
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080042#include "unicode/ustring.h"
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000043#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
51static UFILE*
52finit_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);
Jungshik Shin87232d82017-05-13 21:10:13 -070070 result->fFile = f;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000071
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
106U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
107u_finit(FILE *f,
108 const char *locale,
109 const char *codepage)
110{
111 return finit_owner(f, locale, codepage, FALSE);
112}
113
114U_CAPI UFILE* U_EXPORT2
115u_fadopt(FILE *f,
116 const char *locale,
117 const char *codepage)
118{
119 return finit_owner(f, locale, codepage, TRUE);
120}
121
122U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
123u_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
145U_CAPI UFILE* U_EXPORT2
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800146u_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) {
Jungshik Shin87232d82017-05-13 21:10:13 -0700160 // TODO: test this code path, including wperm.
161 wchar_t wperm[40] = {};
162 size_t retVal;
Jungshik Shinb3189662017-11-07 11:18:34 -0800163 mbstowcs_s(&retVal, wperm, UPRV_LENGTHOF(wperm), perm, _TRUNCATE);
Jungshik Shin87232d82017-05-13 21:10:13 -0700164 FILE *systemFile = _wfopen((const wchar_t *)filename, wperm);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800165 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
178U_CAPI UFILE* U_EXPORT2
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000179u_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) {
Jungshik Shin87232d82017-05-13 21:10:13 -0700192 return NULL; /* Just get out. */
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000193 }
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
211U_CAPI UBool U_EXPORT2
212u_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
225U_CAPI void U_EXPORT2
226u_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
239U_CAPI void
240u_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
254U_CAPI void U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
255u_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
273U_CAPI FILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
274u_fgetfile( UFILE *f)
275{
276 return f->fFile;
277}
278
279#if !UCONFIG_NO_FORMATTING
280
281U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
282u_fgetlocale( UFILE *file)
283{
284 return file->str.fBundle.fLocale;
285}
286
287U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
288u_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
298U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
299u_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
312U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
313u_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
331U_CAPI UConverter * U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
332u_fgetConverter(UFILE *file)
333{
334 return file->fConverter;
335}
336#if !UCONFIG_NO_FORMATTING
337U_CAPI const UNumberFormat* U_EXPORT2 u_fgetNumberFormat(UFILE *file)
338{
339 return u_locbund_getNumberFormat(&file->str.fBundle, UNUM_DECIMAL);
340}
341#endif
342
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800343#endif