diff options
author | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2011-03-28 06:59:20 -0400 |
---|---|---|
committer | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2011-03-28 06:59:20 -0400 |
commit | 15cf835cc555018bed865071cb9f5bcdb6b75060 (patch) | |
tree | 69c3312f104e2ff1a60255b63fc7f6ae34cae494 /libarchive/archive_read_support_format_cab.c | |
parent | f74c5f05faccec9b0946faa3f3fbe41fab276a26 (diff) | |
download | libarchive-15cf835cc555018bed865071cb9f5bcdb6b75060.tar.gz |
Improve character-set conversion functions.
- Change the interface in order to reduece the comparison of
charset names. Previous version always did it when the functions
were called; it was very inefficient. So I have made a conversion
object, struct archive_string_conv, to resolve that issue.
- Integrate *_from_charset and *_to_charset into *_in_locale because
of above.
- Integrate *_from_utf16be and *_to_utf16be into *in_locale.
- On Windows, Make a codepage from a charset name to know whether
current codepage and specified charset are the same or not.
SVN-Revision: 3108
Diffstat (limited to 'libarchive/archive_read_support_format_cab.c')
-rw-r--r-- | libarchive/archive_read_support_format_cab.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index f1f80de6..5628b9db 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -290,7 +290,8 @@ struct cab { unsigned char *uncompressed_buffer; size_t uncompressed_buffer_size; - char *charset; + struct archive_string_conv *sconv; + struct archive_string_conv *sconv_utf8; char format_name[64]; #ifdef HAVE_ZLIB_H @@ -458,12 +459,14 @@ archive_read_format_cab_options(struct archive_read *a, if (val == NULL || val[0] == 0) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "cab: charset option needs a character-set name"); - else if (archive_string_conversion_from_charset( - &a->archive, val) == 0) { - cab->charset = strdup(val); - ret = ARCHIVE_OK; - } else - ret = ARCHIVE_FATAL; + else { + cab->sconv = archive_string_conversion_from_charset( + &a->archive, val, 0); + if (cab->sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } } else archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "cab: unknown keyword ``%s''", key); @@ -792,12 +795,16 @@ cab_read_header(struct archive_read *a) if ((len = cab_strnlen(p, avail-1)) <= 0) goto invalid; archive_string_init(&(file->pathname)); - if ((file->attr & ATTR_NAME_IS_UTF) && cab->charset == NULL) - archive_strncpy_from_locale(&a->archive, - &(file->pathname), p, len, "UTF-8"); - else - archive_strncpy_from_locale(&a->archive, - &(file->pathname), p, len, cab->charset); + if ((file->attr & ATTR_NAME_IS_UTF) && cab->sconv == NULL) { + if (cab->sconv_utf8 == NULL) + cab->sconv_utf8 = + archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + archive_strncpy_in_locale(&(file->pathname), p, len, + cab->sconv_utf8); + } else + archive_strncpy_in_locale(&(file->pathname), p, + len, cab->sconv); __archive_read_consume(a, len + 1); cab->cab_offset += len + 1; /* Convert a path separator '\' -> '/' */ @@ -1970,7 +1977,6 @@ archive_read_format_cab_cleanup(struct archive_read *a) archive_wstring_free(&cab->ws); archive_string_free(&cab->mbs); free(cab->uncompressed_buffer); - free(cab->charset); free(cab); (a->format->data) = NULL; return (ARCHIVE_OK); |