diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -1,6 +1,8 @@ set(TARGET_LIBC_ENTRYPOINTS # ctype.h entrypoints + libc.src.ctype.isalnum libc.src.ctype.isalpha + libc.src.ctype.isdigit # errno.h entrypoints libc.src.errno.__errno_location diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -88,7 +88,9 @@ def CTypeAPI : PublicAPI<"ctype.h"> { let Functions = [ + "isalnum", "isalpha", + "isdigit", ]; } diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -3,7 +3,9 @@ libc.src.assert.__assert_fail # ctype.h entrypoints + libc.src.ctype.isalnum libc.src.ctype.isalpha + libc.src.ctype.isdigit # errno.h entrypoints libc.src.errno.__errno_location diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -46,11 +46,21 @@ [], // Types [], // Enumerations [ + FunctionSpec< + "isalnum", + RetValSpec, + [ArgSpec] + >, FunctionSpec< "isalpha", RetValSpec, [ArgSpec] >, + FunctionSpec< + "isdigit", + RetValSpec, + [ArgSpec] + >, ] >; diff --git a/libc/src/ctype/CMakeLists.txt b/libc/src/ctype/CMakeLists.txt --- a/libc/src/ctype/CMakeLists.txt +++ b/libc/src/ctype/CMakeLists.txt @@ -1,3 +1,14 @@ +add_entrypoint_object( + isalnum + SRCS + isalnum.cpp + HDRS + isalnum.h + DEPENDS + .isalpha + .isdigit +) + add_entrypoint_object( isalpha SRCS @@ -5,3 +16,11 @@ HDRS isalpha.h ) + +add_entrypoint_object( + isdigit + SRCS + isdigit.cpp + HDRS + isdigit.h +) diff --git a/libc/src/ctype/isalnum.h b/libc/src/ctype/isalnum.h new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isalnum.h @@ -0,0 +1,18 @@ +//===-- Implementation header for isalnum -------------------------*-C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_CTYPE_ISALNUM_H +#define LLVM_LIBC_SRC_CTYPE_ISALNUM_H + +namespace __llvm_libc { + +int isalnum(int c); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_CTYPE_ISALNUM_H diff --git a/libc/src/ctype/isalnum.cpp b/libc/src/ctype/isalnum.cpp new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isalnum.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of isalnum------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/ctype/isalnum.h" +#include "src/ctype/isalpha.h" +#include "src/ctype/isdigit.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +// TODO: Currently restricted to default locale. +// These should be extended using locale information. +int LLVM_LIBC_ENTRYPOINT(isalnum)(int c) { return isalpha(c) || isdigit(c); } + +} // namespace __llvm_libc diff --git a/libc/src/ctype/isdigit.h b/libc/src/ctype/isdigit.h new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isdigit.h @@ -0,0 +1,18 @@ +//===-- Implementation header for isdigit -------------------------*-C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_CTYPE_ISDIGIT_H +#define LLVM_LIBC_SRC_CTYPE_ISDIGIT_H + +namespace __llvm_libc { + +int isdigit(int c); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_CTYPE_ISDIGIT_H diff --git a/libc/src/ctype/isdigit.cpp b/libc/src/ctype/isdigit.cpp new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isdigit.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of isdigit------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/ctype/isdigit.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +// TODO: Currently restricted to default locale. +// These should be extended using locale information. +int LLVM_LIBC_ENTRYPOINT(isdigit)(int c) { + const unsigned ch = c; + return (ch - '0') < 10; +} + +} // namespace __llvm_libc diff --git a/libc/test/src/ctype/CMakeLists.txt b/libc/test/src/ctype/CMakeLists.txt --- a/libc/test/src/ctype/CMakeLists.txt +++ b/libc/test/src/ctype/CMakeLists.txt @@ -1,5 +1,15 @@ add_libc_testsuite(libc_ctype_unittests) +add_libc_unittest( + isalnum + SUITE + libc_ctype_unittests + SRCS + isalnum_test.cpp + DEPENDS + libc.src.ctype.isalnum +) + add_libc_unittest( isalpha SUITE @@ -9,3 +19,13 @@ DEPENDS libc.src.ctype.isalpha ) + +add_libc_unittest( + isdigit + SUITE + libc_ctype_unittests + SRCS + isdigit_test.cpp + DEPENDS + libc.src.ctype.isdigit +) diff --git a/libc/test/src/ctype/isalnum_test.cpp b/libc/test/src/ctype/isalnum_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/ctype/isalnum_test.cpp @@ -0,0 +1,27 @@ +//===-- Unittests for isalnum----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/ctype/isalnum.h" +#include "utils/UnitTest/Test.h" + +// Helper function that makes a call to isalnum a bit cleaner +// for use with testing utilities, since it explicitly requires +// a boolean value for EXPECT_TRUE and EXPECT_FALSE. +bool call_isalnum(int c) { return __llvm_libc::isalnum(c); } + +TEST(IsAlNum, DefaultLocale) { + // Loops through all characters, verifying that numbers and letters + // return true and everything else returns false. + for (int c = 0; c < 255; ++c) { + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || + ('0' <= c && c <= '9')) + EXPECT_TRUE(call_isalnum(c)); + else + EXPECT_FALSE(call_isalnum(c)); + } +} diff --git a/libc/test/src/ctype/isdigit_test.cpp b/libc/test/src/ctype/isdigit_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/ctype/isdigit_test.cpp @@ -0,0 +1,26 @@ +//===-- Unittests for isdigit----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/ctype/isdigit.h" +#include "utils/UnitTest/Test.h" + +// Helper function that makes a call to isdigit a bit cleaner +// for use with testing utilities, since it explicitly requires +// a boolean value for EXPECT_TRUE and EXPECT_FALSE. +bool call_isdigit(int c) { return __llvm_libc::isdigit(c); } + +TEST(IsDigit, DefaultLocale) { + // Loops through all characters, verifying that numbers return true + // and everything else returns false. + for (int ch = 0; ch < 255; ++ch) { + if ('0' <= ch && ch <= '9') + EXPECT_TRUE(call_isdigit(ch)); + else + EXPECT_FALSE(call_isdigit(ch)); + } +}