Add base::Version class.

This commit is contained in:
David Capello 2011-06-04 10:43:24 -03:00
parent 7e6d25db88
commit 68fde07334
6 changed files with 347 additions and 6 deletions

View File

@ -12,4 +12,5 @@ add_library(base-lib
serialization.cpp
split_string.cpp
string.cpp
thread.cpp)
thread.cpp
version.cpp)

View File

@ -6,19 +6,52 @@
#include "config.h"
#include <cstdlib>
#include <cstdio>
#include "base/convert_to.h"
#include "base/version.h"
#include <cstdio>
#include <cstdlib>
template<> int base::convert_to(const base::string& from)
namespace base {
template<> int convert_to(const string& from)
{
return std::strtol(from.c_str(), NULL, 10);
}
template<> base::string base::convert_to(const int& from)
template<> string convert_to(const int& from)
{
char buf[32];
std::sprintf(buf, "%d", from);
return buf;
}
template<> Version convert_to(const string& from)
{
Version result;
int i = 0;
int j = 0;
while (j != string::npos) {
j = from.find('.', i);
string digitString = from.substr(i, j - i);
int digit = convert_to<int>(digitString);
result.addDigit(digit);
i = j+1;
}
return result;
}
template<> string convert_to(const Version& from)
{
string result;
result.reserve(3*from.size());
for (size_t i=0; i<from.size(); ++i) {
result += convert_to<string>(from[i]);
if (i < from.size()-1)
result += ".";
}
return result;
}
} // namespace base

View File

@ -11,6 +11,8 @@
namespace base {
class Version;
// Undefined convertion
template<typename To, typename From>
To convert_to(const From& from) {
@ -20,6 +22,9 @@ namespace base {
template<> int convert_to(const base::string& from);
template<> base::string convert_to(const int& from);
template<> Version convert_to(const base::string& from);
template<> base::string convert_to(const Version& from);
}
#endif

67
src/base/version.cpp Normal file
View File

@ -0,0 +1,67 @@
// ASE base library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#include "config.h"
#include "base/version.h"
using namespace base;
Version::Version()
{
}
Version::Version(int major, int minor, int rev, int compilation)
{
if (major >= 0 || minor >= 0 || rev >= 0 || compilation >= 0)
addDigit(major);
if (minor >= 0 || rev >= 0 || compilation >= 0)
addDigit(minor);
if (rev >= 0 || compilation >= 0)
addDigit(rev);
if (compilation >= 0)
addDigit(compilation);
}
bool Version::operator==(const Version& other) const
{
Digits::const_iterator
it1 = m_digits.begin(), end1 = m_digits.end(),
it2 = other.m_digits.begin(), end2 = other.m_digits.end();
while (it1 != end1 || it2 != end2) {
int digit1 = (it1 != end1 ? *it1++: 0);
int digit2 = (it2 != end2 ? *it2++: 0);
if (digit1 != digit2)
return false;
}
return true;
}
bool Version::operator<(const Version& other) const
{
Digits::const_iterator
it1 = m_digits.begin(), end1 = m_digits.end(),
it2 = other.m_digits.begin(), end2 = other.m_digits.end();
while (it1 != end1 || it2 != end2) {
int digit1 = (it1 != end1 ? *it1++: 0);
int digit2 = (it2 != end2 ? *it2++: 0);
if (digit1 < digit2)
return true;
else if (digit1 > digit2)
return false;
// else continue...
}
return false;
}

82
src/base/version.h Normal file
View File

@ -0,0 +1,82 @@
// ASE base library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef BASE_VERSION_H_INCLUDED
#define BASE_VERSION_H_INCLUDED
#include <string>
#include <vector>
namespace base {
class Version
{
public:
Version();
explicit Version(int major, int minor = -1, int revision = -1, int build = -1);
int major() const { return (*this)[0]; }
int minor() const { return (*this)[1]; }
int revision() const { return (*this)[2]; }
int build() const { return (*this)[3]; }
Version& major(int digit) { (*this)[0] = digit; return *this; }
Version& minor(int digit) { (*this)[1] = digit; return *this; }
Version& revision(int digit) { (*this)[2] = digit; return *this; }
Version& build(int digit) { (*this)[3] = digit; return *this; }
size_t size() const {
return m_digits.size();
}
// operator[] that can be used to set version digits.
int& operator[](size_t index) {
if (index >= m_digits.size())
m_digits.resize(index+1);
return m_digits[index];
}
// operator[] that can be used to get version digits.
int operator[](size_t index) const {
if (index < m_digits.size())
return m_digits[index];
else
return 0;
}
// Adds a new digit.
void addDigit(int digit) {
m_digits.push_back(digit);
}
// Comparison
bool operator==(const Version& other) const;
bool operator<(const Version& other) const;
bool operator!=(const Version& other) const {
return !operator==(other);
}
bool operator>(const Version& other) const {
return !operator<(other) && !operator==(other);
}
bool operator>=(const Version& other) const {
return !operator<(other);
}
bool operator<=(const Version& other) const {
return operator<(other) || operator==(other);
}
private:
typedef std::vector<int> Digits;
Digits m_digits;
};
}
#endif

View File

@ -0,0 +1,153 @@
// ASE base library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/version.h"
#include "base/convert_to.h"
using namespace base;
std::ostream& operator<<(std::ostream& os, const Version& ver)
{
return os << convert_to<string>(ver);
}
TEST(Version, Ctor)
{
Version v0;
EXPECT_EQ(0, v0[0]);
EXPECT_EQ(0, v0[1]);
EXPECT_EQ(0, v0[2]);
EXPECT_EQ(0, v0[3]);
EXPECT_EQ(0, v0[4]);
Version v1(1);
EXPECT_EQ(1, v1[0]);
EXPECT_EQ(0, v1[1]);
Version v2(1, 2);
EXPECT_EQ(1, v2[0]);
EXPECT_EQ(2, v2[1]);
EXPECT_EQ(0, v2[2]);
Version v3(1, 2, 3);
EXPECT_EQ(1, v3[0]);
EXPECT_EQ(2, v3[1]);
EXPECT_EQ(3, v3[2]);
EXPECT_EQ(0, v3[3]);
Version v4(1, 2, 3, 4);
EXPECT_EQ(1, v4[0]);
EXPECT_EQ(2, v4[1]);
EXPECT_EQ(3, v4[2]);
EXPECT_EQ(4, v4[3]);
EXPECT_EQ(0, v4[4]);
}
TEST(Version, StringToVersion)
{
EXPECT_EQ(Version(), convert_to<Version>(string("")));
EXPECT_EQ(Version(1), convert_to<Version>(string("1")));
EXPECT_EQ(Version(1, 2), convert_to<Version>(string("1.2")));
EXPECT_EQ(Version(1, 2, 3), convert_to<Version>(string("1.2.3")));
EXPECT_EQ(Version(1, 2, 3, 4), convert_to<Version>(string("1.2.3.4")));
}
TEST(Version, VersionToString)
{
EXPECT_EQ("", convert_to<string>(Version()));
EXPECT_EQ("0", convert_to<string>(Version(0)));
EXPECT_EQ("1", convert_to<string>(Version(1)));
EXPECT_EQ("1.0", convert_to<string>(Version(1, 0)));
EXPECT_EQ("0.0", convert_to<string>(Version(0, 0)));
EXPECT_EQ("1.0.2", convert_to<string>(Version(1, 0, 2)));
}
TEST(Version, Equal)
{
EXPECT_EQ(Version(), Version());
EXPECT_EQ(Version(0), Version());
EXPECT_EQ(Version(1), Version(1));
EXPECT_EQ(Version(1), Version(1, 0));
EXPECT_EQ(Version(1, 0), Version(1));
EXPECT_EQ(Version(1, 2), Version(1, 2));
EXPECT_EQ(Version(1, 2, 3), Version(1, 2, 3));
EXPECT_EQ(Version(1, 0, 0), Version(1));
}
TEST(Version, NotEqual)
{
EXPECT_FALSE(Version() != Version());
EXPECT_TRUE(Version(1) != Version(1, 2));
EXPECT_TRUE(Version() != Version(0, 1));
EXPECT_TRUE(Version(1, 0) != Version(1, 0, 1));
EXPECT_TRUE(Version(1, 2) != Version(1, 3));
EXPECT_TRUE(Version(1, 2, 3) != Version(1, 2, 3, 4));
}
TEST(Version, LessThan)
{
EXPECT_FALSE(Version() < Version(0));
EXPECT_TRUE(Version(0) < Version(1));
EXPECT_TRUE(Version(1, 2) < Version(1, 3));
EXPECT_TRUE(Version(1, 2, 3) < Version(1, 2, 4));
EXPECT_TRUE(Version(1, 2, 0, 4) < Version(1, 2, 3));
EXPECT_FALSE(Version(1, 3) < Version(1, 2));
}
TEST(Version, AllComparisons)
{
EXPECT_TRUE(Version(1, 2, 3) == Version(1, 2, 3));
EXPECT_FALSE(Version(1, 2, 3) < Version(1, 2, 3));
EXPECT_FALSE(Version(1, 2, 3) > Version(1, 2, 3));
EXPECT_FALSE(Version(1, 2, 3) != Version(1, 2, 3));
EXPECT_TRUE(Version(1, 2, 3) <= Version(1, 2, 3));
EXPECT_TRUE(Version(1, 2, 3) >= Version(1, 2, 3));
EXPECT_FALSE(Version(1, 2, 3) == Version(2));
EXPECT_TRUE(Version(1, 2, 3) < Version(2));
EXPECT_FALSE(Version(1, 2, 3) > Version(2));
EXPECT_TRUE(Version(1, 2, 3) != Version(2));
EXPECT_TRUE(Version(1, 2, 3) <= Version(2));
EXPECT_FALSE(Version(1, 2, 3) >= Version(2));
}
TEST(Version, SimpleGetters)
{
Version v0;
EXPECT_EQ(0, v0.major());
EXPECT_EQ(0, v0.minor());
EXPECT_EQ(0, v0.revision());
EXPECT_EQ(0, v0.build());
Version v2(1, 2);
EXPECT_EQ(1, v2.major());
EXPECT_EQ(2, v2.minor());
EXPECT_EQ(0, v2.revision());
Version v4(1, 2, 3, 4);
EXPECT_EQ(1, v4.major());
EXPECT_EQ(2, v4.minor());
EXPECT_EQ(3, v4.revision());
EXPECT_EQ(4, v4.build());
}
TEST(Version, SimpleSetters)
{
EXPECT_EQ(Version(1), Version().major(1));
EXPECT_EQ(Version(1, 2), Version().major(1).minor(2));
EXPECT_EQ(Version(1, 2), Version().minor(2).major(1));
EXPECT_EQ(Version(1, 2, 3, 4), Version().major(1).minor(2).revision(3).build(4));
EXPECT_EQ(Version(1, 2, 3, 4), Version().build(4).revision(3).minor(2).major(1));
EXPECT_EQ(Version(0, 0, 0, 4), Version().build(4));
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}