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