si: change the SI code to a parser

This commit is contained in:
Danny Robson 2019-03-18 14:08:06 +11:00
parent 34ab275578
commit 020d3c0aaf
4 changed files with 86 additions and 18 deletions

View File

@ -606,6 +606,7 @@ if (TESTS)
rational
region
roots/bisection
si
signal
singleton
stream

49
si.cpp
View File

@ -3,16 +3,51 @@
* 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 2011 Danny Robson <danny@nerdcruft.net>
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
#include "si.hpp"
uintmax_t to_KiB (uintmax_t bytes) { return bytes >> 10; }
uintmax_t to_MiB (uintmax_t bytes) { return bytes >> 20; }
uintmax_t to_GiB (uintmax_t bytes) { return bytes >> 30; }
#include "std.hpp"
#include "parse.hpp"
uintmax_t from_KiB (uintmax_t bytes) { return bytes << 10; }
uintmax_t from_MiB (uintmax_t bytes) { return bytes << 20; }
uintmax_t from_GiB (uintmax_t bytes) { return bytes << 30; }
#include <cruft/util/preprocessor.hpp>
#include <charconv>
///////////////////////////////////////////////////////////////////////////////
template <typename ValueT>
cruft::expected<ValueT, std::errc>
cruft::si::parse (cruft::view<char const*> const src)
{
auto remain = src;
ValueT dst = cruft::parse<ValueT> (remain);
switch (remain.size ()) {
case 0:
return dst;
case 1:
switch (remain[0]) {
case 'K': case 'k': return dst * 1024;
case 'M': case 'm': return dst * 1024 * 1024;
case 'G': case 'g': return dst * 1024 * 1024 * 1024;
case 'T': case 't': return dst * 1024 * 1024 * 1024 * 1024;
}
default:
return cruft::unexpected (std::errc::invalid_argument);
}
}
///////////////////////////////////////////////////////////////////////////////
#define INSTANTIATE(KLASS) template cruft::expected<KLASS,std::errc> cruft::si::parse (cruft::view<char const*>);
MAP0 (INSTANTIATE,
u16, u32, u64,
i16, i32, i64,
f32, f64
)

21
si.hpp
View File

@ -3,20 +3,19 @@
* 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 2011 Danny Robson <danny@nerdcruft.net>
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_SI_HPP
#define __UTIL_SI_HPP
#pragma once
#include <cstdint>
#include "expected.hpp"
#include "view.hpp"
uintmax_t to_KiB (uintmax_t bytes);
uintmax_t to_MiB (uintmax_t bytes);
uintmax_t to_GiB (uintmax_t bytes);
#include <system_error>
uintmax_t from_KiB (uintmax_t bytes);
uintmax_t from_MiB (uintmax_t bytes);
uintmax_t from_GiB (uintmax_t bytes);
namespace cruft::si {
template <typename ValueT>
expected<ValueT, std::errc>
parse (cruft::view<char const*>);
}
#endif

33
test/si.cpp Normal file
View File

@ -0,0 +1,33 @@
#include "tap.hpp"
#include "si.hpp"
int main ()
{
cruft::TAP::logger tap;
struct {
char const *str;
std::size_t val;
} const TESTS[] = {
{ "0", 0u },
{ "1", 1u },
{ "1K", 1024u },
{ "1M", 1024u * 1024u },
{ "1G" , 1024u * 1024u * 1024u },
{ "1T", 1024ul * 1024u * 1024u * 1024u },
{ "3M", 3u * 1024u * 1024u },
{ "3k", 3u * 1024u },
};
for (auto const &t: TESTS) {
auto res = cruft::si::parse<std::size_t> (t.str);
if (!res) {
tap.fail ("SI parsing %!", t.str);
} else {
tap.expect_eq (t.val, *res, "SI parsing '%!'", t.str);
}
}
return tap.status ();
}