/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2017-2018 Danny Robson */ #include "parse.hpp" #include "cast.hpp" #include #include using cruft::parse; /////////////////////////////////////////////////////////////////////////////// template struct c_traits; template <> struct c_traits { static constexpr auto func = strtol; }; template <> struct c_traits { static constexpr auto func = strtoll; }; template <> struct c_traits { static constexpr auto func = strtoul; }; template <> struct c_traits { static constexpr auto func = strtoull; }; template <> struct c_traits { static constexpr auto func = strtof; }; template <> struct c_traits { static constexpr auto func = strtod; }; template <> struct c_traits { static constexpr auto func = strtold; }; //----------------------------------------------------------------------------- template T c_iparse (cruft::view &data) { auto head = const_cast (data.begin ()); auto tail = head; auto val = c_traits::func (head, &tail, 0); if (tail == head) throw std::invalid_argument ("unable to parse integer"); data = data.consume (tail); return val; } //----------------------------------------------------------------------------- template T c_fparse (cruft::view &data) { auto head = const_cast (data.begin ()); auto tail = head; auto val = c_traits::func (head, &tail); if (tail == head) throw std::invalid_argument ("unable to parse float"); data = data.consume (tail); return val; } /////////////////////////////////////////////////////////////////////////////// #define C_PARSE(T, KLASS) \ template <> \ T \ cruft::parse ( \ cruft::view &str \ ) { \ return c_ ## KLASS ## parse (str); \ } //----------------------------------------------------------------------------- C_PARSE(long, i) C_PARSE(long long, i) C_PARSE(unsigned long, i) C_PARSE(unsigned long long, i) C_PARSE(float, f) C_PARSE(double, f) C_PARSE(long double, f) #define C_PARSE_WITH_CAST(FINAL, USED) \ template<> \ FINAL \ cruft::parse (cruft::view &str) { \ auto remain = str; \ auto res = parse (remain); \ if (res > std::numeric_limits::max ()) \ throw std::invalid_argument ("overflow during parse"); \ \ str = remain; \ return cruft::cast::narrow (res); \ } C_PARSE_WITH_CAST(unsigned int, unsigned long)