[libc-commits] [libc] e263dcc - [libc] Implements isdigit and isalnum. Adds a utility header to inline

via libc-commits libc-commits at lists.llvm.org
Thu Jul 30 09:38:58 PDT 2020


Author: cgyurgyik
Date: 2020-07-30T12:37:30-04:00
New Revision: e263dcc3efeae419b691730da5e37977e1a681f6

URL: https://github.com/llvm/llvm-project/commit/e263dcc3efeae419b691730da5e37977e1a681f6
DIFF: https://github.com/llvm/llvm-project/commit/e263dcc3efeae419b691730da5e37977e1a681f6.diff

LOG: [libc] Implements isdigit and isalnum. Adds a utility header to inline
functions to avoid overhead of function calls.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D84893

Added: 
    libc/src/ctype/ctype_utils.h
    libc/src/ctype/isalnum.cpp
    libc/src/ctype/isalnum.h
    libc/src/ctype/isdigit.cpp
    libc/src/ctype/isdigit.h
    libc/test/src/ctype/isalnum_test.cpp
    libc/test/src/ctype/isdigit_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/api.td
    libc/config/linux/x86_64/entrypoints.txt
    libc/spec/stdc.td
    libc/src/ctype/CMakeLists.txt
    libc/src/ctype/isalpha.cpp
    libc/test/src/ctype/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 7e3589bcf0ec..8d2cc1618946 100644
--- 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
index aea3fed1b7c3..01e6eab92f01 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -88,7 +88,9 @@ def AssertAPI : PublicAPI<"assert.h"> {
 
 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
index c361fce3dbec..4484f6cbf1a7 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -3,7 +3,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     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
index 1b93960c9a4f..fed24cb2dbdd 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -46,11 +46,21 @@ def StdC : StandardSpec<"stdc"> {
       [], // Types
       [], // Enumerations
       [
+          FunctionSpec<
+              "isalnum",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>]
+          >,
           FunctionSpec<
               "isalpha",
               RetValSpec<IntType>,
               [ArgSpec<IntType>]
           >,
+          FunctionSpec<
+              "isdigit",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>]
+          >,
       ]
   >;
      

diff  --git a/libc/src/ctype/CMakeLists.txt b/libc/src/ctype/CMakeLists.txt
index 686ec7878512..53161b8b179f 100644
--- a/libc/src/ctype/CMakeLists.txt
+++ b/libc/src/ctype/CMakeLists.txt
@@ -1,7 +1,35 @@
+add_header_library(
+  ctype_utils
+  HDRS
+    ctype_utils.h
+)
+
+add_entrypoint_object(
+  isalnum
+  SRCS
+    isalnum.cpp
+  HDRS
+    isalnum.h
+  DEPENDS
+    .ctype_utils
+)
+
 add_entrypoint_object(
   isalpha
   SRCS
     isalpha.cpp
   HDRS
     isalpha.h
+  DEPENDS
+    .ctype_utils
+)
+
+add_entrypoint_object(
+  isdigit
+  SRCS
+    isdigit.cpp
+  HDRS
+    isdigit.h
+  DEPENDS
+    .ctype_utils
 )

diff  --git a/libc/src/ctype/ctype_utils.h b/libc/src/ctype/ctype_utils.h
new file mode 100644
index 000000000000..4e8d3960bb70
--- /dev/null
+++ b/libc/src/ctype/ctype_utils.h
@@ -0,0 +1,34 @@
+//===-- Collection of utils for implementing ctype functions-------*-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_CTYPE_UTILS_H
+#define LLVM_LIBC_SRC_CTYPE_CTYPE_UTILS_H
+
+namespace __llvm_libc {
+namespace internal {
+
+// ------------------------------------------------------
+// Rationale: Since these classification functions are
+// called in other functions, we will avoid the overhead
+// of a function call by inlining them.
+// ------------------------------------------------------
+
+static inline int isdigit(int c) {
+  const unsigned ch = c;
+  return (ch - '0') < 10;
+}
+
+static inline int isalpha(int c) {
+  const unsigned ch = c;
+  return (ch | 32) - 'a' < 26;
+}
+
+} // namespace internal
+} // namespace __llvm_libc
+
+#endif //  LLVM_LIBC_SRC_CTYPE_CTYPE_UTILS_H

diff  --git a/libc/src/ctype/isalnum.cpp b/libc/src/ctype/isalnum.cpp
new file mode 100644
index 000000000000..08b6520e4426
--- /dev/null
+++ b/libc/src/ctype/isalnum.cpp
@@ -0,0 +1,22 @@
+//===-- 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/ctype_utils.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 internal::isalpha(c) || internal::isdigit(c);
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/ctype/isalnum.h b/libc/src/ctype/isalnum.h
new file mode 100644
index 000000000000..beb202a7529d
--- /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/isalpha.cpp b/libc/src/ctype/isalpha.cpp
index e945ca98ffb1..4b3725477a7d 100644
--- a/libc/src/ctype/isalpha.cpp
+++ b/libc/src/ctype/isalpha.cpp
@@ -9,14 +9,12 @@
 #include "src/ctype/isalpha.h"
 
 #include "src/__support/common.h"
+#include "src/ctype/ctype_utils.h"
 
 namespace __llvm_libc {
 
 // TODO: Currently restricted to default locale.
 // These should be extended using locale information.
-int LLVM_LIBC_ENTRYPOINT(isalpha)(int c) {
-  const unsigned ch = c;
-  return (ch | 32) - 'a' < 26;
-}
+int LLVM_LIBC_ENTRYPOINT(isalpha)(int c) { return internal::isalpha(c); }
 
 } // namespace __llvm_libc

diff  --git a/libc/src/ctype/isdigit.cpp b/libc/src/ctype/isdigit.cpp
new file mode 100644
index 000000000000..94ec42a0a3d8
--- /dev/null
+++ b/libc/src/ctype/isdigit.cpp
@@ -0,0 +1,19 @@
+//===-- 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"
+#include "src/ctype/ctype_utils.h"
+
+namespace __llvm_libc {
+
+// TODO: Currently restricted to default locale.
+// These should be extended using locale information.
+int LLVM_LIBC_ENTRYPOINT(isdigit)(int c) { return internal::isdigit(c); }
+
+} // namespace __llvm_libc

diff  --git a/libc/src/ctype/isdigit.h b/libc/src/ctype/isdigit.h
new file mode 100644
index 000000000000..32a76235e059
--- /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/test/src/ctype/CMakeLists.txt b/libc/test/src/ctype/CMakeLists.txt
index b7572d3c5bfa..7834746ab1d7 100644
--- 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 @@ add_libc_unittest(
   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
index 000000000000..1c4ad7d3ff8a
--- /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
index 000000000000..6fea9564db67
--- /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));
+  }
+}


        


More information about the libc-commits mailing list