VclとFireMonkey共通。
“80CC”等、コードポイント(番号)の文字列をStringに変換するには、基本的には以下でOK。
1 2 3 |
String Code( L"80CC" ); // 背 String Str = WideChar( StrToInt( L"0x" + Code ) ); |
ただし実際にはサロゲートペア用に割り当てられた番号(D800~DFFF)に配慮する必要がある。Androidで、サロゲートペア用の番号を指定するとアプリが落ちる場合もある(Android4.4.2で確認)
そこに配慮した関数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
bool CodeToString( const String Code, String& RefStr ) { if( Code.Length() == 4 ) { unsigned int c = StrToInt( L"0x" + Code ); if( c < 0xd800 || 0xdfff < c ) { std::wstring result( 1, c ); RefStr = result.c_str(); return true; } } return false; } |
サロゲートペア文字も取得するには、もう一手間が必要。
サロゲートペア用の番号は”20B9F”など5桁になる。
少し汎用にstd::wstringを使った関数。(注:C++Builderはwchar_tが2byte)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
#include <string> #include <sstream> bool is_surrogate_high( unsigned long c ) { return 0xd800 <= c && c <= 0xdbff; } bool is_surrogate_low( unsigned long c ) { return 0xdc00 <= c && c <= 0xdfff; } bool is_surrogate_high_or_low( unsigned long c ) { return is_surrogate_high( c ) || is_surrogate_low( c ); } bool get_surrogate_pair( unsigned long num, std::pair<unsigned long,unsigned long>* sur_pair ) { unsigned long high, low; num -= 0x10000; high = num / 0x400; high += 0xd800; low = num % 0x400; low += 0xdc00; if( is_surrogate_high( high ) && is_surrogate_low( low ) ) { (*sur_pair).first = high; (*sur_pair).second = low; return true; } return false; } bool code_to_string( const std::wstring code_hex_str, std::wstring& result_str ) { if( code_hex_str.length() == 4 ) { wchar_t* end_ptr; unsigned long c = wcstol( code_hex_str.c_str(), &end_ptr, 16 ); if( is_surrogate_high_or_low( c ) ) return false; result_str = std::wstring( 1, c ); return true; } else if( code_hex_str.length() == 5 ) { wchar_t* end_ptr; unsigned long c = wcstol( code_hex_str.c_str(), &end_ptr, 16 ); std::pair<unsigned long, unsigned long> sur_pair; if( get_surrogate_pair( c, &sur_pair ) ) { wchar_t wc[3]; wc[0] = sur_pair.first; wc[1] = sur_pair.second; wc[2] = L'\0'; result_str = wc; return true; } } return false; } |
(注:C++Builder Berlin Update2では、Androidではwstring版の”wcstol”がバグっているようなので、さらに一手間かけてstring版の”strtol”を使う必要がある)
念のため、Stringに変換するには以下のように呼び出す。
1 2 3 4 5 6 7 8 9 10 11 |
bool CodeToString( String CodeStr, String& ResultStr ) { const std::wstring code_hex_str = CodeStr.c_str(); std::wstring result_str; if( code_to_string( code_hex_str, result_str ) ) { ResultStr = result_str.c_str(); return true; } return false; } |
(なおC++Builder BerlinではStringはUnicodeStringのtypedef)
C++Builder Berlin Update2 / Windows7(Sp1)で確認。