X-Git-Url: https://git.sesse.net/?p=ccbs;a=blobdiff_plain;f=bigscreen%2Fwidestring.cpp;fp=bigscreen%2Fwidestring.cpp;h=f486aaec8dde5e9b5ec96a811324ed92839aa1d8;hp=241183650819a700b9bc36e48c49c5d16c561412;hb=92cf5ad4caee6d0fe35a23107a451797d502707d;hpb=e31944e3c1c8725a85f36153400d27ce99e01c46 diff --git a/bigscreen/widestring.cpp b/bigscreen/widestring.cpp index 2411836..f486aae 100644 --- a/bigscreen/widestring.cpp +++ b/bigscreen/widestring.cpp @@ -6,9 +6,25 @@ #include #include "widestring.h" -static iconv_t ucs4_iconv; +static iconv_t ucs4_iconv, ucs4_reverse_iconv; static bool iconv_initialized = false; +void ensure_iconv_initialized() +{ + if (iconv_initialized) { + return; + } +#if __BYTE_ORDER == __LITTLE_ENDIAN + ucs4_iconv = iconv_open("ucs-4le", "utf-8"); + ucs4_reverse_iconv = iconv_open("utf-8", "ucs-4le"); +#else + ucs4_iconv = iconv_open("ucs-4be", "utf-8"); + ucs4_reverse_iconv = iconv_open("utf-8", "ucs-4be"); +#endif + + iconv_initialized = true; +} + widestring::widestring() { } @@ -30,15 +46,7 @@ widestring::widestring(const std::wstring &from) void widestring::operator= (const char *from) { - if (!iconv_initialized) { -#if __BYTE_ORDER == __LITTLE_ENDIAN - ucs4_iconv = iconv_open("ucs-4le", "utf-8"); -#else - ucs4_iconv = iconv_open("ucs-4be", "utf-8"); -#endif - - iconv_initialized = true; - } + ensure_iconv_initialized(); unsigned bytes = std::strlen(from); char *from_buf = strdup(from); @@ -66,3 +74,35 @@ void widestring::operator= (const char *from) free(from_buf); delete[] to_buf; } + +std::string widestring::to_utf8() const +{ + ensure_iconv_initialized(); + + wchar_t *from_buf = wcsdup(c_str()); + size_t out_max_size = size() * 6; + char *to_buf = new char[out_max_size]; + + char *inptr = reinterpret_cast(from_buf), *outptr = to_buf; + + size_t in_left = size() * sizeof(wchar_t); + size_t out_left = out_max_size; + + size_t ret = iconv(ucs4_reverse_iconv, NULL, NULL, &outptr, &out_left); + if (ret == (size_t)(-1)) { + throw std::runtime_error("Error in iconv during initialization"); + } + + ret = iconv(ucs4_reverse_iconv, &inptr, &in_left, &outptr, &out_left); + if (ret == (size_t)(-1)) { + perror("iconv"); + throw std::runtime_error("Error in iconv during conversion"); + } + + std::string utf8(to_buf, outptr); + + free(from_buf); + delete[] to_buf; + + return utf8; +}