[PATCH] D41458: WIP: [libc++][C++17] Elementary string conversions for integral types

2017-12-22 Thread Zhihao Yuan via Phabricator via cfe-commits
lichray updated this revision to Diff 127996.
lichray added a comment.

Added std::from_chars


Repository:
  rCXX libc++

https://reviews.llvm.org/D41458

Files:
  .gitignore
  include/charconv
  include/support/itoa/
  include/support/itoa/itoa.h
  lib/CMakeLists.txt
  src/support/itoa/
  src/support/itoa/itoa.cpp
  test/std/utilities/charconv/
  test/std/utilities/charconv/charconv.from.chars/
  test/std/utilities/charconv/charconv.from.chars/integral.bool.fail.cpp
  test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp
  test/std/utilities/charconv/charconv.to.chars/
  test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp
  test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
  test/support/charconv_test_helpers.h

Index: test/support/charconv_test_helpers.h
===
--- /dev/null
+++ test/support/charconv_test_helpers.h
@@ -0,0 +1,233 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef SUPPORT_CHARCONV_TEST_HELPERS_H
+#define SUPPORT_CHARCONV_TEST_HELPERS_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "test_macros.h"
+
+using std::false_type;
+using std::true_type;
+
+template 
+constexpr auto
+is_non_narrowing(From a) -> decltype(To{a}, true_type())
+{
+return {};
+}
+
+template 
+constexpr auto
+is_non_narrowing(...) -> false_type
+{
+return {};
+}
+
+template 
+constexpr bool
+_fits_in(T, true_type /* non-narrowing*/, ...)
+{
+return true;
+}
+
+template >
+constexpr bool
+_fits_in(T v, false_type, true_type /* T signed*/, true_type /* X signed */)
+{
+return xl::lowest() <= v && v <= (xl::max)();
+}
+
+template >
+constexpr bool
+_fits_in(T v, false_type, true_type /* T signed */, false_type /* X unsigned*/)
+{
+return 0 <= v && typename std::make_unsigned::type(v) <= (xl::max)();
+}
+
+template >
+constexpr bool
+_fits_in(T v, false_type, false_type /* T unsigned */, ...)
+{
+return v <= typename std::make_unsigned::type((xl::max)());
+}
+
+template 
+constexpr bool
+fits_in(T v)
+{
+return _fits_in(v, is_non_narrowing(v), std::is_signed(),
+   std::is_signed());
+}
+
+template 
+struct to_chars_test_base
+{
+template 
+void test(T v, char const ()[N], Ts... args)
+{
+using std::to_chars;
+std::to_chars_result r;
+
+constexpr size_t len = N - 1;
+static_assert(len > 0, "expected output won't be empty");
+
+if (!fits_in(v))
+return;
+
+r = to_chars(buf, buf + len - 1, X(v), args...);
+LIBCPP_ASSERT(r.ptr == buf + len - 1);
+LIBCPP_ASSERT(r.ec == std::errc::value_too_large);
+
+r = to_chars(buf, buf + sizeof(buf), X(v), args...);
+LIBCPP_ASSERT(r.ptr == buf + len);
+LIBCPP_ASSERT(r.ec == std::errc{});
+LIBCPP_ASSERT(memcmp(buf, expect, len) == 0);
+}
+
+template 
+void test_value(X v, Ts... args)
+{
+using std::to_chars;
+std::to_chars_result r;
+
+r = to_chars(buf, buf + sizeof(buf), v, args...);
+LIBCPP_ASSERT(r.ec == std::errc{});
+*r.ptr = '\0';
+
+auto a = fromchars(buf, r.ptr, args...);
+LIBCPP_ASSERT(v == a);
+
+auto ep = r.ptr - 1;
+r = to_chars(buf, ep, v, args...);
+LIBCPP_ASSERT(r.ptr == ep);
+LIBCPP_ASSERT(r.ec == std::errc::value_too_large);
+}
+
+private:
+using max_t = typename std::conditional::type;
+
+static auto fromchars(char const* p, char const* ep, int base, true_type)
+-> long long
+{
+char* last;
+auto r = strtoll(p, , base);
+LIBCPP_ASSERT(last == ep);
+
+return r;
+}
+
+static auto fromchars(char const* p, char const* ep, int base, false_type)
+-> unsigned long long
+{
+char* last;
+auto r = strtoull(p, , base);
+LIBCPP_ASSERT(last == ep);
+
+return r;
+}
+
+static auto fromchars(char const* p, char const* ep, int base = 10) -> max_t
+{
+return fromchars(p, ep, base, std::is_signed());
+}
+
+char buf[100];
+};
+
+template 
+struct roundtrip_test_base
+{
+template 
+void test(T v, Ts... args)
+{
+using std::from_chars;
+using std::to_chars;
+std::from_chars_result r2;
+std::to_chars_result r;
+X x = 0xc;
+
+if (fits_in(v))
+{
+r = to_chars(buf, buf + sizeof(buf), v, args...);
+LIBCPP_ASSERT(r.ec == std::errc{});
+
+r2 = 

[PATCH] D41458: WIP: [libc++][C++17] Elementary string conversions for integral types

2017-12-20 Thread Marshall Clow via Phabricator via cfe-commits
mclow.lists added a comment.

I've got an implementation for this, too - at 
https://github.com/mclow/snippets/blob/master/to_chars.cpp

I'll compare them.


Repository:
  rCXX libc++

https://reviews.llvm.org/D41458



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D41458: WIP: [libc++][C++17] Elementary string conversions for integral types

2017-12-20 Thread Zhihao Yuan via Phabricator via cfe-commits
lichray created this revision.
lichray added reviewers: mclow.lists, EricWF.
Herald added a subscriber: mgorny.

Progress: std::to_chars for integers
Missing: std::from_chars

References:
 https://wg21.link/p0067r5
 https://wg21.link/p0682r1


Repository:
  rCXX libc++

https://reviews.llvm.org/D41458

Files:
  .gitignore
  include/charconv
  include/support/itoa/
  include/support/itoa/itoa.h
  lib/CMakeLists.txt
  src/support/itoa/
  src/support/itoa/itoa.cpp
  test/std/utilities/charconv/
  test/std/utilities/charconv/charconv.to.chars/
  test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp
  test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp

Index: test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
===
--- /dev/null
+++ test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
@@ -0,0 +1,87 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03
+// 
+
+// to_chars_result to_chars(char* first, char* last, Integral value,
+//  int base = 10)
+
+#include "charconv_test_helpers.h"
+
+template 
+struct test_basics : to_chars_test_base
+{
+using to_chars_test_base::test;
+using to_chars_test_base::test_value;
+
+void operator()()
+{
+
+test(0, "0");
+test(42, "42");
+test(32768, "32768");
+test(0, "0", 10);
+test(42, "42", 10);
+test(32768, "32768", 10);
+test(0xf, "f", 16);
+test(0xdeadbeaf, "deadbeaf", 16);
+test(0755, "755", 8);
+
+for (int b = 2; b < 37; ++b)
+{
+using xl = std::numeric_limits;
+
+test_value(1, b);
+test_value(xl::lowest(), b);
+test_value((xl::max)(), b);
+test_value((xl::max)() / 2, b);
+}
+}
+};
+
+template 
+struct test_signed : to_chars_test_base
+{
+using to_chars_test_base::test;
+using to_chars_test_base::test_value;
+
+void operator()()
+{
+test(-1, "-1");
+test(-12, "-12");
+test(-1, "-1", 10);
+test(-12, "-12", 10);
+test(-21734634, "-21734634", 10);
+test(-2647, "-101001010111", 2);
+test(-0xcc1, "-cc1", 16);
+
+for (int b = 2; b < 37; ++b)
+{
+using xl = std::numeric_limits;
+
+test_value(0, b);
+test_value(xl::lowest(), b);
+test_value((xl::max)(), b);
+}
+}
+};
+
+int
+main()
+{
+auto all_signed =
+type_list();
+auto all_unsigned = type_list();
+auto integrals = concat(all_signed, all_unsigned);
+
+run(integrals);
+run(all_signed);
+}
Index: test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp
===
--- /dev/null
+++ test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp
@@ -0,0 +1,30 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03
+// 
+
+// In
+//
+// to_chars_result to_chars(char* first, char* last, Integral value,
+//  int base = 10)
+//
+// Integral cannot be bool.
+
+#include 
+
+int main()
+{
+using std::to_chars;
+char buf[10];
+bool lv = true;
+
+to_chars(buf, buf + sizeof(buf), false);   // expected-error {{call to deleted function}}
+to_chars(buf, buf + sizeof(buf), lv, 16);  // expected-error {{call to deleted function}}
+}
Index: src/support/itoa/itoa.cpp
===
--- /dev/null
+++ src/support/itoa/itoa.cpp
@@ -0,0 +1,296 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+//