blob: 5b63e823f22ebb0fcfec6407c6acc61bbdb5f1bd [file] [log] [blame]
From fbb68e1b52988199871392b4e16d611158a79995 Mon Sep 17 00:00:00 2001
From: David 'Digit' Turner <digit@google.com>
Date: Wed, 12 Feb 2014 20:04:18 +0800
Subject: [PATCH 1/6] 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 6d75162..d50fd31 100644
--- a/include/__locale
+++ b/include/__locale
@@ -375,7 +375,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;
@@ -387,7 +400,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 4877f2b..66aaca9 100644
--- a/src/locale.cpp
+++ b/src/locale.cpp
@@ -814,6 +814,8 @@ ctype<wchar_t>::do_toupper(char_type c) const
return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
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
@@ -828,6 +830,8 @@ ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
*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
@@ -841,6 +845,8 @@ ctype<wchar_t>::do_tolower(char_type c) const
return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
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
@@ -855,6 +861,8 @@ ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
*low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
: *low;
+#elif defined(__ANDROID__)
+ *low = isascii(*low) ? _tolower_tab_[*low + 1] : *low;
#else
*low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
#endif
@@ -924,6 +932,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<unsigned char>(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
@@ -941,6 +951,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
@@ -958,6 +970,8 @@ ctype<char>::do_tolower(char_type c) const
#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
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
@@ -973,6 +987,8 @@ ctype<char>::do_tolower(char_type* low, const char_type* high) const
*low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*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
@@ -1018,6 +1034,11 @@ 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
{
@@ -1035,6 +1056,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;
#elif defined(_AIX)
return (const unsigned int *)__lc_ctype_ptr->obj->mask;
#else
@@ -1422,7 +1445,7 @@ locale::id codecvt<wchar_t, char, mbstate_t>::id;
codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
: locale::facet(refs),
- __l(_LIBCPP_GET_C_LOCALE)
+ __l(0)
{
}
diff --git a/src/support/android/locale_android.cpp b/src/support/android/locale_android.cpp
new file mode 100644
index 0000000..7193028
--- /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 9 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 9 (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,
+ _C, _C|_S|_BLANK, _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.9.0.rc1.175.g0b1dcb5