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