Created
August 11, 2015 00:27
-
-
Save ptomulik/718b0df040bc6fa8b175 to your computer and use it in GitHub Desktop.
converting wide string to narrow and vice-versa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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