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