rpn/src/stack.hpp

126 lines
3.4 KiB
C++
Raw Normal View History

#ifndef __stack_h__
#define __stack_h__
2014-02-12 11:26:26 +01:00
#include <string.h>
2022-02-07 16:36:27 +01:00
#include <algorithm>
#include <deque>
#include <map>
2022-02-07 16:36:27 +01:00
#include "object.hpp"
using namespace std;
2018-08-13 00:15:20 +02:00
/// @brief stack object, parens of program, storing execution stack values or programs
///
2022-02-07 16:36:27 +01:00
class rpnstack : public deque<object*> {
2018-08-12 15:06:04 +02:00
public:
2022-02-07 16:36:27 +01:00
rpnstack() {}
2022-02-12 19:11:22 +01:00
virtual ~rpnstack() {
for_each(begin(), end(), [](object* o) { delete o; });
2022-02-15 16:57:09 +01:00
deque::erase(begin(), end());
2022-02-12 19:11:22 +01:00
}
2017-05-02 10:47:03 +02:00
2018-08-13 00:15:20 +02:00
/// @brief copy a whole stack entry and push it back to another stack
///
/// @param from copy from
/// @param index_from index t ocopy from
/// @param to copy to
///
2022-02-07 16:36:27 +01:00
static void copy_and_push_front(rpnstack& from, unsigned int index_from, rpnstack& to) {
2022-02-12 19:11:22 +01:00
// carefull: caller must ensure that index_from is correct
2022-02-16 17:36:26 +01:00
to.push_front(from[index_from]->clone());
2018-08-12 15:06:04 +02:00
}
2022-02-11 14:00:15 +01:00
/// @brief erase a stack entry from it index
///
/// @param first index to start
/// @param last index to stop
///
void erase(size_t first = 0, size_t nb = 1, bool del = true) {
2022-02-15 16:57:09 +01:00
size_t last = std::min(first + nb, size());
if (del)
for_each(begin() + first, begin() + last, [](object* o) { delete o; });
2022-02-15 16:57:09 +01:00
deque::erase(begin() + first, begin() + last);
2022-02-11 14:00:15 +01:00
}
2022-02-12 19:11:22 +01:00
/// @brief pop front several entries
2018-08-13 00:15:20 +02:00
///
2022-02-07 16:36:27 +01:00
/// @param levels nb of entries
2018-08-13 00:15:20 +02:00
///
2022-02-15 16:57:09 +01:00
void pop_front(size_t levels = 1) { erase(0, levels); }
void pop() { erase(); }
2022-02-12 19:11:22 +01:00
// access helpers
cmd_type_t type(int level) {
// carefull: caller must ensure that level is correct
return at(level)->_type;
}
2022-02-15 16:57:09 +01:00
template <class objectType>
2022-02-21 02:03:37 +01:00
auto& obj(int level) {
2022-02-12 19:11:22 +01:00
// carefull: caller must ensure that level is correct
2022-02-21 02:03:37 +01:00
return static_cast<objectType&>(*at(level));
2022-02-12 19:11:22 +01:00
}
2022-02-15 16:57:09 +01:00
template <class objectType>
auto& value(int level) {
2022-02-12 19:11:22 +01:00
// carefull: caller must ensure that level is correct
return static_cast<objectType*>(at(level))->value;
}
2022-02-15 16:57:09 +01:00
void push(object* o) { deque<object*>::push_front(o); }
2018-08-12 11:50:49 +02:00
};
2018-08-13 00:15:20 +02:00
/// @brief heap object, storing variables (=named object)
///
2022-02-07 16:36:27 +01:00
class heap : public map<string, object*> {
2018-08-12 15:06:04 +02:00
public:
heap() {}
2022-02-16 16:03:26 +01:00
virtual ~heap() { clear(); }
void clear() {
for_each(begin(), end(), [](auto it) { delete it.second; });
map::erase(begin(), end());
}
2018-08-12 15:06:04 +02:00
2018-08-13 00:15:20 +02:00
/// @brief get a variable
2022-02-07 16:36:27 +01:00
///
2018-08-13 00:15:20 +02:00
/// @param name the variable name
/// @param obj the variable content
/// @return true the variable was found
/// @return false the variable was not found
///
2022-02-07 16:36:27 +01:00
bool get(const string name, object*& obj) {
2018-08-12 15:06:04 +02:00
bool ret = false;
2022-02-07 16:36:27 +01:00
auto i = find(name);
if (i != end()) {
obj = i->second;
2018-08-12 15:06:04 +02:00
ret = true;
}
return ret;
2015-05-19 17:51:03 +02:00
}
2018-08-12 15:06:04 +02:00
2018-08-13 00:15:20 +02:00
/// @brief get a variable by its index in heap
2022-02-07 16:36:27 +01:00
///
2018-08-13 00:15:20 +02:00
/// @param num the variable index
/// @param name the variable name
/// @param obj the variable content
/// @return true the variable was found
/// @return false the variable was not found
///
2022-02-07 16:36:27 +01:00
bool get_by_index(int num, string& name, object*& obj) {
if (num >= 0 && num < (int)size()) {
2018-08-12 15:06:04 +02:00
object* local;
2022-02-07 16:36:27 +01:00
auto i = begin();
for (; num > 0; num--, i++)
;
obj = i->second;
2022-02-20 19:07:55 +01:00
name = i->first;
2018-08-12 15:06:04 +02:00
return true;
} else
return false;
}
};
2018-08-12 11:50:49 +02:00
#endif // __stack_h__