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