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 @@ -3,6 +3,8 @@ libc.src.ctype.isalnum libc.src.ctype.isalpha libc.src.ctype.isdigit + libc.src.ctype.islower + libc.src.ctype.isupper # 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 @@ -91,6 +91,8 @@ "isalnum", "isalpha", "isdigit", + "islower", + "isupper", ]; } 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 @@ -6,6 +6,8 @@ libc.src.ctype.isalnum libc.src.ctype.isalpha libc.src.ctype.isdigit + libc.src.ctype.islower + libc.src.ctype.isupper # 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 @@ -61,6 +61,16 @@ RetValSpec, [ArgSpec] >, + FunctionSpec< + "islower", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "isupper", + 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 @@ -33,3 +33,19 @@ DEPENDS .ctype_utils ) + +add_entrypoint_object( + islower + SRCS + islower.cpp + HDRS + islower.h +) + +add_entrypoint_object( + isupper + SRCS + isupper.cpp + HDRS + isupper.h +) diff --git a/libc/src/ctype/islower.h b/libc/src/ctype/islower.h new file mode 100644 --- /dev/null +++ b/libc/src/ctype/islower.h @@ -0,0 +1,18 @@ +//===-- Implementation header for islower -------------------------*-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_ISLOWER_H +#define LLVM_LIBC_SRC_CTYPE_ISLOWER_H + +namespace __llvm_libc { + +int islower(int c); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_CTYPE_ISLOWER_H diff --git a/libc/src/ctype/islower.cpp b/libc/src/ctype/islower.cpp new file mode 100644 --- /dev/null +++ b/libc/src/ctype/islower.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of islower------------------------------------------===// +// +// 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/islower.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(islower)(int c) { + const unsigned ch = c; + return (ch - 'a') < 26; +} + +} // namespace __llvm_libc diff --git a/libc/src/ctype/isupper.h b/libc/src/ctype/isupper.h new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isupper.h @@ -0,0 +1,18 @@ +//===-- Implementation header for isupper -------------------------*-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_ISUPPER_H +#define LLVM_LIBC_SRC_CTYPE_ISUPPER_H + +namespace __llvm_libc { + +int isupper(int c); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_CTYPE_ISUPPER_H diff --git a/libc/src/ctype/isupper.cpp b/libc/src/ctype/isupper.cpp new file mode 100644 --- /dev/null +++ b/libc/src/ctype/isupper.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of isupper------------------------------------------===// +// +// 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/isupper.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(isupper)(int c) { + const unsigned ch = c; + return (ch - 'A') < 26; +} + +} // 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 @@ -29,3 +29,23 @@ DEPENDS libc.src.ctype.isdigit ) + +add_libc_unittest( + islower + SUITE + libc_ctype_unittests + SRCS + islower_test.cpp + DEPENDS + libc.src.ctype.islower +) + +add_libc_unittest( + isupper + SUITE + libc_ctype_unittests + SRCS + isupper_test.cpp + DEPENDS + libc.src.ctype.isupper +) diff --git a/libc/test/src/ctype/isalnum_test.cpp b/libc/test/src/ctype/isalnum_test.cpp --- a/libc/test/src/ctype/isalnum_test.cpp +++ b/libc/test/src/ctype/isalnum_test.cpp @@ -7,21 +7,17 @@ //===----------------------------------------------------------------------===// #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); } +#include "utils/UnitTest/Test.h" TEST(IsAlNum, DefaultLocale) { // Loops through all characters, verifying that numbers and letters - // return true and everything else returns false. + // return non-zero integer and everything else returns a zero. 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)); + EXPECT_NE(__llvm_libc::isalnum(c), 0); else - EXPECT_FALSE(call_isalnum(c)); + EXPECT_EQ(__llvm_libc::isalnum(c), 0); } } diff --git a/libc/test/src/ctype/isalpha_test.cpp b/libc/test/src/ctype/isalpha_test.cpp --- a/libc/test/src/ctype/isalpha_test.cpp +++ b/libc/test/src/ctype/isalpha_test.cpp @@ -7,20 +7,16 @@ //===----------------------------------------------------------------------===// #include "src/ctype/isalpha.h" -#include "utils/UnitTest/Test.h" -// Helper function that makes a call to isalpha a bit cleaner -// for use with testing utilities, since it explicitly requires -// a boolean value for EXPECT_TRUE and EXPECT_FALSE. -bool call_isalpha(int c) { return __llvm_libc::isalpha(c); } +#include "utils/UnitTest/Test.h" TEST(IsAlpha, DefaultLocale) { - // Loops through all characters, verifying that letters return true - // and everything else returns false. + // Loops through all characters, verifying that letters return a + // non-zero integer and everything else returns zero. for (int ch = 0; ch < 255; ++ch) { if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) - EXPECT_TRUE(call_isalpha(ch)); + EXPECT_NE(__llvm_libc::isalpha(ch), 0); else - EXPECT_FALSE(call_isalpha(ch)); + EXPECT_EQ(__llvm_libc::isalpha(ch), 0); } } diff --git a/libc/test/src/ctype/isdigit_test.cpp b/libc/test/src/ctype/isdigit_test.cpp --- a/libc/test/src/ctype/isdigit_test.cpp +++ b/libc/test/src/ctype/isdigit_test.cpp @@ -7,20 +7,16 @@ //===----------------------------------------------------------------------===// #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); } +#include "utils/UnitTest/Test.h" TEST(IsDigit, DefaultLocale) { - // Loops through all characters, verifying that numbers return true - // and everything else returns false. + // Loops through all characters, verifying that numbers return a + // non-zero integer and everything else returns zero. for (int ch = 0; ch < 255; ++ch) { if ('0' <= ch && ch <= '9') - EXPECT_TRUE(call_isdigit(ch)); + EXPECT_NE(__llvm_libc::isdigit(ch), 0); else - EXPECT_FALSE(call_isdigit(ch)); + EXPECT_EQ(__llvm_libc::isdigit(ch), 0); } } diff --git a/libc/test/src/ctype/islower_test.cpp b/libc/test/src/ctype/islower_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/ctype/islower_test.cpp @@ -0,0 +1,21 @@ +//===-- Unittests for islower----------------------------------------------===// +// +// 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/islower.h" +#include "utils/UnitTest/Test.h" + +TEST(IsLower, DefaultLocale) { + // Loops through all characters, verifying that lowercase letters + // return a non-zero integer and everything else returns zero. + for (int ch = 0; ch < 255; ++ch) { + if ('a' <= ch && ch <= 'z') + EXPECT_NE(__llvm_libc::islower(ch), 0); + else + EXPECT_EQ(__llvm_libc::islower(ch), 0); + } +} diff --git a/libc/test/src/ctype/isupper_test.cpp b/libc/test/src/ctype/isupper_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/ctype/isupper_test.cpp @@ -0,0 +1,21 @@ +//===-- Unittests for isupper----------------------------------------------===// +// +// 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/isupper.h" +#include "utils/UnitTest/Test.h" + +TEST(IsUpper, DefaultLocale) { + // Loops through all characters, verifying that uppercase letters + // return a non-zero integer and everything else returns zero. + for (int ch = 0; ch < 255; ++ch) { + if ('A' <= ch && ch <= 'Z') + EXPECT_NE(__llvm_libc::isupper(ch), 0); + else + EXPECT_EQ(__llvm_libc::isupper(ch), 0); + } +}