| From 9713832a39df1c7257af71cd38195e62768c1229 Mon Sep 17 00:00:00 2001 | 
 | From: David 'Digit' Turner <digit@google.com> | 
 | Date: Tue, 9 Jul 2013 23:20:03 +0200 | 
 | Subject: android: Add locale support. | 
 |  | 
 | This is based on the Bionic <ctype.h> declarations. Note that | 
 | unfortunately, the _ctype_ table exposed by this header has a bug | 
 | so a fixed copy is included here instead. | 
 |  | 
 | See src/support/android/locale_android.cpp for details. | 
 | --- | 
 |  include/__locale                       |  17 +++++- | 
 |  src/locale.cpp                         |  25 +++++++- | 
 |  src/support/android/locale_android.cpp | 101 +++++++++++++++++++++++++++++++++ | 
 |  3 files changed, 140 insertions(+), 3 deletions(-) | 
 |  create mode 100644 src/support/android/locale_android.cpp | 
 |  | 
 | diff --git a/include/__locale b/include/__locale | 
 | index 24d565b..954e7f5 100644 | 
 | --- a/include/__locale | 
 | +++ b/include/__locale | 
 | @@ -369,7 +369,20 @@ public: | 
 |      static const mask punct  = _ISPUNCT; | 
 |      static const mask xdigit = _ISXDIGIT; | 
 |      static const mask blank  = _ISBLANK; | 
 | -#else  // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ || EMSCRIPTEN || __sun__ | 
 | +#elif defined(__ANDROID__) | 
 | +    typedef unsigned short mask; | 
 | +    static const mask space  = _S; | 
 | +    static const mask print  = _P | _U | _L | _N | _B; | 
 | +    static const mask cntrl  = _C; | 
 | +    static const mask upper  = _U; | 
 | +    static const mask lower  = _L; | 
 | +    static const mask alpha  = _U | _L; | 
 | +    static const mask digit  = _N; | 
 | +    static const mask punct  = _P; | 
 | +    static const mask xdigit = _N | _X; | 
 | +    // See src/support/android/locale_android.cpp for details! | 
 | +    static const mask blank  = 0x100; | 
 | +#else  // __ANDROID__ | 
 |      typedef unsigned long mask; | 
 |      static const mask space  = 1<<0; | 
 |      static const mask print  = 1<<1; | 
 | @@ -381,7 +394,7 @@ public: | 
 |      static const mask punct  = 1<<7; | 
 |      static const mask xdigit = 1<<8; | 
 |      static const mask blank  = 1<<9; | 
 | -#endif  // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ | 
 | +#endif  // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ || EMSCRIPTEN || __sun__ || __ANDROID__ | 
 |      static const mask alnum  = alpha | digit; | 
 |      static const mask graph  = alnum | punct; | 
 |   | 
 | diff --git a/src/locale.cpp b/src/locale.cpp | 
 | index 49c1cf2..25ac0a4 100644 | 
 | --- a/src/locale.cpp | 
 | +++ b/src/locale.cpp | 
 | @@ -788,6 +788,8 @@ ctype<wchar_t>::do_toupper(char_type c) const | 
 |      return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; | 
 |  #elif defined(__GLIBC__) || defined(EMSCRIPTEN) | 
 |      return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c; | 
 | +#elif defined(__ANDROID__) | 
 | +    return isascii(c) ? _toupper_tab_[c + 1] : c; | 
 |  #else | 
 |      return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c; | 
 |  #endif | 
 | @@ -802,6 +804,8 @@ ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const | 
 |  #elif defined(__GLIBC__) || defined(EMSCRIPTEN) | 
 |          *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] | 
 |                               : *low; | 
 | +#elif defined(__ANDROID__) | 
 | +        *low = isascii(*low) ? _toupper_tab_[*low + 1] : *low; | 
 |  #else | 
 |          *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low; | 
 |  #endif | 
 | @@ -815,6 +819,8 @@ ctype<wchar_t>::do_tolower(char_type c) const | 
 |      return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; | 
 |  #elif defined(__GLIBC__) || defined(EMSCRIPTEN) | 
 |      return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c; | 
 | +#elif defined(__ANDROID__) | 
 | +    return isascii(c) ? _tolower_tab_[c + 1] : c; | 
 |  #else | 
 |      return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c; | 
 |  #endif | 
 | @@ -829,6 +835,8 @@ ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const | 
 |  #elif defined(__GLIBC__) || defined(EMSCRIPTEN) | 
 |          *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] | 
 |                               : *low; | 
 | +#elif defined(__ANDROID__) | 
 | +        *low = isascii(*low) ? _tolower_tab_[*low] : *low; | 
 |  #else | 
 |          *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low; | 
 |  #endif | 
 | @@ -896,6 +904,8 @@ ctype<char>::do_toupper(char_type c) const | 
 |  #elif defined(__GLIBC__) || defined(EMSCRIPTEN) | 
 |      return isascii(c) ?  | 
 |        static_cast<char>(__classic_upper_table()[static_cast<size_t>(c)]) : c; | 
 | +#elif defined(__ANDROID__) | 
 | +    return isascii(c) ? _toupper_tab_[c + 1] : c; | 
 |  #else | 
 |      return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c; | 
 |  #endif | 
 | @@ -911,6 +921,8 @@ ctype<char>::do_toupper(char_type* low, const char_type* high) const | 
 |  #elif defined(__GLIBC__) || defined(EMSCRIPTEN) | 
 |          *low = isascii(*low) ? | 
 |            static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low; | 
 | +#elif defined(__ANDROID__) | 
 | +        *low = isascii(*low) ? _toupper_tab_[*low + 1] : *low; | 
 |  #else | 
 |          *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low; | 
 |  #endif | 
 | @@ -926,6 +938,8 @@ ctype<char>::do_tolower(char_type c) const | 
 |  #elif defined(__GLIBC__) || defined(EMSCRIPTEN) | 
 |      return isascii(c) ? | 
 |        static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c; | 
 | +#elif defined(__ANDROID__) | 
 | +    return isascii(c) ? _tolower_tab_[c + 1] : c; | 
 |  #else | 
 |      return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c; | 
 |  #endif | 
 | @@ -939,6 +953,8 @@ ctype<char>::do_tolower(char_type* low, const char_type* high) const | 
 |          *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low; | 
 |  #elif defined(__GLIBC__) || defined(EMSCRIPTEN) | 
 |          *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low; | 
 | +#elif defined(__ANDROID__) | 
 | +        *low = isascii(*low) ? _tolower_tab_[*low + 1] : *low; | 
 |  #else | 
 |          *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low; | 
 |  #endif | 
 | @@ -978,12 +994,17 @@ ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, | 
 |      return low; | 
 |  } | 
 |   | 
 | -#ifdef EMSCRIPTEN | 
 | +#if defined(EMSCRIPTEN) | 
 |  extern "C" const unsigned short ** __ctype_b_loc(); | 
 |  extern "C" const int ** __ctype_tolower_loc(); | 
 |  extern "C" const int ** __ctype_toupper_loc(); | 
 |  #endif | 
 |   | 
 | +#if defined(__ANDROID__) | 
 | +// See src/support/android/android_locale.cpp | 
 | +extern "C" const unsigned short* const _ctype_android; | 
 | +#endif | 
 | + | 
 |  const ctype<char>::mask* | 
 |  ctype<char>::classic_table()  _NOEXCEPT | 
 |  { | 
 | @@ -999,6 +1020,8 @@ ctype<char>::classic_table()  _NOEXCEPT | 
 |  // going to end up dereferencing it later... | 
 |  #elif defined(EMSCRIPTEN) | 
 |      return *__ctype_b_loc(); | 
 | +#elif defined(__ANDROID__) | 
 | +    return _ctype_android; | 
 |  #else | 
 |      // Platform not supported: abort so the person doing the port knows what to | 
 |      // fix | 
 | diff --git a/src/support/android/locale_android.cpp b/src/support/android/locale_android.cpp | 
 | new file mode 100644 | 
 | index 0000000..81c3b28 | 
 | --- /dev/null | 
 | +++ b/src/support/android/locale_android.cpp | 
 | @@ -0,0 +1,101 @@ | 
 | +// -*- C++ -*- | 
 | +//===-------------------- support/win32/locale_win32.cpp ------------------===// | 
 | +// | 
 | +//                     The LLVM Compiler Infrastructure | 
 | +// | 
 | +// This file is dual licensed under the MIT and the University of Illinois Open | 
 | +// Source Licenses. See LICENSE.TXT for details. | 
 | +// | 
 | +//===----------------------------------------------------------------------===// | 
 | + | 
 | +#include <ctype.h> | 
 | + | 
 | +// Bionic exports the non-standard _ctype_ array in <ctype.h>, | 
 | +// unfortunately, cannot be used directly for libc++ because it doesn't | 
 | +// have a proper bit-flag for blank characters. | 
 | +// | 
 | +// Note that the header does define a _B flag (as 0x80), but it | 
 | +// is only set on the space (32) character, and used to implement | 
 | +// isprint() properly. The implementation of isblank() relies on | 
 | +// direct comparisons with 7 and 32 instead. | 
 | +// | 
 | +// The following is a local copy of the Bionic _ctype_ array that has | 
 | +// been modified in the following way: | 
 | +// | 
 | +//   - It stores 16-bit unsigned values, instead of 8-bit char ones. | 
 | +// | 
 | +//   - Bit flag _BLANK (0x100) is used to indicate blank characters. | 
 | +//     It is only set for indices 7 (TAB) and 32 (SPACE). | 
 | +// | 
 | +//   - Support signed char properly for indexing. | 
 | + | 
 | +// Used to tag blank characters, this doesn't appear in <ctype.h> nor | 
 | +// the original Bionic _ctype_ array. | 
 | +#define _BLANK  0x100 | 
 | + | 
 | +// NOTE: A standalone forward declaration is required to ensure that this | 
 | +// variable is properly exported with a C name. In other words, this does | 
 | +// _not_ work: | 
 | +// | 
 | +//  extern "C" { | 
 | +//  const char* const _ctype_android = ...; | 
 | +//  } | 
 | +// | 
 | +extern "C" const unsigned short* const _ctype_android; | 
 | + | 
 | +static const unsigned short ctype_android_tab[256+128] = { | 
 | +       /* -128..-1 */ | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, /* 80 */ | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, /* 88 */ | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, /* 90 */ | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, /* 98 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* A0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* A8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* B0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* B8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* C0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* C8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* D0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* D8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* E0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* E8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* F0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* F8 */ | 
 | +       /* 0..127 */ | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C|_BLANK, | 
 | +        _C,     _C|_S,  _C|_S,  _C|_S,  _C|_S,  _C|_S,  _C,     _C, | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, | 
 | +  _S|_B|_BLANK, _P,     _P,     _P,     _P,     _P,     _P,     _P, | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, | 
 | +        _N,     _N,     _N,     _N,     _N,     _N,     _N,     _N, | 
 | +        _N,     _N,     _P,     _P,     _P,     _P,     _P,     _P, | 
 | +        _P,     _U|_X,  _U|_X,  _U|_X,  _U|_X,  _U|_X,  _U|_X,  _U, | 
 | +        _U,     _U,     _U,     _U,     _U,     _U,     _U,     _U, | 
 | +        _U,     _U,     _U,     _U,     _U,     _U,     _U,     _U, | 
 | +        _U,     _U,     _U,     _P,     _P,     _P,     _P,     _P, | 
 | +        _P,     _L|_X,  _L|_X,  _L|_X,  _L|_X,  _L|_X,  _L|_X,  _L, | 
 | +        _L,     _L,     _L,     _L,     _L,     _L,     _L,     _L, | 
 | +        _L,     _L,     _L,     _L,     _L,     _L,     _L,     _L, | 
 | +        /* determine printability based on the IS0 8859 8-bit standard */ | 
 | +        _L,     _L,     _L,     _P,     _P,     _P,     _P,     _C, | 
 | +        /* 128..255, same as -128..127 */ | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, /* 80 */ | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, /* 88 */ | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, /* 90 */ | 
 | +        _C,     _C,     _C,     _C,     _C,     _C,     _C,     _C, /* 98 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* A0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* A8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* B0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* B8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* C0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* C8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* D0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* D8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* E0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* E8 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* F0 */ | 
 | +        _P,     _P,     _P,     _P,     _P,     _P,     _P,     _P, /* F8 */ | 
 | +}; | 
 | + | 
 | +const unsigned short* const _ctype_android = ctype_android_tab + 128; | 
 | --  | 
 | 1.7.12.146.g16d26b1 | 
 |  |