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 42 static UFILE* 43 finit_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 111 U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 112 u_finit(FILE *f, 113 const char *locale, 114 const char *codepage) 115 { 116 return finit_owner(f, locale, codepage, FALSE); 117 } 118 119 U_CAPI UFILE* U_EXPORT2 120 u_fadopt(FILE *f, 121 const char *locale, 122 const char *codepage) 123 { 124 return finit_owner(f, locale, codepage, TRUE); 125 } 126 127 U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 128 u_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 150 U_CAPI UFILE* U_EXPORT2 151 u_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 183 U_CAPI UBool U_EXPORT2 184 u_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 197 U_CAPI void U_EXPORT2 198 u_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 211 U_CAPI void 212 u_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 226 U_CAPI void U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 227 u_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 245 U_CAPI FILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 246 u_fgetfile( UFILE *f) 247 { 248 return f->fFile; 249 } 250 251 #if !UCONFIG_NO_FORMATTING 252 253 U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 254 u_fgetlocale( UFILE *file) 255 { 256 return file->str.fBundle.fLocale; 257 } 258 259 U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 260 u_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 270 U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 271 u_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 284 U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 285 u_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 303 U_CAPI UConverter * U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 304 u_fgetConverter(UFILE *file) 305 { 306 return file->fConverter; 307 } 308 #if !UCONFIG_NO_FORMATTING 309 U_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