Skip to content

Instantly share code, notes, and snippets.

@ptomulik
Created August 11, 2015 00:27
Show Gist options
  • Save ptomulik/718b0df040bc6fa8b175 to your computer and use it in GitHub Desktop.
Save ptomulik/718b0df040bc6fa8b175 to your computer and use it in GitHub Desktop.
converting wide string to narrow and vice-versa
#include <locale>
#include <string>
#include <stdexcept>
std::wstring
widen(std::string const& str, std::codecvt<wchar_t, char, std::mbstate_t> const& cvt)
{
if(str.empty())
return std::wstring();
std::mbstate_t mb = std::mbstate_t();
std::wstring wstr(4 + str.size(), L'\0');
const char* from_beg = &str[0];
const char* from_end = from_beg + str.size();
const char* from_nxt;
wchar_t* to_beg = &wstr[0];
wchar_t* to_end = to_beg + wstr.size();
wchar_t* to_nxt;
switch(cvt.in(mb, from_beg, from_end, from_nxt, to_beg, to_end, to_nxt))
{
case std::codecvt_base::error:
throw std::runtime_error("string conversion error in widen()");
case std::codecvt_base::partial:
throw std::runtime_error("string conversion partial in widen()");
case std::codecvt_base::noconv:
wstr.resize(from_end - from_beg, L'\0');
for(size_t i = 0ul; i != str.size(); ++i)
wstr[i] = static_cast<wchar_t>(str[i]);
break;
case std::codecvt_base::ok:
wstr.resize(to_nxt - to_beg);
break;
default:
throw std::runtime_error("internal error in widen()");
}
return wstr;
}
std::string
narrow(std::wstring const& wstr, std::codecvt<wchar_t, char, std::mbstate_t> const& cvt)
{
if(wstr.empty())
return std::string();
std::mbstate_t mb = std::mbstate_t();
std::string str(4 + wstr.size() * cvt.max_length(), '\0');
const wchar_t* from_beg = &wstr[0];
const wchar_t* from_end = from_beg + wstr.size();
const wchar_t* from_nxt;
char* to_beg = &str[0];
char* to_end = to_beg + str.size();
char* to_nxt;
switch(cvt.out(mb, from_beg, from_end, from_nxt, to_beg, to_end, to_nxt))
{
case std::codecvt_base::error:
throw std::runtime_error("string conversion error in narrow()");
case std::codecvt_base::partial:
throw std::runtime_error("string conversion partial in narrow()");
case std::codecvt_base::noconv:
str.resize(from_end - from_beg, L'\0');
for(size_t i = 0ul; i != wstr.size(); ++i)
str[i] = static_cast<char>(wstr[i]);
break;
case std::codecvt_base::ok:
str.resize(to_nxt - to_beg);
break;
default:
throw std::runtime_error("internal error in narrow()");
}
return str;
}
#include <iostream>
#include <iomanip>
int main()
{
typedef std::codecvt<wchar_t,char,std::mbstate_t> codecvt_t;
std::string s = "\xB3"; // polish l with stroke in latin-2
std::wstring w = widen(s, std::use_facet<codecvt_t>(std::locale("pl_PL.ISO-8859-2")));
std::string u = narrow(w, std::use_facet<codecvt_t>(std::locale("")));
std::cout << u << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment