libcruft-util/cruft/util/version.cpp.rl

321 lines
7.7 KiB
Plaintext
Raw Permalink Normal View History

/*
2019-03-19 16:00:44 +11:00
* This Source Code Form is subject to the terms of the Mozilla Public
* 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/.
*
2012-04-23 13:06:41 +10:00
* Copyright 2010 Danny Robson <danny@nerdcruft.net>
*/
#include <cruft/util/version.hpp>
#include <cruft/util/maths.hpp>
#include <cruft/util/debug/assert.hpp>
#include <cruft/util/debug/panic.hpp>
2011-05-23 17:18:52 +10:00
#include <stdexcept>
#include <ostream>
2011-05-23 17:18:52 +10:00
#include <cstring>
2011-05-23 17:18:52 +10:00
2018-05-03 18:32:08 +10:00
// We generate some really old style C code via ragel here, so we have to
// disable some noisy warnings (doubly so given -Werror)
#pragma GCC diagnostic ignored "-Wold-style-cast"
2011-05-23 17:18:52 +10:00
using cruft::version;
2011-05-23 17:18:52 +10:00
2016-01-19 18:31:35 +11:00
///////////////////////////////////////////////////////////////////////////////
2013-08-05 21:46:11 +10:00
version::version ():
2016-01-19 18:31:35 +11:00
size (0),
release (PRODUCTION)
2013-08-05 21:46:11 +10:00
{ ; }
2011-05-23 17:18:52 +10:00
2016-01-19 18:31:35 +11:00
//-----------------------------------------------------------------------------
version::version (unsigned _major,
unsigned _minor,
unsigned _point,
unsigned _build):
components { _major, _minor, _point, _build }
{
size = 4u;
}
//-----------------------------------------------------------------------------
version::version (unsigned _major,
unsigned _minor,
unsigned _point):
version (_major, _minor, _point, 0)
{
size = 3u;
}
//-----------------------------------------------------------------------------
version::version (unsigned _major,
unsigned _minor):
version (_major, _minor, 0)
{
size = 2u;
}
//-----------------------------------------------------------------------------
version::version (unsigned _major):
version (_major, 0)
{
size = 1u;
2011-05-23 17:18:52 +10:00
}
2016-01-19 18:31:35 +11:00
//-----------------------------------------------------------------------------
2013-08-05 21:46:11 +10:00
version::version (const std::string& str):
2016-01-19 18:31:35 +11:00
version (str.c_str ())
{ ; }
2011-05-23 17:18:52 +10:00
2016-01-19 18:31:35 +11:00
//-----------------------------------------------------------------------------
version::version (const char *str):
2016-01-19 18:31:35 +11:00
version ()
{
2013-08-05 21:46:11 +10:00
*this = version::parse (str);
}
2016-01-19 18:31:35 +11:00
///////////////////////////////////////////////////////////////////////////////
2011-05-23 17:18:52 +10:00
static void
2016-01-19 18:31:35 +11:00
sanity (version::release_t r)
{
2011-05-23 17:18:52 +10:00
switch (r) {
2016-01-19 18:31:35 +11:00
case version::ALPHA:
case version::BETA:
case version::GAMMA:
case version::PRODUCTION:
2011-05-23 17:18:52 +10:00
return;
}
panic ("invalid release_t value");
}
2016-01-19 18:31:35 +11:00
//-----------------------------------------------------------------------------
2011-05-23 17:18:52 +10:00
void
version::sanity (void) const {
2013-08-05 21:46:11 +10:00
::sanity (release);
CHECK (size > 0);
2011-05-23 17:18:52 +10:00
}
2016-01-19 18:31:35 +11:00
///////////////////////////////////////////////////////////////////////////////
unsigned version::major (void) const { return components[MAJOR]; }
unsigned version::minor (void) const { return components[MINOR]; }
unsigned version::point (void) const { return components[POINT]; }
unsigned version::build (void) const { return components[BUILD]; }
///////////////////////////////////////////////////////////////////////////////
const unsigned*
version::begin (void) const noexcept
2016-01-19 18:31:35 +11:00
{
return components.begin ();
}
//-----------------------------------------------------------------------------
2016-01-19 18:31:35 +11:00
const unsigned*
version::end (void) const noexcept
2016-01-19 18:31:35 +11:00
{
return components.begin () + size;
}
//-----------------------------------------------------------------------------
const unsigned*
version::cbegin (void) const noexcept
{
return begin ();
}
//-----------------------------------------------------------------------------
const unsigned*
version::cend (void) const noexcept
{
return end ();
}
//-----------------------------------------------------------------------------
const unsigned&
version::operator[] (size_t i) const
{
return components[i];
}
//-----------------------------------------------------------------------------
unsigned&
version::operator[] (size_t i)
{
return components[i];
}
2016-01-19 18:31:35 +11:00
///////////////////////////////////////////////////////////////////////////////
2011-05-23 17:18:52 +10:00
%%{
machine version;
action clear
2013-08-05 21:46:11 +10:00
{ accum = 0; }
2011-05-23 17:18:52 +10:00
action increment
2013-08-05 21:46:11 +10:00
{ accum *= 10;
accum += (uintptr_t)(fc - (unsigned char)'0'); }
2011-05-23 17:18:52 +10:00
action finish
2016-01-19 18:31:35 +11:00
{ v.components[v.size++] = accum ; }
2011-05-23 17:18:52 +10:00
number = (digit+)
>clear
$increment
%finish;
dots = (number '.')* number;
2016-01-19 18:31:35 +11:00
type = ('beta'i | 'b'i) %{ v.release = BETA; }
| ('alpha'i | 'a'i) %{ v.release = ALPHA; }
| ('gamma'i | 'g'i) %{ v.release = GAMMA; };
2011-05-23 17:18:52 +10:00
version := (dots type?) >clear
2013-08-05 21:46:11 +10:00
$!{ throw std::invalid_argument (str); };
2011-05-23 17:18:52 +10:00
write data;
2011-05-23 17:18:52 +10:00
}%%
2013-08-05 21:46:11 +10:00
//-----------------------------------------------------------------------------
cruft::version
cruft::version::parse (const std::string& str) {
unsigned accum = 0;
2011-05-23 17:18:52 +10:00
int cs;
2011-05-23 17:18:52 +10:00
const char *p = str.data (),
*pe = str.data () + str.size (),
*eof = pe;
2013-08-05 21:46:11 +10:00
version v;
2011-05-23 17:18:52 +10:00
%%write init;
%%write exec;
2013-08-05 21:46:11 +10:00
return v;
2011-05-23 17:18:52 +10:00
}
2016-01-19 18:31:35 +11:00
//-----------------------------------------------------------------------------
cruft::version
cruft::version::parse (const char *str) {
2013-08-05 21:46:11 +10:00
return parse (std::string (str));
}
2016-01-19 18:31:35 +11:00
///////////////////////////////////////////////////////////////////////////////
2011-05-23 17:18:52 +10:00
bool
version::operator< (const version &rhs) const noexcept
2016-01-19 18:31:35 +11:00
{
auto count = cruft::min (size, rhs.size);
2011-05-23 17:18:52 +10:00
// make sure each element we have in common is LT
for (decltype (count) i = 0; i < count; ++i)
if ((*this)[i] < rhs[i])
return true;
2011-05-23 17:18:52 +10:00
// if they have extra elements and they're not zeros then we must be LT
2016-01-19 18:31:35 +11:00
if (size < rhs.size)
if (std::none_of (rhs.cbegin () + count, rhs.cend (), [] (auto i) { return i == 0; }))
return true;
// test if we have an earlier release schedule
if (release < rhs.release)
return true;
// we're equal or greater to rhs
return false;
}
//-----------------------------------------------------------------------------
bool
version::operator== (const version &rhs) const noexcept
{
auto count = cruft::min (size, rhs.size);
2011-05-23 17:18:52 +10:00
bool front = std::equal (cbegin (), cbegin () + count, rhs.cbegin ());
bool left = std::all_of (this->cbegin () + count, this->cend (), [] (auto i) { return i == 0; });
bool right = std::all_of (rhs.cbegin () + count, rhs.cend (), [] (auto i) { return i == 0; });
2011-05-23 17:18:52 +10:00
return front && (size > rhs.size ? left : right) && release == rhs.release;
2011-05-23 17:18:52 +10:00
}
2016-01-19 18:31:35 +11:00
//-----------------------------------------------------------------------------
2013-08-05 21:46:11 +10:00
bool
version::operator<= (const version &rhs) const noexcept
{
return *this < rhs || *this == rhs;
}
//-----------------------------------------------------------------------------
bool
version::operator> (const version &rhs) const noexcept
{
return !(*this <= rhs);
2013-08-05 21:46:11 +10:00
}
2011-05-23 17:18:52 +10:00
2016-01-19 18:31:35 +11:00
///////////////////////////////////////////////////////////////////////////////
namespace cruft {
2016-01-19 18:31:35 +11:00
std::ostream&
operator<< (std::ostream& os, const cruft::version::release_t r)
2016-01-19 18:31:35 +11:00
{
switch (r) {
case version::ALPHA: return os << 'a';
case version::BETA: return os << 'b';
case version::GAMMA: return os << 'g';
case version::PRODUCTION: return os;
2016-01-19 18:31:35 +11:00
}
unreachable ();
2016-01-19 18:31:35 +11:00
}
}
//-----------------------------------------------------------------------------
2013-08-05 21:46:11 +10:00
std::ostream&
cruft::operator<< (std::ostream& os, const cruft::version& rhs)
2016-01-19 18:31:35 +11:00
{
2013-08-05 21:46:11 +10:00
size_t elements = rhs.size;
CHECK_GT (elements, 0u);
2011-05-23 17:18:52 +10:00
2016-01-19 18:31:35 +11:00
do {
os << rhs.major ();
if (!--elements)
break;
os << "." << rhs.minor ();
if (!--elements)
break;
2013-08-05 21:46:11 +10:00
2016-01-19 18:31:35 +11:00
os << "." << rhs.point ();
if (!--elements)
break;
2013-08-05 21:46:11 +10:00
2016-01-19 18:31:35 +11:00
os << "." << rhs.build ();
CHECK_EQ (elements - 1, 0u);
} while (0);
2013-08-05 21:46:11 +10:00
2016-01-19 18:31:35 +11:00
os << rhs.release;
2013-08-05 21:46:11 +10:00
return os;
}