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 45 static UFILE* 46 finit_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 114 U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 115 u_finit(FILE *f, 116 const char *locale, 117 const char *codepage) 118 { 119 return finit_owner(f, locale, codepage, FALSE); 120 } 121 122 U_CAPI UFILE* U_EXPORT2 123 u_fadopt(FILE *f, 124 const char *locale, 125 const char *codepage) 126 { 127 return finit_owner(f, locale, codepage, TRUE); 128 } 129 130 U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 131 u_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 153 U_CAPI UFILE* U_EXPORT2 154 u_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 186 U_CAPI UBool U_EXPORT2 187 u_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 200 U_CAPI void U_EXPORT2 201 u_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 214 U_CAPI void 215 u_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 229 U_CAPI void U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 230 u_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 248 U_CAPI FILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 249 u_fgetfile( UFILE *f) 250 { 251 return f->fFile; 252 } 253 254 #if !UCONFIG_NO_FORMATTING 255 256 U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 257 u_fgetlocale( UFILE *file) 258 { 259 return file->str.fBundle.fLocale; 260 } 261 262 U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 263 u_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 273 U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 274 u_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 287 U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 288 u_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 306 U_CAPI UConverter * U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ 307 u_fgetConverter(UFILE *file) 308 { 309 return file->fConverter; 310 } 311 312