-int
-mbs_to_utf16le_nbytes(const mbchar *mbs, size_t mbs_nbytes,
- size_t *utf16le_nbytes_ret)
-{
- iconv_t *cd = get_iconv(&iconv_mbs_to_utf16le);
- if (*cd == (iconv_t)-1)
- return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
-
- /* Worst case length */
- utf16lechar buf[mbs_nbytes * 2];
- char *inbuf = (char*)mbs;
- char *outbuf = (char*)buf;
- size_t outbytesleft = sizeof(buf);
- size_t inbytesleft = mbs_nbytes;
- size_t len;
- int ret;
-
- len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
- if (len == (size_t)-1) {
- ret = WIMLIB_ERR_INVALID_MULTIBYTE_STRING;
- } else {
- *utf16le_nbytes_ret = sizeof(buf) - outbytesleft;
- ret = 0;
- }
- put_iconv(cd);
- return ret;
+#define DEFINE_CHAR_CONVERSION_FUNCTIONS(varname1, longname1, chartype1,\
+ varname2, longname2, chartype2,\
+ worst_case_len_expr, \
+ err_return, \
+ err_msg) \
+static ICONV_LIST(iconv_##varname1##_to_##varname2, \
+ longname1, longname2); \
+ \
+int \
+varname1##_to_##varname2##_nbytes(const chartype1 *in, size_t in_nbytes,\
+ size_t *out_nbytes_ret) \
+{ \
+ iconv_t *cd = get_iconv(&iconv_##varname1##_to_##varname2); \
+ if (cd == NULL) \
+ return WIMLIB_ERR_ICONV_NOT_AVAILABLE; \
+ \
+ /* Worst case length */ \
+ chartype2 buf[worst_case_len_expr]; \
+ char *inbuf = (char*)in; \
+ size_t inbytesleft = in_nbytes; \
+ char *outbuf = (char*)buf; \
+ size_t outbytesleft = sizeof(buf); \
+ size_t len; \
+ int ret; \
+ \
+ len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); \
+ if (len == (size_t)-1) { \
+ err_msg; \
+ ret = err_return; \
+ } else { \
+ *out_nbytes_ret = sizeof(buf) - outbytesleft; \
+ ret = 0; \
+ } \
+ put_iconv(cd); \
+ return ret; \
+} \
+ \
+int \
+varname1##_to_##varname2##_buf(const chartype1 *in, size_t in_nbytes, \
+ chartype2 *out) \
+{ \
+ iconv_t *cd = get_iconv(&iconv_##varname1##_to_##varname2); \
+ if (cd == NULL) \
+ return WIMLIB_ERR_ICONV_NOT_AVAILABLE; \
+ \
+ char *inbuf = (char*)in; \
+ size_t inbytesleft = in_nbytes; \
+ char *outbuf = (char*)out; \
+ const size_t LARGE_NUMBER = 1000000000; \
+ size_t outbytesleft = LARGE_NUMBER; \
+ size_t len; \
+ int ret; \
+ \
+ len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); \
+ if (len == (size_t)-1) { \
+ err_msg; \
+ ret = err_return; \
+ } else { \
+ out[(LARGE_NUMBER-outbytesleft)/sizeof(chartype2)] = 0; \
+ ret = 0; \
+ } \
+ put_iconv(cd); \
+ return ret; \
+} \
+ \
+int \
+varname1##_to_##varname2(const chartype1 *in, size_t in_nbytes, \
+ chartype2 **out_ret, \
+ size_t *out_nbytes_ret) \
+{ \
+ int ret; \
+ chartype2 *out; \
+ size_t out_nbytes; \
+ \
+ ret = varname1##_to_##varname2##_nbytes(in, in_nbytes, \
+ &out_nbytes); \
+ if (ret) \
+ return ret; \
+ \
+ out = MALLOC(out_nbytes + sizeof(chartype2)); \
+ if (!out) \
+ return WIMLIB_ERR_NOMEM; \
+ \
+ ret = varname1##_to_##varname2##_buf(in, in_nbytes, out); \
+ if (ret) { \
+ int errno_save = errno; \
+ FREE(out); \
+ errno = errno_save; \
+ } else { \
+ *out_ret = out; \
+ *out_nbytes_ret = out_nbytes; \
+ } \
+ return ret; \