@@ -81,8 +81,8 @@ template string operator+ <char, char_traits<char>, allocator<char>>(char const*
8181
8282namespace {
8383
84- inline void throw_from_string_out_of_range (const string& func) {
85- std::__throw_out_of_range ((func + " : out of range" ).c_str ());
84+ inline void throw_from_string_out_of_range (const char * func) {
85+ std::__throw_out_of_range ((std::string ( func) + " : out of range" ).c_str ());
8686}
8787
8888inline void throw_from_string_invalid_arg (const string& func) {
@@ -92,7 +92,7 @@ inline void throw_from_string_invalid_arg(const string& func) {
9292// as_integer
9393
9494template <typename V, typename S, typename F>
95- inline V as_integer_helper (const string& func, const S& str, size_t * idx, int base, F f) {
95+ inline V as_integer_helper (const char * func, const S& str, size_t * idx, int base, F f) {
9696 typename S::value_type* ptr = nullptr ;
9797 const typename S::value_type* const p = str.c_str ();
9898 __libcpp_remove_reference_t <decltype (errno)> errno_save = errno;
@@ -109,42 +109,14 @@ inline V as_integer_helper(const string& func, const S& str, size_t* idx, int ba
109109}
110110
111111template <typename V, typename S>
112- inline V as_integer (const string& func, const S& s, size_t * idx, int base);
112+ inline V as_integer (const char * func, const S& s, size_t * idx, int base);
113113
114114// string
115- template <>
116- inline int as_integer (const string& func, const string& s, size_t * idx, int base) {
117- // Use long as no Standard string to integer exists.
118- long r = as_integer_helper<long >(func, s, idx, base, strtol);
119- if (r < numeric_limits<int >::min () || numeric_limits<int >::max () < r)
120- throw_from_string_out_of_range (func);
121- return static_cast <int >(r);
122- }
123-
124- template <>
125- inline long as_integer (const string& func, const string& s, size_t * idx, int base) {
126- return as_integer_helper<long >(func, s, idx, base, strtol);
127- }
128-
129- template <>
130- inline unsigned long as_integer (const string& func, const string& s, size_t * idx, int base) {
131- return as_integer_helper<unsigned long >(func, s, idx, base, strtoul);
132- }
133-
134- template <>
135- inline long long as_integer (const string& func, const string& s, size_t * idx, int base) {
136- return as_integer_helper<long long >(func, s, idx, base, strtoll);
137- }
138-
139- template <>
140- inline unsigned long long as_integer (const string& func, const string& s, size_t * idx, int base) {
141- return as_integer_helper<unsigned long long >(func, s, idx, base, strtoull);
142- }
143115
144116#if _LIBCPP_HAS_WIDE_CHARACTERS
145117// wstring
146118template <>
147- inline int as_integer (const string& func, const wstring& s, size_t * idx, int base) {
119+ inline int as_integer (const char * func, const wstring& s, size_t * idx, int base) {
148120 // Use long as no Stantard string to integer exists.
149121 long r = as_integer_helper<long >(func, s, idx, base, wcstol);
150122 if (r < numeric_limits<int >::min () || numeric_limits<int >::max () < r)
@@ -153,30 +125,30 @@ inline int as_integer(const string& func, const wstring& s, size_t* idx, int bas
153125}
154126
155127template <>
156- inline long as_integer (const string& func, const wstring& s, size_t * idx, int base) {
128+ inline long as_integer (const char * func, const wstring& s, size_t * idx, int base) {
157129 return as_integer_helper<long >(func, s, idx, base, wcstol);
158130}
159131
160132template <>
161- inline unsigned long as_integer (const string& func, const wstring& s, size_t * idx, int base) {
133+ inline unsigned long as_integer (const char * func, const wstring& s, size_t * idx, int base) {
162134 return as_integer_helper<unsigned long >(func, s, idx, base, wcstoul);
163135}
164136
165137template <>
166- inline long long as_integer (const string& func, const wstring& s, size_t * idx, int base) {
138+ inline long long as_integer (const char * func, const wstring& s, size_t * idx, int base) {
167139 return as_integer_helper<long long >(func, s, idx, base, wcstoll);
168140}
169141
170142template <>
171- inline unsigned long long as_integer (const string& func, const wstring& s, size_t * idx, int base) {
143+ inline unsigned long long as_integer (const char * func, const wstring& s, size_t * idx, int base) {
172144 return as_integer_helper<unsigned long long >(func, s, idx, base, wcstoull);
173145}
174146#endif // _LIBCPP_HAS_WIDE_CHARACTERS
175147
176148// as_float
177149
178150template <typename V, typename S, typename F>
179- inline V as_float_helper (const string& func, const S& str, size_t * idx, F f) {
151+ inline V as_float_helper (const char * func, const S& str, size_t * idx, F f) {
180152 typename S::value_type* ptr = nullptr ;
181153 const typename S::value_type* const p = str.c_str ();
182154 __libcpp_remove_reference_t <decltype (errno)> errno_save = errno;
@@ -193,54 +165,71 @@ inline V as_float_helper(const string& func, const S& str, size_t* idx, F f) {
193165}
194166
195167template <typename V, typename S>
196- inline V as_float (const string& func, const S& s, size_t * idx = nullptr );
168+ inline V as_float (const char * func, const S& s, size_t * idx = nullptr );
197169
198170template <>
199- inline float as_float (const string& func, const string& s, size_t * idx) {
171+ inline float as_float (const char * func, const string& s, size_t * idx) {
200172 return as_float_helper<float >(func, s, idx, strtof);
201173}
202174
203175template <>
204- inline double as_float (const string& func, const string& s, size_t * idx) {
176+ inline double as_float (const char * func, const string& s, size_t * idx) {
205177 return as_float_helper<double >(func, s, idx, strtod);
206178}
207179
208180template <>
209- inline long double as_float (const string& func, const string& s, size_t * idx) {
181+ inline long double as_float (const char * func, const string& s, size_t * idx) {
210182 return as_float_helper<long double >(func, s, idx, strtold);
211183}
212184
213185#if _LIBCPP_HAS_WIDE_CHARACTERS
214186template <>
215- inline float as_float (const string& func, const wstring& s, size_t * idx) {
187+ inline float as_float (const char * func, const wstring& s, size_t * idx) {
216188 return as_float_helper<float >(func, s, idx, wcstof);
217189}
218190
219191template <>
220- inline double as_float (const string& func, const wstring& s, size_t * idx) {
192+ inline double as_float (const char * func, const wstring& s, size_t * idx) {
221193 return as_float_helper<double >(func, s, idx, wcstod);
222194}
223195
224196template <>
225- inline long double as_float (const string& func, const wstring& s, size_t * idx) {
197+ inline long double as_float (const char * func, const wstring& s, size_t * idx) {
226198 return as_float_helper<long double >(func, s, idx, wcstold);
227199}
228200#endif // _LIBCPP_HAS_WIDE_CHARACTERS
229201
202+ template <class Integer >
203+ Integer string_to_integer_impl (const char * func_name, const string& str, size_t * index, int base) {
204+ Integer result;
205+ from_chars_result status = std::from_chars (str.data (), str.data () + str.size (), result, base);
206+ if (status.ec != std::errc ()) {
207+ if (status.ec == std::errc::result_out_of_range)
208+ throw_from_string_out_of_range (func_name);
209+ throw_from_string_invalid_arg (func_name);
210+ }
211+ if (index)
212+ *index = status.ptr - str.data ();
213+
214+ return result;
215+ }
216+
230217} // unnamed namespace
231218
232- int stoi (const string& str, size_t * idx, int base) { return as_integer <int >(" stoi" , str, idx, base); }
219+ int stoi (const string& str, size_t * idx, int base) { return string_to_integer_impl <int >(" stoi" , str, idx, base); }
233220
234- long stol (const string& str, size_t * idx, int base) { return as_integer <long >(" stol" , str, idx, base); }
221+ long stol (const string& str, size_t * idx, int base) { return string_to_integer_impl <long >(" stol" , str, idx, base); }
235222
236223unsigned long stoul (const string& str, size_t * idx, int base) {
237- return as_integer <unsigned long >(" stoul" , str, idx, base);
224+ return string_to_integer_impl <unsigned long >(" stoul" , str, idx, base);
238225}
239226
240- long long stoll (const string& str, size_t * idx, int base) { return as_integer<long long >(" stoll" , str, idx, base); }
227+ long long stoll (const string& str, size_t * idx, int base) {
228+ return string_to_integer_impl<long long >(" stoll" , str, idx, base);
229+ }
241230
242231unsigned long long stoull (const string& str, size_t * idx, int base) {
243- return as_integer <unsigned long long >(" stoull" , str, idx, base);
232+ return string_to_integer_impl <unsigned long long >(" stoull" , str, idx, base);
244233}
245234
246235float stof (const string& str, size_t * idx) { return as_float<float >(" stof" , str, idx); }
0 commit comments