rpn/src/stack.h

368 lines
8.9 KiB
C
Raw Normal View History

#ifndef __stack_h__
#define __stack_h__
2014-02-12 11:26:26 +01:00
#include <string.h>
#include <assert.h>
#include <vector>
#include <map>
using namespace std;
2015-03-01 16:02:23 +01:00
#include "debug.h"
// allocation base size
#define ALLOC_STACK_CHUNK (64*1024)
#define ALLOC_BLOB_CHUNK (64*1024)
#define LOCAL_COPY_PLACES 3
#define LOCAL_COPY_SIZE 128
//
class stack
{
private:
2015-05-19 17:51:03 +02:00
struct local_copy
{
unsigned int length;
int type;
int blob;
};
public:
2015-05-19 17:51:03 +02:00
stack()
{
_base = new char[ALLOC_STACK_CHUNK];
_blob = new char[ALLOC_BLOB_CHUNK];
_total_size = ALLOC_STACK_CHUNK;
_total_blob_size = ALLOC_BLOB_CHUNK;
2015-05-19 17:51:03 +02:00
_current = _base;
_current_blob = _blob;
2015-05-19 17:51:03 +02:00
_count = 0;
}
virtual ~stack()
2015-05-19 17:51:03 +02:00
{
delete[] _base;
delete[] _blob;
}
void push_back(void* obj, unsigned int size, int type = 0, bool dont_copy = false, void* blob = NULL, unsigned int blob_size = 0)
{
void* allocated_blob;
void* allocated = allocate_back(size, type, blob_size, &allocated_blob);
if (!dont_copy)
2015-05-19 17:51:03 +02:00
{
if (size > 0)
memcpy(allocated, obj, size);
if (blob != NULL && blob_size > 0)
memcpy(allocated_blob, blob, blob_size);
2015-05-19 17:51:03 +02:00
}
}
2015-05-19 17:51:03 +02:00
static void copy_and_push_back(stack& from, unsigned int index_from, stack& to)
{
// copy a whole stack entry (with blob) and push it back to another stack
void* allocated_blob;
void* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from), from.seq_blob_size(index_from), &allocated_blob);
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
memcpy(allocated_blob, from.seq_blob(index_from), from.seq_blob_size(index_from));
2015-05-19 17:51:03 +02:00
}
void* allocate_back(unsigned int size, int type, unsigned int blob_size = 0, void** blob = NULL)
{
void* allocated;
if (_current + size > _base + _total_size)
{
//TODO gerer les pbs de memoire
unsigned long offset = _current - _base;
_total_size += ALLOC_STACK_CHUNK;
_base = (char*)realloc(_base, _total_size);
_current = _base + offset;
}
if (_current_blob + blob_size > _blob + _total_blob_size)
{
//TODO gerer les pbs de memoire
unsigned long offset = _current_blob - _blob;
_total_blob_size += ALLOC_BLOB_CHUNK;
_blob = (char*)realloc(_blob, _total_blob_size);
_current_blob = _blob + offset;
}
_vlen.push_back(size);
_vpointer.push_back(_current);
allocated = _current;
_current += size;
_vlen_blob.push_back(blob_size);
_vpointer_blob.push_back(_current_blob);
if (blob != NULL)
*blob = _current_blob;
_current_blob += blob_size;
_vtype.push_back(type);
_count++;
return allocated;
}
void* pop_back()
2015-05-19 17:51:03 +02:00
{
void* back = NULL;
2015-05-19 17:51:03 +02:00
if (_count > 0)
{
_current = _vpointer[_count - 1];
_vlen.pop_back();
_vpointer.pop_back();
_current_blob = _vpointer_blob[_count - 1];
_vlen_blob.pop_back();
_vpointer_blob.pop_back();
2015-05-19 17:51:03 +02:00
_vtype.pop_back();
_count--;
back = _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)
void* get_obj(unsigned int index)
{
if (index<_count)
return _vpointer[_count-index-1];
else
return NULL;
}
void* operator[](unsigned int index)
{
return get_obj(index);
}
void* back()
{
if (_count>0)
return _vpointer[_count-1];
else
return NULL;
}
void* back_blob()
{
if (_count>0)
return _vpointer_blob[_count-1];
else
return NULL;
}
2015-05-19 17:51:03 +02:00
unsigned int get_len(unsigned int index)
{
if (index<_count)
return _vlen[_count-index-1];
else
return 0;
}
int get_type(unsigned int index)
{
if (index<_count)
return _vtype[_count-index-1];
else
return 0;
}
// sequential access (index is counted from front)
void* seq_obj(unsigned int index)
{
if (index<_count)
return _vpointer[index];
else
return NULL;
}
unsigned int seq_len(unsigned int index)
{
if (index<_count)
return _vlen[index];
else
return 0;
}
void* seq_blob(unsigned int index)
{
if (index<_count)
return _vpointer_blob[index];
else
return NULL;
}
unsigned int seq_blob_size(unsigned int index)
{
if (index<_count)
return _vlen_blob[index];
else
return 0;
}
2015-05-19 17:51:03 +02:00
int seq_type(unsigned int index)
{
if (index<_count)
return _vtype[index];
else
return 0;
}
// local objects copy
void copy_obj_to_local(unsigned int index, unsigned int to_place)
{
2015-05-19 17:51:03 +02:00
assert(to_place < LOCAL_COPY_PLACES);
struct local_copy* local = (struct local_copy*)_places[to_place];
local->length = get_len(index);
local->type= get_type(index);
memcpy(&local->blob, get_obj(index), local->length);
}
void push_obj_from_local(unsigned int from_place)
{
2015-05-19 17:51:03 +02:00
assert(from_place < LOCAL_COPY_PLACES);
struct local_copy* local = (struct local_copy*)_places[from_place];
push_back(&local->blob, local->length, local->type);
}
private:
2015-05-19 17:51:03 +02:00
char* _base;
char* _blob;
2015-05-19 17:51:03 +02:00
char* _current;
char* _current_blob;
2015-05-19 17:51:03 +02:00
vector<char*> _vpointer;//pointer on each entry
vector<char*> _vpointer_blob;//pointer on each entry blob
vector<unsigned int> _vlen;// size of each entry in bytes
vector<unsigned int> _vlen_blob;// size of each blob entry in bytes
2015-05-19 17:51:03 +02:00
vector<int> _vtype;//type of each entry
unsigned int _count;// =_vlen.size()=_vpointer.size()=_vtype.size()
unsigned int _total_size;//total allocated size in bytes
unsigned int _total_blob_size;//total allocated blob size in bytes
2015-05-19 17:51:03 +02:00
char _places[LOCAL_COPY_PLACES][LOCAL_COPY_SIZE];
};
//
class heap
{
private:
2015-05-19 17:51:03 +02:00
struct local_var
{
unsigned int length;
int type;
int blob;
};
public:
2015-05-19 17:51:03 +02:00
heap() { }
virtual ~heap()
{
for(map<string, struct local_var*>::iterator i=_map.begin(); i!=_map.end(); i++)
free(i->second);
}
void* add(const string name, void* obj, unsigned int size, int type = 0)
2015-05-19 17:51:03 +02:00
{
struct local_var* blob = _map[name];
if (blob == NULL)
{
2015-02-25 15:38:16 +01:00
//TODO gerer les pbs de memoire
2015-05-19 17:51:03 +02:00
blob = (struct local_var*)malloc(size + sizeof(local_var));
_map[name] = blob;
2015-03-01 16:30:13 +01:00
}
2015-05-19 17:51:03 +02:00
else if (size != blob->length)
{
2015-02-25 15:38:16 +01:00
//TODO gerer les pbs de memoire
2015-05-19 17:51:03 +02:00
blob = (struct local_var*)realloc(blob, size + sizeof(local_var));
_map[name] = blob;
2015-03-01 16:30:13 +01:00
}
2015-05-19 17:51:03 +02:00
blob->length = size;
blob->type= type;
if (obj != NULL)
memcpy(&blob->blob, obj, size);
2015-05-19 17:51:03 +02:00
return (void*)&blob->blob;
}
2015-05-19 17:51:03 +02:00
bool get(const string name, void*& obj, unsigned int& size, int& type)
{
map<string, struct local_var*>::iterator i = _map.find(name);
if (i != _map.end())
{
if (i->second != NULL)
{
obj = &i->second->blob;
size = i->second->length;
type = i->second->type;
}
return true;
}
else
return false;
}
bool exist(const string name)
{
return (_map.find(name) != _map.end());
}
bool get_by_index(int num, string& name, void*& obj, unsigned int& size, int& type)
{
if (num>=0 && num<(int)_map.size())
{
struct local_var* blob;
map<string, struct local_var*>::iterator i=_map.begin();
//TODO moche moche moche
for(int j=0;j<num;j++)
i++;
blob = (struct local_var*)i->second;
assert(blob != NULL);
name = i->first;
obj = &blob->blob;
size = blob->length;
type = blob->type;
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
{
map<string, struct local_var*>::iterator i = _map.find(name);
if (i != _map.end())
{
2015-03-01 16:30:13 +01:00
free(i->second);
2015-05-19 17:51:03 +02:00
_map.erase(i->first);
return true;
}
return false;
}
2015-05-19 17:51:03 +02:00
unsigned int size() { return _map.size(); }
private:
2015-05-19 17:51:03 +02:00
map<string, struct local_var*> _map;
};
#endif // __stack_h__