156 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// <charconv>12 13// constexpr from_chars_result from_chars(const char* first, const char* last,14// Integral& value, int base = 10)15 16#include <charconv>17#include <system_error>18 19#include "test_macros.h"20#include "charconv_test_helpers.h"21 22template <typename T>23struct test_basics24{25 TEST_CONSTEXPR_CXX23 void operator()()26 {27 std::from_chars_result r;28 T x;29 30 {31 char s[] = "001x";32 33 // the expected form of the subject sequence is a sequence of34 // letters and digits representing an integer with the radix35 // specified by base (C11 7.22.1.4/3)36 r = std::from_chars(s, s + sizeof(s), x);37 assert(r.ec == std::errc{});38 assert(r.ptr == s + 3);39 assert(x == 1);40 }41 42 {43 // The string has more characters than valid in an 128-bit value.44 char s[] = "0X7BAtSGHDkEIXZgQRfYChLpOzRnM ";45 46 // The letters from a (or A) through z (or Z) are ascribed the47 // values 10 through 35; (C11 7.22.1.4/3)48 r = std::from_chars(s, s + sizeof(s), x, 36);49 assert(r.ec == std::errc::result_out_of_range);50 // The member ptr of the return value points to the first character51 // not matching the pattern52 assert(r.ptr == s + sizeof(s) - 2);53 assert(x == 1);54 55 // no "0x" or "0X" prefix shall appear if the value of base is 1656 r = std::from_chars(s, s + sizeof(s), x, 16);57 assert(r.ec == std::errc{});58 assert(r.ptr == s + 1);59 assert(x == 0);60 61 // only letters and digits whose ascribed values are less than that62 // of base are permitted. (C11 7.22.1.4/3)63 r = std::from_chars(s + 2, s + sizeof(s), x, 12);64 // If the parsed value is not in the range representable by the type65 // of value,66 if (!fits_in<T>(1150))67 {68 // value is unmodified and69 assert(x == 0);70 // the member ec of the return value is equal to71 // errc::result_out_of_range72 assert(r.ec == std::errc::result_out_of_range);73 }74 else75 {76 // Otherwise, value is set to the parsed value,77 assert(x == 1150);78 // and the member ec is value-initialized.79 assert(r.ec == std::errc{});80 }81 assert(r.ptr == s + 5);82 }83 }84};85 86template <typename T>87struct test_signed88{89 TEST_CONSTEXPR_CXX23 void operator()()90 {91 std::from_chars_result r;92 T x = 42;93 94 {95 // If the pattern allows for an optional sign,96 // but the string has no digit characters following the sign,97 char s[] = "- 9+12";98 r = std::from_chars(s, s + sizeof(s), x);99 // value is unmodified,100 assert(x == 42);101 // no characters match the pattern.102 assert(r.ptr == s);103 assert(r.ec == std::errc::invalid_argument);104 }105 106 {107 char s[] = "9+12";108 r = std::from_chars(s, s + sizeof(s), x);109 assert(r.ec == std::errc{});110 // The member ptr of the return value points to the first character111 // not matching the pattern,112 assert(r.ptr == s + 1);113 assert(x == 9);114 }115 116 {117 char s[] = "12";118 r = std::from_chars(s, s + 2, x);119 assert(r.ec == std::errc{});120 // or has the value last if all characters match.121 assert(r.ptr == s + 2);122 assert(x == 12);123 }124 125 {126 // '-' is the only sign that may appear127 char s[] = "+30";128 // If no characters match the pattern,129 r = std::from_chars(s, s + sizeof(s), x);130 // value is unmodified,131 assert(x == 12);132 // the member ptr of the return value is first and133 assert(r.ptr == s);134 // the member ec is equal to errc::invalid_argument.135 assert(r.ec == std::errc::invalid_argument);136 }137 }138};139 140TEST_CONSTEXPR_CXX23 bool test()141{142 run<test_basics>(integrals);143 run<test_signed>(all_signed);144 145 return true;146}147 148int main(int, char**) {149 test();150#if TEST_STD_VER > 20151 static_assert(test());152#endif153 154 return 0;155}156