Skip to content

Commit

Permalink
Refactor Stack utility class
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Sep 2, 2020
1 parent eacb0ed commit e1e96c6
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 130 deletions.
40 changes: 17 additions & 23 deletions lib/fizzy/stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,42 @@
namespace fizzy
{
template <typename T>
class Stack : public std::vector<T>
class Stack
{
public:
using difference_type = typename std::vector<T>::difference_type;

using std::vector<T>::vector;

using std::vector<T>::back;
using std::vector<T>::emplace_back;
using std::vector<T>::pop_back;
using std::vector<T>::resize;
using std::vector<T>::size;
std::vector<T> m_container;

// Also used: size(), resize(), clear(), empty(), end()

void push(T val) { emplace_back(val); }
public:
void push(T val) { m_container.emplace_back(val); }

template <typename... Args>
void emplace(Args&&... args)
{
std::vector<T>::emplace_back(std::forward<Args>(args)...);
m_container.emplace_back(std::forward<Args>(args)...);
}

T pop()
T pop() noexcept
{
const auto res = back();
pop_back();
const auto res = m_container.back();
m_container.pop_back();
return res;
}

T& operator[](size_t index) noexcept { return std::vector<T>::operator[](size() - index - 1); }
bool empty() const noexcept { return m_container.empty(); }

T& top() noexcept { return (*this)[0]; }
size_t size() const noexcept { return m_container.size(); }

/// Drops @a num_elements elements from the top of the stack.
void drop(size_t num_elements = 1) noexcept { resize(size() - num_elements); }
T& operator[](size_t index) noexcept { return m_container[size() - index - 1]; }

T& top() noexcept { return (*this)[0]; }

void shrink(size_t new_size) noexcept
{
assert(new_size <= size());
resize(new_size);
m_container.resize(new_size);
}

/// Drops @a num_elements elements from the top of the stack.
void drop(size_t num_elements = 1) noexcept { shrink(size() - num_elements); }
};

class OperandStack
Expand Down
150 changes: 43 additions & 107 deletions test/unittests/stack_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ TEST(stack, emplace)
EXPECT_TRUE(stack.empty());
}

TEST(stack, drop_and_peek)
TEST(stack, drop)
{
Stack<char> stack;
stack.push('w');
Expand Down Expand Up @@ -80,93 +80,72 @@ TEST(stack, drop_and_peek)
EXPECT_TRUE(stack.empty());
}

TEST(stack, clear)
TEST(stack, shrink)
{
Stack<char> stack;
stack.push('a');
stack.push('b');
stack.push('c');
stack.push('d');
EXPECT_EQ(stack.top(), 'd');
EXPECT_EQ(stack.size(), 4);

EXPECT_FALSE(stack.empty());
EXPECT_EQ(stack.size(), 2);
stack.shrink(4);
EXPECT_EQ(stack.top(), 'd');
EXPECT_EQ(stack.size(), 4);

stack.drop(0);
EXPECT_FALSE(stack.empty());
stack.shrink(2);
EXPECT_EQ(stack.top(), 'b');
EXPECT_EQ(stack.size(), 2);

stack.clear();
stack.shrink(0);
EXPECT_TRUE(stack.empty());
EXPECT_EQ(stack.size(), 0);
}

TEST(stack, resize)
TEST(stack, struct_item)
{
Stack<char> stack;
stack.push('a');
stack.push('b');
struct StackItem
{
char a, b, c;
StackItem() = default; // required for drop() (which calls resize())
StackItem(char _a, char _b, char _c) : a(_a), b(_b), c(_c) {}
};

EXPECT_FALSE(stack.empty());
EXPECT_EQ(stack.size(), 2);
Stack<StackItem> stack;

// grow stack
stack.resize(4);
EXPECT_FALSE(stack.empty());
EXPECT_EQ(stack.top(), 0);
EXPECT_EQ(stack[1], 0);
EXPECT_EQ(stack[2], 'b');
EXPECT_EQ(stack[3], 'a');
EXPECT_EQ(stack.size(), 4);
stack.emplace('a', 'b', 'c');
stack.emplace('d', 'e', 'f');
stack.emplace('g', 'h', 'i');

stack.drop();
EXPECT_FALSE(stack.empty());
EXPECT_EQ(stack.size(), 3);

// shrink stack
stack.resize(1);
EXPECT_FALSE(stack.empty());
EXPECT_EQ(stack.size(), 1);

stack.clear();
EXPECT_TRUE(stack.empty());
EXPECT_EQ(stack.size(), 0);

// resize and shrink
stack.resize(4);
EXPECT_EQ(stack.size(), 4);
stack.shrink(2);
EXPECT_EQ(stack.size(), 2);
stack.shrink(0);
EXPECT_TRUE(stack.empty());
EXPECT_EQ(stack.size(), 0);
}

TEST(stack, iterator)
{
Stack<char> stack;
stack.push('a');
stack.push('b');
stack.push('c');

EXPECT_FALSE(stack.empty());
EXPECT_EQ(stack.size(), 3);
EXPECT_EQ(stack.top().a, 'g');
EXPECT_EQ(stack.top().b, 'h');
EXPECT_EQ(stack.top().c, 'i');
EXPECT_EQ(stack[1].a, 'd');
EXPECT_EQ(stack[1].b, 'e');
EXPECT_EQ(stack[1].c, 'f');
EXPECT_EQ(stack[2].a, 'a');
EXPECT_EQ(stack[2].b, 'b');
EXPECT_EQ(stack[2].c, 'c');

auto bottom_item = stack.begin();
EXPECT_EQ(*bottom_item, 'a');
EXPECT_EQ(stack.pop().a, 'g');

auto top_item = stack.end() - 1;
EXPECT_EQ(*top_item, 'c');
EXPECT_EQ(stack.top().a, 'd');
EXPECT_EQ(stack.top().b, 'e');
EXPECT_EQ(stack.top().c, 'f');
EXPECT_EQ(stack[1].a, 'a');
EXPECT_EQ(stack[1].b, 'b');
EXPECT_EQ(stack[1].c, 'c');

for (auto it = stack.begin(); it < stack.end(); it++)
*it = 'x';
stack.drop();

for (unsigned item = 0; item < stack.size(); item++)
EXPECT_EQ(stack[item], 'x');
EXPECT_EQ(stack.top().a, 'a');
EXPECT_EQ(stack.top().b, 'b');
EXPECT_EQ(stack.top().c, 'c');
}

TEST(stack, clear_on_empty)
{
Stack<char> stack;
stack.clear();
}

TEST(operand_stack, construct)
{
Expand Down Expand Up @@ -287,46 +266,3 @@ TEST(operand_stack, to_vector)
EXPECT_EQ(result[1].i64, 2);
EXPECT_EQ(result[2].i64, 3);
}

TEST(stack, struct_item)
{
struct StackItem
{
char a, b, c;
StackItem() = default; // required for drop() (which calls resize())
StackItem(char _a, char _b, char _c) : a(_a), b(_b), c(_c) {}
};

Stack<StackItem> stack;

stack.emplace('a', 'b', 'c');
stack.emplace('d', 'e', 'f');
stack.emplace('g', 'h', 'i');

EXPECT_EQ(stack.size(), 3);

EXPECT_EQ(stack.top().a, 'g');
EXPECT_EQ(stack.top().b, 'h');
EXPECT_EQ(stack.top().c, 'i');
EXPECT_EQ(stack[1].a, 'd');
EXPECT_EQ(stack[1].b, 'e');
EXPECT_EQ(stack[1].c, 'f');
EXPECT_EQ(stack[2].a, 'a');
EXPECT_EQ(stack[2].b, 'b');
EXPECT_EQ(stack[2].c, 'c');

EXPECT_EQ(stack.pop().a, 'g');

EXPECT_EQ(stack.top().a, 'd');
EXPECT_EQ(stack.top().b, 'e');
EXPECT_EQ(stack.top().c, 'f');
EXPECT_EQ(stack[1].a, 'a');
EXPECT_EQ(stack[1].b, 'b');
EXPECT_EQ(stack[1].c, 'c');

stack.drop();

EXPECT_EQ(stack.top().a, 'a');
EXPECT_EQ(stack.top().b, 'b');
EXPECT_EQ(stack.top().c, 'c');
}

0 comments on commit e1e96c6

Please sign in to comment.