diff options
| author | 2016-12-22 07:02:23 -0500 | |
|---|---|---|
| committer | 2016-12-23 09:44:09 -0500 | |
| commit | 594d959f09ea3087b2903ed161e24cec67585796 (patch) | |
| tree | ee085c70778a29d320eb780d2c56c08446edfede /src/tools | |
| parent | 63b7b9d521712404dc35156ef8d7e606440b4156 (diff) | |
[Imgtool] Rewrote charconv; now an interface rather than an enumeration
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/imgtool/charconv.cpp | 186 | ||||
| -rw-r--r-- | src/tools/imgtool/charconv.h | 66 | ||||
| -rw-r--r-- | src/tools/imgtool/imgtool.cpp | 58 | ||||
| -rw-r--r-- | src/tools/imgtool/library.h | 3 | ||||
| -rw-r--r-- | src/tools/imgtool/modules/amiga.cpp | 2 |
5 files changed, 141 insertions, 174 deletions
diff --git a/src/tools/imgtool/charconv.cpp b/src/tools/imgtool/charconv.cpp index a57d15e1a73..89c5f01af56 100644 --- a/src/tools/imgtool/charconv.cpp +++ b/src/tools/imgtool/charconv.cpp @@ -2,7 +2,7 @@ // copyright-holders:Nathan Woods /*************************************************************************** - charconv.c + charconv.cpp Imgtool character set conversion routines. @@ -10,153 +10,83 @@ #include "corestr.h" #include "charconv.h" +#include "unicode.h" +#include "coretmpl.h" - -/*------------------------------------------------- - utf8_from_latin1 - convert an ISO-8859-1 - character sequence to an UTF-8 string --------------------------------------------------*/ - -static char *utf8_from_latin1(const char *src) +static const char32_t iso_8859_1_code_page[128] = { - char *buffer, *bufptr; - - /* validate input */ - if (!src) - { - return nullptr; - } - - /* allocate space for result, twice the source len to be safe */ - buffer = (char *) malloc(strlen(src) * 2 + 1); - - /* point to the start */ - bufptr = buffer; + // 0x80 - 0x8F + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // 0x90 - 0x9F + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // 0xA0 - 0xAF + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + // 0xB0 - 0xBF + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + // 0xC0 - 0xCF + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + // 0xD0 - 0xDF + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + // 0xE0 - 0xEF + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + // 0xF0 - 0xFF + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF +}; + +imgtool::simple_charconverter imgtool::charconverter_iso_8859_1(iso_8859_1_code_page); + + +//------------------------------------------------- +// from_utf8 +//------------------------------------------------- + +void imgtool::simple_charconverter::from_utf8(std::ostream &dest, const std::string &src) const +{ + const util::contiguous_sequence_wrapper<const char32_t> lookup(m_highpage, 0x80); - do + auto iter = src.begin(); + while(iter != src.end()) { - unsigned char c = *src; + char32_t ch; + iter += uchar_from_utf8(&ch, &*iter, src.end() - iter); - if (c < 0x80) - { - *bufptr++ = c; - } - else if (c < 0xc0) + if (ch <= 0x7F) { - *bufptr++ = '\xc2'; - *bufptr++ = c; + dest << (char)ch; } else { - *bufptr++ = '\xc3'; - *bufptr++ = c - 0x40; - } - } while (*src++); + auto lookup_iter = std::find(lookup.begin(), lookup.end(), ch); + if (lookup_iter == lookup.end()) + throw charconverter_exception(); - return buffer; + dest << (char)(0x80 + (lookup_iter - lookup.begin())); + } + } } -/*------------------------------------------------- - latin1_from_utf8 - convert an UTF-8 - character sequence to an ISO-8859-1 string --------------------------------------------------*/ +//------------------------------------------------- +// to_utf8 +//------------------------------------------------- -static char *latin1_from_utf8(const char *src) +void imgtool::simple_charconverter::to_utf8(std::ostream &dest, const std::string &src) const { - char *buffer, *bufptr; - - /* validate input */ - if (!src) + for (auto iter = src.begin(); iter != src.end(); iter++) { - return nullptr; - } - - /* allocate space for result */ - buffer = (char *) malloc(strlen(src) + 1); - - /* point to the start */ - bufptr = buffer; - - do - { - unsigned char c = *src; - - if (c < 0x80) + if ((*iter & 0x80) == 0) { - *bufptr++ = c; - } - else if (c == 0xc2) - { - c = *++src; - *bufptr++ = c; - } - else if (c == 0xc3) - { - c = *++src; - *bufptr++ = c + 0x40; + // low page (0x00 - 0x7F) - pass it on + dest << *iter; } else { - /* conversion failed */ - *bufptr++ = '\0'; - break; - } - } while(*src++); - - return buffer; -} - - -/*------------------------------------------------- - utf8_from_native - convert specified character - sequence to an UTF-8 string --------------------------------------------------*/ - -char *utf8_from_native(imgtool_charset charset, const char *src) -{ - char *result; - - switch (charset) - { - case IMGTOOL_CHARSET_UTF8: - result = core_strdup(src); - break; - - case IMGTOOL_CHARSET_ISO_8859_1: - result = utf8_from_latin1(src); - break; + // high page (0x80 - 0xFF) - we need to do a lookup + char32_t ch = m_highpage[((unsigned char)(*iter)) - 0x80]; + if (ch == 0) + throw charconverter_exception(); - default: - result = nullptr; - break; - } - return result; -} - - -/*------------------------------------------------- - native_from_utf8 - convert an UTF-8 string - to specified character set --------------------------------------------------*/ - -char *native_from_utf8(imgtool_charset charset, const char *src) -{ - char *result; - - switch (charset) - { - case IMGTOOL_CHARSET_UTF8: - result = core_strdup(src); - break; - - case IMGTOOL_CHARSET_ISO_8859_1: - result = latin1_from_utf8(src); - break; - - default: - result = nullptr; - break; + dest << utf8_from_uchar(ch); + } } - return result; } diff --git a/src/tools/imgtool/charconv.h b/src/tools/imgtool/charconv.h index 1544e9df402..e2abb3ecd57 100644 --- a/src/tools/imgtool/charconv.h +++ b/src/tools/imgtool/charconv.h @@ -9,23 +9,63 @@ ***************************************************************************/ -#ifndef __CHARCONV_H__ -#define __CHARCONV_H__ +#ifndef IMGTOOL_CHARCONV_H +#define IMGTOOL_CHARCONV_H - -/* Supported character sets */ -enum imgtool_charset +namespace imgtool { - IMGTOOL_CHARSET_UTF8, - IMGTOOL_CHARSET_ISO_8859_1, -}; + // ======================> charconverter + + // abstract base class for character conversions + class charconverter + { + public: + virtual void from_utf8(std::ostream &dest, const std::string &src) const = 0; + virtual void to_utf8(std::ostream &dest, const std::string &src) const = 0; + + std::string from_utf8(const std::string &src) const + { + // inlining so that the return value can potentially be removed by return value optimization + std::ostringstream stream; + from_utf8(stream, src); + return stream.str(); + } + + std::string to_utf8(const std::string &src) const + { + // inlining so that the return value can potentially be removed by return value optimization + std::ostringstream stream; + to_utf8(stream, src); + return stream.str(); + } + + }; + // ======================> simple_charconverter -/* Convert specified charset to UTF-8 */ -char *utf8_from_native(imgtool_charset charset, const char *src); + // a simple implementation of charconverter that simply defines a code page for 0x80-0xFF + class simple_charconverter : public charconverter + { + public: + constexpr simple_charconverter(const char32_t highpage[0x80]) + : m_highpage(highpage) + { + } -/* Convert UTF-8 string to specified charset */ -char *native_from_utf8(imgtool_charset charset, const char *src); + virtual void from_utf8(std::ostream &dest, const std::string &src) const override; + virtual void to_utf8(std::ostream &dest, const std::string &src) const override; + + private: + const char32_t *m_highpage; + }; + + // exception that can be thrown from charconverter::from_utf8() if a character is illegal (charconverter::to_utf8() should never throw this) + class charconverter_exception + { + }; + + extern simple_charconverter charconverter_iso_8859_1; +}; -#endif /* __CHARCONV_H__ */ +#endif // IMGTOOL_CHARCONV_H diff --git a/src/tools/imgtool/imgtool.cpp b/src/tools/imgtool/imgtool.cpp index bb7e6c860db..97158ddf04a 100644 --- a/src/tools/imgtool/imgtool.cpp +++ b/src/tools/imgtool/imgtool.cpp @@ -113,13 +113,11 @@ static void internal_error(const imgtool_module *module, const char *message) char *imgtool::partition::normalize_filename(const char *src) { - imgtool_charset charset; + // get charconverter from module + imgtool::charconverter *charconverter = (imgtool::charconverter *) get_info_ptr(IMGTOOLINFO_PTR_CHARCONVERTER); - // get charset from module - charset = (imgtool_charset) (int) get_info_int(IMGTOOLINFO_INT_CHARSET); - - // and dupe it - return native_from_utf8(charset, src); + // and convert + return core_strdup(charconverter ? charconverter->from_utf8(src).c_str() : src); } @@ -1919,8 +1917,7 @@ imgtoolerr_t imgtool::partition::put_file(const char *newfname, const char *fork { imgtoolerr_t err; imgtool::stream::ptr f; - imgtool_charset charset; - char *alloc_newfname = nullptr; + std::string alloc_newfname; std::string basename; if (!newfname) @@ -1929,18 +1926,19 @@ imgtoolerr_t imgtool::partition::put_file(const char *newfname, const char *fork newfname = basename.c_str(); } - charset = (imgtool_charset) (int) get_info_int(IMGTOOLINFO_INT_CHARSET); - if (charset != IMGTOOL_CHARSET_UTF8) + imgtool::charconverter *charconverter = (imgtool::charconverter *) get_info_ptr(IMGTOOLINFO_PTR_CHARCONVERTER); + if (charconverter) { - /* convert to native format */ - alloc_newfname = native_from_utf8(charset, newfname); - if (alloc_newfname == nullptr) + // convert to native format + try { - err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_NATIVEFILE); - goto done; + alloc_newfname = charconverter->from_utf8(newfname); } - - newfname = alloc_newfname; + catch (charconverter_exception) + { + return (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_NATIVEFILE); + } + newfname = alloc_newfname.c_str(); } f = imgtool::stream::open(source, OSD_FOPEN_READ); @@ -1949,10 +1947,6 @@ imgtoolerr_t imgtool::partition::put_file(const char *newfname, const char *fork else err = (imgtoolerr_t)(IMGTOOLERR_FILENOTFOUND | IMGTOOLERR_SRC_NATIVEFILE); -done: - /* clean up */ - if (alloc_newfname != nullptr) - free(alloc_newfname); return err; } @@ -2484,17 +2478,19 @@ imgtoolerr_t imgtool::directory::get_next(imgtool_dirent &ent) if (err) return markerrorsource(err); - int charset = m_partition.get_info_int(IMGTOOLINFO_INT_CHARSET); - - if (charset) + imgtool::charconverter *charconverter = (imgtool::charconverter *) m_partition.get_info_ptr(IMGTOOLINFO_PTR_CHARCONVERTER); + if (charconverter) { - char *new_fname = utf8_from_native((imgtool_charset)charset, ent.filename); - - if (!new_fname) - return IMGTOOLERR_BADFILENAME; - - snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", new_fname); - free(new_fname); + std::string new_fname; + try + { + new_fname = charconverter->to_utf8(ent.filename); + } + catch (charconverter_exception) + { + return (imgtoolerr_t)(IMGTOOLERR_BADFILENAME); + } + snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", new_fname.c_str()); } // don't trust the module! diff --git a/src/tools/imgtool/library.h b/src/tools/imgtool/library.h index 6305ca8ba1f..c64f02a33d5 100644 --- a/src/tools/imgtool/library.h +++ b/src/tools/imgtool/library.h @@ -165,7 +165,6 @@ enum IMGTOOLINFO_INT_CREATION_UNTESTED, IMGTOOLINFO_INT_SUPPORTS_BOOTBLOCK, IMGTOOLINFO_INT_BLOCK_SIZE, - IMGTOOLINFO_INT_CHARSET, IMGTOOLINFO_INT_CLASS_SPECIFIC = 0x08000, @@ -205,6 +204,7 @@ enum IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE, IMGTOOLINFO_PTR_MAKE_CLASS, IMGTOOLINFO_PTR_LIST_PARTITIONS, + IMGTOOLINFO_PTR_CHARCONVERTER, IMGTOOLINFO_PTR_CLASS_SPECIFIC = 0x18000, @@ -311,6 +311,7 @@ union imgtoolinfo const util::option_guide *createimage_optguide; const util::option_guide *writefile_optguide; + const imgtool::charconverter *charconverter; }; diff --git a/src/tools/imgtool/modules/amiga.cpp b/src/tools/imgtool/modules/amiga.cpp index e4959bd7bc6..7a7a3572320 100644 --- a/src/tools/imgtool/modules/amiga.cpp +++ b/src/tools/imgtool/modules/amiga.cpp @@ -2386,7 +2386,6 @@ void amiga_floppy_get_info(const imgtool_class *imgclass, uint32_t state, union case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(amiga_iterator); break; case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME: info->i = 1; break; case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '/'; break; - case IMGTOOLINFO_INT_CHARSET: info->i = IMGTOOL_CHARSET_ISO_8859_1; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "amiga_floppy"); break; @@ -2415,5 +2414,6 @@ void amiga_floppy_get_info(const imgtool_class *imgclass, uint32_t state, union case IMGTOOLINFO_PTR_GET_ICON_INFO: info->get_iconinfo = amiga_image_geticoninfo; break; case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = amiga_image_suggesttransfer; break; case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = &amiga_createimage_optionguide; break; + case IMGTOOLINFO_PTR_CHARCONVERTER: info->charconverter = &imgtool::charconverter_iso_8859_1; break; } } |
