Reconstruct version type as a struct

This commit is contained in:
Danny Robson 2013-08-05 21:46:11 +10:00
parent e67e0329fa
commit 8b7f915c01
2 changed files with 121 additions and 109 deletions

View File

@ -26,38 +26,41 @@
#include "debug.hpp" #include "debug.hpp"
using namespace std;
using namespace util; using namespace util;
//-----------------------------------------------------------------------------
version::version ():
size (0)
{ ; }
version::version (unsigned int _major, version::version (unsigned int _major,
unsigned int _minor): unsigned int _minor):
m_size (2), size (2),
m_release (RELEASE_PRODUCTION) release (RELEASE_PRODUCTION)
{ {
m_values[OFFSET_MAJOR] = _major; values[OFFSET_MAJOR] = _major;
m_values[OFFSET_MINOR] = _minor; values[OFFSET_MINOR] = _minor;
} }
version::version (const string& str): version::version (const std::string& str):
m_size (0), size (0)
m_release (RELEASE_PRODUCTION)
{ {
parse (str); *this = version::parse (str);
} }
version::version (const char *str): version::version (const char *str):
m_size (0), size (0)
m_release (RELEASE_PRODUCTION)
{ {
parse (str); *this = version::parse (str);
} }
//-----------------------------------------------------------------------------
static void static void
check_release (version::release_t r) { sanity (version::release_t r) {
switch (r) { switch (r) {
case version::RELEASE_ALPHA: case version::RELEASE_ALPHA:
case version::RELEASE_BETA: case version::RELEASE_BETA:
@ -72,21 +75,22 @@ check_release (version::release_t r) {
void void
version::sanity (void) const { version::sanity (void) const {
check_release (m_release); ::sanity (release);
CHECK (m_size > 0); CHECK (size > 0);
} }
//-----------------------------------------------------------------------------
%%{ %%{
machine version; machine version;
action clear action clear
{ current = 0; } { accum = 0; }
action increment action increment
{ current *= 10; { accum *= 10;
current += (uintptr_t)(fc - (unsigned char)'0'); } accum += (uintptr_t)(fc - (unsigned char)'0'); }
action finish action finish
{ m_values[m_size++] = current; } { v.values[v.size++] = accum ; }
number = (digit+) number = (digit+)
>clear >clear
@ -95,87 +99,105 @@ version::sanity (void) const {
dots = (number '.')* number; dots = (number '.')* number;
type = ('beta'i | 'b'i) %{ m_release = RELEASE_BETA; } type = ('beta'i | 'b'i) %{ v.release = RELEASE_BETA; }
| ('alpha'i | 'a'i) %{ m_release = RELEASE_ALPHA; } | ('alpha'i | 'a'i) %{ v.release = RELEASE_ALPHA; }
| ('gamma'i | 'g'i) %{ m_release = RELEASE_GAMMA; }; | ('gamma'i | 'g'i) %{ v.release = RELEASE_GAMMA; };
version := (dots type?) version := (dots type?)
$!{ throw invalid_argument (str); }; $!{ throw std::invalid_argument (str); };
write data; write data;
}%% }%%
void //-----------------------------------------------------------------------------
version::parse (const string& str) { util::version
unsigned int current; util::version::parse (const std::string& str) {
unsigned int accum;
int cs; int cs;
const char *p = str.data (), const char *p = str.data (),
*pe = str.data () + str.size (), *pe = str.data () + str.size (),
*eof = pe; *eof = pe;
%%write init; version v;
%%write exec;
}
void
version::parse (const char *str) {
unsigned int current;
int cs;
const char *p = str,
*pe = str + strlen (str),
*eof = pe;
%%write init; %%write init;
%%write exec; %%write exec;
return v;
} }
static string util::version
release_string (const version::release_t r) { util::version::parse (const char *str) {
switch (r) { return parse (std::string (str));
case (version::RELEASE_ALPHA): return "a"; }
case (version::RELEASE_BETA): return "b";
case (version::RELEASE_GAMMA): return "g";
case (version::RELEASE_PRODUCTION): return "";
}
panic ("invalid release_t");
//-----------------------------------------------------------------------------
static std::string
release_to_string (version::release_t r) {
sanity (r);
static const char* RELEASE_STRINGS[] = {
"a", // RELEASE_ALPHA
"b", // RELEASE_BETA
"g", // RELEASE_GAMMA
"" // RELEASE_PRODUCTION
};
return RELEASE_STRINGS[r];
} }
bool bool
version::operator> (const version &rhs) const { version::operator> (const version &rhs) const {
unsigned int count = min (m_values.size (), rhs.m_values.size ()); unsigned int count = min (values.size (), rhs.values.size ());
for (unsigned int i = 0; i < count; ++i) for (unsigned int i = 0; i < count; ++i)
if (m_values[i] < rhs.m_values[i]) if (values[i] < rhs.values[i])
return false; return false;
if (m_values.size () < rhs.m_values.size()) if (values.size () < rhs.values.size())
return false; return false;
if (m_release <= rhs.m_release) if (release <= rhs.release)
return false; return false;
return true; return true;
} }
namespace util { bool
ostream& version::operator== (const version &rhs) const {
operator <<(ostream& os, const util::version& rhs) { return values == rhs.values &&
auto i = rhs.m_values.begin(); size == rhs.size &&
os << *i; ++i; release == rhs.release;
for (; i != rhs.m_values.end(); ++i)
os << '.' << *i;
os << release_string (rhs.m_release);
return os;
}
} }
std::ostream&
operator <<(std::ostream& os, const util::version& rhs) {
size_t elements = rhs.size;
CHECK_HARD (elements > 0);
os << rhs.major ();
if (!--elements)
goto done;
os << "." << rhs.minor ();
if (!--elements)
goto done;
os << "." << rhs.point ();
if (!--elements)
goto done;
os << "." << rhs.build ();
CHECK_EQ (--elements, 0);
done:
os << release_to_string (rhs.release);
return os;
}

View File

@ -26,8 +26,7 @@
namespace util { namespace util {
class version { struct version {
public:
enum release_t { enum release_t {
RELEASE_ALPHA, RELEASE_ALPHA,
RELEASE_BETA, RELEASE_BETA,
@ -35,16 +34,13 @@ namespace util {
RELEASE_PRODUCTION RELEASE_PRODUCTION
}; };
version (unsigned int _major, version ();
unsigned int _minor); version (unsigned int _major, unsigned int _minor);
version (const std::string& str); version (const std::string& str);
version (const char *str); version (const char *str);
virtual ~version () { ; } void sanity (void) const;
virtual void sanity (void) const;
protected:
enum { enum {
OFFSET_MAJOR = 0, OFFSET_MAJOR = 0,
OFFSET_MINOR = 1, OFFSET_MINOR = 1,
@ -54,33 +50,27 @@ namespace util {
NUM_OFFSETS NUM_OFFSETS
}; };
std::array<unsigned int, NUM_OFFSETS> m_values; unsigned major (void) const { return values[OFFSET_MAJOR]; }
size_t m_size; unsigned minor (void) const { return values[OFFSET_MINOR]; }
release_t m_release; unsigned point (void) const { return values[OFFSET_POINT]; }
unsigned build (void) const { return values[OFFSET_BUILD]; }
void parse (const std::string&); std::array<unsigned int, NUM_OFFSETS> values;
void parse (const char*); size_t size;
release_t release;
public: static version parse (const std::string&);
unsigned int major (void) const { return m_values[OFFSET_MAJOR]; } static version parse (const char*);
unsigned int minor (void) const { return m_values[OFFSET_MINOR]; }
unsigned int point (void) const { return m_values[OFFSET_POINT]; }
unsigned int build (void) const { return m_values[OFFSET_BUILD]; }
size_t size (void) const { return m_size; }
bool operator < (const version& rhs) const; bool operator < (const version& rhs) const;
bool operator > (const version& rhs) const; bool operator > (const version& rhs) const;
bool operator >= (const version& rhs) const; bool operator >= (const version& rhs) const;
bool operator <= (const version& rhs) const; bool operator <= (const version& rhs) const;
bool operator == (const version& rhs) const bool operator == (const version& rhs) const;
{ return m_values == rhs.m_values &&
m_release == rhs.m_release; }
friend std::ostream&
operator <<(std::ostream& os, const version& rhs);
}; };
} }
std::ostream& operator<< (std::ostream& os, const util::version& rhs);
#endif // __VERSION_HPP #endif // __VERSION_HPP