Skip to content

Commit

Permalink
support unit int string for -b -o -s -c option.
Browse files Browse the repository at this point in the history
  • Loading branch information
starpos committed Nov 5, 2014
1 parent eeff5f9 commit 7764469
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 6 deletions.
7 changes: 4 additions & 3 deletions iores.cpp
Expand Up @@ -34,6 +34,7 @@
#include "ioreth.hpp"
#include "util.hpp"
#include "rand.hpp"
#include "unit_int.hpp"

class Options
{
Expand Down Expand Up @@ -140,16 +141,16 @@ class Options

switch (c) {
case 's': /* disk access range in blocks */
accessRange_ = ::atol(optarg);
accessRange_ = fromUnitIntString(optarg);
break;
case 'b': /* blocksize */
blockSize_ = ::atol(optarg);
blockSize_ = fromUnitIntString(optarg);
break;
case 'p': /* period */
period_ = ::atol(optarg);
break;
case 'c': /* count */
count_ = ::atol(optarg);
count_ = fromUnitIntString(optarg);
break;
case 'w': /* write */
mode_ = WRITE_MODE;
Expand Down
7 changes: 4 additions & 3 deletions ioth.cpp
Expand Up @@ -35,6 +35,7 @@
#include "ioreth.hpp"
#include "util.hpp"
#include "thread_pool.hpp"
#include "unit_int.hpp"

/**
* Parse commane-line arguments as options.
Expand Down Expand Up @@ -127,16 +128,16 @@ class Options

switch (c) {
case 's': /* start offset in blocks */
startBlockId_ = ::atol(optarg);
startBlockId_ = fromUnitIntString(optarg);
break;
case 'b': /* blocksize */
blockSize_ = ::atol(optarg);
blockSize_ = fromUnitIntString(optarg);
break;
case 'p': /* period */
period_ = ::atol(optarg);
break;
case 'c': /* count */
count_ = ::atol(optarg);
count_ = fromUnitIntString(optarg);
break;
case 'w': /* write */
mode_ = WRITE_MODE;
Expand Down
100 changes: 100 additions & 0 deletions unit_int.hpp
@@ -0,0 +1,100 @@
#pragma once

#include <string>
#include <cstdio>
#include <cstdlib>
#include <exception>
#include <cinttypes>

/**
* Formst string with va_list.
*/
inline std::string formatStringV(const char *format, va_list ap)
{
char *p = nullptr;
int ret = ::vasprintf(&p, format, ap);
if (ret < 0) throw std::runtime_error("vasprintf failed.");
try {
std::string s(p, ret);
::free(p);
return s;
} catch (...) {
::free(p);
throw;
}
}

/**
* Create a std::string using printf() like formatting.
*/
inline std::string formatString(const char * format, ...)
{
std::string s;
std::exception_ptr ep;
va_list args;
va_start(args, format);
try {
s = formatStringV(format, args);
} catch (...) {
ep = std::current_exception();
}
va_end(args);
if (ep) std::rethrow_exception(ep);
return s;
}

/**
* Convert size string with unit suffix to unsigned integer.
*/
inline uint64_t fromUnitIntString(const std::string &valStr)
{
if (valStr.empty()) {
throw std::runtime_error("fromUnitIntString: invalid argument.");
}
char *endp;
uint64_t val = ::strtoll(valStr.c_str(), &endp, 10);
int shift = 0;
switch (*endp) {
case 'e': case 'E': shift = 60; break;
case 'p': case 'P': shift = 50; break;
case 't': case 'T': shift = 40; break;
case 'g': case 'G': shift = 30; break;
case 'm': case 'M': shift = 20; break;
case 'k': case 'K': shift = 10; break;
case '\0': break;
default:
throw std::runtime_error("fromUnitIntString: invalid suffix charactor.");
}
if (((val << shift) >> shift) != val) {
throw std::runtime_error("fromUnitIntString: overflow.");
}
return val << shift;
}

/**
* Unit suffixes:
* k: 2^10
* m: 2^20
* g: 2^30
* t: 2^40
* p: 2^50
* e: 2^60
*/
inline std::string toUnitIntString(uint64_t val)
{
uint64_t mask = (1ULL << 10) - 1;
const char units[] = " kmgtpezy";

size_t i = 0;
while (i < sizeof(units)) {
if ((val & ~mask) != val) { break; }
i++;
val >>= 10;
}

if (0 < i && i < sizeof(units)) {
return formatString("%" PRIu64 "%c", val, units[i]);
} else {
return formatString("%" PRIu64 "", val);
}
}

0 comments on commit 7764469

Please sign in to comment.