| /* |
| ****************************************************************************** |
| * |
| * Copyright (C) 1998-2001, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| * |
| ****************************************************************************** |
| * |
| * File ufile.c |
| * |
| * Modification History: |
| * |
| * Date Name Description |
| * 11/19/98 stephen Creation. |
| * 03/12/99 stephen Modified for new C API. |
| * 06/16/99 stephen Changed T_LocaleBundle to u_locbund |
| * 07/19/99 stephen Fixed to use ucnv's default codepage. |
| ****************************************************************************** |
| */ |
| |
| #include "uhash.h" |
| #include "unicode/ustdio.h" |
| #include "ufile.h" |
| #include "unicode/uloc.h" |
| #include "loccache.h" |
| #include "unicode/ures.h" |
| #include "unicode/ucnv.h" |
| |
| #include <string.h> |
| #include <stdlib.h> |
| |
| |
| /* the data in the following two functions should REALLY be somewhere else */ |
| /* convert from a country code (only the first 2 chars are significant) */ |
| /* to an IBM codepage */ |
| |
| /* TODO: We should consider using uprv_defaultCodePageForLocale() instead of this table |
| (less to maintain when the ISO-639 standard changes */ |
| |
| /* thanks to http://czyborra.com/charsets/iso8859.htm for most of this info */ |
| static const char *ufile_locale2codepage[] = { |
| "af", "latin-1", /* Afrikaans */ |
| "ar", "ibm-1256", /* arabic */ |
| |
| "be", "ibm-915" , /* Byelorussian */ |
| "bg", "ibm-915" , /* Bulgarian */ |
| |
| "ca", "latin-1" , /* catalan */ |
| "cs", "ibm-912" , /* Czech */ |
| |
| "da", "latin-1" , /* danish */ |
| "de", "latin-1" , /* german */ |
| |
| "el", "ibm-813" , /* Greek */ |
| "en", "latin-1" , /* English */ |
| "eo", "ibm-913" , /* Esperanto */ |
| "es", "latin-1" , /* Spanish */ |
| "eu", "latin-1" , /* basque */ |
| "et", "ibm-914" , /* Estonian */ |
| |
| "fi", "latin-1" , /* Finnish */ |
| "fo", "latin-1" , /* faroese */ |
| "fr", "latin-1" , /* French */ |
| |
| "ga", "latin-1" , /* Irish (Gaelic) */ |
| "gd", "latin-1" , /* Scottish */ |
| |
| "hr", "ibm-912" , /* Croatian */ |
| "hu", "ibm-912" , /* Hungarian */ |
| |
| "in", "latin-1" , /* Indonesian */ |
| "is", "latin-1" , /* Icelandic */ |
| "it", "latin-1" , /* Italian */ |
| "iw", "ibm-916", /* hebrew */ |
| |
| "ja", "ibm-943", /* Japanese */ |
| "ji", "ibm-916", /* Yiddish */ |
| |
| "kl", "ibm-914", /* Greenlandic */ |
| "ko", "ibm-949", /* korean */ |
| |
| "lt", "ibm-914", /* Lithuanian */ |
| "lv", "ibm-914", /* latvian (lettish) */ |
| |
| "mk", "ibm-915" , /* Macedonian */ |
| "mt", "ibm-1208" , /* Maltese [UTF8] */ |
| |
| "nl", "latin-1" , /* dutch */ |
| "no", "latin-1" , /* Norwegian */ |
| |
| "pl", "ibm-912" , /* Polish */ |
| "pt", "latin-1" , /* Portugese */ |
| |
| "rm", "latin-1" , /* Rhaeto-romanic (?) */ |
| "ro", "ibm-912" , /* Romanian */ |
| "ru", "ibm-878" , /* Russian */ |
| |
| "sk", "ibm-912" , /* Slovak */ |
| |
| "sl", "ibm-912" , /* Slovenian */ |
| "sq", "latin-1" , /* albanian */ |
| "sr", "ibm-915" , /* Serbian */ |
| "sv", "latin-1" , /* Swedish */ |
| "sw", "latin-1" , /* Swahili */ |
| |
| "th", "ibm-1208" , /* Thai - UTF8 */ |
| |
| "tr", "ibm-920", /* Turkish */ |
| |
| "uk", "ibm-915" , /* pre 1990 Ukranian (?) */ |
| |
| "zh", "Big-5", /* Chinese */ |
| 0, 0 |
| }; |
| |
| static const char* |
| ufile_lookup_codepage(const char *locale) |
| { |
| int32_t i; |
| for(i = 0; ufile_locale2codepage[i]; i+= 2) |
| if( ! strncmp(ufile_locale2codepage[i], locale, 2)) |
| return ufile_locale2codepage[i + 1]; |
| return 0; |
| } |
| |
| static UBool hasICUData(const char *cp) { |
| UErrorCode status = U_ZERO_ERROR; |
| UConverter *cnv = NULL; |
| #if 0 |
| UResourceBundle *r = NULL; |
| |
| r = ures_open(NULL, NULL, &status); |
| if(U_FAILURE(status)) { |
| return FALSE; |
| } else { |
| ures_close(r); |
| } |
| #endif |
| cnv = ucnv_open(cp, &status); |
| if(cnv == NULL) { |
| return FALSE; |
| } else { |
| ucnv_close(cnv); |
| } |
| |
| return TRUE; |
| } |
| |
| |
| |
| UFILE* |
| u_fopen(const char *filename, |
| const char *perm, |
| const char *locale, |
| const char *codepage) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| UBool useSysCP = (UBool)(locale == 0 && codepage == 0); |
| UFILE *result = (UFILE*) malloc(sizeof(UFILE)); |
| if(result == 0) |
| return 0; |
| |
| result->fFile = fopen(filename, perm); |
| if(result->fFile == 0) { |
| free(result); |
| return 0; |
| } |
| |
| result->fOwnFile = TRUE; |
| |
| /* if locale is 0, use the default */ |
| if(locale == 0) |
| locale = uloc_getDefault(); |
| |
| result->fBundle = u_loccache_get(locale); |
| if(result->fBundle == 0) { |
| fclose(result->fFile); |
| free(result); |
| return 0; |
| } |
| |
| result->fOwnBundle = FALSE; |
| result->fUCPos = result->fUCBuffer; |
| result->fUCLimit = result->fUCBuffer; |
| |
| /* if the codepage is 0, use the default for the locale */ |
| if(codepage == 0) { |
| codepage = ufile_lookup_codepage(locale); |
| |
| /* if the codepage is still 0, the default codepage will be used */ |
| } |
| |
| /* if both locale and codepage are 0, use the system default codepage */ |
| else if(useSysCP) |
| codepage = 0; |
| |
| result->fConverter = ucnv_open(codepage, &status); |
| if(U_FAILURE(status) || result->fConverter == 0) { |
| fclose(result->fFile); |
| free(result); |
| return 0; |
| } |
| |
| return result; |
| } |
| |
| UFILE* |
| u_finit(FILE *f, |
| const char *locale, |
| const char *codepage) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| UBool useSysCP = (UBool)(locale == NULL && codepage == NULL); |
| UFILE *result = (UFILE*) malloc(sizeof(UFILE)); |
| if(result == 0) |
| return 0; |
| |
| |
| #ifdef WIN32 |
| result->fFile = &_iob[_fileno(f)]; |
| #else |
| result->fFile = f; |
| #endif |
| result->fOwnFile = FALSE; |
| result->fOwnBundle = FALSE; |
| result->fUCPos = result->fUCBuffer; |
| result->fUCLimit = result->fUCBuffer; |
| result->fConverter = NULL; |
| result->fBundle = NULL; |
| |
| if(hasICUData(codepage) == TRUE) { |
| /* if locale is 0, use the default */ |
| if(locale == 0) |
| locale = uloc_getDefault(); |
| |
| result->fBundle = u_loccache_get(locale); |
| if(result->fBundle == 0) { |
| /* DO NOT FCLOSE HERE! */ |
| free(result); |
| return 0; |
| } |
| } else { |
| /* bootstrap mode */ |
| return result; |
| } |
| |
| /* if the codepage is 0, use the default for the locale */ |
| if(codepage == 0) { |
| codepage = ufile_lookup_codepage(locale); |
| |
| |
| |
| /* if the codepage is still 0, the default codepage will be used */ |
| if(codepage == 0) { |
| result->fConverter = ucnv_open(0, &status); |
| if(U_FAILURE(status) || result->fConverter == 0) { |
| /* DO NOT fclose here!!!!!! */ |
| free(result); |
| return 0; |
| } |
| } |
| } else if (*codepage != '\0') { |
| result->fConverter = ucnv_open(codepage, &status); |
| if(U_FAILURE(status) || result->fConverter == 0) { |
| /* DO NOT fclose here!!!!!! */ |
| free(result); |
| return 0; |
| } |
| } else if(useSysCP) { /* if both locale and codepage are 0, use the system default codepage */ |
| codepage = 0; |
| } |
| return result; |
| } |
| |
| void |
| u_fclose(UFILE *file) |
| { |
| fflush(file->fFile); |
| |
| if(file->fOwnFile) |
| fclose(file->fFile); |
| |
| if(file->fOwnBundle) |
| u_locbund_delete(file->fBundle); |
| |
| ucnv_close(file->fConverter); |
| |
| free(file); |
| } |
| |
| FILE* |
| u_fgetfile( UFILE *f) |
| { |
| return f->fFile; |
| } |
| |
| const char* |
| u_fgetlocale( UFILE *file) |
| { |
| return file->fBundle->fLocale; |
| } |
| |
| int32_t |
| u_fsetlocale(const char *locale, |
| UFILE *file) |
| { |
| if(file->fOwnBundle) |
| u_locbund_delete(file->fBundle); |
| |
| file->fBundle = u_loccache_get(locale); |
| file->fOwnBundle = FALSE; |
| |
| return file->fBundle == 0 ? -1 : 0; |
| } |
| |
| const char* |
| u_fgetcodepage(UFILE *file) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| const char *codepage; |
| |
| codepage = ucnv_getName(file->fConverter, &status); |
| if(U_FAILURE(status)) return 0; |
| return codepage; |
| } |
| |
| int32_t |
| u_fsetcodepage( const char *codepage, |
| UFILE *file) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| |
| /* if the codepage is 0, use the default for the locale */ |
| if(codepage == 0) { |
| codepage = ufile_lookup_codepage(file->fBundle->fLocale); |
| |
| /* if the codepage is still 0, fall back on the default codepage */ |
| } |
| |
| ucnv_close(file->fConverter); |
| file->fConverter = ucnv_open(codepage, &status); |
| if(U_FAILURE(status)) |
| return -1; |
| return 0; |
| } |
| |
| |
| UConverter * u_fgetConverter(UFILE *file) |
| { |
| return file->fConverter; |
| } |