Skip to content

Commit 7ce89be

Browse files
committed
Adding stuff for the Date Time Lab
1 parent ffb0d93 commit 7ce89be

13 files changed

+1343
-1
lines changed

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
66
set(CMAKE_CXX_EXTENSIONS OFF)
77
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
88
set(RUN_AUTOMATED_TESTS OFF CACHE PATH "Run the unit tests")
9+
set(USE_GRAPHICS_LIBRARY OFF CACHE BOOL "Build the SFML library")
910

1011

1112
include_directories(.)
1213
include_directories(Utility)
1314
include_directories($ENV{CPPUTEST_INCLUDE}/include)
1415

16+
1517
function(create_test COM LINKLIST)
1618
list(GET LINKLIST 0 MODULE_NAME)
1719
add_executable(${MODULE_NAME} ${MODULE_NAME}.cpp)
@@ -25,10 +27,10 @@ function(create_test COM LINKLIST)
2527
)
2628
endif()
2729
endfunction()
28-
add_subdirectory(HelloWorld)
2930
add_subdirectory(CppUTest)
3031
add_subdirectory(InClassDemo)
3132
add_subdirectory(Calculator)
3233
add_subdirectory(InClassBasicEmployee)
3334
add_subdirectory(Utility)
3435
add_subdirectory(Shapes)
36+
add_subdirectory(DateTime)

DateTime/ArtRollover.hpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#ifndef ART_ROLLOVER_HPP
2+
#define ART_ROLLOVER_HPP
3+
#include <type_traits>
4+
#include "OperatorHelper.hpp"
5+
6+
template<typename int_t>
7+
struct FullAddition
8+
{
9+
FullAddition(int_t value, bool carry = false) : value(value), carry(carry){}
10+
operator int_t() const { return value; }
11+
operator bool() const { return carry; }
12+
private:
13+
int_t value;
14+
bool carry;
15+
};
16+
17+
//For now we will have double_t has a template parameter, but
18+
//eventually it would be nice to have it calculated automagically
19+
template<typename int_t, typename double_t, int_t rollover>
20+
struct ArtRollover :
21+
PlusHelper<FullAddition<ArtRollover<int_t,double_t,rollover>>,ArtRollover<int_t,double_t,rollover>,ArtRollover<int_t,double_t,rollover>>,
22+
MinusHelper<FullAddition<ArtRollover<int_t,double_t,rollover>>,ArtRollover<int_t,double_t,rollover>,ArtRollover<int_t,double_t,rollover>>,
23+
NegationHelper<FullAddition<ArtRollover<int_t,double_t,rollover>>,ArtRollover<int_t,double_t,rollover>,ArtRollover<int_t,double_t,rollover>>
24+
{
25+
static_assert(std::is_unsigned<int_t>::value,"");
26+
static_assert(std::is_unsigned<double_t>::value,"");
27+
constexpr ArtRollover() = default;
28+
template<typename T,typename = std::enable_if_t<std::is_integral<T>::value>>
29+
constexpr ArtRollover(const T& t) : inner(unsigned_mod(t)){}
30+
static constexpr ArtRollover one()
31+
{
32+
return 1;
33+
}
34+
static constexpr ArtRollover zero()
35+
{
36+
return 0;
37+
}
38+
static constexpr ArtRollover max = rollover - 1;
39+
template<typename T>
40+
ArtRollover& operator=(const T& other)
41+
{
42+
this->inner = unsigned_mod(other);
43+
return *this;
44+
}
45+
46+
template<typename T,typename = std::enable_if_t<std::is_integral<T>::value>>
47+
constexpr operator T() const { return inner; }
48+
49+
FullAddition<ArtRollover> operator+=(const ArtRollover& other)
50+
{
51+
double_t ret = this->inner += other.inner;
52+
this->inner %= rollover;
53+
return FullAddition<ArtRollover>(ret,this->inner != ret);
54+
}
55+
ArtRollover negate() const
56+
{
57+
return -inner;
58+
}
59+
bool operator==(const ArtRollover& other) const
60+
{
61+
return this->inner == other.inner;
62+
}
63+
bool operator<(const ArtRollover& other) const
64+
{
65+
return this->inner < other.inner;
66+
}
67+
private:
68+
template<typename T>
69+
static constexpr int_t unsigned_mod(const T& other)
70+
{
71+
return (other%rollover+rollover)%rollover;
72+
}
73+
int_t inner;
74+
};
75+
76+
#endif

DateTime/ArtRolloverTest.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#include "CppUTest/TestHarness.h"
2+
#include "CppUTest/CommandLineTestRunner.h"
3+
#include "ArtRollover.hpp"
4+
#include "cstdint"
5+
6+
using _100_t = ArtRollover<std::uint8_t,std::uint16_t,100>;
7+
8+
TEST_GROUP(ArtRollover)
9+
{
10+
};
11+
void InitializationTest(int x,int expect)
12+
{
13+
_100_t v0 = x;
14+
LONGS_EQUAL(expect,v0);
15+
}
16+
TEST(ArtRollover, InitializationTest)
17+
{
18+
InitializationTest(123,23);
19+
InitializationTest(100,0);
20+
InitializationTest(0,0);
21+
InitializationTest(42,42);
22+
InitializationTest(-1,99);
23+
}
24+
25+
void AssignmentTest(int x,int expect)
26+
{
27+
_100_t v0;
28+
v0 = x;
29+
LONGS_EQUAL(expect,v0);
30+
}
31+
TEST(ArtRollover, AssignmentTest)
32+
{
33+
AssignmentTest(123,23);
34+
AssignmentTest(100,0);
35+
AssignmentTest(0,0);
36+
AssignmentTest(42,42);
37+
AssignmentTest(-1,99);
38+
}
39+
void AdditionTest(int intial, int add, int expect)
40+
{
41+
_100_t var = intial;
42+
LONGS_EQUAL(expect, _100_t(var + add));
43+
var += _100_t(add);
44+
LONGS_EQUAL(expect, var);
45+
}
46+
TEST(ArtRollover, AdditionTest)
47+
{
48+
AdditionTest(10,23,33);
49+
AdditionTest(50,50,0);
50+
AdditionTest(50,75,25);
51+
AdditionTest(10,-23,87);
52+
AdditionTest(10,-5,5);
53+
}
54+
void NegationTest(int value, int expect)
55+
{
56+
_100_t var = _100_t(value).negate();
57+
LONGS_EQUAL(expect,var);
58+
}
59+
TEST(ArtRollover, NegationTest)
60+
{
61+
NegationTest(23,77);
62+
NegationTest(0,0);
63+
NegationTest(1,99);
64+
NegationTest(99,1);
65+
NegationTest(45,55);
66+
}
67+
void MinusTest(int intial, int add, int expect)
68+
{
69+
_100_t var = intial;
70+
LONGS_EQUAL(expect, _100_t(var - _100_t(add)));
71+
var -= _100_t(add);
72+
LONGS_EQUAL(expect, var);
73+
}
74+
TEST(ArtRollover, MinusTest)
75+
{
76+
MinusTest(10,23,87);
77+
MinusTest(50,50,0);
78+
MinusTest(50,75,75);
79+
MinusTest(10,-23,33);
80+
MinusTest(10,-5,15);
81+
}
82+
int main(int ac, char** av)
83+
{
84+
return CommandLineTestRunner::RunAllTests(ac,av);
85+
}
86+

DateTime/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
create_test("Artificial Rollover Tests" "ArtRolloverTest;CppUTest;CppUTestExt")
2+
create_test("Chain Tests" "ChainTest;CppUTest;CppUTestExt")
3+
create_test("Time Tests" "TimeTest;CppUTest;CppUTestExt")

DateTime/Chain.hpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#ifndef CHAIN_HPP
2+
#define CHAIN_HPP
3+
#include <tuple>
4+
#include <type_traits>
5+
#include "OperatorHelper.hpp"
6+
#include "ArtRollover.hpp"
7+
8+
namespace detail
9+
{
10+
template<long index>
11+
struct foreach_helper
12+
{
13+
template<typename T>
14+
void operator()(T lambda)
15+
{
16+
foreach_helper<index-1>()(lambda);
17+
lambda(std::integral_constant<long,index>());
18+
}
19+
};
20+
template<>
21+
struct foreach_helper<0>
22+
{
23+
template<typename T>
24+
void operator()(T lambda)
25+
{
26+
lambda(std::integral_constant<long,0>());
27+
}
28+
};
29+
template<typename... list>
30+
using foreach = foreach_helper<sizeof...(list)-1>;
31+
32+
template<long index, typename tuple>
33+
auto& get(std::integral_constant<long,index>, tuple& t)
34+
{
35+
return std::get<index>(t);
36+
}
37+
template<typename first, typename... rest>
38+
constexpr auto getOne()
39+
{
40+
return std::make_tuple(first(first::one()),rest(rest::zero())...);
41+
}
42+
}
43+
44+
45+
//First is the least significant
46+
template<typename... l>
47+
struct Chain :
48+
PlusHelper<FullAddition<Chain<l...>>,Chain<l...>,Chain<l...>>,
49+
MinusHelper<FullAddition<Chain<l...>>,Chain<l...>,Chain<l...>>,
50+
ComparableHelper<Chain<l...>>,
51+
NegationHelper<FullAddition<Chain<l...>>,Chain<l...>,Chain<l...>>
52+
53+
{
54+
static constexpr Chain zero()
55+
{
56+
return Chain(l::zero()...);
57+
}
58+
static constexpr Chain one()
59+
{
60+
return Chain(detail::getOne<l...>());
61+
}
62+
static constexpr Chain max = Chain(l::max...);
63+
constexpr Chain(const std::tuple<l...>& tuple) : inner(tuple){}
64+
constexpr Chain(l... things) : inner(std::make_tuple(things...))
65+
{
66+
}
67+
FullAddition<Chain> operator+=(const Chain& other)
68+
{
69+
bool carry = false;
70+
detail::foreach<l...>()(
71+
[&](auto x)
72+
{
73+
using type = std::remove_reference_t<
74+
decltype(detail::get(x,this->inner))
75+
>;
76+
77+
auto lhs = detail::get(x,other.inner);
78+
auto with_carry = lhs + type::one();
79+
using carry_t = decltype(with_carry);
80+
carry_t add = carry ? with_carry : carry_t(lhs);
81+
carry = detail::get(x,this->inner) += add;
82+
carry |= add;
83+
}
84+
);
85+
return *this;
86+
}
87+
Chain negate() const
88+
{
89+
Chain ret = *this;
90+
detail::foreach<l...>()(
91+
[&](auto x)
92+
{
93+
using type = std::remove_reference_t<
94+
decltype(detail::get(x,this->inner))
95+
>;
96+
auto& r = detail::get(x,ret.inner);
97+
const auto& o = detail::get(x,this->inner);
98+
r = type((type)o.negate() - type::one());
99+
}
100+
);
101+
return ret+one();
102+
}
103+
bool operator==(const Chain& other) const
104+
{
105+
return this->inner == other.inner;
106+
}
107+
bool operator<(const Chain& other) const
108+
{
109+
bool lt[sizeof...(l)];
110+
bool eq[sizeof...(l)];
111+
detail::foreach<l...>()(
112+
[&](auto x)
113+
{
114+
lt[x()] = this->Get(x) < other.Get(x);
115+
eq[x()] = this->Get(x) == other.Get(x);
116+
}
117+
);
118+
for (size_t x = sizeof...(l)-1; x != size_t(-1); x--)
119+
{
120+
if (lt[x])
121+
{
122+
return true;
123+
}
124+
else if (eq[x])
125+
{
126+
continue;
127+
}
128+
else
129+
{
130+
return false;
131+
}
132+
}
133+
return false;
134+
}
135+
template<typename T>
136+
auto& Get(T index)
137+
{
138+
return detail::get(index,this->inner);
139+
}
140+
template<typename T>
141+
const auto& Get(T index) const
142+
{
143+
return detail::get(index,this->inner);
144+
}
145+
template<long index>
146+
auto& Get()
147+
{
148+
return detail::get(std::integral_constant<long,index>(),this->inner);
149+
}
150+
template<long index>
151+
const auto& Get() const
152+
{
153+
return detail::get(std::integral_constant<long,index>(),this->inner);
154+
}
155+
protected:
156+
std::tuple<l...> inner;
157+
};
158+
159+
160+
#endif

0 commit comments

Comments
 (0)