#include "dmm.hh"
#ifdef DMM_ONLINE
struct Map_Entry
{
bool is_used;
enum_debug_code debug_code;
int how_many;
Map_Entry()
{
is_used = false;
}
Map_Entry(enum_debug_code debug_code)
{
this->is_used = true;
this->debug_code = debug_code;
this->how_many = 1;
}
};
class Map
{
private:
static const int NUM_ENTRIES = 1000;
int first_free;
Map_Entry entries[NUM_ENTRIES];
public:
Map()
{
first_free = 0;
}
void increment_key(enum_debug_code debug_code)
{
bool found = false;
for (int i=0; i<NUM_ENTRIES; i++) {
if (entries[i].is_used && entries[i].debug_code == debug_code) {
entries[i].how_many++;
found = true;
break;
}
}
if (!found) {
ASSERT(first_free < NUM_ENTRIES);
entries[first_free] = Map_Entry(debug_code);
first_free++;
}
}
private:
#define DCODE_CASE(var) case var: return #var;
const char* debug_decode(enum_debug_code code)
{
switch (code)
{
DCODE_CASE(DCODE_UNKNOWN);
DCODE_CASE(DCODE_BOOL);
DCODE_CASE(DCODE_INT);
DCODE_CASE(DCODE_XYI);
DCODE_CASE(DCODE_XYQ);
DCODE_CASE(DCODE_V3Q);
DCODE_CASE(DCODE_INT_MANUAL);
DCODE_CASE(DCODE_QUICK);
DCODE_CASE(DCODE_STRING);
DCODE_CASE(DCODE_VECTOR_2D_CARTESIAN);
DCODE_CASE(DCODE_LIST);
DCODE_CASE(DCODE_NODE);
DCODE_CASE(DCODE_ARRAY);
DCODE_CASE(DCODE_SPRITE_GRABBER_ACTION);
DCODE_CASE(DCODE_TRI_RANDOM);
DCODE_CASE(DCODE_FOO);
}
return "<Error>";
}
public:
void print()
{
std::cout << "**** BEGIN unfreed memory printout\n";
for (int i=0; i<first_free; i++) {
Map_Entry& me = entries[i];
std::cout << '(';
std::cout << debug_decode(me.debug_code);
std::cout << ' ' << me.how_many << ")\n";
}
std::cout << "**** END unfreed memory printout\n";
}
};
class Debug_Allocator
{
public:
bool is_used;
int address;
Debug_Allocator()
{
this->is_used = false;
this->address = 0;
}
Debug_Allocator(int address)
{
this->is_used = true;
this->address = address;
}
};
const int DEBUG_MEMORY_TABLE_ARRAY_SIZE = 1000 * 1000;
Debug_Allocator debug_memory_table_array[DEBUG_MEMORY_TABLE_ARRAY_SIZE];
void dmm_print_and_exit()
{
std::cout << "**** BEGIN dmm_print_and_exit\n";
Map m;
int total_count = 0;
int unknown_count = 0;
for (int i=0; i<DEBUG_MEMORY_TABLE_ARRAY_SIZE; i++) {
if (debug_memory_table_array[i].is_used) {
total_count++;
int* addr = reinterpret_cast<int*>(debug_memory_table_array[i].address);
int code = *(addr + 1);
enum_debug_code edc = static_cast<enum_debug_code>(code);
#undef DCODE_CASE
#define DCODE_CASE(var) case var: m.increment_key(edc); found = true; break
bool found = false;
switch (edc) {
DCODE_CASE(DCODE_UNKNOWN);
DCODE_CASE(DCODE_INT);
DCODE_CASE(DCODE_BOOL);
DCODE_CASE(DCODE_XYI);
DCODE_CASE(DCODE_XYQ);
DCODE_CASE(DCODE_V3Q);
DCODE_CASE(DCODE_INT_MANUAL);
DCODE_CASE(DCODE_QUICK);
DCODE_CASE(DCODE_STRING);
DCODE_CASE(DCODE_VECTOR_2D_CARTESIAN);
DCODE_CASE(DCODE_LIST);
DCODE_CASE(DCODE_NODE);
DCODE_CASE(DCODE_ARRAY);
DCODE_CASE(DCODE_SPRITE_GRABBER_ACTION);
DCODE_CASE(DCODE_TRI_RANDOM);
DCODE_CASE(DCODE_FOO);
}
if (!found) {
unknown_count++;
}
}
}
int known_count = total_count - unknown_count;
PRINT(unknown_count);
PRINT(known_count);
PRINT(total_count);
PRINT(DEBUG_MEMORY_TABLE_ARRAY_SIZE);
m.print();
std::cout << "**** END dmm_print_and_exit\n";
std::cout << "*** Called exit(EXIT_SUCCESS);\n";
exit(EXIT_SUCCESS);
}
void* operator new (size_t size)
{
void* address = ::malloc(size);
if (address == null) {
std::cout << "*** Bugger memory exhausted\n";
exit(EXIT_FAILURE);
}
bool found = false;
for (int i=0; i<DEBUG_MEMORY_TABLE_ARRAY_SIZE; i++) {
if (!debug_memory_table_array[i].is_used) {
debug_memory_table_array[i] = Debug_Allocator(reinterpret_cast<int>(address));
found = true;
break;
}
}
if (!found) {
std::cout << "debug_memory_table_array is full\n";
exit(EXIT_FAILURE);
}
return address;
}
void operator delete (void* p)
{
if (p == null) {
return;
}
int address = reinterpret_cast<int>(p);
bool found = false;
for (int i=0; i<DEBUG_MEMORY_TABLE_ARRAY_SIZE; i++) {
if (debug_memory_table_array[i].is_used &&
(debug_memory_table_array[i].address == address)) {
debug_memory_table_array[i].is_used = false;
found = true;
break;
}
}
if (!found) {
}
::free(p);
}
#endif