WIP prototypical Digxel implementation complete

This commit is contained in:
Fischlurch 2011-01-05 05:14:28 +01:00
parent e66bed65e4
commit 031f61f31d
2 changed files with 109 additions and 91 deletions

View file

@ -64,9 +64,11 @@
#include "lib/error.hpp"
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include <boost/operators.hpp>
#include <boost/lexical_cast.hpp>
#include <tr1/functional>
#include <cstdlib> ///////////TODO
#include <cmath>
#include <string>
@ -75,11 +77,11 @@
namespace lib {
namespace time {
// using std::string;
using std::string;
namespace digxel {
using std::string;
using util::cStr;
using lib::Literal;
using boost::lexical_cast;
@ -117,17 +119,31 @@ namespace time {
PrintfFormatter (Literal fmt)
: printbuffer_()
, formatSpec_(fmt)
{
printbuffer_[0] = '\0';
{
clear();
}
void
void clear() { printbuffer_[0] = '\0'; }
bool empty() { return bool(*printbuffer_); }
size_t
maxlen() const
{
return len;
}
CBuf
show (NUM val)
{
size_t space = std::snprintf (printbuffer_, bufsiz, "%5d", val);
REQUIRE (space <= bufsiz, "Digxel value exceeded available buffer size. "
"For showing %s, %d chars instead of just %d would be required."
, lexical_cast<string>(val), space, bufsiz);
if (empty())
{
size_t space = std::snprintf (printbuffer_, bufsiz, formatSpec_, val);
REQUIRE (space < bufsiz, "Digxel value exceeded available buffer size. "
"For showing %s, %lu chars instead of just %d would be required."
, cStr(lexical_cast<string>(val)), space, bufsiz); ///////////TICKET #197
}
ENSURE (!empty());
return printbuffer_;
}
};
@ -149,61 +165,10 @@ namespace time {
Formatter() : PrintfFormatter<double,7>("%06.3f") { }
};
/**
* The outward hull of a concrete Digxel implementation.
* Inheriting from the Digxel interface, it embodies a concrete
* Formatter specialised to yield the desired behaviour.
*
* @param TODO
* @todo WIP-WIP-WIP
*/
template< typename NUM
, class FMT
>
class Holder
{
protected:
FMT buffer_;
NUM value_;
/* === Digxel implementation === */
int
getIntValue() const
{
return ValTrait<NUM>::asInt (value_);
}
CBuf
getFormatted()
{
UNIMPLEMENTED("call formatting or cache");
}
//
// void
// changeTo (int i)
// {
// UNIMPLEMENTED("mutate INT");
// }
//
// void
// changeTo (double d)
// {
// UNIMPLEMENTED("mutate FLOAT");
// }
public:
Holder ()
: buffer_()
, value_()
{ }
};
} //(End) digxel configuration namespace
/**
* A number element for building structured numeric displays.
* The purpose is to represent parts of a numeric format, like
@ -222,32 +187,74 @@ namespace time {
, class FMT = digxel::Formatter<NUM>
>
class Digxel
: public digxel::Holder<NUM,FMT>
, public boost::totally_ordered<Digxel<NUM,FMT>,
boost::totally_ordered<Digxel<NUM,FMT>, NUM
> >
: public boost::totally_ordered<Digxel<NUM,FMT> >
// ,
// boost::totally_ordered<Digxel<NUM,FMT>, NUM
// > >
{
typedef digxel::Holder<NUM,FMT> _Holder;
mutable
FMT buffer_;
NUM value_;
typedef const char* CBuf;
static NUM use_newValue_as_is (NUM n) { return n; }
typedef std::tr1::function<NUM(NUM)> _Mutator;
public:
/** a functor to be applied on any new digxel value.
* This allows individual instances to limit the possible digxel values,
* or to update an compound value (e.g. a time comprised of hour, minute
* and second digxel elements). By default, new values can be set without
* any restrictions or side effects.
*/
_Mutator mutator;
operator int() const { return getIntValue(); }
CBuf show() { return getFormatted(); }
Digxel ()
: buffer_()
, value_()
, mutator(use_newValue_as_is)
{ }
// using the standard copy operations
operator NUM() const { return value_; }
operator string() const { return show(); }
size_t maxlen() const { return buffer_.maxlen(); }
digxel::CBuf
show() const
{
return buffer_.show (value_);
}
void
operator= (NUM n)
{
NUM changedValue = mutator(n);
this->setValueRaw (changedValue);
}
void
setValueRaw (NUM newVal)
{
if (newVal != value_)
{
value_ = newVal;
buffer_.clear();
}
}
//---Supporting-totally_ordered---------
bool operator< (Digxel const& o) const { return value_ < NUM(o); }
bool operator== (Digxel const& o) const { return value_ == NUM(o); }
bool operator== (NUM n) const { return value_ == n ; }
bool operator< (NUM n) const { return value_ < n ; }
bool operator> (NUM n) const { return value_ > n ; }
// bool operator== (NUM n) const { return value_ == n ; }
// bool operator< (NUM n) const { return value_ < n ; }
// bool operator> (NUM n) const { return value_ > n ; }
protected:
virtual int getIntValue() const =0;
virtual CBuf getFormatted() =0;
};

View file

@ -28,7 +28,7 @@
//#include <boost/lexical_cast.hpp>
//#include <boost/algorithm/string/join.hpp>
#include <boost/lambda/lambda.hpp>
//#include <boost/lambda/lambda.hpp>
#include <iostream> //TODO
#include <cstdlib>
@ -49,9 +49,6 @@ namespace test{
namespace { // Test data
// Placeholder to mark the function argument in a "lambda-expression"
boost::lambda::placeholder1_type _1_;
const uint REPEAT = 40;
const uint RAND_RANGE = 100;
const uint RAND_DENOM = 3;
@ -65,6 +62,21 @@ namespace test{
return arbitrary;
}
inline uint
isOdd (uint i)
{
return i % 2;
}
double sum(0),
checksum(0);
double
sideeffectSum (double val)
{
sum += val;
return val;
}
/* === special Digxel configuration for this test === */
@ -78,11 +90,12 @@ namespace test{
struct VerySpecialFormat
: digxel::PrintfFormatter<double, 11>
{
VerySpecialFormat() : digxel::PrintfFormatter<double,11>("## %4.1f ##") { }
};
typedef digxel::Holder<double, VerySpecialFormat> TestDigxel;
typedef Digxel<double, VerySpecialFormat> TestDigxel;
}
@ -114,11 +127,11 @@ namespace test{
{
TestDigxel digi;
CHECK (0 == digi);
CHECK ("## 0 ##" == digi.show());
CHECK ("## 0 ##" == string(digi));
digi = 88;
CHECK (88 == digi);
CHECK ("## 88.0 ##" == digi.show());
CHECK ("## 88.0 ##" == string(digi));
}
@ -127,10 +140,9 @@ namespace test{
{
TestDigxel digi;
uint sum(0), checksum(0);
// configure what the Digxel does on "mutation"
digi.mutator = ( var(sum) += _1_ );
digi.mutator = sideeffectSum;
sum = checksum = 0;
CHECK (0 == digi);
for (uint i=0; i < REPEAT; ++i)
@ -176,7 +188,7 @@ namespace test{
d1 = someValue;
CHECK (d1 == someValue);
TextDigxel d2(d1);
TestDigxel d2(d1);
CHECK (d2 == someValue);
CHECK (!isSameObject (d1, d2));
@ -192,7 +204,7 @@ namespace test{
TestDigxel digi;
digi = 123456789.12345678;
string formatted (digi.show()); // should trigger assertion
string formatted (digi); // should trigger assertion
CHECK (formatted.length() <= digi.maxlen());
}
@ -207,8 +219,8 @@ namespace test{
start = clock();
for (uint i=0; i < TIMING_CNT; ++i)
{
val odd = i % 2;
digi = 1;
isOdd (i);
}
stop = clock();
uint without_reformatting = stop - start;
@ -217,8 +229,7 @@ namespace test{
start = clock();
for (uint i=0; i < TIMING_CNT; ++i)
{
val odd = i % 2;
digi = odd;
digi = isOdd (i);
}
stop = clock();
uint with_reformatting = stop - start;