Home | History | Annotate | Download | only in io
      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