diff --git a/src/convert.cpp b/src/convert.cpp index fc92407288..79c3229ec5 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -22,13 +22,11 @@ #include #include -#if defined _WIN32 -#include -#endif - #ifdef EXV_HAVE_ICONV #include #include +#elif defined _WIN32 +#include #endif // Adobe XMP Toolkit @@ -1412,7 +1410,51 @@ bool convertStringCharset(std::string& str, const char* from, const char* to) { namespace { using namespace Exiv2; -#if defined _WIN32 +#if defined EXV_HAVE_ICONV +bool convertStringCharsetIconv(std::string& str, const char* from, const char* to) { + if (strcmp(from, to) == 0) + return true; // nothing to do + + bool ret = true; + auto cd = iconv_open(to, from); + if (cd == iconv_t(-1)) { +#ifndef SUPPRESS_WARNINGS + EXV_WARNING << "iconv_open: " << strError() << "\n"; +#endif + return false; + } + std::string outstr; +#ifdef WINICONV_CONST + auto inptr = (WINICONV_CONST char*)(str.c_str()); +#else + auto inptr = (EXV_ICONV_CONST char*)(str.c_str()); +#endif + size_t inbytesleft = str.length(); + while (inbytesleft) { + char outbuf[256]; + char* outptr = outbuf; + size_t outbytesleft = sizeof(outbuf); + size_t rc = iconv(cd, &inptr, &inbytesleft, &outptr, &outbytesleft); + const size_t outbytesProduced = sizeof(outbuf) - outbytesleft; + if (rc == std::numeric_limits::max() && errno != E2BIG) { +#ifndef SUPPRESS_WARNINGS + EXV_WARNING << "iconv: " << strError() << " inbytesleft = " << inbytesleft << "\n"; +#endif + ret = false; + break; + } + outstr.append(std::string(outbuf, outbytesProduced)); + } + + if (cd) + iconv_close(cd); + + if (ret) + str = outstr; + return ret; +} + +#elif defined(_WIN32) bool swapBytes(std::string& str) { // Naive byte-swapping, I'm sure this can be done more efficiently if (str.size() & 1) { @@ -1560,52 +1602,6 @@ const ConvFctList convFctList[] = { return ret; } -#endif // defined _WIN32 -#if defined EXV_HAVE_ICONV -bool convertStringCharsetIconv(std::string& str, const char* from, const char* to) { - if (0 == strcmp(from, to)) - return true; // nothing to do - - bool ret = true; - iconv_t cd; - cd = iconv_open(to, from); - if (cd == iconv_t(-1)) { -#ifndef SUPPRESS_WARNINGS - EXV_WARNING << "iconv_open: " << strError() << "\n"; -#endif - return false; - } - std::string outstr; -#ifdef WINICONV_CONST - auto inptr = (WINICONV_CONST char*)(str.c_str()); -#else - auto inptr = (EXV_ICONV_CONST char*)(str.c_str()); -#endif - size_t inbytesleft = str.length(); - while (inbytesleft) { - char outbuf[256]; - char* outptr = outbuf; - size_t outbytesleft = sizeof(outbuf); - size_t rc = iconv(cd, &inptr, &inbytesleft, &outptr, &outbytesleft); - const size_t outbytesProduced = sizeof(outbuf) - outbytesleft; - if (rc == static_cast(-1) && errno != E2BIG) { -#ifndef SUPPRESS_WARNINGS - EXV_WARNING << "iconv: " << strError() << " inbytesleft = " << inbytesleft << "\n"; -#endif - ret = false; - break; - } - outstr.append(std::string(outbuf, outbytesProduced)); - } - if (cd) { - iconv_close(cd); - } - - if (ret) - str = outstr; - return ret; -} - #endif // EXV_HAVE_ICONV bool getTextValue(std::string& value, const XmpData::iterator& pos) { if (pos->typeId() == langAlt) {