parse: add more documentation for parsing templates
This commit is contained in:
parent
4c29123d4d
commit
4b37f59e22
70
parse.cpp
70
parse.cpp
@ -9,6 +9,7 @@
|
|||||||
#include "parse.hpp"
|
#include "parse.hpp"
|
||||||
|
|
||||||
#include "cast.hpp"
|
#include "cast.hpp"
|
||||||
|
#include "preprocessor.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -16,15 +17,22 @@
|
|||||||
using cruft::parse;
|
using cruft::parse;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T> struct c_traits;
|
/// A trait class that records the C string parsing function for a given type.
|
||||||
template <> struct c_traits<long> { static constexpr auto func = strtol; };
|
///
|
||||||
template <> struct c_traits<long long> { static constexpr auto func = strtoll; };
|
/// Not all types will necessarily have a corresponding parsing function. eg,
|
||||||
template <> struct c_traits<unsigned long> { static constexpr auto func = strtoul; };
|
template <typename ValueT> struct parse_traits { };
|
||||||
template <> struct c_traits<unsigned long long> { static constexpr auto func = strtoull; };
|
|
||||||
|
|
||||||
template <> struct c_traits<float> { static constexpr auto func = strtof; };
|
//-----------------------------------------------------------------------------
|
||||||
template <> struct c_traits<double> { static constexpr auto func = strtod; };
|
template <> struct parse_traits<long> { static constexpr auto value = strtol; };
|
||||||
template <> struct c_traits<long double> { static constexpr auto func = strtold; };
|
template <> struct parse_traits<long long> { static constexpr auto value = strtoll; };
|
||||||
|
template <> struct parse_traits<unsigned long> { static constexpr auto value = strtoul; };
|
||||||
|
template <> struct parse_traits<unsigned long long> { static constexpr auto value = strtoull; };
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <> struct parse_traits<float> { static constexpr auto value = strtof; };
|
||||||
|
template <> struct parse_traits<double> { static constexpr auto value = strtod; };
|
||||||
|
template <> struct parse_traits<long double> { static constexpr auto value = strtold; };
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -34,7 +42,7 @@ c_iparse (cruft::view<char const*> &data)
|
|||||||
{
|
{
|
||||||
auto head = const_cast<char *> (data.begin ());
|
auto head = const_cast<char *> (data.begin ());
|
||||||
auto tail = head;
|
auto tail = head;
|
||||||
auto val = c_traits<T>::func (head, &tail, 0);
|
auto val = parse_traits<T>::value (head, &tail, 0);
|
||||||
|
|
||||||
if (tail == head)
|
if (tail == head)
|
||||||
throw std::invalid_argument ("unable to parse integer");
|
throw std::invalid_argument ("unable to parse integer");
|
||||||
@ -51,7 +59,7 @@ c_fparse (cruft::view<char const*> &data)
|
|||||||
{
|
{
|
||||||
auto head = const_cast<char *> (data.begin ());
|
auto head = const_cast<char *> (data.begin ());
|
||||||
auto tail = head;
|
auto tail = head;
|
||||||
auto val = c_traits<T>::func (head, &tail);
|
auto val = parse_traits<T>::value (head, &tail);
|
||||||
|
|
||||||
if (tail == head)
|
if (tail == head)
|
||||||
throw std::invalid_argument ("unable to parse float");
|
throw std::invalid_argument ("unable to parse float");
|
||||||
@ -64,27 +72,45 @@ c_fparse (cruft::view<char const*> &data)
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define C_PARSE(T, KLASS) \
|
/// Specialise cruft::parse for the type KLASS and dispatch the actual parsing
|
||||||
|
/// to safe template wrappers around the C parsing functions.
|
||||||
|
#define C_PARSE(PREFIX, KLASS) \
|
||||||
template <> \
|
template <> \
|
||||||
T \
|
KLASS \
|
||||||
cruft::parse<T> ( \
|
cruft::parse<KLASS> ( \
|
||||||
cruft::view<const char *> &str \
|
cruft::view<const char *> &str \
|
||||||
) { \
|
) { \
|
||||||
return c_ ## KLASS ## parse<T> (str); \
|
return c_ ## PREFIX ## parse<KLASS> (str); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
C_PARSE(long, i)
|
MAP1(C_PARSE, i,
|
||||||
C_PARSE(long long, i)
|
unsigned long,
|
||||||
C_PARSE(unsigned long, i)
|
unsigned long long,
|
||||||
C_PARSE(unsigned long long, i)
|
long,
|
||||||
|
long long
|
||||||
C_PARSE(float, f)
|
)
|
||||||
C_PARSE(double, f)
|
|
||||||
C_PARSE(long double, f)
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
MAP1(C_PARSE, f,
|
||||||
|
float,
|
||||||
|
double,
|
||||||
|
long double
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Specialise cruft::parse for the type FINAL and dispatch the actual parsing
|
||||||
|
/// to the safe template wrappers defined above, but use the type USED as an
|
||||||
|
/// intermediary type.
|
||||||
|
///
|
||||||
|
/// We need to parse using the type `USED` because there aren't C parsing
|
||||||
|
/// routines for all the fundamental types.
|
||||||
|
///
|
||||||
|
/// We check that the final result can safely fit within `FINAL` before
|
||||||
|
/// returning the value, else we raise an exception.
|
||||||
#define C_PARSE_WITH_CAST(FINAL, USED) \
|
#define C_PARSE_WITH_CAST(FINAL, USED) \
|
||||||
template<> \
|
template<> \
|
||||||
FINAL \
|
FINAL \
|
||||||
|
Loading…
Reference in New Issue
Block a user