From 3376c23daceddd603478347c00163f39e7c9e1ee Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 13 Feb 2018 23:14:12 -0800 Subject: [PATCH] Add remaining _l function stubs. Bug: http://b/65595804 Test: ran tests Change-Id: I3bea3af20b354d1f0d3e05fd35421a9045f29020 --- libc/bionic/wchar_l.cpp | 40 +++++++++++++++++++++++++++++----------- libc/include/sys/cdefs.h | 1 + libc/include/time.h | 7 ++++--- libc/include/wchar.h | 5 +++++ libc/libc.arm.map | 6 ++++++ libc/libc.arm64.map | 6 ++++++ libc/libc.map.txt | 6 ++++++ libc/libc.mips.map | 6 ++++++ libc/libc.mips64.map | 6 ++++++ libc/libc.x86.map | 6 ++++++ libc/libc.x86_64.map | 6 ++++++ libc/tzcode/strptime.c | 4 ++++ tests/time_test.cpp | 17 +++++++++++++++++ tests/wchar_test.cpp | 32 +++++++++++++++++++++++++++++++- 14 files changed, 133 insertions(+), 15 deletions(-) diff --git a/libc/bionic/wchar_l.cpp b/libc/bionic/wchar_l.cpp index 6c39e8d35..a86961f20 100644 --- a/libc/bionic/wchar_l.cpp +++ b/libc/bionic/wchar_l.cpp @@ -37,24 +37,42 @@ int wcsncasecmp_l(const wchar_t* ws1, const wchar_t* ws2, size_t n, locale_t) { return wcsncasecmp(ws1, ws2, n); } -int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) { +int wcscoll_l(const wchar_t* ws1, const wchar_t* ws2, locale_t) { return wcscoll(ws1, ws2); } -size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n, locale_t) { - return wcsxfrm(dest, src, n); +size_t wcsftime_l(wchar_t* buf, size_t n, const wchar_t* fmt, const struct tm* tm, locale_t) { + return wcsftime(buf, n, fmt, tm); } -long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, int base, - locale_t) { - return wcstoll(nptr, endptr, base); +size_t wcsxfrm_l(wchar_t* dst, const wchar_t* src, size_t n, locale_t) { + return wcsxfrm(dst, src, n); } -unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr, - int base, locale_t) { - return wcstoull(nptr, endptr, base); +double wcstod_l(const wchar_t* s, wchar_t** end_ptr, locale_t) { + return wcstod(s, end_ptr); } -long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, locale_t) { - return wcstold(nptr, endptr); +float wcstof_l(const wchar_t* s, wchar_t** end_ptr, locale_t) { + return wcstof(s, end_ptr); +} + +long wcstol_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) { + return wcstol(s, end_ptr, base); +} + +long long wcstoll_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) { + return wcstoll(s, end_ptr, base); +} + +unsigned long wcstoul_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) { + return wcstoul(s, end_ptr, base); +} + +unsigned long long wcstoull_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) { + return wcstoull(s, end_ptr, base); +} + +long double wcstold_l(const wchar_t* s, wchar_t** end_ptr, locale_t) { + return wcstold(s, end_ptr); } diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h index 26dd9a2e3..c270bb513 100644 --- a/libc/include/sys/cdefs.h +++ b/libc/include/sys/cdefs.h @@ -120,6 +120,7 @@ #define __printflike(x, y) __attribute__((__format__(printf, x, y))) #define __scanflike(x, y) __attribute__((__format__(scanf, x, y))) +#define __strftimelike(x) __attribute__((__format__(strftime, x, 0))) /* * GNU C version 2.96 added explicit branch prediction so that diff --git a/libc/include/time.h b/libc/include/time.h index 8e7894927..17751d76c 100644 --- a/libc/include/time.h +++ b/libc/include/time.h @@ -74,11 +74,12 @@ struct tm* localtime_r(const time_t* __t, struct tm* __tm); struct tm* gmtime(const time_t* __t); struct tm* gmtime_r(const time_t* __t, struct tm* __tm); -char* strptime(const char* __s, const char* __fmt, struct tm* __tm); -size_t strftime(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm); +char* strptime(const char* __s, const char* __fmt, struct tm* __tm) __strftimelike(2); +char* strptime_l(const char* __s, const char* __fmt, struct tm* __tm, locale_t __l) __strftimelike(2) __INTRODUCED_IN(28); +size_t strftime(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm) __strftimelike(3); #if __ANDROID_API__ >= __ANDROID_API_L__ -size_t strftime_l(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm, locale_t __l) __INTRODUCED_IN(21); +size_t strftime_l(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm, locale_t __l) __strftimelike(3) __INTRODUCED_IN(21); #else // Implemented as static inline before 21. #endif diff --git a/libc/include/wchar.h b/libc/include/wchar.h index 1cf498c83..f33af5f9c 100644 --- a/libc/include/wchar.h +++ b/libc/include/wchar.h @@ -81,6 +81,7 @@ int wcscoll(const wchar_t* __lhs, const wchar_t* __rhs); wchar_t* wcscpy(wchar_t* __dst, const wchar_t* __src); size_t wcscspn(const wchar_t* __s, const wchar_t* __accept); size_t wcsftime(wchar_t* __buf, size_t __n, const wchar_t* __fmt, const struct tm* __tm); +size_t wcsftime_l(wchar_t* __buf, size_t __n, const wchar_t* __fmt, const struct tm* __tm, locale_t __l) __INTRODUCED_IN(28); size_t wcslen(const wchar_t* __s); int wcsncasecmp(const wchar_t* __lhs, const wchar_t* __rhs, size_t __n); int wcsncasecmp_l(const wchar_t* __lhs, const wchar_t* __rhs, size_t __n, locale_t __l) __INTRODUCED_IN(23); @@ -94,12 +95,16 @@ size_t wcsrtombs(char* __dst, const wchar_t** __src, size_t __dst_n, mbstate_t* size_t wcsspn(const wchar_t* __s, const wchar_t* __accept); wchar_t* wcsstr(const wchar_t* __haystack, const wchar_t* __needle); double wcstod(const wchar_t* __s, wchar_t** __end_ptr); +double wcstod_l(const wchar_t* __s, wchar_t** __end_ptr, locale_t __l) __INTRODUCED_IN(28); float wcstof(const wchar_t* __s, wchar_t** __end_ptr) __INTRODUCED_IN(21); +float wcstof_l(const wchar_t* __s, wchar_t** __end_ptr, locale_t __l) __INTRODUCED_IN(28); wchar_t* wcstok(wchar_t* __s, const wchar_t* __delimiter, wchar_t** __ptr); long wcstol(const wchar_t* __s, wchar_t** __end_ptr, int __base); +long wcstol_l(const wchar_t* __s, wchar_t** __end_ptr, int __base, locale_t __l) __INTRODUCED_IN(28); long long wcstoll(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21); long double wcstold(const wchar_t* __s, wchar_t** __end_ptr) __RENAME_LDBL(wcstod, 3, 21); unsigned long wcstoul(const wchar_t* __s, wchar_t** __end_ptr, int __base); +unsigned long wcstoul_l(const wchar_t* __s, wchar_t** __end_ptr, int __base, locale_t __l) __INTRODUCED_IN(28); unsigned long long wcstoull(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21); int wcswidth(const wchar_t* __s, size_t __n); size_t wcsxfrm(wchar_t* __dst, const wchar_t* __src, size_t __n); diff --git a/libc/libc.arm.map b/libc/libc.arm.map index a7977ebf7..883a259c5 100644 --- a/libc/libc.arm.map +++ b/libc/libc.arm.map @@ -1400,8 +1400,14 @@ LIBC_P { # introduced=P sigtimedwait64; sigwait64; sigwaitinfo64; + strptime_l; swab; syncfs; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstol_l; + wcstoul_l; } LIBC_O; LIBC_PRIVATE { diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map index 1cae22b56..bb5f1440b 100644 --- a/libc/libc.arm64.map +++ b/libc/libc.arm64.map @@ -1320,8 +1320,14 @@ LIBC_P { # introduced=P sigtimedwait64; sigwait64; sigwaitinfo64; + strptime_l; swab; syncfs; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstol_l; + wcstoul_l; } LIBC_O; LIBC_PRIVATE { diff --git a/libc/libc.map.txt b/libc/libc.map.txt index 1188a853a..c2c75c0f1 100644 --- a/libc/libc.map.txt +++ b/libc/libc.map.txt @@ -1425,8 +1425,14 @@ LIBC_P { # introduced=P sigtimedwait64; sigwait64; sigwaitinfo64; + strptime_l; swab; syncfs; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstol_l; + wcstoul_l; } LIBC_O; LIBC_PRIVATE { diff --git a/libc/libc.mips.map b/libc/libc.mips.map index 3d9507994..6a03babd2 100644 --- a/libc/libc.mips.map +++ b/libc/libc.mips.map @@ -1384,8 +1384,14 @@ LIBC_P { # introduced=P sigtimedwait64; sigwait64; sigwaitinfo64; + strptime_l; swab; syncfs; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstol_l; + wcstoul_l; } LIBC_O; LIBC_PRIVATE { diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map index 1cae22b56..bb5f1440b 100644 --- a/libc/libc.mips64.map +++ b/libc/libc.mips64.map @@ -1320,8 +1320,14 @@ LIBC_P { # introduced=P sigtimedwait64; sigwait64; sigwaitinfo64; + strptime_l; swab; syncfs; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstol_l; + wcstoul_l; } LIBC_O; LIBC_PRIVATE { diff --git a/libc/libc.x86.map b/libc/libc.x86.map index bcb5feb0f..519a0f000 100644 --- a/libc/libc.x86.map +++ b/libc/libc.x86.map @@ -1382,8 +1382,14 @@ LIBC_P { # introduced=P sigtimedwait64; sigwait64; sigwaitinfo64; + strptime_l; swab; syncfs; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstol_l; + wcstoul_l; } LIBC_O; LIBC_PRIVATE { diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map index 1cae22b56..bb5f1440b 100644 --- a/libc/libc.x86_64.map +++ b/libc/libc.x86_64.map @@ -1320,8 +1320,14 @@ LIBC_P { # introduced=P sigtimedwait64; sigwait64; sigwaitinfo64; + strptime_l; swab; syncfs; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstol_l; + wcstoul_l; } LIBC_O; LIBC_PRIVATE { diff --git a/libc/tzcode/strptime.c b/libc/tzcode/strptime.c index 0567aa419..210063007 100644 --- a/libc/tzcode/strptime.c +++ b/libc/tzcode/strptime.c @@ -430,3 +430,7 @@ _conv_num(const unsigned char **buf, int *dest, int llim, int ulim) *dest = result; return (1); } + +char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t l) { + return strptime(buf, fmt, tm); +} diff --git a/tests/time_test.cpp b/tests/time_test.cpp index fccff6737..2b9935a90 100644 --- a/tests/time_test.cpp +++ b/tests/time_test.cpp @@ -279,6 +279,23 @@ TEST(time, strptime) { EXPECT_STREQ("09:41:53", buf); } +TEST(time, strptime_l) { + setenv("TZ", "UTC", 1); + + struct tm t; + char buf[64]; + + memset(&t, 0, sizeof(t)); + strptime_l("11:14", "%R", &t, LC_GLOBAL_LOCALE); + strftime_l(buf, sizeof(buf), "%H:%M", &t, LC_GLOBAL_LOCALE); + EXPECT_STREQ("11:14", buf); + + memset(&t, 0, sizeof(t)); + strptime_l("09:41:53", "%T", &t, LC_GLOBAL_LOCALE); + strftime_l(buf, sizeof(buf), "%H:%M:%S", &t, LC_GLOBAL_LOCALE); + EXPECT_STREQ("09:41:53", buf); +} + void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) { itimerspec ts; ts.it_value.tv_sec = value_s; diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp index 6f90c6c00..b42e13cb1 100644 --- a/tests/wchar_test.cpp +++ b/tests/wchar_test.cpp @@ -539,7 +539,7 @@ TEST(wchar, mbsnrtowcs) { ASSERT_EQ(EILSEQ, errno); } -TEST(wchar, wcsftime) { +TEST(wchar, wcsftime__wcsftime_l) { setenv("TZ", "UTC", 1); struct tm t; @@ -552,6 +552,8 @@ TEST(wchar, wcsftime) { EXPECT_EQ(24U, wcsftime(buf, sizeof(buf), L"%c", &t)); EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf); + EXPECT_EQ(24U, wcsftime_l(buf, sizeof(buf), L"%c", &t, LC_GLOBAL_LOCALE)); + EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf); } TEST(wchar, wmemmove_smoke) { @@ -878,6 +880,34 @@ TEST(wchar, wcstold_hex_inf_nan) { TestWcsToFloatInfNan(wcstold); } +TEST(wchar, wcstod_l) { + EXPECT_EQ(1.23, wcstod_l(L"1.23", nullptr, LC_GLOBAL_LOCALE)); +} + +TEST(wchar, wcstof_l) { + EXPECT_EQ(1.23f, wcstof_l(L"1.23", nullptr, LC_GLOBAL_LOCALE)); +} + +TEST(wchar, wcstol_l) { + EXPECT_EQ(123L, wcstol_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE)); +} + +TEST(wchar, wcstold_l) { + EXPECT_EQ(1.23L, wcstold_l(L"1.23", nullptr, LC_GLOBAL_LOCALE)); +} + +TEST(wchar, wcstoll_l) { + EXPECT_EQ(123LL, wcstoll_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE)); +} + +TEST(wchar, wcstoul_l) { + EXPECT_EQ(123UL, wcstoul_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE)); +} + +TEST(wchar, wcstoull_l) { + EXPECT_EQ(123ULL, wcstoul_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE)); +} + static void AssertWcwidthRange(wchar_t begin, wchar_t end, int expected) { for (wchar_t i = begin; i < end; ++i) { EXPECT_EQ(expected, wcwidth(i)) << static_cast(i);