Last active
December 15, 2015 14:09
-
-
Save kbinani/5272091 to your computer and use it in GitHub Desktop.
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 "convert_text_encoding.hpp" | |
#include <CoreServices/CoreServices.h> | |
#include <memory> | |
namespace detail | |
{ | |
//! | |
//! @brief Get string encoding of wstring. | |
CFStringEncoding get_wide_string_encoding(); | |
//! | |
//! @brief Create CFStringRef from std::basic_string | |
template<typename StringType> | |
CFStringRef create_string(const StringType &string, CFStringEncoding encoding); | |
size_t estimate_converted_string_bytes(const CFStringRef string, CFStringEncoding encode_to); | |
template<typename CharType> | |
bool convert( | |
const CFStringRef string, | |
CFStringEncoding encode_to, | |
const std::auto_ptr<CharType> &buffer, | |
size_t num_characters); | |
} | |
template< | |
typename DestStringType, | |
typename SourceStringType | |
> | |
DestStringType convert_encoding( | |
SourceStringType source, | |
CFStringEncoding encode_from, | |
CFStringEncoding encode_to) | |
{ | |
typedef typename SourceStringType::value_type SourceCharType; | |
typedef typename DestStringType::value_type DestCharType; | |
const CFStringRef intermediate = detail::create_string(source, encode_from); | |
if (!intermediate) { | |
CFRelease(intermediate); | |
return DestStringType(); | |
} | |
const size_t estimated_string_bytes = detail::estimate_converted_string_bytes(intermediate, encode_to); | |
if (estimated_string_bytes == 0) { | |
CFRelease(intermediate); | |
return DestStringType(); | |
} | |
const size_t num_characters = estimated_string_bytes / sizeof(DestCharType); | |
const std::auto_ptr<DestCharType> buffer(new DestCharType[num_characters + 1]); | |
if (!buffer.get()) { | |
CFRelease(intermediate); | |
return DestStringType(); | |
} | |
if (detail::convert(intermediate, encode_to, buffer, num_characters)) { | |
CFRelease(intermediate); | |
return DestStringType(buffer.get(), num_characters); | |
} else { | |
CFRelease(intermediate); | |
return DestStringType(); | |
} | |
} | |
namespace detail | |
{ | |
CFStringEncoding get_wide_string_encoding() | |
{ | |
return CreateTextEncoding(kTextEncodingUnicodeDefault, | |
kTextEncodingDefaultVariant, | |
kUnicodeUTF32LEFormat); | |
} | |
template<typename StringType> | |
CFStringRef create_string(const StringType &string, CFStringEncoding encoding) | |
{ | |
typedef typename StringType::value_type CharType; | |
const CFAllocatorRef allocator = NULL; | |
const Boolean has_external_representation = false; | |
const size_t string_bytes = string.size() * sizeof(CharType); | |
return CFStringCreateWithBytes(allocator, | |
(const UInt8 *)string.data(), | |
string_bytes, | |
encoding, | |
has_external_representation); | |
} | |
size_t estimate_converted_string_bytes(const CFStringRef string, CFStringEncoding encode_to) | |
{ | |
const CFRange range = CFRangeMake(0, CFStringGetLength(string)); | |
const UInt8 loss_byte = 0; | |
const Boolean has_external_representation = false; | |
const CFIndex max_buffer_length = 0; | |
CFIndex result = 0; | |
const CFIndex converted_characters = CFStringGetBytes(string, | |
range, | |
encode_to, | |
loss_byte, | |
has_external_representation, | |
NULL, | |
max_buffer_length, | |
&result); | |
if (converted_characters <= 0) { | |
return 0; | |
} else { | |
return result; | |
} | |
} | |
template<typename CharType> | |
bool convert( | |
const CFStringRef string, | |
CFStringEncoding encode_to, | |
const std::auto_ptr<CharType> &buffer, | |
size_t num_characters) | |
{ | |
const size_t buffer_bytes = sizeof(CharType) * (num_characters + 1); | |
memset(buffer.get(), 0, buffer_bytes); | |
const CFRange range = CFRangeMake(0, CFStringGetLength(string)); | |
const UInt8 loss_byte = 0; | |
const Boolean has_external_representation = false; | |
const CFIndex converted_characters = CFStringGetBytes(string, | |
range, | |
encode_to, | |
loss_byte, | |
has_external_representation, | |
(UInt8 *)buffer.get(), | |
buffer_bytes, | |
NULL); | |
return converted_characters > 0; | |
} | |
} | |
std::string encode(const std::wstring &string, CFStringEncoding encode_to) | |
{ | |
return convert_encoding<std::string, std::wstring>(string, detail::get_wide_string_encoding(), encode_to); | |
} | |
std::wstring encode(const std::string &string, CFStringEncoding encode_from) | |
{ | |
return convert_encoding<std::wstring, std::string>(string, encode_from, detail::get_wide_string_encoding()); | |
} |
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
#ifndef convert_text_encoding_convert_text_encoding_hpp | |
#define convert_text_encoding_convert_text_encoding_hpp | |
#include <CoreFoundation/CFString.h> | |
#include <string> | |
std::string encode(const std::wstring &string, CFStringEncoding encode_to); | |
std::wstring encode(const std::string &string, CFStringEncoding encode_from); | |
#endif |
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 "convert_text_encoding.hpp" | |
#include <iostream> | |
#include <string> | |
int main() | |
{ | |
std::wstring source(L"わはー"); | |
std::string result = encode(source, kCFStringEncodingUTF8); | |
std::cout << result << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment