-#define DEFINE_CHAR_CONVERSION_FUNCTIONS(varname1, longname1, chartype1,\
- varname2, longname2, chartype2,\
- earlyreturn_on_utf8_locale, \
- earlyreturn_expr, \
- worst_case_len_expr, \
- err_return, \
- err_msg, \
- modifier) \
-static ICONV_LIST(iconv_##varname1##_to_##varname2, \
- longname1, longname2); \
- \
-modifier 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; \
- \
- chartype2 *buf; \
- size_t bufsize; \
- bool buf_onheap; \
- bufsize = (worst_case_len_expr) * sizeof(chartype2); \
- /* Worst case length */ \
- if (bufsize <= STACK_MAX) { \
- buf = alloca(bufsize); \
- buf_onheap = false; \
- } else { \
- buf = MALLOC(bufsize); \
- if (!buf) \
- return WIMLIB_ERR_NOMEM; \
- buf_onheap = true; \
- } \
- \
- char *inbuf = (char*)in; \
- size_t inbytesleft = in_nbytes; \
- char *outbuf = (char*)buf; \
- size_t outbytesleft = bufsize; \
- 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 = bufsize - outbytesleft; \
- ret = 0; \
- } \
- put_iconv(cd); \
- if (buf_onheap) \
- FREE(buf); \
- return ret; \
-} \
- \
-modifier 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; \
-} \
- \
-modifier 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; \
- \
- if (earlyreturn_on_utf8_locale && wimlib_mbs_is_utf8) { \
- earlyreturn_expr; \
- /* Out same as in */ \
- out = MALLOC(in_nbytes + sizeof(chartype2)); \
- if (!out) \
- return WIMLIB_ERR_NOMEM; \
- memcpy(out, in, in_nbytes); \
- out[in_nbytes / sizeof(chartype2)] = 0; \
- *out_ret = out; \
- *out_nbytes_ret = in_nbytes; \
- return 0; \
- } \
- \
- 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) { \
- FREE(out); \
- } else { \
- *out_ret = out; \
- *out_nbytes_ret = out_nbytes; \
- } \
- return ret; \