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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03 10 // UNSUPPORTED: !stdlib=libc++ && c++11 11 // UNSUPPORTED: !stdlib=libc++ && c++14 12 13 // <charconv> 14 15 // from_chars_result from_chars(const char* first, const char* last, 16 // Integral& value, int base = 10) 17 18 #include <charconv> 19 #include "test_macros.h" 20 #include "charconv_test_helpers.h" 21 22 template <typename T> 23 struct test_basics 24 { 25 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 of 34 // letters and digits representing an integer with the radix 35 // 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 char s[] = "0X7BAtSGHDkEIXZg "; 44 45 // The letters from a (or A) through z (or Z) are ascribed the 46 // values 10 through 35; (C11 7.22.1.4/3) 47 r = std::from_chars(s, s + sizeof(s), x, 36); 48 assert(r.ec == std::errc::result_out_of_range); 49 // The member ptr of the return value points to the first character 50 // not matching the pattern 51 assert(r.ptr == s + sizeof(s) - 2); 52 assert(x == 1); 53 54 // no "0x" or "0X" prefix shall appear if the value of base is 16 55 r = std::from_chars(s, s + sizeof(s), x, 16); 56 assert(r.ec == std::errc{}); 57 assert(r.ptr == s + 1); 58 assert(x == 0); 59 60 // only letters and digits whose ascribed values are less than that 61 // of base are permitted. (C11 7.22.1.4/3) 62 r = std::from_chars(s + 2, s + sizeof(s), x, 12); 63 // If the parsed value is not in the range representable by the type 64 // of value, 65 if (!fits_in<T>(1150)) 66 { 67 // value is unmodified and 68 assert(x == 0); 69 // the member ec of the return value is equal to 70 // errc::result_out_of_range 71 assert(r.ec == std::errc::result_out_of_range); 72 } 73 else 74 { 75 // Otherwise, value is set to the parsed value, 76 assert(x == 1150); 77 // and the member ec is value-initialized. 78 assert(r.ec == std::errc{}); 79 } 80 assert(r.ptr == s + 5); 81 } 82 } 83 }; 84 85 template <typename T> 86 struct test_signed 87 { 88 void operator()() 89 { 90 std::from_chars_result r; 91 T x; 92 93 { 94 // If the pattern allows for an optional sign, 95 // but the string has no digit characters following the sign, 96 char s[] = "- 9+12"; 97 r = std::from_chars(s, s + sizeof(s), x); 98 // no characters match the pattern. 99 assert(r.ptr == s); 100 assert(r.ec == std::errc::invalid_argument); 101 } 102 103 { 104 char s[] = "9+12"; 105 r = std::from_chars(s, s + sizeof(s), x); 106 assert(r.ec == std::errc{}); 107 // The member ptr of the return value points to the first character 108 // not matching the pattern, 109 assert(r.ptr == s + 1); 110 assert(x == 9); 111 } 112 113 { 114 char s[] = "12"; 115 r = std::from_chars(s, s + 2, x); 116 assert(r.ec == std::errc{}); 117 // or has the value last if all characters match. 118 assert(r.ptr == s + 2); 119 assert(x == 12); 120 } 121 122 { 123 // '-' is the only sign that may appear 124 char s[] = "+30"; 125 // If no characters match the pattern, 126 r = std::from_chars(s, s + sizeof(s), x); 127 // value is unmodified, 128 assert(x == 12); 129 // the member ptr of the return value is first and 130 assert(r.ptr == s); 131 // the member ec is equal to errc::invalid_argument. 132 assert(r.ec == std::errc::invalid_argument); 133 } 134 } 135 }; 136 137 int main(int, char**) 138 { 139 run<test_basics>(integrals); 140 run<test_signed>(all_signed); 141 142 return 0; 143 } 144