+// UTF8ToCodeset - Convert some UTF-8 string for some codeset /*{{{*/
+// ---------------------------------------------------------------------
+/* This is handy to use before display some information for enduser */
+bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest)
+{
+ iconv_t cd;
+ const char *inbuf;
+ char *inptr, *outbuf;
+ size_t insize, bufsize;
+ dest->clear();
+
+ cd = iconv_open(codeset, "UTF-8");
+ if (cd == (iconv_t)(-1)) {
+ // Something went wrong
+ if (errno == EINVAL)
+ _error->Error("conversion from 'UTF-8' to '%s' not available",
+ codeset);
+ else
+ perror("iconv_open");
+
+ return false;
+ }
+
+ insize = bufsize = orig.size();
+ inbuf = orig.data();
+ inptr = (char *)inbuf;
+ outbuf = new char[bufsize];
+ size_t lastError = -1;
+
+ while (insize != 0)
+ {
+ char *outptr = outbuf;
+ size_t outsize = bufsize;
+ size_t const err = iconv(cd, &inptr, &insize, &outptr, &outsize);
+ dest->append(outbuf, outptr - outbuf);
+ if (err == (size_t)(-1))
+ {
+ switch (errno)
+ {
+ case EILSEQ:
+ insize--;
+ inptr++;
+ // replace a series of unknown multibytes with a single "?"
+ if (lastError != insize) {
+ lastError = insize - 1;
+ dest->append("?");
+ }
+ break;
+ case EINVAL:
+ insize = 0;
+ break;
+ case E2BIG:
+ if (outptr == outbuf)
+ {
+ bufsize *= 2;
+ delete[] outbuf;
+ outbuf = new char[bufsize];
+ }
+ break;
+ }
+ }
+ }
+
+ delete[] outbuf;
+
+ iconv_close(cd);
+
+ return true;
+}
+ /*}}}*/