michael@0: /* michael@0: ****************************************************************************** michael@0: * michael@0: * Copyright (C) 1998-2013, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: * michael@0: ****************************************************************************** michael@0: * michael@0: * File ufile.c michael@0: * michael@0: * Modification History: michael@0: * michael@0: * Date Name Description michael@0: * 11/19/98 stephen Creation. michael@0: * 03/12/99 stephen Modified for new C API. michael@0: * 06/16/99 stephen Changed T_LocaleBundle to u_locbund michael@0: * 07/19/99 stephen Fixed to use ucnv's default codepage. michael@0: ****************************************************************************** michael@0: */ michael@0: michael@0: /* michael@0: * fileno is not declared when building with GCC in strict mode. michael@0: */ michael@0: #if defined(__GNUC__) && defined(__STRICT_ANSI__) michael@0: #undef __STRICT_ANSI__ michael@0: #endif michael@0: michael@0: #include "locmap.h" michael@0: #include "unicode/ustdio.h" michael@0: #include "ufile.h" michael@0: #include "unicode/uloc.h" michael@0: #include "unicode/ures.h" michael@0: #include "unicode/ucnv.h" michael@0: #include "cstring.h" michael@0: #include "cmemory.h" michael@0: michael@0: #if U_PLATFORM_USES_ONLY_WIN32_API && !defined(fileno) michael@0: /* Windows likes to rename Unix-like functions */ michael@0: #define fileno _fileno michael@0: #endif michael@0: michael@0: static UFILE* michael@0: finit_owner(FILE *f, michael@0: const char *locale, michael@0: const char *codepage, michael@0: UBool take michael@0: ) michael@0: { michael@0: UErrorCode status = U_ZERO_ERROR; michael@0: UFILE *result; michael@0: if(f == NULL) { michael@0: return 0; michael@0: } michael@0: result = (UFILE*) uprv_malloc(sizeof(UFILE)); michael@0: if(result == NULL) { michael@0: return 0; michael@0: } michael@0: michael@0: uprv_memset(result, 0, sizeof(UFILE)); michael@0: result->fFileno = fileno(f); michael@0: michael@0: #if U_PLATFORM_USES_ONLY_WIN32_API michael@0: if (0 <= result->fFileno && result->fFileno <= 2) { michael@0: /* stdin, stdout and stderr need to be special cased for Windows 98 */ michael@0: #if _MSC_VER >= 1400 michael@0: result->fFile = &__iob_func()[_fileno(f)]; michael@0: #else michael@0: result->fFile = &_iob[_fileno(f)]; michael@0: #endif michael@0: } michael@0: else michael@0: #endif michael@0: { michael@0: result->fFile = f; michael@0: } michael@0: michael@0: result->str.fBuffer = result->fUCBuffer; michael@0: result->str.fPos = result->fUCBuffer; michael@0: result->str.fLimit = result->fUCBuffer; michael@0: michael@0: #if !UCONFIG_NO_FORMATTING michael@0: /* if locale is 0, use the default */ michael@0: if(u_locbund_init(&result->str.fBundle, locale) == 0) { michael@0: /* DO NOT FCLOSE HERE! */ michael@0: uprv_free(result); michael@0: return 0; michael@0: } michael@0: #endif michael@0: michael@0: /* If the codepage is not "" use the ucnv_open default behavior */ michael@0: if(codepage == NULL || *codepage != '\0') { michael@0: result->fConverter = ucnv_open(codepage, &status); michael@0: } michael@0: /* else result->fConverter is already memset'd to NULL. */ michael@0: michael@0: if(U_SUCCESS(status)) { michael@0: result->fOwnFile = take; michael@0: } michael@0: else { michael@0: #if !UCONFIG_NO_FORMATTING michael@0: u_locbund_close(&result->str.fBundle); michael@0: #endif michael@0: /* DO NOT fclose here!!!!!! */ michael@0: uprv_free(result); michael@0: result = NULL; michael@0: } michael@0: michael@0: return result; michael@0: } michael@0: michael@0: U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ michael@0: u_finit(FILE *f, michael@0: const char *locale, michael@0: const char *codepage) michael@0: { michael@0: return finit_owner(f, locale, codepage, FALSE); michael@0: } michael@0: michael@0: U_CAPI UFILE* U_EXPORT2 michael@0: u_fadopt(FILE *f, michael@0: const char *locale, michael@0: const char *codepage) michael@0: { michael@0: return finit_owner(f, locale, codepage, TRUE); michael@0: } michael@0: michael@0: U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ michael@0: u_fopen(const char *filename, michael@0: const char *perm, michael@0: const char *locale, michael@0: const char *codepage) michael@0: { michael@0: UFILE *result; michael@0: FILE *systemFile = fopen(filename, perm); michael@0: if(systemFile == 0) { michael@0: return 0; michael@0: } michael@0: michael@0: result = finit_owner(systemFile, locale, codepage, TRUE); michael@0: michael@0: if (!result) { michael@0: /* Something bad happened. michael@0: Maybe the converter couldn't be opened. */ michael@0: fclose(systemFile); michael@0: } michael@0: michael@0: return result; /* not a file leak */ michael@0: } michael@0: michael@0: U_CAPI UFILE* U_EXPORT2 michael@0: u_fstropen(UChar *stringBuf, michael@0: int32_t capacity, michael@0: const char *locale) michael@0: { michael@0: UFILE *result; michael@0: michael@0: if (capacity < 0) { michael@0: return NULL; michael@0: } michael@0: michael@0: result = (UFILE*) uprv_malloc(sizeof(UFILE)); michael@0: /* Null pointer test */ michael@0: if (result == NULL) { michael@0: return NULL; /* Just get out. */ michael@0: } michael@0: uprv_memset(result, 0, sizeof(UFILE)); michael@0: result->str.fBuffer = stringBuf; michael@0: result->str.fPos = stringBuf; michael@0: result->str.fLimit = stringBuf+capacity; michael@0: michael@0: #if !UCONFIG_NO_FORMATTING michael@0: /* if locale is 0, use the default */ michael@0: if(u_locbund_init(&result->str.fBundle, locale) == 0) { michael@0: /* DO NOT FCLOSE HERE! */ michael@0: uprv_free(result); michael@0: return 0; michael@0: } michael@0: #endif michael@0: michael@0: return result; michael@0: } michael@0: michael@0: U_CAPI UBool U_EXPORT2 michael@0: u_feof(UFILE *f) michael@0: { michael@0: UBool endOfBuffer; michael@0: if (f == NULL) { michael@0: return TRUE; michael@0: } michael@0: endOfBuffer = (UBool)(f->str.fPos >= f->str.fLimit); michael@0: if (f->fFile != NULL) { michael@0: return endOfBuffer && feof(f->fFile); michael@0: } michael@0: return endOfBuffer; michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: u_fflush(UFILE *file) michael@0: { michael@0: ufile_flush_translit(file); michael@0: ufile_flush_io(file); michael@0: if (file->fFile) { michael@0: fflush(file->fFile); michael@0: } michael@0: else if (file->str.fPos < file->str.fLimit) { michael@0: *(file->str.fPos++) = 0; michael@0: } michael@0: /* TODO: flush input */ michael@0: } michael@0: michael@0: U_CAPI void michael@0: u_frewind(UFILE *file) michael@0: { michael@0: u_fflush(file); michael@0: ucnv_reset(file->fConverter); michael@0: if (file->fFile) { michael@0: rewind(file->fFile); michael@0: file->str.fLimit = file->fUCBuffer; michael@0: file->str.fPos = file->fUCBuffer; michael@0: } michael@0: else { michael@0: file->str.fPos = file->str.fBuffer; michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ michael@0: u_fclose(UFILE *file) michael@0: { michael@0: if (file) { michael@0: u_fflush(file); michael@0: ufile_close_translit(file); michael@0: michael@0: if(file->fOwnFile) michael@0: fclose(file->fFile); michael@0: michael@0: #if !UCONFIG_NO_FORMATTING michael@0: u_locbund_close(&file->str.fBundle); michael@0: #endif michael@0: michael@0: ucnv_close(file->fConverter); michael@0: uprv_free(file); michael@0: } michael@0: } michael@0: michael@0: U_CAPI FILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ michael@0: u_fgetfile( UFILE *f) michael@0: { michael@0: return f->fFile; michael@0: } michael@0: michael@0: #if !UCONFIG_NO_FORMATTING michael@0: michael@0: U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ michael@0: u_fgetlocale( UFILE *file) michael@0: { michael@0: return file->str.fBundle.fLocale; michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ michael@0: u_fsetlocale(UFILE *file, michael@0: const char *locale) michael@0: { michael@0: u_locbund_close(&file->str.fBundle); michael@0: michael@0: return u_locbund_init(&file->str.fBundle, locale) == 0 ? -1 : 0; michael@0: } michael@0: michael@0: #endif michael@0: michael@0: U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ michael@0: u_fgetcodepage(UFILE *file) michael@0: { michael@0: UErrorCode status = U_ZERO_ERROR; michael@0: const char *codepage = NULL; michael@0: michael@0: if (file->fConverter) { michael@0: codepage = ucnv_getName(file->fConverter, &status); michael@0: if(U_FAILURE(status)) michael@0: return 0; michael@0: } michael@0: return codepage; michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ michael@0: u_fsetcodepage( const char *codepage, michael@0: UFILE *file) michael@0: { michael@0: UErrorCode status = U_ZERO_ERROR; michael@0: int32_t retVal = -1; michael@0: michael@0: /* We use the normal default codepage for this system, and not the one for the locale. */ michael@0: if ((file->str.fPos == file->str.fBuffer) && (file->str.fLimit == file->str.fBuffer)) { michael@0: ucnv_close(file->fConverter); michael@0: file->fConverter = ucnv_open(codepage, &status); michael@0: if(U_SUCCESS(status)) { michael@0: retVal = 0; michael@0: } michael@0: } michael@0: return retVal; michael@0: } michael@0: michael@0: michael@0: U_CAPI UConverter * U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ michael@0: u_fgetConverter(UFILE *file) michael@0: { michael@0: return file->fConverter; michael@0: } michael@0: #if !UCONFIG_NO_FORMATTING michael@0: U_CAPI const UNumberFormat* U_EXPORT2 u_fgetNumberFormat(UFILE *file) michael@0: { michael@0: return u_locbund_getNumberFormat(&file->str.fBundle, UNUM_DECIMAL); michael@0: } michael@0: #endif michael@0: