1 From 315b90e29f532ed75066bca52223b0ba98961ae0 Mon Sep 17 00:00:00 2001 2 From: David 'Digit' Turner <digit (a] google.com> 3 Date: Tue, 9 Jul 2013 23:20:03 +0200 4 Subject: android: Add locale support. 5 6 This is based on the Bionic <ctype.h> declarations. Note that 7 unfortunately, the _ctype_ table exposed by this header has a bug 8 so a fixed copy is included here instead. 9 10 See src/support/android/locale_android.cpp for details. 11 --- 12 include/__locale | 17 +++++- 13 src/locale.cpp | 25 +++++++- 14 src/support/android/locale_android.cpp | 101 +++++++++++++++++++++++++++++++++ 15 3 files changed, 140 insertions(+), 3 deletions(-) 16 create mode 100644 src/support/android/locale_android.cpp 17 18 diff --git a/include/__locale b/include/__locale 19 index 92f4e0c..d95b565 100644 20 --- a/include/__locale 21 +++ b/include/__locale 22 @@ -373,7 +373,20 @@ public: 23 static const mask punct = _ISPUNCT; 24 static const mask xdigit = _ISXDIGIT; 25 static const mask blank = _ISBLANK; 26 -#else // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ || EMSCRIPTEN || __sun__ 27 +#elif defined(__ANDROID__) 28 + typedef unsigned short mask; 29 + static const mask space = _S; 30 + static const mask print = _P | _U | _L | _N | _B; 31 + static const mask cntrl = _C; 32 + static const mask upper = _U; 33 + static const mask lower = _L; 34 + static const mask alpha = _U | _L; 35 + static const mask digit = _N; 36 + static const mask punct = _P; 37 + static const mask xdigit = _N | _X; 38 + // See src/support/android/locale_android.cpp for details! 39 + static const mask blank = 0x100; 40 +#else // __ANDROID__ 41 typedef unsigned long mask; 42 static const mask space = 1<<0; 43 static const mask print = 1<<1; 44 @@ -385,7 +398,7 @@ public: 45 static const mask punct = 1<<7; 46 static const mask xdigit = 1<<8; 47 static const mask blank = 1<<9; 48 -#endif // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ 49 +#endif // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ || EMSCRIPTEN || __sun__ || __ANDROID__ 50 static const mask alnum = alpha | digit; 51 static const mask graph = alnum | punct; 52 53 diff --git a/src/locale.cpp b/src/locale.cpp 54 index 47c4061..42ef374 100644 55 --- a/src/locale.cpp 56 +++ b/src/locale.cpp 57 @@ -792,6 +792,8 @@ ctype<wchar_t>::do_toupper(char_type c) const 58 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; 59 #elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__) 60 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c; 61 +#elif defined(__ANDROID__) 62 + return isascii(c) ? _toupper_tab_[c + 1] : c; 63 #else 64 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c; 65 #endif 66 @@ -806,6 +808,8 @@ ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const 67 #elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__) 68 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] 69 : *low; 70 +#elif defined(__ANDROID__) 71 + *low = isascii(*low) ? _toupper_tab_[*low + 1] : *low; 72 #else 73 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low; 74 #endif 75 @@ -819,6 +823,8 @@ ctype<wchar_t>::do_tolower(char_type c) const 76 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; 77 #elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__) 78 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c; 79 +#elif defined(__ANDROID__) 80 + return isascii(c) ? _tolower_tab_[c + 1] : c; 81 #else 82 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c; 83 #endif 84 @@ -833,6 +839,8 @@ ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const 85 #elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__) 86 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] 87 : *low; 88 +#elif defined(__ANDROID__) 89 + *low = isascii(*low) ? _tolower_tab_[*low] : *low; 90 #else 91 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low; 92 #endif 93 @@ -902,6 +910,8 @@ ctype<char>::do_toupper(char_type c) const 94 #elif defined(__GLIBC__) || defined(EMSCRIPTEN) 95 return isascii(c) ? 96 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c; 97 +#elif defined(__ANDROID__) 98 + return isascii(c) ? _toupper_tab_[c + 1] : c; 99 #else 100 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c; 101 #endif 102 @@ -919,6 +929,8 @@ ctype<char>::do_toupper(char_type* low, const char_type* high) const 103 #elif defined(__GLIBC__) || defined(EMSCRIPTEN) 104 *low = isascii(*low) ? 105 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low; 106 +#elif defined(__ANDROID__) 107 + *low = isascii(*low) ? _toupper_tab_[*low + 1] : *low; 108 #else 109 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low; 110 #endif 111 @@ -936,6 +948,8 @@ ctype<char>::do_tolower(char_type c) const 112 #elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__) 113 return isascii(c) ? 114 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c; 115 +#elif defined(__ANDROID__) 116 + return isascii(c) ? _tolower_tab_[c + 1] : c; 117 #else 118 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c; 119 #endif 120 @@ -951,6 +965,8 @@ ctype<char>::do_tolower(char_type* low, const char_type* high) const 121 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]); 122 #elif defined(__GLIBC__) || defined(EMSCRIPTEN) 123 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low; 124 +#elif defined(__ANDROID__) 125 + *low = isascii(*low) ? _tolower_tab_[*low + 1] : *low; 126 #else 127 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low; 128 #endif 129 @@ -996,6 +1012,11 @@ extern "C" const int ** __ctype_tolower_loc(); 130 extern "C" const int ** __ctype_toupper_loc(); 131 #endif 132 133 +#if defined(__ANDROID__) 134 +// See src/support/android/android_locale.cpp 135 +extern "C" const unsigned short* const _ctype_android; 136 +#endif 137 + 138 const ctype<char>::mask* 139 ctype<char>::classic_table() _NOEXCEPT 140 { 141 @@ -1013,6 +1034,8 @@ ctype<char>::classic_table() _NOEXCEPT 142 // going to end up dereferencing it later... 143 #elif defined(EMSCRIPTEN) 144 return *__ctype_b_loc(); 145 +#elif defined(__ANDROID__) 146 + return _ctype_android; 147 #else 148 // Platform not supported: abort so the person doing the port knows what to 149 // fix 150 @@ -1397,7 +1420,7 @@ locale::id codecvt<wchar_t, char, mbstate_t>::id; 151 152 codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) 153 : locale::facet(refs), 154 - __l(_LIBCPP_GET_C_LOCALE) 155 + __l(0) 156 { 157 } 158 159 diff --git a/src/support/android/locale_android.cpp b/src/support/android/locale_android.cpp 160 new file mode 100644 161 index 0000000..81c3b28 162 --- /dev/null 163 +++ b/src/support/android/locale_android.cpp 164 @@ -0,0 +1,101 @@ 165 +// -*- C++ -*- 166 +//===-------------------- support/win32/locale_win32.cpp ------------------===// 167 +// 168 +// The LLVM Compiler Infrastructure 169 +// 170 +// This file is dual licensed under the MIT and the University of Illinois Open 171 +// Source Licenses. See LICENSE.TXT for details. 172 +// 173 +//===----------------------------------------------------------------------===// 174 + 175 +#include <ctype.h> 176 + 177 +// Bionic exports the non-standard _ctype_ array in <ctype.h>, 178 +// unfortunately, cannot be used directly for libc++ because it doesn't 179 +// have a proper bit-flag for blank characters. 180 +// 181 +// Note that the header does define a _B flag (as 0x80), but it 182 +// is only set on the space (32) character, and used to implement 183 +// isprint() properly. The implementation of isblank() relies on 184 +// direct comparisons with 7 and 32 instead. 185 +// 186 +// The following is a local copy of the Bionic _ctype_ array that has 187 +// been modified in the following way: 188 +// 189 +// - It stores 16-bit unsigned values, instead of 8-bit char ones. 190 +// 191 +// - Bit flag _BLANK (0x100) is used to indicate blank characters. 192 +// It is only set for indices 7 (TAB) and 32 (SPACE). 193 +// 194 +// - Support signed char properly for indexing. 195 + 196 +// Used to tag blank characters, this doesn't appear in <ctype.h> nor 197 +// the original Bionic _ctype_ array. 198 +#define _BLANK 0x100 199 + 200 +// NOTE: A standalone forward declaration is required to ensure that this 201 +// variable is properly exported with a C name. In other words, this does 202 +// _not_ work: 203 +// 204 +// extern "C" { 205 +// const char* const _ctype_android = ...; 206 +// } 207 +// 208 +extern "C" const unsigned short* const _ctype_android; 209 + 210 +static const unsigned short ctype_android_tab[256+128] = { 211 + /* -128..-1 */ 212 + _C, _C, _C, _C, _C, _C, _C, _C, /* 80 */ 213 + _C, _C, _C, _C, _C, _C, _C, _C, /* 88 */ 214 + _C, _C, _C, _C, _C, _C, _C, _C, /* 90 */ 215 + _C, _C, _C, _C, _C, _C, _C, _C, /* 98 */ 216 + _P, _P, _P, _P, _P, _P, _P, _P, /* A0 */ 217 + _P, _P, _P, _P, _P, _P, _P, _P, /* A8 */ 218 + _P, _P, _P, _P, _P, _P, _P, _P, /* B0 */ 219 + _P, _P, _P, _P, _P, _P, _P, _P, /* B8 */ 220 + _P, _P, _P, _P, _P, _P, _P, _P, /* C0 */ 221 + _P, _P, _P, _P, _P, _P, _P, _P, /* C8 */ 222 + _P, _P, _P, _P, _P, _P, _P, _P, /* D0 */ 223 + _P, _P, _P, _P, _P, _P, _P, _P, /* D8 */ 224 + _P, _P, _P, _P, _P, _P, _P, _P, /* E0 */ 225 + _P, _P, _P, _P, _P, _P, _P, _P, /* E8 */ 226 + _P, _P, _P, _P, _P, _P, _P, _P, /* F0 */ 227 + _P, _P, _P, _P, _P, _P, _P, _P, /* F8 */ 228 + /* 0..127 */ 229 + _C, _C, _C, _C, _C, _C, _C, _C|_BLANK, 230 + _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C, 231 + _C, _C, _C, _C, _C, _C, _C, _C, 232 + _C, _C, _C, _C, _C, _C, _C, _C, 233 + _S|_B|_BLANK, _P, _P, _P, _P, _P, _P, _P, 234 + _P, _P, _P, _P, _P, _P, _P, _P, 235 + _N, _N, _N, _N, _N, _N, _N, _N, 236 + _N, _N, _P, _P, _P, _P, _P, _P, 237 + _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U, 238 + _U, _U, _U, _U, _U, _U, _U, _U, 239 + _U, _U, _U, _U, _U, _U, _U, _U, 240 + _U, _U, _U, _P, _P, _P, _P, _P, 241 + _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L, 242 + _L, _L, _L, _L, _L, _L, _L, _L, 243 + _L, _L, _L, _L, _L, _L, _L, _L, 244 + /* determine printability based on the IS0 8859 8-bit standard */ 245 + _L, _L, _L, _P, _P, _P, _P, _C, 246 + /* 128..255, same as -128..127 */ 247 + _C, _C, _C, _C, _C, _C, _C, _C, /* 80 */ 248 + _C, _C, _C, _C, _C, _C, _C, _C, /* 88 */ 249 + _C, _C, _C, _C, _C, _C, _C, _C, /* 90 */ 250 + _C, _C, _C, _C, _C, _C, _C, _C, /* 98 */ 251 + _P, _P, _P, _P, _P, _P, _P, _P, /* A0 */ 252 + _P, _P, _P, _P, _P, _P, _P, _P, /* A8 */ 253 + _P, _P, _P, _P, _P, _P, _P, _P, /* B0 */ 254 + _P, _P, _P, _P, _P, _P, _P, _P, /* B8 */ 255 + _P, _P, _P, _P, _P, _P, _P, _P, /* C0 */ 256 + _P, _P, _P, _P, _P, _P, _P, _P, /* C8 */ 257 + _P, _P, _P, _P, _P, _P, _P, _P, /* D0 */ 258 + _P, _P, _P, _P, _P, _P, _P, _P, /* D8 */ 259 + _P, _P, _P, _P, _P, _P, _P, _P, /* E0 */ 260 + _P, _P, _P, _P, _P, _P, _P, _P, /* E8 */ 261 + _P, _P, _P, _P, _P, _P, _P, _P, /* F0 */ 262 + _P, _P, _P, _P, _P, _P, _P, _P, /* F8 */ 263 +}; 264 + 265 +const unsigned short* const _ctype_android = ctype_android_tab + 128; 266 -- 267 1.7.12.146.g16d26b1 268 269