+/* Uses CONV to convert the INBYTES starting at IP into the OUTBYTES starting
+ at OP, and appends a null terminator to the output.
+
+ Returns true if successful, false if the output buffer is too small. */
+static bool
+try_recode (iconv_t conv,
+ const char *ip, size_t inbytes,
+ char *op, size_t outbytes)
+{
+ /* FIXME: Need to ensure that this char is valid in the target encoding */
+ const char fallbackchar = '?';
+
+ /* Put the converter into the initial shift state, in case there was any
+ state information left over from its last usage. */
+ iconv (conv, NULL, 0, NULL, 0);
+
+ while (iconv (conv, (ICONV_CONST char **) &ip, &inbytes,
+ &op, &outbytes) == -1)
+ switch (errno)
+ {
+ case EILSEQ:
+ case EINVAL:
+ if (outbytes == 0)
+ return false;
+
+ *op++ = fallbackchar;
+ outbytes--;
+ ip++;
+ inbytes--;
+ break;
+
+ case E2BIG:
+ return false;
+
+ default:
+ /* should never happen */
+ fprintf (stderr, "Character conversion error: %s\n", strerror (errno));
+ NOT_REACHED ();
+ break;
+ }
+
+ if (outbytes == 0)
+ return false;
+
+ *op = '\0';
+ return true;
+}
+