/*
 * 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 <danny@nerdcruft.net>
 */

#pragma once

#include "../view.hpp"
#include "enum.hpp"

namespace cruft::parse {
    ///////////////////////////////////////////////////////////////////////////
    /// Extracts an instance of a native type T from the string [first, last).
    ///
    /// Throws std::invalid_argument when the type cannot be parsed.
    ///
    /// The view is modified in place to reflect the unused data.
    template <typename T> T value (cruft::view<const char *> &);
    template <typename T> T value (cruft::view<      char *> &);


    /// Parses a prefix string to obtain an instance of T.
    ///
    /// This only differs from `parse` in that it throws if the entire string
    /// isn't consumed during the parse, rather than reporting the remaining
    /// data.
    template <typename T>
    T
    from_string (cruft::view<const char*> data)
    {
        if constexpr (std::is_enum_v<T>) {
            return enumeration::from_string<T> (data);
        } else {
            T res = value<T> (data);
            if (!data.empty ())
                throw std::invalid_argument ("unable to parse");
            return res;
        }
    }

    template <typename T> T from_string (const char *data) { return from_string<T> (cruft::view (data)); }
    template <typename T> T from_string (std::string const &data) { return from_string<T> (cruft::view (data)); }
}