Merge "Fix <wctype.h>."

am: 146cbacea0

* commit '146cbacea0754356a784608474149d291d92500a':
  Fix <wctype.h>.

Change-Id: Ica0217c3d10677f3d6d502ffa4ca4f6b8d56226d
This commit is contained in:
Elliott Hughes 2016-04-29 18:18:11 +00:00 committed by android-build-merger
commit 005276fd95
16 changed files with 356 additions and 42 deletions

View file

@ -26,11 +26,13 @@
* SUCH DAMAGE.
*/
#include <wctype.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <wctype.h>
// TODO: these only work for the ASCII range; rewrite to dlsym icu4c? http://b/14499654
@ -85,8 +87,8 @@ int iswctype_l(wint_t wc, wctype_t char_class, locale_t) {
wint_t towlower(wint_t wc) { return tolower(wc); }
wint_t towupper(wint_t wc) { return toupper(wc); }
int towupper_l(int c, locale_t) { return towupper(c); }
int towlower_l(int c, locale_t) { return towlower(c); }
wint_t towupper_l(int c, locale_t) { return towupper(c); }
wint_t towlower_l(int c, locale_t) { return towlower(c); }
wctype_t wctype(const char* property) {
static const char* const properties[WC_TYPE_MAX] = {
@ -109,3 +111,27 @@ wctype_t wctype_l(const char* property, locale_t) {
int wcwidth(wchar_t wc) {
return (wc > 0);
}
static wctrans_t wctrans_tolower = wctrans_t(1);
static wctrans_t wctrans_toupper = wctrans_t(2);
wctrans_t wctrans(const char* name) {
if (strcmp(name, "tolower") == 0) return wctrans_tolower;
if (strcmp(name, "toupper") == 0) return wctrans_toupper;
return 0;
}
wctrans_t wctrans_l(const char* name, locale_t) {
return wctrans(name);
}
wint_t towctrans(wint_t c, wctrans_t t) {
if (t == wctrans_tolower) return towlower(c);
if (t == wctrans_toupper) return towupper(c);
errno = EINVAL;
return 0;
}
wint_t towctrans_l(wint_t c, wctrans_t t, locale_t) {
return towctrans(c, t);
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _BITS_WCTYPE_H_
#define _BITS_WCTYPE_H_
#include <sys/cdefs.h>
__BEGIN_DECLS
typedef __WINT_TYPE__ wint_t;
int iswalnum(wint_t);
int iswalpha(wint_t);
int iswblank(wint_t);
int iswcntrl(wint_t);
int iswdigit(wint_t);
int iswgraph(wint_t);
int iswlower(wint_t);
int iswprint(wint_t);
int iswpunct(wint_t);
int iswspace(wint_t);
int iswupper(wint_t);
int iswxdigit(wint_t);
wint_t towlower(wint_t);
wint_t towupper(wint_t);
typedef long wctype_t;
wctype_t wctype(const char*);
int iswctype(wint_t, wctype_t);
typedef const void* wctrans_t;
wint_t towctrans(wint_t, wctrans_t);
wctrans_t wctrans(const char*);
__END_DECLS
#endif

View file

@ -37,10 +37,10 @@
#include <xlocale.h>
#include <bits/wchar_limits.h>
#include <bits/wctype.h>
__BEGIN_DECLS
typedef __WINT_TYPE__ wint_t;
typedef struct {
uint8_t __seq[4];
#ifdef __LP64__
@ -65,26 +65,11 @@ enum {
WC_TYPE_MAX
};
typedef long wctype_t;
#define WEOF ((wint_t)(-1))
extern wint_t btowc(int);
extern int fwprintf(FILE *, const wchar_t *, ...);
extern int fwscanf(FILE *, const wchar_t *, ...);
extern int iswalnum(wint_t);
extern int iswalpha(wint_t);
extern int iswblank(wint_t);
extern int iswcntrl(wint_t);
extern int iswdigit(wint_t);
extern int iswgraph(wint_t);
extern int iswlower(wint_t);
extern int iswprint(wint_t);
extern int iswpunct(wint_t);
extern int iswspace(wint_t);
extern int iswupper(wint_t);
extern int iswxdigit(wint_t);
extern int iswctype(wint_t, wctype_t);
extern wint_t fgetwc(FILE *);
extern wchar_t *fgetws(wchar_t *, int, FILE *);
extern wint_t fputwc(wchar_t, FILE *);
@ -101,8 +86,6 @@ extern wint_t putwc(wchar_t, FILE *);
extern wint_t putwchar(wchar_t);
extern int swprintf(wchar_t *, size_t, const wchar_t *, ...);
extern int swscanf(const wchar_t *, const wchar_t *, ...);
extern wint_t towlower(wint_t);
extern wint_t towupper(wint_t);
extern wint_t ungetwc(wint_t, FILE *);
extern int vfwprintf(FILE*, const wchar_t*, va_list);
extern int vfwscanf(FILE*, const wchar_t*, va_list);
@ -145,7 +128,6 @@ extern unsigned long long wcstoull(const wchar_t*, wchar_t**, int);
extern int wcswidth(const wchar_t *, size_t);
extern size_t wcsxfrm(wchar_t *, const wchar_t *, size_t);
extern int wctob(wint_t);
extern wctype_t wctype(const char *);
extern int wcwidth(wchar_t);
extern wchar_t *wmemchr(const wchar_t *, wchar_t, size_t);
extern int wmemcmp(const wchar_t *, const wchar_t *, size_t);
@ -168,10 +150,6 @@ extern size_t wcsxfrm_l(wchar_t *, const wchar_t *, size_t, locale_t);
extern size_t wcslcat(wchar_t*, const wchar_t*, size_t);
extern size_t wcslcpy(wchar_t*, const wchar_t*, size_t);
typedef void *wctrans_t;
extern wint_t towctrans(wint_t, wctrans_t) __UNAVAILABLE;
extern wctrans_t wctrans(const char*) __UNAVAILABLE;
#if __POSIX_VISIBLE >= 200809
FILE* open_wmemstream(wchar_t**, size_t*);
wchar_t* wcsdup(const wchar_t*);

View file

@ -31,25 +31,31 @@
#include <wchar.h>
#include <bits/wctype.h>
__BEGIN_DECLS
extern int iswalnum_l(wint_t, locale_t);
extern int iswalpha_l(wint_t, locale_t);
extern int iswblank_l(wint_t, locale_t);
extern int iswcntrl_l(wint_t, locale_t);
extern int iswdigit_l(wint_t, locale_t);
extern int iswgraph_l(wint_t, locale_t);
extern int iswlower_l(wint_t, locale_t);
extern int iswprint_l(wint_t, locale_t);
extern int iswpunct_l(wint_t, locale_t);
extern int iswspace_l(wint_t, locale_t);
extern int iswupper_l(wint_t, locale_t);
extern int iswxdigit_l(wint_t, locale_t);
extern int towlower_l(int, locale_t);
extern int towupper_l(int, locale_t);
int iswalnum_l(wint_t, locale_t);
int iswalpha_l(wint_t, locale_t);
int iswblank_l(wint_t, locale_t);
int iswcntrl_l(wint_t, locale_t);
int iswdigit_l(wint_t, locale_t);
int iswgraph_l(wint_t, locale_t);
int iswlower_l(wint_t, locale_t);
int iswprint_l(wint_t, locale_t);
int iswpunct_l(wint_t, locale_t);
int iswspace_l(wint_t, locale_t);
int iswupper_l(wint_t, locale_t);
int iswxdigit_l(wint_t, locale_t);
extern int iswctype_l(wint_t, wctype_t, locale_t);
extern wctype_t wctype_l(const char*, locale_t);
wint_t towlower_l(int, locale_t);
wint_t towupper_l(int, locale_t);
wint_t towctrans_l(wint_t, wctrans_t, locale_t);
wctrans_t wctrans_l(const char*, locale_t);
wctype_t wctype_l(const char*, locale_t);
int iswctype_l(wint_t, wctype_t, locale_t);
__END_DECLS

View file

@ -1291,6 +1291,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -1291,6 +1291,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -1213,6 +1213,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -1316,6 +1316,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -1275,6 +1275,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -1275,6 +1275,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -1213,6 +1213,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -1273,6 +1273,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -1273,6 +1273,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -1213,6 +1213,10 @@ LIBC_O {
sigrelse;
sigset;
sync_file_range;
towctrans;
towctrans_l;
wctrans;
wctrans_l;
} LIBC_N;
LIBC_PRIVATE {

View file

@ -129,6 +129,7 @@ libBionicStandardTests_src_files := \
unistd_test.cpp \
utmp_test.cpp \
wchar_test.cpp \
wctype_test.cpp \
libBionicStandardTests_cflags := \
$(test_cflags) \

199
tests/wctype_test.cpp Normal file
View file

@ -0,0 +1,199 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <wctype.h>
#include <gtest/gtest.h>
class UtfLocale {
public:
UtfLocale() : l(newlocale(LC_ALL, "C.UTF-8", 0)) {}
~UtfLocale() { freelocale(l); }
locale_t l;
};
static void TestIsWideFn(int fn(wint_t),
int fn_l(wint_t, locale_t),
const wchar_t* trues,
const wchar_t* falses) {
UtfLocale l;
for (const wchar_t* p = trues; *p; ++p) {
EXPECT_TRUE(fn(*p)) << *p;
EXPECT_TRUE(fn_l(*p, l.l)) << *p;
}
for (const wchar_t* p = falses; *p; ++p) {
EXPECT_FALSE(fn(*p)) << *p;
EXPECT_FALSE(fn_l(*p, l.l)) << *p;
}
}
TEST(wctype, iswalnum) {
TestIsWideFn(iswalnum, iswalnum_l, L"1aA", L"! \b");
}
TEST(wctype, iswalpha) {
TestIsWideFn(iswalpha, iswalpha_l, L"aA", L"1! \b");
}
TEST(wctype, iswblank) {
TestIsWideFn(iswblank, iswblank_l, L" \t", L"1aA!\b");
}
TEST(wctype, iswcntrl) {
TestIsWideFn(iswcntrl, iswcntrl_l, L"\b", L"1aA! ");
}
TEST(wctype, iswdigit) {
TestIsWideFn(iswdigit, iswdigit_l, L"1", L"aA! \b");
}
TEST(wctype, iswgraph) {
TestIsWideFn(iswgraph, iswgraph_l, L"1aA!", L" \b");
}
TEST(wctype, iswlower) {
TestIsWideFn(iswlower, iswlower_l, L"a", L"1A! \b");
}
TEST(wctype, iswprint) {
TestIsWideFn(iswprint, iswprint_l, L"1aA! ", L"\b");
}
TEST(wctype, iswpunct) {
TestIsWideFn(iswpunct, iswpunct_l, L"!", L"1aA \b");
}
TEST(wctype, iswspace) {
TestIsWideFn(iswspace, iswspace_l, L" \f\t", L"1aA!\b");
}
TEST(wctype, iswupper) {
TestIsWideFn(iswupper, iswupper_l, L"A", L"1a! \b");
}
TEST(wctype, iswxdigit) {
TestIsWideFn(iswxdigit, iswxdigit_l, L"01aA", L"xg! \b");
}
TEST(wctype, towlower) {
EXPECT_EQ(wint_t('!'), towlower(L'!'));
EXPECT_EQ(wint_t('a'), towlower(L'a'));
EXPECT_EQ(wint_t('a'), towlower(L'A'));
}
TEST(wctype, towlower_l) {
UtfLocale l;
EXPECT_EQ(wint_t('!'), towlower_l(L'!', l.l));
EXPECT_EQ(wint_t('a'), towlower_l(L'a', l.l));
EXPECT_EQ(wint_t('a'), towlower_l(L'A', l.l));
}
TEST(wctype, towupper) {
EXPECT_EQ(wint_t('!'), towupper(L'!'));
EXPECT_EQ(wint_t('A'), towupper(L'a'));
EXPECT_EQ(wint_t('A'), towupper(L'A'));
}
TEST(wctype, towupper_l) {
UtfLocale l;
EXPECT_EQ(wint_t('!'), towupper_l(L'!', l.l));
EXPECT_EQ(wint_t('A'), towupper_l(L'a', l.l));
EXPECT_EQ(wint_t('A'), towupper_l(L'A', l.l));
}
TEST(wctype, wctype) {
EXPECT_TRUE(wctype("alnum") != 0);
EXPECT_TRUE(wctype("alpha") != 0);
EXPECT_TRUE(wctype("blank") != 0);
EXPECT_TRUE(wctype("cntrl") != 0);
EXPECT_TRUE(wctype("digit") != 0);
EXPECT_TRUE(wctype("graph") != 0);
EXPECT_TRUE(wctype("lower") != 0);
EXPECT_TRUE(wctype("print") != 0);
EXPECT_TRUE(wctype("punct") != 0);
EXPECT_TRUE(wctype("space") != 0);
EXPECT_TRUE(wctype("upper") != 0);
EXPECT_TRUE(wctype("xdigit") != 0);
EXPECT_TRUE(wctype("monkeys") == 0);
}
TEST(wctype, wctype_l) {
UtfLocale l;
EXPECT_TRUE(wctype_l("alnum", l.l) != 0);
EXPECT_TRUE(wctype_l("alpha", l.l) != 0);
EXPECT_TRUE(wctype_l("blank", l.l) != 0);
EXPECT_TRUE(wctype_l("cntrl", l.l) != 0);
EXPECT_TRUE(wctype_l("digit", l.l) != 0);
EXPECT_TRUE(wctype_l("graph", l.l) != 0);
EXPECT_TRUE(wctype_l("lower", l.l) != 0);
EXPECT_TRUE(wctype_l("print", l.l) != 0);
EXPECT_TRUE(wctype_l("punct", l.l) != 0);
EXPECT_TRUE(wctype_l("space", l.l) != 0);
EXPECT_TRUE(wctype_l("upper", l.l) != 0);
EXPECT_TRUE(wctype_l("xdigit", l.l) != 0);
EXPECT_TRUE(wctype_l("monkeys", l.l) == 0);
}
TEST(wctype, iswctype) {
EXPECT_TRUE(iswctype(L'a', wctype("alnum")));
EXPECT_TRUE(iswctype(L'1', wctype("alnum")));
EXPECT_FALSE(iswctype(L' ', wctype("alnum")));
EXPECT_EQ(0, iswctype(WEOF, wctype("alnum")));
}
TEST(wctype, iswctype_l) {
UtfLocale l;
EXPECT_TRUE(iswctype_l(L'a', wctype_l("alnum", l.l), l.l));
EXPECT_TRUE(iswctype_l(L'1', wctype_l("alnum", l.l), l.l));
EXPECT_FALSE(iswctype_l(L' ', wctype_l("alnum", l.l), l.l));
EXPECT_EQ(0, iswctype_l(WEOF, wctype_l("alnum", l.l), l.l));
}
TEST(wctype, towctrans) {
EXPECT_TRUE(wctrans("tolower") != 0);
EXPECT_TRUE(wctrans("toupper") != 0);
EXPECT_TRUE(wctrans("monkeys") == 0);
}
TEST(wctype, towctrans_l) {
UtfLocale l;
EXPECT_TRUE(wctrans_l("tolower", l.l) != 0);
EXPECT_TRUE(wctrans_l("toupper", l.l) != 0);
EXPECT_TRUE(wctrans_l("monkeys", l.l) == 0);
}
TEST(wctype, wctrans) {
EXPECT_EQ(wint_t('a'), towctrans(L'A', wctrans("tolower")));
EXPECT_EQ(WEOF, towctrans(WEOF, wctrans("tolower")));
EXPECT_EQ(wint_t('A'), towctrans(L'a', wctrans("toupper")));
EXPECT_EQ(WEOF, towctrans(WEOF, wctrans("toupper")));
}
TEST(wctype, wctrans_l) {
UtfLocale l;
EXPECT_EQ(wint_t('a'), towctrans_l(L'A', wctrans_l("tolower", l.l), l.l));
EXPECT_EQ(WEOF, towctrans_l(WEOF, wctrans_l("tolower", l.l), l.l));
EXPECT_EQ(wint_t('A'), towctrans_l(L'a', wctrans_l("toupper", l.l), l.l));
EXPECT_EQ(WEOF, towctrans_l(WEOF, wctrans_l("toupper", l.l), l.l));
}