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