rpn/src/stack.h

290 lines
7.1 KiB
C
Raw Normal View History

#ifndef __stack_h__
#define __stack_h__
2014-02-12 11:26:26 +01:00
#include <string.h>
#include <map>
using namespace std;
// allocation base size
#define ALLOC_STACK_CHUNK (64*1024)
//
class stack
{
public:
2015-05-19 17:51:03 +02:00
stack()
{
2017-04-29 15:43:05 +02:00
_base = NULL;
2017-05-22 18:22:15 +02:00
_base_pointer = NULL;
2017-04-29 15:43:05 +02:00
_total_size = 0;
2017-05-22 18:22:15 +02:00
_total_count_pointer = 0;
2017-04-23 15:49:28 +02:00
erase();
}
2015-05-19 17:51:03 +02:00
virtual ~stack()
2015-05-19 17:51:03 +02:00
{
2017-04-29 15:43:05 +02:00
if (_base != NULL)
free(_base);
2017-05-22 18:22:15 +02:00
if (_base_pointer != NULL)
free(_base_pointer);
}
2017-04-23 15:49:28 +02:00
void erase()
{
_current = _base;
_count = 0;
}
2017-05-02 10:47:03 +02:00
//
static void copy_and_push_back(stack& from, unsigned int index_from, stack& to)
{
2017-05-02 10:47:03 +02:00
// copy a whole stack entry and push it back to another stack
object* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from));
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
2017-05-02 10:47:03 +02:00
if (allocated->_type == cmd_number)
2017-05-22 18:22:15 +02:00
((number*)allocated)->_value.set_significand(((number*)allocated) + 1);
}
2015-05-19 17:51:03 +02:00
//
2017-05-02 10:47:03 +02:00
static void copy_and_push_back(object* from, stack& to, unsigned int size)
{
2017-05-02 10:47:03 +02:00
// copy a whole stack entry and push it back to another stack
object* allocated = to.allocate_back(size, from->_type);
memcpy(allocated, from, size);
2017-05-02 10:47:03 +02:00
if (allocated->_type == cmd_number)
2017-05-22 18:22:15 +02:00
((number*)allocated)->_value.set_significand(((number*)allocated) + 1);
2015-05-19 17:51:03 +02:00
}
2017-05-02 10:47:03 +02:00
object* allocate_back(unsigned int size, cmd_type_t type)
{
2017-05-02 10:47:03 +02:00
object* allocated;
2017-05-02 10:47:03 +02:00
// manage memory allocation
if (_current + size > _base + _total_size)
{
unsigned long offset = _current - _base;
_total_size += ALLOC_STACK_CHUNK;
_base = (char*)realloc(_base, _total_size);
_current = _base + offset;
2017-05-22 18:22:15 +02:00
//TODO si realloc alors les pointeurs doivent etre recalculés !
}
if ((_count+1) > _total_count_pointer)
{
_base_pointer = (object**)realloc(_base_pointer, (_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK);
_total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object));
}
2017-05-02 10:47:03 +02:00
// manage stack itself
2017-05-22 18:22:15 +02:00
_base_pointer[_count++]=(object*)_current;
2017-05-02 10:47:03 +02:00
allocated = (object*)_current;
_current += size;
2017-05-02 10:47:03 +02:00
// init object
allocated->_type = type;
allocated->_size = size;
if (type == cmd_number)
2017-05-22 18:22:15 +02:00
((number*)allocated)->_value.init(((number*)allocated) + 1);
2017-05-02 10:47:03 +02:00
return allocated;
}
2017-05-02 10:47:03 +02:00
object* pop_back()
2015-05-19 17:51:03 +02:00
{
2017-05-02 10:47:03 +02:00
object* back = NULL;
2015-05-19 17:51:03 +02:00
if (_count > 0)
{
2017-05-22 18:22:15 +02:00
_current = (char*)_base_pointer[_count - 1];
2015-05-19 17:51:03 +02:00
_count--;
2017-05-02 10:47:03 +02:00
back = (object*)_current;
2015-05-19 17:51:03 +02:00
}
return back;
2015-05-19 17:51:03 +02:00
}
unsigned int size()
{
return _count;
}
// stack access (index is counted from back)
2017-05-02 10:47:03 +02:00
object* get_obj(unsigned int index)
2015-05-19 17:51:03 +02:00
{
if (index<_count)
2017-05-22 18:22:15 +02:00
return _base_pointer[_count - index - 1];
2015-05-19 17:51:03 +02:00
else
return NULL;
}
2017-05-02 10:47:03 +02:00
object* operator[](unsigned int index)
2015-05-19 17:51:03 +02:00
{
return get_obj(index);
}
2017-05-02 10:47:03 +02:00
object* back()
2015-05-19 17:51:03 +02:00
{
if (_count>0)
2017-05-22 18:22:15 +02:00
return _base_pointer[_count - 1];
2015-05-19 17:51:03 +02:00
else
return NULL;
}
unsigned int get_len(unsigned int index)
{
if (index<_count)
2017-05-22 18:22:15 +02:00
return _base_pointer[_count - index - 1]->_size;
2015-05-19 17:51:03 +02:00
else
return 0;
}
2017-05-02 10:47:03 +02:00
cmd_type_t get_type(unsigned int index)
2015-05-19 17:51:03 +02:00
{
if (index<_count)
2017-05-22 18:22:15 +02:00
return _base_pointer[_count - index - 1]->_type;
2015-05-19 17:51:03 +02:00
else
2017-05-02 10:47:03 +02:00
return cmd_undef;
2015-05-19 17:51:03 +02:00
}
// sequential access (index is counted from front)
2017-05-02 10:47:03 +02:00
object* seq_obj(unsigned int index)
2015-05-19 17:51:03 +02:00
{
if (index<_count)
2017-05-22 18:22:15 +02:00
return _base_pointer[index];
2015-05-19 17:51:03 +02:00
else
return NULL;
}
unsigned int seq_len(unsigned int index)
{
if (index<_count)
2017-05-22 18:22:15 +02:00
return _base_pointer[index]->_size;
2015-05-19 17:51:03 +02:00
else
return 0;
}
2017-05-02 10:47:03 +02:00
cmd_type_t seq_type(unsigned int index)
2015-05-19 17:51:03 +02:00
{
if (index<_count)
2017-05-22 18:22:15 +02:00
return _base_pointer[index]->_type;
2015-05-19 17:51:03 +02:00
else
2017-05-02 10:47:03 +02:00
return cmd_undef;
2015-05-19 17:51:03 +02:00
}
private:
2015-05-19 17:51:03 +02:00
char* _base;
char* _current;
2017-05-22 18:22:15 +02:00
object** _base_pointer;
2017-05-02 10:47:03 +02:00
unsigned int _count;// =_vlen.size()=_vpointer.size()
2017-05-22 18:22:15 +02:00
unsigned int _total_count_pointer;//total number of possible pointers
2015-05-19 17:51:03 +02:00
unsigned int _total_size;//total allocated size in bytes
};
//
2017-05-22 18:22:15 +02:00
class heap : public stack
{
public:
2015-05-19 17:51:03 +02:00
heap() { }
2017-05-22 18:22:15 +02:00
virtual ~heap() { }
2015-05-19 17:51:03 +02:00
2017-05-22 18:22:15 +02:00
object* add(const string name, object* obj, unsigned int size)
{
object* local = _map[name];
// variable does not exist in heap or already exists but its size is too short -> allocate
if (local==NULL || (local!=NULL && size>local->_size))
2015-05-19 17:51:03 +02:00
{
2017-05-22 18:22:15 +02:00
copy_and_push_back(obj, *this, size);
_map[name] = back();
2015-03-01 16:30:13 +01:00
}
2017-05-22 18:22:15 +02:00
else
2015-05-19 17:51:03 +02:00
{
2017-05-22 18:22:15 +02:00
// variable already exists in heap but previous was larger -> don't reallocate
// copy a whole stack entry and push it back to another stack
memcpy(local, obj, size);
if (local->_type == cmd_number)
((number*)local)->_value.set_significand(((number*)local)+1);
2015-03-01 16:30:13 +01:00
}
2017-05-17 18:15:03 +02:00
2017-05-22 18:22:15 +02:00
return local;
}
2017-05-02 10:47:03 +02:00
bool get(const string name, object*& obj, unsigned int& size)
2015-05-19 17:51:03 +02:00
{
2017-05-22 18:22:15 +02:00
bool ret = false;
map<string, object*>::iterator i = _map.find(name);
if (i!=_map.end() && i->second!=NULL)
2015-05-19 17:51:03 +02:00
{
2017-05-22 18:22:15 +02:00
obj = i->second;
size = i->second->_size;
ret = true;
2015-05-19 17:51:03 +02:00
}
2017-05-22 18:22:15 +02:00
return ret;
2015-05-19 17:51:03 +02:00
}
2017-05-17 18:15:03 +02:00
bool replace_value(const string name, object* obj, unsigned int size)
{
bool ret=false;
2017-05-22 18:22:15 +02:00
map<string, object*>::iterator i = _map.find(name);
2017-05-17 18:15:03 +02:00
2017-05-22 18:22:15 +02:00
if (i!=_map.end() && i->second!=NULL && size==i->second->_size)
2017-05-17 18:15:03 +02:00
{
2017-05-22 18:22:15 +02:00
(void)memcpy(i->second, obj, size);
if (i->second->_type == cmd_number)
((number*)i->second)->_value.set_significand(((number*)i->second)+1);
ret = true;
2017-05-17 18:15:03 +02:00
}
}
2015-05-19 17:51:03 +02:00
bool exist(const string name)
{
return (_map.find(name) != _map.end());
}
2017-05-02 10:47:03 +02:00
bool get_by_index(int num, string& name, object*& obj, unsigned int& size)
2015-05-19 17:51:03 +02:00
{
if (num>=0 && num<(int)_map.size())
{
2017-05-22 18:22:15 +02:00
object* local;
map<string, object*>::iterator i= _map.begin();
2015-05-19 17:51:03 +02:00
2017-05-22 18:22:15 +02:00
//TODO another formulation, please
2015-05-19 17:51:03 +02:00
for(int j=0;j<num;j++)
i++;
2017-05-22 18:22:15 +02:00
local = (object*)i->second;
2015-05-19 17:51:03 +02:00
name = i->first;
2017-05-22 18:22:15 +02:00
obj = local;
size = local->_size;
2015-05-19 17:51:03 +02:00
return true;
}
else
return false;
}
2015-03-01 16:30:13 +01:00
bool erase(const string& name)
2015-05-19 17:51:03 +02:00
{
2017-05-22 18:22:15 +02:00
map<string, object*>::iterator i = _map.find(name);
bool ret = false;
2015-05-19 17:51:03 +02:00
if (i != _map.end())
{
_map.erase(i->first);
2017-05-22 18:22:15 +02:00
ret = true;
2015-05-19 17:51:03 +02:00
}
2017-05-22 18:22:15 +02:00
return ret;
2015-05-19 17:51:03 +02:00
}
2015-05-19 17:51:03 +02:00
unsigned int size() { return _map.size(); }
private:
2017-05-22 18:22:15 +02:00
map<string, object*> _map;
};
#endif // __stack_h__