// Copyright 2015, Tobias Hermann and the FunctionalPlus contributors. // https://github.com/Dobiasd/FunctionalPlus // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #pragma once #include #include #include #include namespace fplus { namespace internal { template struct helper_read_value_struct {}; template <> struct helper_read_value_struct { static void read(const std::string& str, int& result, std::size_t& num_chars_used) { result = std::stoi(str, &num_chars_used); } }; template <> struct helper_read_value_struct { static void read(const std::string& str, long& result, std::size_t& num_chars_used) { result = std::stol(str, &num_chars_used); } }; template <> struct helper_read_value_struct { static void read(const std::string& str, long long& result, std::size_t& num_chars_used) { result = std::stoll(str, &num_chars_used); } }; template <> struct helper_read_value_struct { static void read(const std::string& str, unsigned int& result, std::size_t& num_chars_used) { unsigned long result_u_l = std::stoul(str, &num_chars_used); result = static_cast(result_u_l); } }; template <> struct helper_read_value_struct { static void read(const std::string& str, unsigned long& result, std::size_t& num_chars_used) { result = std::stoul(str, &num_chars_used); } }; template <> struct helper_read_value_struct { static void read(const std::string& str, unsigned long long& result, std::size_t& num_chars_used) { result = std::stoull(str, &num_chars_used); } }; template <> struct helper_read_value_struct { static void read(const std::string& str, float& result, std::size_t& num_chars_used) { result = std::stof(str, &num_chars_used); } }; template <> struct helper_read_value_struct { static void read(const std::string& str, double& result, std::size_t& num_chars_used) { result = std::stod(str, &num_chars_used); } }; template <> struct helper_read_value_struct { static void read(const std::string& str, long double& result, std::size_t& num_chars_used) { result = std::stold(str, &num_chars_used); } }; template <> struct helper_read_value_struct { static void read(const std::string& str, std::string& result, std::size_t& num_chars_used) { num_chars_used = str.size(); result = str; } }; } // API search type: read_value_result : String -> Result a // Try to deserialize a value. template result read_value_result(const std::string& str) { try { T result; std::size_t num_chars_used = 0; internal::helper_read_value_struct::read(str, result, num_chars_used); if (num_chars_used != str.size()) { return error(std::string("String not fully parsable.")); } return ok(result); } catch(const std::invalid_argument& e) { return error(e.what()); } catch(const std::out_of_range& e) { return error(e.what()); } } // API search type: read_value : String -> Maybe a // Try to deserialize/parse a value, e.g.: // String to Int // String to Float // String to Double // read_value("42") == 42 // etc. template maybe read_value(const std::string& str) { return to_maybe(read_value_result(str)); } // API search type: read_value_with_default : (a, String) -> a // fwd bind count: 1 // Try to deserialize a value, return given default on failure, e.g.: // String to Int // String to Float // String to Double // read_value_with_default(3, "42") == 42 // read_value_with_default(3, "") == 3 // read_value_with_default(3, "foo") == 3 // etc. template T read_value_with_default(const T& def, const std::string& str) { return just_with_default(def, to_maybe(read_value_result(str))); } // API search type: read_value_unsafe : String -> a // Try to deserialize a value, crash on failure, e.g.: // String to Int // String to Float // String to Double // read_value_unsafe("42") == 42 // read_value_unsafe("") == crash // read_value_unsafe("foo") == crash // See read_value and read_value_with_default for safe versions. // etc. template T read_value_unsafe(const std::string& str) { return unsafe_get_just(to_maybe(read_value_result(str))); } } // namespace fplus