parse: change parsing functions to modify the data view

This commit is contained in:
Danny Robson 2018-12-16 13:26:48 +11:00
parent 44760c6869
commit 5fedbdbdfe
5 changed files with 74 additions and 80 deletions

View File

@ -14,7 +14,7 @@
///////////////////////////////////////////////////////////////////////////////
static cruft::srgba4f
parse_hex (cruft::view<const char*> str)
parse_hex (cruft::view<const char*> &str)
{
if (str.size () != strlen ("#012345"))
throw std::invalid_argument ("expected length of 7");
@ -36,6 +36,7 @@ parse_hex (cruft::view<const char*> str)
uint8_t g = cruft::ascii::from_hex (str[3]) << 4u | cruft::ascii::from_hex (str[4]);
uint8_t b = cruft::ascii::from_hex (str[5]) << 4u | cruft::ascii::from_hex (str[6]);
str = str.consume (7);
return cruft::srgba<4,uint8_t> { r, g, b, 255 }.template cast<float> ();
}
@ -44,7 +45,7 @@ parse_hex (cruft::view<const char*> str)
///////////////////////////////////////////////////////////////////////////////
template <>
cruft::srgba4f
cruft::parse<cruft::srgba4f> (cruft::view<const char*> str)
cruft::parse<cruft::srgba4f> (cruft::view<const char*> &str)
{
return parse_hex (str);
}

View File

@ -19,7 +19,7 @@ static unsigned
default_parallelism (void)
{
if (auto var = getenv ("JOB_THREADS")) {
return cruft::parse<unsigned> (var);
return cruft::from_string<unsigned> (var);
}
return std::thread::hardware_concurrency ();
@ -31,7 +31,7 @@ static unsigned
default_depth (void)
{
if (auto var = getenv ("JOB_DEPTH")) {
return cruft::parse<unsigned> (var);
return cruft::from_string<unsigned> (var);
}
return 1024;

View File

@ -3,7 +3,7 @@
* 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 Danny Robson <danny@nerdcruft.net>
* Copyright 2017-2018 Danny Robson <danny@nerdcruft.net>
*/
#include "parse.hpp"
@ -30,14 +30,16 @@ template <> struct c_traits<long double> { static constexpr auto func = strtold;
//-----------------------------------------------------------------------------
template <typename T>
T
c_iparse (const char *first, const char *last)
c_iparse (cruft::view<char const*> &data)
{
auto tail = const_cast<char *> (last);
auto val = c_traits<T>::func (first, &tail, 0);
auto head = const_cast<char *> (data.begin ());
auto tail = head;
auto val = c_traits<T>::func (head, &tail, 0);
if (tail != last)
throw std::invalid_argument ("unable to parse");
if (tail == head)
throw std::invalid_argument ("unable to parse integer");
data = data.consume (tail);
return val;
}
@ -45,14 +47,16 @@ c_iparse (const char *first, const char *last)
//-----------------------------------------------------------------------------
template <typename T>
T
c_fparse (const char *first, const char *last)
c_fparse (cruft::view<char const*> &data)
{
auto tail = const_cast<char *> (last);
auto val = c_traits<T>::func (first, &tail);
auto head = const_cast<char *> (data.begin ());
auto tail = head;
auto val = c_traits<T>::func (head, &tail);
if (tail != last)
throw std::invalid_argument ("unable to parse");
if (tail == head)
throw std::invalid_argument ("unable to parse float");
data = data.consume (tail);
return val;
}
@ -60,46 +64,38 @@ c_fparse (const char *first, const char *last)
///////////////////////////////////////////////////////////////////////////////
#define C_PARSE(T, KLASS) \
template <> \
T \
cruft::parse<T> (cruft::view<const char *> str) \
{ \
return c_ ## KLASS ## parse<T> (std::cbegin (str), std::cend (str)); \
#define C_PARSE(T, KLASS) \
template <> \
T \
cruft::parse<T> ( \
cruft::view<const char *> &str \
) { \
return c_ ## KLASS ## parse<T> (str); \
}
//-----------------------------------------------------------------------------
C_PARSE(long, i)
C_PARSE(long long, i)
C_PARSE(unsigned long, i)
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(float, f)
C_PARSE(double, f)
C_PARSE(long double, f)
template <>
int
cruft::parse<int> (cruft::view<const char*> str)
{
auto intermediate = cruft::parse<long> (str);
return cruft::cast::lossless<int> (intermediate);
#define C_PARSE_WITH_CAST(FINAL, USED) \
template<> \
FINAL \
cruft::parse<FINAL> (cruft::view<char const*> &str) { \
auto remain = str; \
auto res = parse<USED> (remain); \
if (res > std::numeric_limits<FINAL>::max ()) \
throw std::invalid_argument ("overflow during parse"); \
\
str = remain; \
return cruft::cast::narrow<FINAL> (res); \
}
template <>
unsigned
cruft::parse<unsigned> (cruft::view<const char*> str)
{
return cruft::cast::narrow<unsigned> (parse<unsigned long> (str));
}
template <>
unsigned short
cruft::parse<unsigned short> (cruft::view<const char*> str)
{
return cruft::cast::narrow<unsigned short> (parse<unsigned long> (str));
}
C_PARSE_WITH_CAST(unsigned int, unsigned long)

View File

@ -3,43 +3,40 @@
* 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 Danny Robson <danny@nerdcruft.net>
* Copyright 2017-2018 Danny Robson <danny@nerdcruft.net>
*/
#ifndef CRUFT_UTIL_PARSE_HPP
#define CRUFT_UTIL_PARSE_HPP
#pragma once
#include "view.hpp"
#include <cstring>
#include <string>
#include <iterator>
namespace cruft {
///////////////////////////////////////////////////////////////////////////
/// extracts an instance of a native type T from the string [first, last).
/// Extracts an instance of a native type T from the string [first, last).
///
/// throws std::invalid_argument when the type cannot be parsed.
template <typename T>
T parse (cruft::view<const char *>);
//-------------------------------------------------------------------------
template <typename T>
T parse (const char *str)
{
return parse<T> (make_view (str));
}
//-------------------------------------------------------------------------
/// 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
parse (const std::string &str)
{
return parse<T> (make_view (str));
}
}
parse (cruft::view<const char *> &);
#endif
/// 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)
{
T res = parse<T> (data);
if (!data.empty ())
throw std::invalid_argument ("unable to parse");
return std::move (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)); }
}

View File

@ -8,11 +8,11 @@ main (void)
{
cruft::TAP::logger tap;
tap.expect_eq (cruft::parse<long> ("1"), 1L, "parsing long '1'");
tap.expect_throw<std::invalid_argument> ([] () { cruft::parse<long> ("a"); }, "parsing long 'a'");
tap.expect_eq (cruft::from_string<long> ("1"), 1L, "parsing long '1'");
tap.expect_throw<std::invalid_argument> ([] () { cruft::from_string<long> ("a"); }, "parsing long 'a'");
tap.expect_eq (cruft::parse<float> ("1"), 1.f, "parsing float '1'");
tap.expect_throw<std::invalid_argument> ([] () { cruft::parse<float> ("a"); }, "parsing float 'a'");
tap.expect_eq (cruft::from_string<float> ("1"), 1.f, "parsing float '1'");
tap.expect_throw<std::invalid_argument> ([] () { cruft::from_string<float> ("a"); }, "parsing float 'a'");
return tap.status ();
}