libc++: Add wchar support wrappers.

This implements many missing wchar-related functions needed to build the library.

This will probably better placed in its own static library in the future.

Note that this reimplements the functions for all API levels. This is because
of the following situation:

- Before API level 9, The NDK <wchar.h> defines wchar_t as 'unsigned char'
  and all implemented functions (e.g. wcslen()) by the system's C library
  are just stub to their string version (e.g. wcslen() -> strlen()).

  There was no official support for wchar_t in Bionic. The existing
  header was only used to be able to build the GNU toolchain with it.

- After API level 9, wchar_t switched to a 32-bit type, and wchar
  functions were implemented correctly, though some of them are
  missing.

By reimplementing everything, there is no need to check for the target
API level, and the resulting libraries will work on all Android systems.

Change-Id: I1cc42e32ab4be9ca68697dcac319d2cbba5a0ace
diff --git a/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk b/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk
index 7270b10..4bca4f6 100644
--- a/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk
+++ b/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk
@@ -29,7 +29,8 @@
 	valarray.cpp
 
 llvm_libc++_sources += \
-    support/android/locale_support.c
+    support/android/locale_support.c \
+    support/android/wchar_support.c
 
 llvm_libc++_sources := $(llvm_libc++_sources:%=src/%)
 llvm_libc++_cxxflags := -std=c++11
diff --git a/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c b/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c
new file mode 100644
index 0000000..6987bcd
--- /dev/null
+++ b/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c
@@ -0,0 +1,379 @@
+// -*- C++ -*-
+//===-------------------- support/android/wchar_support.c ------------------===//
+//
+//                     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 <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+// Returns 1 if 'wc' is in the 'delim' string, 0 otherwise.
+static int _wc_indelim(wchar_t wc, const wchar_t* delim) {
+    while (*delim) {
+        if (wc == *delim)
+            return 1;
+    }
+    return 0;
+}
+
+wchar_t *wcpcpy(wchar_t *to, const wchar_t *from) {
+    size_t n = 0;
+    for (;;) {
+        wchar_t wc = from[n];
+        to[n] = wc;
+        if (wc == L'\0')
+            break;
+        n++;
+    }
+    return to;
+}
+
+wchar_t *wcpncpy(wchar_t *dst, const wchar_t *src, size_t n) {
+    size_t i;
+    for (i = 0; i < n; ++i) {
+        wchar_t wc = src[i];
+        dst[i] = wc;
+        if (wc == L'\0')
+            break;
+    }
+    while (i < n) {
+        dst[i] = L'\0';
+        ++i;
+    }
+    return &dst[n-1];
+}
+
+int wcscasecmp(const wchar_t *s1, const wchar_t *s2) {
+    size_t n = 0;
+    for (;;) {
+        wchar_t wc1 = towlower(s1[n]);
+        wchar_t wc2 = towlower(s2[n]);
+        if (wc1 != wc2)
+            return (wc1 > wc2) ? +1 : -1;
+        if (wc1 == L'\0')
+            return 0;
+        n++;
+    }
+}
+
+wchar_t *wcscat(wchar_t *s1, const wchar_t *s2) {
+    size_t n = 0;
+    while (s1[n] != L'\0')
+        n++;
+
+    size_t i = 0;
+    for (;;) {
+        wchar_t wc = s2[i];
+        s1[n+i] = wc;
+        if (wc == L'\0')
+            break;
+    }
+    return s1;
+}
+
+size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t siz) {
+    // Sanity check simplifies code below
+    if (siz == 0)
+        return 0;
+
+    // Skip dst characters.
+    size_t n;
+    for (n = 0; n < siz && dst[n] != L'\0'; ++n)
+        ;
+
+    // Copy as much source characters as they fit into siz-1 bytes.
+    size_t i;
+    for (i = 0; n+i+1 < siz && src[i] != L'\0'; ++i)
+        dst[n+i] = src[i];
+
+    // Always zero terminate destination
+    dst[n+i] = L'\0';
+
+    // Skip remaining source characters
+    while (src[i] != L'\0')
+        i++;
+
+    return n+i;
+}
+
+size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) {
+    size_t i;
+
+    // Copy all non-zero bytes that fit into siz-1 destination bytes
+    for (i = 0; i + 1 < siz && src[i] != L'\0'; ++i)
+        dst[i] = src[i];
+
+    // Always zero-terminate destination buffer
+    dst[i] = L'\0';
+
+    // Skip other source characters.
+    while (src[i] != L'\0')
+        ++i;
+
+    return i;
+}
+
+size_t wcslen(const wchar_t *s) {
+    size_t n = 0;
+    for (;;) {
+        wchar_t wc = s[n];
+        if (wc == L'\0')
+            return n;
+        n++;
+    }
+}
+
+int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
+    size_t i;
+    for (i = 0; i < n; ++i) {
+        wchar_t wc1 = towlower(s1[i]);
+        wchar_t wc2 = towlower(s2[i]);
+        if (wc1 != wc2)
+            return (wc1 > wc2) ? +1 : -1;
+    }
+    return 0;
+}
+
+wchar_t *wcsncat(wchar_t *s1, const wchar_t *s2, size_t n) {
+    size_t start = 0;
+    while (s1[start] != L'\0')
+        start++;
+
+    // Append s2.
+    size_t i;
+    for (i = 0; i < n; ++i) {
+        wchar_t wc = s2[i];
+        s1[start + i] = wc;
+        if (wc == L'\0')
+            break;
+    }
+    return (wchar_t*)s1;
+}
+
+int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
+    size_t i;
+    for (i = 0; i < n; ++i) {
+        wchar_t wc = s1[i];
+        if (wc != s2[i])
+            return (wc > s2[i]) ? +1 : -1;
+        if (wc == L'\0')
+            break;
+    }
+    return 0;
+}
+
+wchar_t *wcsncpy(wchar_t *dst, const wchar_t *src, size_t n) {
+    // Copy initial characters.
+    size_t i;
+    for (i = 0; i < n; ++i) {
+        wchar_t wc = src[i];
+        if (wc == L'\0')
+            break;
+        dst[i] = wc;
+    }
+    // zero-pad the remainder.
+    for ( ; i < n; ++i)
+        dst[i] = L'\0';
+
+    return dst;
+}
+
+size_t wcsnlen(const wchar_t *s, size_t maxlen) {
+    size_t n;
+    for (n = 0; n < maxlen; ++n) {
+        if (s[n] == L'\0')
+            break;
+    }
+    return n;
+}
+
+wchar_t *wcspbrk(const wchar_t *s, const wchar_t *set) {
+    size_t n = 0;
+    for (;;) {
+        wchar_t wc = s[n];
+        if (!wc)
+            return NULL;
+        if (_wc_indelim(wc, set))
+            return (wchar_t*)&s[n];
+        n++;
+    }
+}
+
+wchar_t *wcsrchr(const wchar_t *s, wchar_t c) {
+    size_t n = 0;
+    wchar_t* last = NULL;
+    for (;;) {
+        wchar_t wc = s[n];
+        if (wc == c)
+            last = (wchar_t*)s + n;
+        if (wc == L'\0')
+            break;
+        n++;
+    }
+    return last;
+}
+
+size_t wcsspn(const wchar_t *s, const wchar_t *set) {
+    size_t n = 0;
+    for (;;) {
+        wchar_t wc = s[n];
+        if (wc == L'\0')
+            break;
+        if (!_wc_indelim(wc, set))
+            break;
+        ++n;
+    }
+    return n;
+}
+
+wchar_t *wcsstr(const wchar_t *s, const wchar_t *find) {
+    wchar_t find_c;
+
+    // Always find the empty string
+    find_c = *find++;
+    if (!find_c)
+        return (wchar_t*)s;
+
+    size_t find_len = wcslen(find);
+
+    for (;;) {
+        wchar_t* p = wcschr(s, find_c);
+        if (p == NULL)
+            return NULL;
+
+        if (!wmemcmp(p, find, find_len))
+            return p;
+
+        s = p + 1;
+    }
+    return NULL;
+}
+
+wchar_t *wcstok(wchar_t *s, const wchar_t *delim, wchar_t **last) {
+    if (s == NULL) {
+        s = *last;
+        if (s == NULL)
+            return NULL;
+    }
+
+    // Skip leading delimiters first.
+    size_t i = 0;
+    wchar_t wc;
+    for (;;) {
+        wc = s[i];
+        if (wc && _wc_indelim(wc, delim)) {
+            i++;
+            continue;
+        }
+        break;
+    }
+
+    if (!wc) {
+        // Nothing left.
+        *last = NULL;
+        return NULL;
+    }
+
+    size_t tok_start = i;
+
+    // Skip non delimiters now.
+    for (;;) {
+        wc = s[i];
+        if (wc && !_wc_indelim(wc, delim)) {
+            i++;
+            continue;
+        }
+        break;
+    }
+
+    if (!wc) {
+        *last = NULL;
+    } else {
+        s[i] = L'\0';
+        *last = &s[i+1];
+    }
+    return &s[tok_start];
+}
+
+int wcswidth(const wchar_t *str, size_t n) {
+    int len = 0;
+    size_t i;
+    for (i = 0; i < n; ++i) {
+        wchar_t wc = str[i];
+        if (wc == L'\0')
+            break;
+        int l = wcwidth(wc);
+        if (l < 0)
+            return -1;
+        len += l;
+    }
+    return len;
+}
+
+// TODO(digit): Handle real collations.
+size_t wcsxfrm(wchar_t *dst, const wchar_t *src, size_t len) {
+    // Handle trivial case first.
+    if (src[0] == L'\0') {
+        if (len != 0)
+            dst[0] = L'\0';
+        return 0;
+    }
+
+    size_t slen = wcslen(src);
+    if (len > 0) {
+        if (slen < len)
+            wcscpy(dst, src);
+        else {
+            wcsncpy(dst, src, len-1);
+            dst[len - 1] = L'\0';
+        }
+    }
+    return slen;
+}
+
+wchar_t * wmemchr(const wchar_t *s, wchar_t c, size_t n) {
+    size_t i;
+    for (i = 0; i < n; ++i) {
+        if (s[i] == c)
+            return (wchar_t*)&s[i];
+    }
+    return NULL;
+}
+
+int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
+    size_t i;
+    for (i = 0; i < n; ++i) {
+        if (s1[i] == s2[i])
+            continue;
+        if (s1[i] > s2[i])
+            return 1;
+        else
+            return -1;
+    }
+    return 0;
+}
+
+wchar_t * wmemcpy(wchar_t *d, const wchar_t *s, size_t n) {
+        return (wchar_t *)memcpy((char*)d,
+                                 (const char*)s,
+                                 n * sizeof(wchar_t));
+}
+
+wchar_t* wmemmove(wchar_t* d, const wchar_t* s, size_t n) {
+        return (wchar_t* )memmove((char*)d,
+                                  (const char*)s,
+                                  n * sizeof(wchar_t));
+}
+
+wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n) {
+    size_t i;
+    for (i = 0; i < n; ++i)
+        s[i] = c;
+    return s;
+}
+