summaryrefslogtreecommitdiffstatshomepage
path: root/src/tools
diff options
context:
space:
mode:
author Nathan Woods <npwoods@mess.org>2016-12-22 07:02:23 -0500
committer Nathan Woods <npwoods@mess.org>2016-12-23 09:44:09 -0500
commit594d959f09ea3087b2903ed161e24cec67585796 (patch)
treeee085c70778a29d320eb780d2c56c08446edfede /src/tools
parent63b7b9d521712404dc35156ef8d7e606440b4156 (diff)
[Imgtool] Rewrote charconv; now an interface rather than an enumeration
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/imgtool/charconv.cpp186
-rw-r--r--src/tools/imgtool/charconv.h66
-rw-r--r--src/tools/imgtool/imgtool.cpp58
-rw-r--r--src/tools/imgtool/library.h3
-rw-r--r--src/tools/imgtool/modules/amiga.cpp2
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;
}
}