Skip to content

Commit f35547f

Browse files
authored
Merge pull request #2 from attwoodn/implement-operators
Implement operators
2 parents dca2b87 + 528a2bb commit f35547f

File tree

6 files changed

+351
-7
lines changed

6 files changed

+351
-7
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
build
1+
build
2+
.vscode

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,9 @@ if (NOT DEFINED CMAKE_CXX_STANDARD)
1010
set(CMAKE_CXX_STANDARD 11)
1111
endif()
1212

13+
if (NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
14+
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
15+
endif()
16+
1317
include_directories( include )
1418
add_subdirectory( tests )
Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,71 @@
11
#pragma once
22

3-
#include <iostream>
4-
53
namespace attwoodn::expression_tree {
6-
static inline void say_hello() {
7-
std::cout << "hello world!" << std::endl;
4+
5+
namespace op {
6+
7+
template<typename T>
8+
inline bool less_than(T a, T b) {
9+
return a < b;
10+
}
11+
12+
template<typename T>
13+
inline bool less_than(T* a, T* b) {
14+
if(a == nullptr || b == nullptr) return false;
15+
return *a < *b;
16+
}
17+
18+
template<typename T>
19+
inline bool greater_than(T a, T b) {
20+
return a > b;
21+
}
22+
23+
template<typename T>
24+
inline bool greater_than(T* a, T* b) {
25+
if(a == nullptr || b == nullptr) return false;
26+
return *a > *b;
27+
}
28+
29+
template<typename T>
30+
inline bool equals(T a, T b) {
31+
return a == b;
32+
}
33+
34+
template<typename T>
35+
inline bool equals(T* a, T* b) {
36+
if(a == nullptr && b == nullptr) return true;
37+
if(a == nullptr || b == nullptr) return false;
38+
return *a == *b;
39+
}
40+
41+
template<typename T>
42+
inline bool not_equals(T a, T b) {
43+
return a != b;
44+
}
45+
46+
template<typename T>
47+
inline bool not_equals(T* a, T* b) {
48+
if(a == nullptr && b == nullptr) return false;
49+
if(a == nullptr || b == nullptr) return true;
50+
return *a != *b;
51+
}
52+
}
53+
54+
namespace tree {
55+
56+
/**
57+
* The base class representing expression tree nodes
58+
*/
59+
template<typename Obj>
60+
class expression_tree_node_base {
61+
public:
62+
virtual ~expression_tree_node_base() {};
63+
virtual bool evaluate(const Obj& obj) = 0;
64+
};
65+
66+
class expression_tree_op_node;
67+
class expression_tree_leaf_node;
68+
69+
870
}
971
}

tests/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
if(BUILD_TESTING)
22
add_executable( expression_tree_test test.cpp )
33
add_test( expression_tree_test ${EXECUTABLE_OUTPUT_PATH}/expression_tree_test )
4+
5+
add_executable( operators_test operators.cpp )
6+
add_test( operators_test ${EXECUTABLE_OUTPUT_PATH}/operators_test )
47
endif()

tests/operators.cpp

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
#include <attwoodn/expression_tree.hpp>
2+
#include <limits>
3+
#include <iomanip>
4+
#include <cassert>
5+
6+
using namespace attwoodn::expression_tree;
7+
8+
void test_equals();
9+
void test_not_equals();
10+
void test_less_than();
11+
void test_greater_than();
12+
13+
int main(int argc, char** argv) {
14+
test_equals();
15+
test_not_equals();
16+
test_less_than();
17+
test_greater_than();
18+
19+
return EXIT_SUCCESS;
20+
}
21+
22+
void test_equals() {
23+
// test string equality/inequality
24+
{
25+
std::string hello = "hello world";
26+
27+
assert(op::equals(hello, hello));
28+
assert(op::equals(hello, std::string("hello world")));
29+
assert(op::equals(std::string("hello world"), std::string("hello world")));
30+
assert(op::equals(std::string(" "), std::string(" ")));
31+
assert(op::equals(std::string("100 100 100 10000"), std::string("100 100 100 10000")));
32+
33+
// NOTE: pointer types are dereferenced prior to comparison. This may be misleading.
34+
// E.g., if the type is a char*, only the first character is compared.
35+
assert(op::equals("1", "1 "));
36+
assert(op::equals("test", "testing testing 123"));
37+
assert(op::equals("hello world", "hey, world"));
38+
assert(op::equals("A", "A"));
39+
40+
assert(!op::equals("\"", "\'"));
41+
assert(!op::equals("1", " 1"));
42+
assert(!op::equals("A", "B"));
43+
assert(!op::equals(std::string("hello world"), std::string("hey, world")));
44+
assert(!op::equals(std::string("test"), std::string(" test ")));
45+
assert(!op::equals(std::string(" "), std::string(" ")));
46+
assert(!op::equals(std::string("1"), std::string("1 ")));
47+
assert(!op::equals(std::string("1"), std::string(" 1")));
48+
}
49+
50+
// test integer equality/inequality
51+
{
52+
int low = 55, low_too = 55;
53+
int high = 999999, high_too = 999999;
54+
55+
assert(op::equals(5, 5));
56+
assert(op::equals(0, 0));
57+
assert(op::equals(-5, -5));
58+
assert(op::equals(123456789, 123456789));
59+
assert(op::equals(123456789L, 123456789L));
60+
assert(op::equals(255, 0xff));
61+
assert(op::equals(0xbeef, 0xbeef));
62+
assert(op::equals(std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max()));
63+
assert(op::equals(std::numeric_limits<uint16_t>::max(), std::numeric_limits<uint16_t>::max()));
64+
assert(op::equals(std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::min()));
65+
assert(op::equals(low, low));
66+
assert(op::equals(&low, &low));
67+
assert(op::equals(low, low_too));
68+
assert(op::equals(&low, &low_too));
69+
assert(op::equals(high, high));
70+
assert(op::equals(&high, &high));
71+
assert(op::equals(high, high_too));
72+
assert(op::equals(&high, &high_too));
73+
74+
assert(!op::equals(-5, 5));
75+
assert(!op::equals(0, 1));
76+
assert(!op::equals(254, 0xff));
77+
assert(!op::equals(123456789L, 123456789000L));
78+
assert(!op::equals(low, high));
79+
assert(!op::equals(&low, &high));
80+
}
81+
82+
// test float equality/inequality
83+
{
84+
float low = 55.5555, low_too = 55.5555;
85+
float high = 999999.999, high_too = 999999.999;
86+
87+
assert(op::equals(5.0, 5.0));
88+
assert(op::equals(0.000, 0.000));
89+
assert(op::equals(-5.0, -5.0));
90+
assert(op::equals(3.400f, 3.4f));
91+
assert(op::equals((float) 99999.0, (float) 99999.0));
92+
assert(op::equals(12345.999f, 12345.999f));
93+
assert(op::equals((double) 99999.999, (double) 99999.999));
94+
assert(op::equals(low, low));
95+
assert(op::equals(&low, &low));
96+
assert(op::equals(low, low_too));
97+
assert(op::equals(&low, &low_too));
98+
assert(op::equals(high, high));
99+
assert(op::equals(&high, &high));
100+
assert(op::equals(high, high_too));
101+
assert(op::equals(&high, &high_too));
102+
103+
assert(!op::equals(5.0, -5.0));
104+
assert(!op::equals(0.000, 0.000001));
105+
assert(!op::equals(-5.0, -4.999999));
106+
assert(!op::equals(low, high));
107+
assert(!op::equals(&low, &high));
108+
}
109+
110+
// test other
111+
{
112+
char* a = nullptr;
113+
assert(op::equals(a, a));
114+
115+
assert(!op::equals((char*) "a", a));
116+
}
117+
}
118+
119+
void test_not_equals() {
120+
// test string equality/inequality
121+
{
122+
std::string hello = "hello world";
123+
124+
assert(op::not_equals("\"", "\'"));
125+
assert(op::not_equals("1", " 1"));
126+
assert(op::not_equals("A", "B"));
127+
assert(op::not_equals(std::string("hello world"), std::string("hey, world")));
128+
assert(op::not_equals(std::string("test"), std::string(" test ")));
129+
assert(op::not_equals(std::string(" "), std::string(" ")));
130+
assert(op::not_equals(std::string("1"), std::string("1 ")));
131+
assert(op::not_equals(std::string("1"), std::string(" 1")));
132+
133+
assert(!op::not_equals(hello, hello));
134+
assert(!op::not_equals(hello, std::string("hello world")));
135+
assert(!op::not_equals(std::string("hello world"), std::string("hello world")));
136+
assert(!op::not_equals(std::string(" "), std::string(" ")));
137+
assert(!op::not_equals(std::string("100 100 100 10000"), std::string("100 100 100 10000")));
138+
139+
// NOTE: pointer types are dereferenced prior to comparison. This may be misleading.
140+
// E.g., if the type is a char*, only the first character is compared.
141+
assert(!op::not_equals("1", "1 "));
142+
assert(!op::not_equals("test", "testing testing 123"));
143+
assert(!op::not_equals("hello world", "hey, world"));
144+
assert(!op::not_equals("A", "A"));
145+
}
146+
147+
// test integer equality/inequality
148+
{
149+
int low = 55, low_too = 55;
150+
int high = 999999, high_too = 999999;
151+
152+
assert(op::not_equals(-5, 5));
153+
assert(op::not_equals(0, 1));
154+
assert(op::not_equals(254, 0xff));
155+
assert(op::not_equals(123456789L, 123456789000L));
156+
assert(op::not_equals(low, high));
157+
assert(op::not_equals(&low, &high));
158+
159+
assert(!op::not_equals(5, 5));
160+
assert(!op::not_equals(0, 0));
161+
assert(!op::not_equals(-5, -5));
162+
assert(!op::not_equals(123456789, 123456789));
163+
assert(!op::not_equals(123456789L, 123456789L));
164+
assert(!op::not_equals(255, 0xff));
165+
assert(!op::not_equals(0xbeef, 0xbeef));
166+
assert(!op::not_equals(std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max()));
167+
assert(!op::not_equals(std::numeric_limits<uint16_t>::max(), std::numeric_limits<uint16_t>::max()));
168+
assert(!op::not_equals(std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::min()));
169+
assert(!op::not_equals(low, low));
170+
assert(!op::not_equals(&low, &low));
171+
assert(!op::not_equals(low, low_too));
172+
assert(!op::not_equals(&low, &low_too));
173+
assert(!op::not_equals(high, high));
174+
assert(!op::not_equals(&high, &high));
175+
assert(!op::not_equals(high, high_too));
176+
assert(!op::not_equals(&high, &high_too));
177+
}
178+
179+
// test float equality/inequality
180+
{
181+
float low = 55.5555, low_too = 55.5555;
182+
float high = 999999.999, high_too = 999999.999;
183+
184+
assert(op::not_equals(5.0, -5.0));
185+
assert(op::not_equals(0.000, 0.000001));
186+
assert(op::not_equals(-5.0, -4.999999));
187+
assert(op::not_equals(low, high));
188+
assert(op::not_equals(&low, &high));
189+
190+
assert(!op::not_equals(5.0, 5.0));
191+
assert(!op::not_equals(0.000, 0.000));
192+
assert(!op::not_equals(-5.0, -5.0));
193+
assert(!op::not_equals(3.400f, 3.4f));
194+
assert(!op::not_equals((float) 99999.0, (float) 99999.0));
195+
assert(!op::not_equals(12345.999f, 12345.999f));
196+
assert(!op::not_equals((double) 99999.999, (double) 99999.999));
197+
assert(!op::not_equals(low, low));
198+
assert(!op::not_equals(&low, &low));
199+
assert(!op::not_equals(low, low_too));
200+
assert(!op::not_equals(&low, &low_too));
201+
assert(!op::not_equals(high, high));
202+
assert(!op::not_equals(&high, &high));
203+
assert(!op::not_equals(high, high_too));
204+
assert(!op::not_equals(&high, &high_too));
205+
}
206+
207+
// test other
208+
{
209+
char* a = nullptr;
210+
assert(op::not_equals((char*) "a", a));
211+
212+
assert(!op::not_equals(a, a));
213+
}
214+
}
215+
216+
void test_less_than() {
217+
assert(op::less_than(5, 6));
218+
assert(op::less_than(1, 10));
219+
assert(op::less_than(0, 1));
220+
assert(op::less_than(-1, 1));
221+
assert(op::less_than(-1, 0));
222+
assert(op::less_than(5.0, 6.665));
223+
assert(op::less_than(6.664, 6.665));
224+
assert(op::less_than(1.199999, 1.2));
225+
assert(op::less_than(0xfe, 0xff));
226+
assert(op::less_than(std::string("hello"), std::string("hi")));
227+
assert(op::less_than("a", "b"));
228+
assert(op::less_than("A", "C"));
229+
assert(op::less_than("Q", "Z"));
230+
assert(op::less_than(std::string("a"), std::string("abc")));
231+
232+
assert(!op::less_than(0, -1));
233+
assert(!op::less_than(0, -1000));
234+
assert(!op::less_than(-1, -1));
235+
assert(!op::less_than(0, 0));
236+
assert(!op::less_than(999999, 999999));
237+
assert(!op::less_than(0xff, 0xff));
238+
assert(!op::less_than("hello", "hello"));
239+
assert(!op::less_than("a", "a"));
240+
assert(!op::less_than("z", "a"));
241+
assert(!op::less_than("E", "B"));
242+
assert(!op::less_than(std::string("abc"), std::string("a")));
243+
assert(!op::less_than(std::string("hi"), std::string("hello")));
244+
}
245+
246+
void test_greater_than() {
247+
assert(op::greater_than(0, -1));
248+
assert(op::greater_than(0, -1000));
249+
assert(op::greater_than("z", "a"));
250+
assert(op::greater_than("E", "B"));
251+
assert(op::greater_than(std::string("abc"), std::string("a")));
252+
assert(op::greater_than(std::string("hi"), std::string("hello")));
253+
254+
assert(!op::greater_than(5, 6));
255+
assert(!op::greater_than(1, 10));
256+
assert(!op::greater_than(0, 1));
257+
assert(!op::greater_than(-1, 1));
258+
assert(!op::greater_than(-1, 0));
259+
assert(!op::greater_than(-1, -1));
260+
assert(!op::greater_than(0, 0));
261+
assert(!op::greater_than(999999, 999999));
262+
assert(!op::greater_than(0xff, 0xff));
263+
assert(!op::greater_than("hello", "hello"));
264+
assert(!op::greater_than("a", "a"));
265+
assert(!op::greater_than(5.0, 6.665));
266+
assert(!op::greater_than(6.664, 6.665));
267+
assert(!op::greater_than(1.199999, 1.2));
268+
assert(!op::greater_than(0xfe, 0xff));
269+
assert(!op::greater_than(std::string("hello"), std::string("hi")));
270+
assert(!op::greater_than("a", "b"));
271+
assert(!op::greater_than("A", "C"));
272+
assert(!op::greater_than("Q", "Z"));
273+
assert(!op::greater_than(std::string("a"), std::string("abc")));
274+
}

tests/test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#include <attwoodn/expression_tree.hpp>
1+
#include <iostream>
22

33
int main(int argc, char** argv) {
4-
attwoodn::expression_tree::say_hello();
4+
std::cout << "hello world!" << std::endl;
55

66
return EXIT_SUCCESS;
77
}

0 commit comments

Comments
 (0)