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