Add more special formatters and Digxel testcases
The Digxel implementation draft can be considered complete now
This commit is contained in:
parent
8e90b3d5dc
commit
c85f7e0715
6 changed files with 212 additions and 86 deletions
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
Timecode - implementation of fixed grid aligned time specifications
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2010, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
#include "lib/time/digxel.hpp"
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace time {
|
||||
|
||||
|
||||
|
||||
|
||||
/** */
|
||||
|
||||
|
||||
|
||||
}} // lib::time
|
||||
|
||||
|
|
@ -35,21 +35,23 @@
|
|||
** \par properties of a "Digxel"
|
||||
**
|
||||
** Semantically, it's a number or number component. It holds an internal numeric representation
|
||||
** and is implicitly convertible both to integrals and floating point numbers. This implicit
|
||||
** conversion is a compromise to support generic processing.
|
||||
** and is implicitly convertible back to the underlying numeric type (usually int or double).
|
||||
**
|
||||
** But at the same time, a Digxel has a definite textual format and the ability to present
|
||||
** its numeric value formatted accordingly. To this end, the contract \em requires that
|
||||
** numeric data pushed to the Digxel be kept within such limits to prevent exceeding the
|
||||
** embedded formatting buffer. There is an assertion in debug mode, and a range check,
|
||||
** but the result will be just truncated, so this is clearly the caller's responsibility.
|
||||
** Digxel might be considered an implementation support class, and performance is important
|
||||
** to some limited degree; especially, formatted values will be cached.
|
||||
** but the result will be just truncated, so passing only sane values is clearly the
|
||||
** caller's responsibility. Digxel might be considered an implementation support class,
|
||||
** and performance is important to some limited degree;
|
||||
** especially, formatted values will be \em cached.
|
||||
**
|
||||
** To support in-place modification, the digxel stores a mutation signal (functor) and exposes
|
||||
** a special \c mutate(newVal) function, which invokes this stored functor, if defined. Usually
|
||||
** this should invoke some internal recalculations, resulting in a new value being pushed to
|
||||
** the Digxel for display.
|
||||
** To support in-place modification, the digxel stores a mutation signal (functor). This
|
||||
** functor will be invoked, whenever a new value gets assigned. The actual functor is free
|
||||
** to cause side effects; the value returned from this functor will be the new value to set.
|
||||
** If not configured, the default implementation just accepts the given value unaltered. Usually
|
||||
** this mutation functor should invoke some internal recalculations, maybe resulting in a new
|
||||
** value being pushed to the Digxel for display.
|
||||
**
|
||||
** \par configuration
|
||||
** the Digxel template can be configured to some degree to adjust the stored numeric data
|
||||
|
|
@ -69,16 +71,15 @@
|
|||
#include <boost/operators.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <tr1/functional>
|
||||
#include <cstdlib> ///////////TODO
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace time {
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace digxel {
|
||||
|
||||
using util::cStr;
|
||||
|
|
@ -86,27 +87,13 @@ namespace time {
|
|||
using boost::lexical_cast;
|
||||
|
||||
typedef const char* CBuf;
|
||||
|
||||
|
||||
template<typename NUM>
|
||||
struct ValTrait;
|
||||
|
||||
template<>
|
||||
struct ValTrait<int>
|
||||
{
|
||||
static int asInt (int val) { return val; }
|
||||
static double asDouble (int val) { return val; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ValTrait<double>
|
||||
{
|
||||
static int asInt (double val) { return std::floor(0.5+val); } ///< in accordance with Lumiera's time handling RfC
|
||||
static double asDouble (double val) { return val; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Default / base implementation for Digxel formatting.
|
||||
* This formatter holds an inline buffer of limited size,
|
||||
* receiving and caching the textual representation
|
||||
*/
|
||||
template<typename NUM, size_t len>
|
||||
class PrintfFormatter
|
||||
{
|
||||
|
|
@ -124,7 +111,7 @@ namespace time {
|
|||
}
|
||||
|
||||
void clear() { printbuffer_[0] = '\0'; }
|
||||
bool empty() { return ! bool(*printbuffer_); }
|
||||
bool empty() { return '\0' == *printbuffer_; }
|
||||
|
||||
size_t
|
||||
maxlen() const
|
||||
|
|
@ -147,6 +134,11 @@ namespace time {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* default configured Formatter implementations
|
||||
* for some of the basic numeric types
|
||||
*/
|
||||
template<typename NUM>
|
||||
struct Formatter;
|
||||
|
||||
|
|
@ -154,8 +146,7 @@ namespace time {
|
|||
struct Formatter<int>
|
||||
: PrintfFormatter<int, 6>
|
||||
{
|
||||
Formatter() : PrintfFormatter<int,6>("%5d") { }
|
||||
|
||||
Formatter() : PrintfFormatter<int,6>("%3d") { }
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
@ -163,25 +154,46 @@ namespace time {
|
|||
: PrintfFormatter<double, 7>
|
||||
{
|
||||
Formatter() : PrintfFormatter<double,7>("%06.3f") { }
|
||||
|
||||
};
|
||||
|
||||
/* == other specialised Formatters == */
|
||||
struct SexaFormatter
|
||||
: PrintfFormatter<int, 4>
|
||||
{
|
||||
SexaFormatter() : PrintfFormatter<int,4>("%02d") { }
|
||||
};
|
||||
|
||||
struct HexaFormatter
|
||||
: PrintfFormatter<uint, 2>
|
||||
{
|
||||
HexaFormatter() : PrintfFormatter<uint,2>("%02X") { }
|
||||
};
|
||||
|
||||
|
||||
} //(End) digxel configuration namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A number element for building structured numeric displays.
|
||||
* The purpose is to represent parts of a numeric format, like
|
||||
* e.g. the sexagesimal "digits" of a timecode display. Digxel
|
||||
* e.g. the sexagesimal "digits" of a timecode display. A Digxel
|
||||
* - is customised by template parameters to a specific number format
|
||||
* - requires that any number set must not overflow the format buffer
|
||||
* - requires that any given number must not overflow the format buffer
|
||||
* - can receive new numbers by assignment
|
||||
* - stores and these given value numerically
|
||||
* - will then format these numbers and cache the formatted representation
|
||||
* - can store and invoke a mutation functor
|
||||
*
|
||||
* - can store and invoke a mutation functor to pre-process values on setting
|
||||
*
|
||||
* @note comparisons are assumed to be not performance relevant
|
||||
* @param NUM numeric type to be used for the value
|
||||
* @param FMT a formatter and buffer holder type
|
||||
* @see digxel::Formatter default printf based formatter
|
||||
* @see lib::time::TCode
|
||||
* @todo WIP-WIP-WIP
|
||||
* @see Digxel_test
|
||||
*
|
||||
*/
|
||||
template< typename NUM
|
||||
, class FMT = digxel::Formatter<NUM>
|
||||
|
|
@ -208,7 +220,7 @@ namespace time {
|
|||
|
||||
Digxel ()
|
||||
: buffer_()
|
||||
, value_()
|
||||
, value_ ()
|
||||
, mutator(use_newValue_as_is)
|
||||
{ }
|
||||
|
||||
|
|
@ -219,6 +231,7 @@ namespace time {
|
|||
|
||||
size_t maxlen() const { return buffer_.maxlen(); }
|
||||
|
||||
|
||||
digxel::CBuf
|
||||
show() const
|
||||
{
|
||||
|
|
@ -229,7 +242,7 @@ namespace time {
|
|||
void
|
||||
operator= (NUM n)
|
||||
{
|
||||
NUM changedValue = mutator(n);
|
||||
NUM changedValue = mutator(n);
|
||||
this->setValueRaw (changedValue);
|
||||
}
|
||||
|
||||
|
|
@ -248,13 +261,14 @@ namespace time {
|
|||
//---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 ; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* == predefined Digxel configurations == */
|
||||
typedef Digxel< int, digxel::SexaFormatter> SexaDigit; ///< for displaying time components (sexagesimal)
|
||||
typedef Digxel<uint, digxel::HexaFormatter> HexaDigit; ///< for displaying a hex byte
|
||||
|
||||
|
||||
}} // lib::time
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
//#include <boost/operators.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
|
@ -39,6 +40,29 @@ namespace time {
|
|||
|
||||
LUMIERA_ERROR_DECLARE (UNKNOWN_GRID); ///< referring to an undefined grid or scale in value quantisation
|
||||
|
||||
|
||||
namespace { // stashed here for later
|
||||
|
||||
template<typename NUM>
|
||||
struct ValTrait;
|
||||
|
||||
template<>
|
||||
struct ValTrait<int>
|
||||
{
|
||||
static int asInt (int val) { return val; }
|
||||
static double asDouble (int val) { return val; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ValTrait<double>
|
||||
{
|
||||
static int asInt (double val) { return std::floor(0.5+val); } ///< in accordance with Lumiera's time handling RfC
|
||||
static double asDouble (double val) { return val; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Facility to create grid-aligned time values.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -231,6 +231,26 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
TEST "A Digxel (numeric component)" Digxel_test <<END
|
||||
out-lit: empty____## +0.0 ##
|
||||
out-lit: value____##-88.8 ##
|
||||
out: without reformatting = .+sec
|
||||
out: with reformatting = .+sec
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "Digxel standard configurations" DigxelConfigurations_test <<END
|
||||
out: .+Digxel.+Formatter.+--empty-- 0--\(val=123\)--123\|
|
||||
out: .+Digxel.+Formatter.+--empty--00.000--\(val=123.457\)--123.457
|
||||
out: .+Digxel.+SexaFormatter.+--empty--00--\(val=42\)--42
|
||||
out: .+Digxel.+SexaFormatter.+--empty--00--\(val=-5\)---5
|
||||
out: .+Digxel.+HexaFormatter.+--empty--00--\(val=12\)--0C
|
||||
out: .+Digxel.+HexaFormatter.+--empty--00--\(val=111\)--6F
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "Duck typing support" DuckDetector_test <<END
|
||||
out: HasNested_Core<PropperGander> : Yes
|
||||
out: HasNested_Core<Propaganda> : No
|
||||
|
|
|
|||
105
tests/lib/time/digxel-configurations-test.cpp
Normal file
105
tests/lib/time/digxel-configurations-test.cpp
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
DigxelConfigurations(Test) - verify predefined standard Digxel configurations
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2011, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "lib/time/display.hpp"
|
||||
#include "lib/time/digxel.hpp"
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
using lumiera::error::LUMIERA_ERROR_ASSERTION;
|
||||
using util::isSameObject;
|
||||
using lib::test::showType;
|
||||
using std::rand;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace time{
|
||||
namespace test{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* @test verify correctness of the predefined standard Digxels.
|
||||
* Some widely used standard configurations, including
|
||||
* - default Digxel for int and double values
|
||||
* - sexagesimal Digxel
|
||||
* - hex byte Digxel
|
||||
* - ...more to come
|
||||
* @todo cover any newly added Digxel configurations.
|
||||
*/
|
||||
class DigxelConfigurations_test : public Test
|
||||
{
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
verifyConfiguration<Digxel<int> > (123);
|
||||
verifyConfiguration<Digxel<double> > (123.4567);
|
||||
verifyConfiguration<SexaDigit > (42);
|
||||
verifyConfiguration<SexaDigit > (-5);
|
||||
verifyConfiguration<HexaDigit > (0xc);
|
||||
verifyConfiguration<HexaDigit > (0x6f);
|
||||
}
|
||||
|
||||
|
||||
template<class DIX, typename VAL>
|
||||
void
|
||||
verifyConfiguration (VAL testval)
|
||||
{
|
||||
DIX digxel;
|
||||
CHECK (0 == digxel);
|
||||
cout << showType(digxel) << "--empty--"<<digxel;
|
||||
|
||||
digxel = testval;
|
||||
cout << "--(val="<<testval<<")--"<<digxel;
|
||||
|
||||
// verify buffer overrun protection
|
||||
digxel = 123456789.12345;
|
||||
string formatted;
|
||||
#if false ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT
|
||||
VERIFY_ERROR (ASSERTION, formatted = digxel.show() ); // should trigger assertion
|
||||
formatted = digxel.show(); // second time doesn't reformat
|
||||
CHECK (formatted.length() == digxel.maxlen());
|
||||
cout << "--(clipped)--"<< digxel;
|
||||
#endif ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT
|
||||
|
||||
cout <<"|"<< endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (DigxelConfigurations_test, "unit common");
|
||||
|
||||
|
||||
|
||||
}}} // namespace lib::time::test
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
using lumiera::error::LUMIERA_ERROR_ASSERTION;
|
||||
using util::isSameObject;
|
||||
using std::rand;
|
||||
using std::cout;
|
||||
|
|
@ -247,7 +248,7 @@ namespace test{
|
|||
string formatted;
|
||||
#if false ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT
|
||||
VERIFY_ERROR (ASSERTION, formatted = digi.show() ); // should trigger assertion
|
||||
formatted = digi.show(); // second time doesn't reformat
|
||||
formatted = digi.show(); // second time doesn't reformat
|
||||
#endif ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT
|
||||
|
||||
CHECK (formatted.length() <= digi.maxlen());
|
||||
|
|
|
|||
Loading…
Reference in a new issue