diff options
author | John Mark Bell <jmb@netsurf-browser.org> | 2009-01-05 23:49:51 +0000 |
---|---|---|
committer | John Mark Bell <jmb@netsurf-browser.org> | 2009-01-05 23:49:51 +0000 |
commit | ce231ac3f456d2e92730d344cda1578eaf1d8add (patch) | |
tree | ad227ae870e2ce38beae910b159de41f79e7d842 /src | |
parent | 5946e302829ff1ebd4905dbf2fa8021ed24cbedc (diff) | |
download | iconv-ce231ac3f456d2e92730d344cda1578eaf1d8add.tar.gz iconv-ce231ac3f456d2e92730d344cda1578eaf1d8add.tar.bz2 |
Improve error reporting from iconv_eightbit_new. This means we correctly return EINVAL if we can't find a mapping table, rather than assuming ENOMEM.
Bump version number while we're at it.
svn path=/trunk/iconv/; revision=5962
Diffstat (limited to 'src')
-rw-r--r-- | src/eightbit.c | 26 | ||||
-rw-r--r-- | src/iconv.c | 91 | ||||
-rw-r--r-- | src/internal.h | 7 |
3 files changed, 71 insertions, 53 deletions
diff --git a/src/eightbit.c b/src/eightbit.c index da1cd4b..f201f31 100644 --- a/src/eightbit.c +++ b/src/eightbit.c @@ -21,7 +21,7 @@ struct table_entry { /* Table should be ordered by enc_num */ static const struct table_entry mapping_table[] = { - { "US-ASCII", 0 }, + { "US-ASCII", NULL }, { "HP-ROMAN8", "HPR8" }, { "MACINTOSH", "Apple" DIR_SEP "Roman"}, { "IBM437", "Microsoft" DIR_SEP "CP437" }, @@ -224,9 +224,12 @@ int iconv_eightbit_write(struct encoding_context *e, UCS4 c, * Load an 8bit encoding * * \param enc_num The encoding number to load - * \return Pointer to lookup table for encoding, or NULL on error + * \param table Pointer to location to receive LUT + * \return EIGHTBIT_OK on success, + * _NOMEM on memory exhaustion, + * or _UNKNOWN if a LUT cannot be found. */ -unsigned short *iconv_eightbit_new(int enc_num) +eightbit_ret iconv_eightbit_new(int enc_num, unsigned short **table) { const char *filename = NULL; const char *name; @@ -237,13 +240,14 @@ unsigned short *iconv_eightbit_new(int enc_num) name = mibenum_to_name(enc_num); if (!name) - return NULL; + return EIGHTBIT_UNKNOWN; /* Lookup filename in table */ for (i = 0; i != TABLE_SIZE; i++) if (strcasecmp(mapping_table[i].canon, name) == 0) { - if (mapping_table[i].filename == 0) - return NULL; + /* Found in the map, but no LUT needed (i.e. ASCII) */ + if (mapping_table[i].filename == NULL) + return EIGHTBIT_OK; filename = get_table_path(mapping_table[i].filename); @@ -255,7 +259,7 @@ unsigned short *iconv_eightbit_new(int enc_num) /* Open */ fp = fopen(filename, "rb"); if (!fp) { - return NULL; + return EIGHTBIT_UNKNOWN; } /* Get extent */ @@ -266,21 +270,23 @@ unsigned short *iconv_eightbit_new(int enc_num) /* Unexpected length => give up */ if (len != 256) { fclose(fp); - return NULL; + return EIGHTBIT_UNKNOWN; } /* Create buffer */ ret = calloc(128, sizeof(short)); if (!ret) { fclose(fp); - return NULL; + return EIGHTBIT_NOMEM; } fread(ret, 128, sizeof(short), fp); fclose(fp); - return ret; + *table = ret; + + return EIGHTBIT_OK; } /** diff --git a/src/iconv.c b/src/iconv.c index dccd23b..45bd15f 100644 --- a/src/iconv.c +++ b/src/iconv.c @@ -67,6 +67,7 @@ iconv_t iconv_open(const char *tocode, const char *fromcode) char totemp[128], fromtemp[128]; const char *slash; unsigned int len; + eightbit_ret error; /* can't do anything without these */ if (!tocode || !fromcode) { @@ -184,60 +185,66 @@ iconv_t iconv_open(const char *tocode, const char *fromcode) } /* bit 30 set indicates that this is an 8bit encoding */ - if (from & (1<<30)) - e->intab = iconv_eightbit_new(from & ~(1<<30)); - else { + if (from & (1<<30)) { + error = iconv_eightbit_new(from & ~(1<<30), &e->intab); + if (error != EIGHTBIT_OK) { + free(e); + errno = (error == EIGHTBIT_NOMEM) ? ENOMEM : EINVAL; + return (iconv_t)(-1); + } + } else { e->in = encoding_new(from, encoding_READ); - if (e->in) { - /* Set encoding flags */ - unsigned int flags = 0; - if (from_force_le) - flags |= encoding_FLAG_LITTLE_ENDIAN; + if (e->in == NULL) { + free(e); + errno = ENOMEM; /* Assume memory exhaustion */ + return (iconv_t)(-1); + } - if (from == csUnicode || from_no_bom) - flags |= encoding_FLAG_NO_HEADER; + /* Set encoding flags */ + unsigned int flags = 0; + if (from_force_le) + flags |= encoding_FLAG_LITTLE_ENDIAN; - encoding_set_flags(e->in, flags, flags); + if (from == csUnicode || from_no_bom) + flags |= encoding_FLAG_NO_HEADER; - e->inflags = flags; - } - } + encoding_set_flags(e->in, flags, flags); - /* neither created => memory error or somesuch. assume ENOMEM */ - /* no table is ever generated for ASCII */ - if (!e->in && !e->intab && (from & ~(1<<30)) != csASCII) { - free(e); - errno = ENOMEM; - return (iconv_t)(-1); + e->inflags = flags; } - if (to & (1<<30)) - e->outtab = iconv_eightbit_new(to & ~(1<<30)); - else { + if (to & (1<<30)) { + error = iconv_eightbit_new(to & ~(1<<30), &e->outtab); + if (error != EIGHTBIT_OK) { + if (e->in) + encoding_delete(e->in); + iconv_eightbit_delete(e); + free(e); + errno = (error == EIGHTBIT_NOMEM) ? ENOMEM : EINVAL; + return (iconv_t)(-1); + } + } else { e->out = encoding_new(to, encoding_WRITE_STRICT); - if (e->out) { - /* Set encoding flags */ - unsigned int flags = 0; - if (to_force_le) - flags |= encoding_FLAG_LITTLE_ENDIAN; + if (e->out == NULL) { + if (e->in) + encoding_delete(e->in); + iconv_eightbit_delete(e); + free(e); + errno = ENOMEM; /* Assume memory exhaustion */ + return (iconv_t)(-1); + } - if (to == csUnicode || to_no_bom) - flags |= encoding_FLAG_NO_HEADER; + /* Set encoding flags */ + unsigned int flags = 0; + if (to_force_le) + flags |= encoding_FLAG_LITTLE_ENDIAN; - encoding_set_flags(e->out, flags, flags); + if (to == csUnicode || to_no_bom) + flags |= encoding_FLAG_NO_HEADER; - e->outflags = flags; - } - } + encoding_set_flags(e->out, flags, flags); - /* neither created => ENOMEM */ - if (!e->out && !e->outtab && (to & ~(1<<30)) != csASCII) { - if (e->in) - encoding_delete(e->in); - iconv_eightbit_delete(e); - free(e); - errno = ENOMEM; - return (iconv_t)(-1); + e->outflags = flags; } /* add to list */ diff --git a/src/internal.h b/src/internal.h index eb11589..42efefe 100644 --- a/src/internal.h +++ b/src/internal.h @@ -34,13 +34,18 @@ struct encoding_context { }; /* in eightbit.c */ +typedef enum eightbit_ret { + EIGHTBIT_OK, + EIGHTBIT_UNKNOWN, + EIGHTBIT_NOMEM +} eightbit_ret; int iconv_eightbit_number_from_name(const char *name); unsigned iconv_eightbit_read(struct encoding_context *e, int (*callback)(void *handle, UCS4 c), const char *s, unsigned int n, void *handle); int iconv_eightbit_write(struct encoding_context *e, UCS4 c, char **buf, int *bufsize); -unsigned short *iconv_eightbit_new(int enc_num); +eightbit_ret iconv_eightbit_new(int enc_num, unsigned short **table); void iconv_eightbit_delete(struct encoding_context *e); /* in alias.c */ |