#include "base/strings/sys_string_conversions.h"
#include <stddef.h>
#include <string.h>
#include <wchar.h>
#include <string_view>
#include "base/compiler_specific.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
namespace base {
std::string SysWideToUTF8(const std::wstring& wide) {
return WideToUTF8(wide);
}
std::wstring SysUTF8ToWide(std::string_view utf8) {
std::wstring out;
UTF8ToWide(utf8.data(), utf8.size(), &out);
return out;
}
#if defined(SYSTEM_NATIVE_UTF8) || BUILDFLAG(IS_ANDROID)
std::string SysWideToNativeMB(const std::wstring& wide) {
return WideToUTF8(wide);
}
std::wstring SysNativeMBToWide(std::string_view native_mb) {
return SysUTF8ToWide(native_mb);
}
#else
std::string SysWideToNativeMB(const std::wstring& wide) {
mbstate_t ps = {};
size_t num_out_chars = 0;
for (auto src : wide) {
char buf[16];
size_t res = src ? wcrtomb(buf, src, &ps) : 0;
switch (res) {
case static_cast<size_t>(-1):
return std::string();
case 0:
++num_out_chars;
break;
default:
num_out_chars += res;
break;
}
}
if (num_out_chars == 0) {
return std::string();
}
std::string out;
out.resize(num_out_chars);
ps = {};
for (size_t i = 0, j = 0; i < wide.size(); ++i) {
const wchar_t src = wide[i];
size_t res = src ? wcrtomb(&out[j], src, &ps) : 0;
switch (res) {
case static_cast<size_t>(-1):
return std::string();
case 0:
++j;
break;
default:
j += res;
break;
}
}
return out;
}
std::wstring SysNativeMBToWide(std::string_view native_mb) {
mbstate_t ps = {};
size_t num_out_chars = 0;
for (size_t i = 0; i < native_mb.size();) {
const char* src = UNSAFE_TODO(native_mb.data() + i);
size_t res = mbrtowc(nullptr, src, native_mb.size() - i, &ps);
switch (res) {
case static_cast<size_t>(-2):
case static_cast<size_t>(-1):
return std::wstring();
case 0:
i += 1;
[[fallthrough]];
default:
i += res;
++num_out_chars;
break;
}
}
if (num_out_chars == 0) {
return std::wstring();
}
std::wstring out;
out.resize(num_out_chars);
ps = {};
for (size_t i = 0, j = 0; i < native_mb.size(); ++j) {
const char* src = UNSAFE_TODO(native_mb.data() + i);
wchar_t* dst = &out[j];
size_t res = mbrtowc(dst, src, native_mb.size() - i, &ps);
switch (res) {
case static_cast<size_t>(-2):
case static_cast<size_t>(-1):
return std::wstring();
case 0:
i += 1;
break;
default:
i += res;
break;
}
}
return out;
}
#endif
}