#include "stdutil.hpp" #include #include #include #include using namespace std; #ifdef MEMDEBUG struct Mem { Mem * next, *prev; const char* file; int line, size, tag; }; static bool track; static Mem head, tail; static Mem x_head, x_tail; static void remove(Mem* m) { m->next->prev = m->prev; m->prev->next = m->next; } static void insert(Mem* m, Mem* next) { m->next = next; m->prev = next->prev; next->prev->next = m; next->prev = m; } static void init() { if (head.next) return; head.next = head.prev = &tail; head.tag = 'HEAD'; tail.next = tail.prev = &head; tail.tag = 'TAIL'; x_head.next = x_head.prev = &x_tail; x_head.tag = 'HEAD'; x_tail.next = x_tail.prev = &x_head; x_tail.tag = 'TAIL'; } static void check(Mem* m) { if (m->tag != 'DNEW') { MessageBox(GetDesktopWindow(), "mem_check: pre_tag!='DNEW'", "Memory error", MB_OK | MB_ICONWARNING); if (m->tag == 'NDWE') { string t = "Probable double delete"; t += "- new file: " + string(m->file) + " line:" + itoa(m->line); MessageBox(GetDesktopWindow(), t.c_str(), "Memory error", MB_OK | MB_ICONWARNING); } ExitProcess(0); } int* t = (int*)((char*)(m + 1) + m->size); if (*t != 'dnew') { MessageBox(GetDesktopWindow(), "mem_check: post_tag!='dnew'", "Memory error", MB_OK | MB_ICONWARNING); string t = "Probable memory overwrite - new file: " + string(m->file) + " line:" + itoa(m->line); MessageBox(GetDesktopWindow(), t.c_str(), "Memory error", MB_OK | MB_ICONWARNING); ExitProcess(0); } } static void* op_new(size_t size, const char* file = "", int line = 0) { init(); Mem* m = (Mem*)malloc(sizeof(Mem) + size + sizeof(int)); memset(m + 1, 0xcc, size); m->file = file; m->line = line; m->size = size; m->tag = 'DNEW'; int* t = (int*)((char*)(m + 1) + size); *t = 'dnew'; if (track) insert(m, head.next); else insert(m, x_head.next); return m + 1; } static void op_delete(void* q) { init(); if (!q) return; Mem* m = (Mem*)q - 1; check(m); remove(m); m->tag = 'NDWE'; *(int*)((char*)(m + 1) + m->size) = 'ndwe'; free(m); } void trackmem(bool enable) { init(); if (track == enable) return; track = enable; Mem* m; while ((m = head.next) != &tail) { remove(m); insert(m, x_head.next); } } void checkmem(ostream& out) { init(); Mem *m, *next; int sum = 0, usum = 0, xsum = 0; for (m = head.next; m != &tail; m = next) { check(m); next = m->next; if (m->line) { out << m->file << " line:" << m->line << " " << m->size << " bytes" << endl; sum += m->size; } else { usum += m->size; } } for (m = x_head.next; m != &x_tail; m = m->next) { check(m); xsum += m->size; } out << "Tracked blitz mem in use:" << sum << endl; out << "Tracked other mem in use:" << usum << endl; out << "Untracked mem in use:" << xsum << endl; out << "Total mem in use:" << (sum + usum + xsum) << endl; } void* _cdecl operator new(size_t size) { return op_new(size); } void* _cdecl operator new[](size_t size) { return op_new(size); } void* _cdecl operator new(size_t size, const char* file, int line) { return op_new(size, file, line); } void* _cdecl operator new[](size_t size, const char* file, int line) { return op_new(size, file, line); } void _cdecl operator delete(void* q) { op_delete(q); } void _cdecl operator delete[](void* q) { op_delete(q); } void _cdecl operator delete(void* q, const char* file, int line) { op_delete(q); } void _cdecl operator delete[](void* q, const char* file, int line) { op_delete(q); } #endif int atoi(const string& s) { return atoi(s.c_str()); } double atof(const string& s) { return atof(s.c_str()); } string itoa(int n) { char buff[32]; _itoa(n, buff, 10); return string(buff); } //static int _finite(double n) { // definition: exponent anything but 2047. // // int e; // 11 bit exponent // const int eMax = 2047; // 0x7ff, all bits = 1 // // int *pn = (int *)&n; // // e = *++pn; // Intel order! // e = (e >> 20) & eMax; // // return e != eMax; //} // //static int _isnan(double n) { // definition: exponent 2047, nonzero fraction. // // int e; // 11 bit exponent // const int eMax = 2047; // 0x7ff, all bits = 1 // // int *pn = (int *)&n; // // e = *++pn; // Intel order! // e = (e >> 20) & eMax; // // if (e != 2047) return 0; // almost always return here // // int fHi, fLo; // 52 bit fraction // // fHi = (*pn) & 0xfffff; // first 20 bits // fLo = *--pn; // last 32 bits // // return (fHi | fLo) != 0; // returns 0,1 not just 0,nonzero //} ///////////// //By FLOYD!// ///////////// string ftoa(float n) { static const int digits = 6; int eNeg = -4, ePos = 8; // limits for e notation. char buffer[50]; // from MSDN example, 25 would probably suffice string t; int dec, sign; if (_finite(n)) { // if ( digits < 1 ) digits = 1; // less than one digit is nonsense // if ( digits > 8 ) digits = 8; // practical maximum for float t = _ecvt(n, digits, &dec, &sign); if (dec <= eNeg + 1 || dec > ePos) { _gcvt(n, digits, buffer); t = buffer; return t; } // Here is the tricky case. We want a nicely formatted // number with no e-notation or multiple trailing zeroes. if (dec <= 0) { t = "0." + string(-dec, '0') + t; dec = 1; // new location for decimal point } else if (dec < digits) { t = t.substr(0, dec) + "." + t.substr(dec); } else { t = t + string(dec - digits, '0') + ".0"; dec += dec - digits; } // Finally, trim off excess zeroes. int dp1 = dec + 1, p = t.length(); while (--p > dp1 && t[p] == '0') ; t = string(t, 0, ++p); return sign ? "-" + t : t; } // end of finite case if (_isnan(n)) return "NaN"; if (n > 0.0) return "Infinity"; if (n < 0.0) return "-Infinity"; abort(); } /* string ftoa( float n ){ static const float min=.000001f,max=9999999.0f; int i=*(int*)&n; int e=(i>>23)&0xff; int f=i&0x007fffff; if( e==0xff && f ) return "NAN"; string t; int s=(i>>31)&0x01; if( e==0xff ){ t="INFINITY"; }else if( !e && !f ){ t="0.000000"; }else if( n>=min && n<=max ){ int dec,sgn; t=_fcvt( fabs(n),6,&dec,&sgn ); if( dec<=0 ){ t="0."+string( -dec,'0' )+t; }else if( dec