brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.2 KiB · 5028fc8 Raw
374 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#include <__assert>10#include <cerrno>11#include <charconv>12#include <cstdlib>13#include <limits>14#include <stdexcept>15#include <string>16 17#if _LIBCPP_HAS_WIDE_CHARACTERS18#  include <cwchar>19#endif20 21_LIBCPP_BEGIN_NAMESPACE_STD22 23#ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON24 25template <bool>26struct __basic_string_common;27 28// The struct isn't declared anymore in the headers. It's only here for ABI compatibility.29template <>30struct __basic_string_common<true> {31  [[noreturn]] _LIBCPP_EXPORTED_FROM_ABI void __throw_length_error() const;32  [[noreturn]] _LIBCPP_EXPORTED_FROM_ABI void __throw_out_of_range() const;33};34 35void __basic_string_common<true>::__throw_length_error() const { std::__throw_length_error("basic_string"); }36void __basic_string_common<true>::__throw_out_of_range() const { std::__throw_out_of_range("basic_string"); }37 38#endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON39 40// Define legacy ABI functions41// ---------------------------42 43#ifndef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION44 45// This initializes the string with [__s, __s + __sz), but capacity() == __reserve. Assumes that __reserve >= __sz.46template <class _CharT, class _Traits, class _Allocator>47void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz, size_type __reserve) {48  pointer __p = __init_internal_buffer(__reserve);49  __annotate_delete();50  __set_size(__sz);51  traits_type::copy(std::__to_address(__p), __s, __sz);52  traits_type::assign(__p[__sz], value_type());53  __annotate_new(__sz);54}55 56#  define STRING_LEGACY_API(CharT)                                                                                     \57    template _LIBCPP_EXPORTED_FROM_ABI void basic_string<CharT>::__init(const value_type*, size_type, size_type)58 59STRING_LEGACY_API(char);60#  if _LIBCPP_HAS_WIDE_CHARACTERS61STRING_LEGACY_API(wchar_t);62#  endif63 64#endif // _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION65 66#define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template _LIBCPP_EXPORTED_FROM_ABI __VA_ARGS__;67#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION68_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)69#  if _LIBCPP_HAS_WIDE_CHARACTERS70_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)71#  endif72#else73_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)74#  if _LIBCPP_HAS_WIDE_CHARACTERS75_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)76#  endif77#endif78#undef _LIBCPP_EXTERN_TEMPLATE_DEFINE79 80template string operator+ <char, char_traits<char>, allocator<char>>(char const*, string const&);81 82namespace {83 84inline void throw_from_string_out_of_range(const string& func) {85  std::__throw_out_of_range((func + ": out of range").c_str());86}87 88inline void throw_from_string_invalid_arg(const string& func) {89  std::__throw_invalid_argument((func + ": no conversion").c_str());90}91 92// as_integer93 94template <typename V, typename S, typename F>95inline V as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) {96  typename S::value_type* ptr                             = nullptr;97  const typename S::value_type* const p                   = str.c_str();98  __libcpp_remove_reference_t<decltype(errno)> errno_save = errno;99  errno                                                   = 0;100  V r                                                     = f(p, &ptr, base);101  swap(errno, errno_save);102  if (errno_save == ERANGE)103    throw_from_string_out_of_range(func);104  if (ptr == p)105    throw_from_string_invalid_arg(func);106  if (idx)107    *idx = static_cast<size_t>(ptr - p);108  return r;109}110 111template <typename V, typename S>112inline V as_integer(const string& func, const S& s, size_t* idx, int base);113 114// string115template <>116inline 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 124template <>125inline 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 129template <>130inline 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 134template <>135inline 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 139template <>140inline 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}143 144#if _LIBCPP_HAS_WIDE_CHARACTERS145// wstring146template <>147inline int as_integer(const string& func, const wstring& s, size_t* idx, int base) {148  // Use long as no Stantard string to integer exists.149  long r = as_integer_helper<long>(func, s, idx, base, wcstol);150  if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)151    throw_from_string_out_of_range(func);152  return static_cast<int>(r);153}154 155template <>156inline long as_integer(const string& func, const wstring& s, size_t* idx, int base) {157  return as_integer_helper<long>(func, s, idx, base, wcstol);158}159 160template <>161inline unsigned long as_integer(const string& func, const wstring& s, size_t* idx, int base) {162  return as_integer_helper<unsigned long>(func, s, idx, base, wcstoul);163}164 165template <>166inline long long as_integer(const string& func, const wstring& s, size_t* idx, int base) {167  return as_integer_helper<long long>(func, s, idx, base, wcstoll);168}169 170template <>171inline unsigned long long as_integer(const string& func, const wstring& s, size_t* idx, int base) {172  return as_integer_helper<unsigned long long>(func, s, idx, base, wcstoull);173}174#endif // _LIBCPP_HAS_WIDE_CHARACTERS175 176// as_float177 178template <typename V, typename S, typename F>179inline V as_float_helper(const string& func, const S& str, size_t* idx, F f) {180  typename S::value_type* ptr                             = nullptr;181  const typename S::value_type* const p                   = str.c_str();182  __libcpp_remove_reference_t<decltype(errno)> errno_save = errno;183  errno                                                   = 0;184  V r                                                     = f(p, &ptr);185  swap(errno, errno_save);186  if (errno_save == ERANGE)187    throw_from_string_out_of_range(func);188  if (ptr == p)189    throw_from_string_invalid_arg(func);190  if (idx)191    *idx = static_cast<size_t>(ptr - p);192  return r;193}194 195template <typename V, typename S>196inline V as_float(const string& func, const S& s, size_t* idx = nullptr);197 198template <>199inline float as_float(const string& func, const string& s, size_t* idx) {200  return as_float_helper<float>(func, s, idx, strtof);201}202 203template <>204inline double as_float(const string& func, const string& s, size_t* idx) {205  return as_float_helper<double>(func, s, idx, strtod);206}207 208template <>209inline long double as_float(const string& func, const string& s, size_t* idx) {210  return as_float_helper<long double>(func, s, idx, strtold);211}212 213#if _LIBCPP_HAS_WIDE_CHARACTERS214template <>215inline float as_float(const string& func, const wstring& s, size_t* idx) {216  return as_float_helper<float>(func, s, idx, wcstof);217}218 219template <>220inline double as_float(const string& func, const wstring& s, size_t* idx) {221  return as_float_helper<double>(func, s, idx, wcstod);222}223 224template <>225inline long double as_float(const string& func, const wstring& s, size_t* idx) {226  return as_float_helper<long double>(func, s, idx, wcstold);227}228#endif // _LIBCPP_HAS_WIDE_CHARACTERS229 230} // unnamed namespace231 232int stoi(const string& str, size_t* idx, int base) { return as_integer<int>("stoi", str, idx, base); }233 234long stol(const string& str, size_t* idx, int base) { return as_integer<long>("stol", str, idx, base); }235 236unsigned long stoul(const string& str, size_t* idx, int base) {237  return as_integer<unsigned long>("stoul", str, idx, base);238}239 240long long stoll(const string& str, size_t* idx, int base) { return as_integer<long long>("stoll", str, idx, base); }241 242unsigned long long stoull(const string& str, size_t* idx, int base) {243  return as_integer<unsigned long long>("stoull", str, idx, base);244}245 246float stof(const string& str, size_t* idx) { return as_float<float>("stof", str, idx); }247 248double stod(const string& str, size_t* idx) { return as_float<double>("stod", str, idx); }249 250long double stold(const string& str, size_t* idx) { return as_float<long double>("stold", str, idx); }251 252#if _LIBCPP_HAS_WIDE_CHARACTERS253int stoi(const wstring& str, size_t* idx, int base) { return as_integer<int>("stoi", str, idx, base); }254 255long stol(const wstring& str, size_t* idx, int base) { return as_integer<long>("stol", str, idx, base); }256 257unsigned long stoul(const wstring& str, size_t* idx, int base) {258  return as_integer<unsigned long>("stoul", str, idx, base);259}260 261long long stoll(const wstring& str, size_t* idx, int base) { return as_integer<long long>("stoll", str, idx, base); }262 263unsigned long long stoull(const wstring& str, size_t* idx, int base) {264  return as_integer<unsigned long long>("stoull", str, idx, base);265}266 267float stof(const wstring& str, size_t* idx) { return as_float<float>("stof", str, idx); }268 269double stod(const wstring& str, size_t* idx) { return as_float<double>("stod", str, idx); }270 271long double stold(const wstring& str, size_t* idx) { return as_float<long double>("stold", str, idx); }272#endif // _LIBCPP_HAS_WIDE_CHARACTERS273 274// to_string275 276namespace {277 278// as_string279 280template <typename S, typename P, typename V >281inline S as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) {282  typedef typename S::size_type size_type;283  size_type available = s.size();284  while (true) {285    int status = sprintf_like(&s[0], available + 1, fmt, a);286    if (status >= 0) {287      size_type used = static_cast<size_type>(status);288      if (used <= available) {289        s.resize(used);290        break;291      }292      available = used; // Assume this is advice of how much space we need.293    } else294      available = available * 2 + 1;295    s.resize(available);296  }297  return s;298}299 300template <class S>301struct initial_string;302 303template <>304struct initial_string<string> {305  string operator()() const {306    string s;307    s.resize(s.capacity());308    return s;309  }310};311 312#if _LIBCPP_HAS_WIDE_CHARACTERS313template <>314struct initial_string<wstring> {315  wstring operator()() const {316    wstring s(20, wchar_t());317    s.resize(s.capacity());318    return s;319  }320};321 322typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t* __restrict, ...);323 324inline wide_printf get_swprintf() {325#  ifndef _LIBCPP_MSVCRT326  return swprintf;327#  else328  return static_cast<int(__cdecl*)(wchar_t* __restrict, size_t, const wchar_t* __restrict, ...)>(_snwprintf);329#  endif330}331#endif // _LIBCPP_HAS_WIDE_CHARACTERS332 333template <typename S, typename V>334S i_to_string(V v) {335  //  numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.336  //  For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),337  //  so we need +1 here.338  constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10339  char buf[bufsize];340  const auto res = to_chars(buf, buf + bufsize, v);341  _LIBCPP_ASSERT_INTERNAL(res.ec == errc(), "bufsize must be large enough to accomodate the value");342  return S(buf, res.ptr);343}344 345} // unnamed namespace346 347string to_string(int val) { return i_to_string< string>(val); }348string to_string(long val) { return i_to_string< string>(val); }349string to_string(long long val) { return i_to_string< string>(val); }350string to_string(unsigned val) { return i_to_string< string>(val); }351string to_string(unsigned long val) { return i_to_string< string>(val); }352string to_string(unsigned long long val) { return i_to_string< string>(val); }353 354#if _LIBCPP_HAS_WIDE_CHARACTERS355wstring to_wstring(int val) { return i_to_string<wstring>(val); }356wstring to_wstring(long val) { return i_to_string<wstring>(val); }357wstring to_wstring(long long val) { return i_to_string<wstring>(val); }358wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); }359wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); }360wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); }361#endif362 363string to_string(float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); }364string to_string(double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); }365string to_string(long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); }366 367#if _LIBCPP_HAS_WIDE_CHARACTERS368wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); }369wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); }370wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); }371#endif372 373_LIBCPP_END_NAMESPACE_STD374