[libc] add atoi, atol, and atoll
authorMichael Jones <michaelrj@google.com>
Wed, 18 Aug 2021 17:24:14 +0000 (17:24 +0000)
committerMichael Jones <michaelrj@google.com>
Thu, 19 Aug 2021 18:02:51 +0000 (18:02 +0000)
This is based on the work done to add strtoll and the other strto
functions. The atoi functions also were added to stdc and
entrypoints.txt.

Reviewed By: sivachandra

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

12 files changed:
libc/config/linux/x86_64/entrypoints.txt
libc/spec/stdc.td
libc/src/stdlib/CMakeLists.txt
libc/src/stdlib/atoi.cpp [new file with mode: 0644]
libc/src/stdlib/atoi.h [new file with mode: 0644]
libc/src/stdlib/atol.cpp [new file with mode: 0644]
libc/src/stdlib/atol.h [new file with mode: 0644]
libc/src/stdlib/atoll.cpp [new file with mode: 0644]
libc/src/stdlib/atoll.h [new file with mode: 0644]
libc/test/src/stdlib/atoi_test.cpp [new file with mode: 0644]
libc/test/src/stdlib/atol_test.cpp [new file with mode: 0644]
libc/test/src/stdlib/atoll_test.cpp [new file with mode: 0644]

index e99fb4e..4fb4ad4 100644 (file)
@@ -157,6 +157,9 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.stdlib._Exit
     libc.src.stdlib.abort
     libc.src.stdlib.abs
+    libc.src.stdlib.atoi
+    libc.src.stdlib.atol
+    libc.src.stdlib.atoll
     libc.src.stdlib.labs
     libc.src.stdlib.llabs
     libc.src.stdlib.strtol
index 6aa68a3..dadf90e 100644 (file)
@@ -476,6 +476,9 @@ def StdC : StandardSpec<"stdc"> {
       [
           FunctionSpec<"abort", RetValSpec<NoReturn>, [ArgSpec<VoidType>]>,
           FunctionSpec<"abs", RetValSpec<IntType>, [ArgSpec<IntType>]>,
+          FunctionSpec<"atoi", RetValSpec<IntType>, [ArgSpec<ConstCharPtr>]>,
+          FunctionSpec<"atol", RetValSpec<LongType>, [ArgSpec<ConstCharPtr>]>,
+          FunctionSpec<"atoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharPtr>]>,
           FunctionSpec<"labs", RetValSpec<LongType>, [ArgSpec<LongType>]>,
           FunctionSpec<"llabs", RetValSpec<LongLongType>, [ArgSpec<LongLongType>]>,
           FunctionSpec<"strtol", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
index 642202d..cd2f2f1 100644 (file)
@@ -32,6 +32,36 @@ add_entrypoint_object(
 )
 
 add_entrypoint_object(
+  atoi
+  SRCS
+    atoi.cpp
+  HDRS
+    atoi.h
+  DEPENDS
+    libc.src.__support.str_conv_utils
+)
+
+add_entrypoint_object(
+  atol
+  SRCS
+    atol.cpp
+  HDRS
+    atol.h
+  DEPENDS
+    libc.src.__support.str_conv_utils
+)
+
+add_entrypoint_object(
+  atoll
+  SRCS
+    atoll.cpp
+  HDRS
+    atoll.h
+  DEPENDS
+    libc.src.__support.str_conv_utils
+)
+
+add_entrypoint_object(
   labs
   SRCS
     labs.cpp
diff --git a/libc/src/stdlib/atoi.cpp b/libc/src/stdlib/atoi.cpp
new file mode 100644 (file)
index 0000000..f0e57ca
--- /dev/null
@@ -0,0 +1,19 @@
+//===-- Implementation of atoi --------------------------------------------===//
+//
+// 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/stdlib/atoi.h"
+#include "src/__support/common.h"
+#include "src/__support/str_conv_utils.h"
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, atoi, (const char *str)) {
+  return internal::strtointeger<int>(str, nullptr, 10);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdlib/atoi.h b/libc/src/stdlib/atoi.h
new file mode 100644 (file)
index 0000000..bb6c978
--- /dev/null
@@ -0,0 +1,18 @@
+//===-- Implementation header for atoi --------------------------*- 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_STDLIB_ATOI_H
+#define LLVM_LIBC_SRC_STDLIB_ATOI_H
+
+namespace __llvm_libc {
+
+int atoi(const char *str);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDLIB_ATOI_H
diff --git a/libc/src/stdlib/atol.cpp b/libc/src/stdlib/atol.cpp
new file mode 100644 (file)
index 0000000..8f0ed88
--- /dev/null
@@ -0,0 +1,19 @@
+//===-- Implementation of atol --------------------------------------------===//
+//
+// 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/stdlib/atol.h"
+#include "src/__support/common.h"
+#include "src/__support/str_conv_utils.h"
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(long, atol, (const char *str)) {
+  return internal::strtointeger<long>(str, nullptr, 10);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdlib/atol.h b/libc/src/stdlib/atol.h
new file mode 100644 (file)
index 0000000..8ba6337
--- /dev/null
@@ -0,0 +1,18 @@
+//===-- Implementation header for atol --------------------------*- 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_STDLIB_ATOL_H
+#define LLVM_LIBC_SRC_STDLIB_ATOL_H
+
+namespace __llvm_libc {
+
+long atol(const char *str);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDLIB_ATOL_H
diff --git a/libc/src/stdlib/atoll.cpp b/libc/src/stdlib/atoll.cpp
new file mode 100644 (file)
index 0000000..c75e521
--- /dev/null
@@ -0,0 +1,19 @@
+//===-- Implementation of atoll -------------------------------------------===//
+//
+// 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/stdlib/atoll.h"
+#include "src/__support/common.h"
+#include "src/__support/str_conv_utils.h"
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(long long, atoll, (const char *str)) {
+  return internal::strtointeger<long long>(str, nullptr, 10);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdlib/atoll.h b/libc/src/stdlib/atoll.h
new file mode 100644 (file)
index 0000000..d99184f
--- /dev/null
@@ -0,0 +1,18 @@
+//===-- Implementation header for atoll -------------------------*- 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_STDLIB_ATOLL_H
+#define LLVM_LIBC_SRC_STDLIB_ATOLL_H
+
+namespace __llvm_libc {
+
+long long atoll(const char *str);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDLIB_ATOLL_H
diff --git a/libc/test/src/stdlib/atoi_test.cpp b/libc/test/src/stdlib/atoi_test.cpp
new file mode 100644 (file)
index 0000000..892f93a
--- /dev/null
@@ -0,0 +1,68 @@
+//===-- Unittests for atoi -----------------------------------------------===//
+//
+// 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/stdlib/atoi.h"
+
+#include "utils/UnitTest/Test.h"
+
+#include <limits.h>
+
+TEST(LlvmLibcAToITest, ValidNumbers) {
+  const char *zero = "0";
+  ASSERT_EQ(__llvm_libc::atoi(zero), 0);
+
+  const char *ten = "10";
+  ASSERT_EQ(__llvm_libc::atoi(ten), 10);
+
+  const char *negative_hundred = "-100";
+  ASSERT_EQ(__llvm_libc::atoi(negative_hundred), -100);
+
+  const char *positive_thousand = "+1000";
+  ASSERT_EQ(__llvm_libc::atoi(positive_thousand), 1000);
+
+  const char *spaces_before = "     12345";
+  ASSERT_EQ(__llvm_libc::atoi(spaces_before), 12345);
+
+  const char *tabs_before = "\t\t\t\t67890";
+  ASSERT_EQ(__llvm_libc::atoi(tabs_before), 67890);
+
+  const char *letters_after = "123abc";
+  ASSERT_EQ(__llvm_libc::atoi(letters_after), 123);
+
+  const char *letters_between = "456def789";
+  ASSERT_EQ(__llvm_libc::atoi(letters_between), 456);
+
+  const char *all_together = "\t   110 times 5 = 550";
+  ASSERT_EQ(__llvm_libc::atoi(all_together), 110);
+
+  const char *biggest_int = "2147483647";
+  ASSERT_EQ(__llvm_libc::atoi(biggest_int), INT_MAX);
+
+  const char *smallest_int = "-2147483648";
+  ASSERT_EQ(__llvm_libc::atoi(smallest_int), INT_MIN);
+}
+
+TEST(LlvmLibcAToITest, NonBaseTenWholeNumbers) {
+  const char *hexadecimal = "0x10";
+  ASSERT_EQ(__llvm_libc::atoi(hexadecimal), 0);
+
+  const char *octal = "010";
+  ASSERT_EQ(__llvm_libc::atoi(octal), 10);
+
+  const char *decimal_point = "5.9";
+  ASSERT_EQ(__llvm_libc::atoi(decimal_point), 5);
+}
+
+TEST(LlvmLibcAToITest, NotNumbers) {
+  const char *ten_as_word = "ten";
+  ASSERT_EQ(__llvm_libc::atoi(ten_as_word), 0);
+
+  const char *lots_of_letters =
+      "wtragsdhfgjykutjdyfhgnchgmjhkyurktfgjhlu;po7urtdjyfhgklyk";
+  ASSERT_EQ(__llvm_libc::atoi(lots_of_letters), 0);
+}
diff --git a/libc/test/src/stdlib/atol_test.cpp b/libc/test/src/stdlib/atol_test.cpp
new file mode 100644 (file)
index 0000000..a2e0444
--- /dev/null
@@ -0,0 +1,62 @@
+//===-- Unittests for atol -----------------------------------------------===//
+//
+// 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/stdlib/atol.h"
+
+#include "utils/UnitTest/Test.h"
+
+#include <limits.h>
+
+TEST(LlvmLibcAToLTest, ValidNumbers) {
+  const char *zero = "0";
+  ASSERT_EQ(__llvm_libc::atol(zero), 0l);
+
+  const char *ten = "10";
+  ASSERT_EQ(__llvm_libc::atol(ten), 10l);
+
+  const char *negative_hundred = "-100";
+  ASSERT_EQ(__llvm_libc::atol(negative_hundred), -100l);
+
+  const char *positive_thousand = "+1000";
+  ASSERT_EQ(__llvm_libc::atol(positive_thousand), 1000l);
+
+  const char *spaces_before = "     12345";
+  ASSERT_EQ(__llvm_libc::atol(spaces_before), 12345l);
+
+  const char *tabs_before = "\t\t\t\t67890";
+  ASSERT_EQ(__llvm_libc::atol(tabs_before), 67890l);
+
+  const char *letters_after = "123abc";
+  ASSERT_EQ(__llvm_libc::atol(letters_after), 123l);
+
+  const char *letters_between = "456def789";
+  ASSERT_EQ(__llvm_libc::atol(letters_between), 456l);
+
+  const char *all_together = "\t   110 times 5 = 550";
+  ASSERT_EQ(__llvm_libc::atol(all_together), 110l);
+}
+
+TEST(LlvmLibcAToLTest, NonBaseTenWholeNumbers) {
+  const char *hexadecimal = "0x10";
+  ASSERT_EQ(__llvm_libc::atol(hexadecimal), 0l);
+
+  const char *octal = "010";
+  ASSERT_EQ(__llvm_libc::atol(hexadecimal), 10l);
+
+  const char *decimal_point = "5.9";
+  ASSERT_EQ(__llvm_libc::atol(decimal_point), 5l);
+}
+
+TEST(LlvmLibcAToLTest, NotNumbers) {
+  const char *ten_as_word = "ten";
+  ASSERT_EQ(__llvm_libc::atol(ten_as_word), 0l);
+
+  const char *lots_of_letters =
+      "wtragsdhfgjykutjdyfhgnchgmjhkyurktfgjhlu;po7urtdjyfhgklyk";
+  ASSERT_EQ(__llvm_libc::atol(lots_of_letters), 0l);
+}
diff --git a/libc/test/src/stdlib/atoll_test.cpp b/libc/test/src/stdlib/atoll_test.cpp
new file mode 100644 (file)
index 0000000..c716367
--- /dev/null
@@ -0,0 +1,68 @@
+//===-- Unittests for atoll -----------------------------------------------===//
+//
+// 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/stdlib/atoll.h"
+
+#include "utils/UnitTest/Test.h"
+
+#include <limits.h>
+
+TEST(LlvmLibcAToLLTest, ValidNumbers) {
+  const char *zero = "0";
+  ASSERT_EQ(__llvm_libc::atoll(zero), 0ll);
+
+  const char *ten = "10";
+  ASSERT_EQ(__llvm_libc::atoll(ten), 10ll);
+
+  const char *negative_hundred = "-100";
+  ASSERT_EQ(__llvm_libc::atoll(negative_hundred), -100ll);
+
+  const char *positive_thousand = "+1000";
+  ASSERT_EQ(__llvm_libc::atoll(positive_thousand), 1000ll);
+
+  const char *spaces_before = "     12345";
+  ASSERT_EQ(__llvm_libc::atoll(spaces_before), 12345ll);
+
+  const char *tabs_before = "\t\t\t\t67890";
+  ASSERT_EQ(__llvm_libc::atoll(tabs_before), 67890ll);
+
+  const char *letters_after = "123abc";
+  ASSERT_EQ(__llvm_libc::atoll(letters_after), 123ll);
+
+  const char *letters_between = "456def789";
+  ASSERT_EQ(__llvm_libc::atoll(letters_between), 456ll);
+
+  const char *all_together = "\t   110 times 5 = 550";
+  ASSERT_EQ(__llvm_libc::atoll(all_together), 110ll);
+
+  const char *biggest_long_long = "9223372036854775807";
+  ASSERT_EQ(__llvm_libc::atoll(biggest_int), LLONG_MAX);
+
+  const char *smallest_long_long = "-9223372036854775808";
+  ASSERT_EQ(__llvm_libc::atoll(smallest_int), LLONG_MIN);
+}
+
+TEST(LlvmLibcAToLLTest, NonBaseTenWholeNumbers) {
+  const char *hexadecimal = "0x10";
+  ASSERT_EQ(__llvm_libc::atoll(hexadecimal), 0ll);
+
+  const char *octal = "010";
+  ASSERT_EQ(__llvm_libc::atoll(hexadecimal), 10ll);
+
+  const char *decimal_point = "5.9";
+  ASSERT_EQ(__llvm_libc::atol(decimal_point), 5l);
+}
+
+TEST(LlvmLibcAToLLTest, NotNumbers) {
+  const char *ten_as_word = "ten";
+  ASSERT_EQ(__llvm_libc::atoll(ten_as_word), 0ll);
+
+  const char *lots_of_letters =
+      "wtragsdhfgjykutjdyfhgnchgmjhkyurktfgjhlu;po7urtdjyfhgklyk";
+  ASSERT_EQ(__llvm_libc::atoll(lots_of_letters), 0ll);
+}