00001
00025 #include <iostream>
00026 #include <malloc.h>
00027 #include <stdlib.h>
00028
00029 #include "magic/mobject.h"
00030 #include "magic/mclass.h"
00031 #include "magic/mmath.h"
00032 #include "magic/mmagisupp.h"
00033 #include "magic/mdatastream.h"
00034
00035 BEGIN_NAMESPACE (MagiC);
00036
00037 decl_module (object);
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 const char nullchar = '\x00';
00048 FILE* dbgout = stderr;
00049
00050 impl_abstract (Object, {})
00051 impl_abstract (Comparable, {Object});
00052 impl_dynamic (Int, {Comparable})
00053
00054
00063 ostream& operator<< (ostream& out, const Object& obj) {
00064 obj >> out;
00065 return out;
00066 }
00067
00068 istream& operator>> (istream& in, Object& obj) {
00069 obj << in;
00070 return in;
00071 }
00072
00074
00075
00076
00077
00078
00079
00080
00082
00083 OStream& operator<< (OStream& out, const Object& obj)
00084 {
00085 obj >> out;
00086 return out;
00087 }
00088
00098 TextOStream& operator<< (TextOStream& out, const Object& obj)
00099 {
00100 obj >> out;
00101 return out;
00102 }
00103
00107 TextIStream& operator>> (TextIStream& in, Object& obj)
00108 {
00109 obj << in;
00110 return in;
00111 }
00112
00119 DataOStream& operator<< (DataOStream& out, const Object& obj)
00120 {
00121 if (out.mFormatMode & DataOStream::FMT_TEXT)
00122 out.printComma ();
00123
00124 out.mDepth++;
00125
00126 if (out.mFormatMode & DataOStream::FMT_RECORD) {
00127
00128
00129
00130 if (out.mDepth==1)
00131 obj >> out;
00132 else
00133 out.mAttribs->add (new String (out.nextName()));
00134 } else {
00135 if (out.mFormatMode & DataOStream::FMT_TEXT) {
00136 if ((out.mFormatMode & DataOStream::FMT_CLASSNAMES) && !isnull (obj.getclass().getname()))
00137 out << obj.getclass().getname();
00138
00139
00140 if (!out.mNextName.isEmpty()) {
00141 out << out.nextName();
00142 out << '=';
00143 out.name ("");
00144 }
00145 out << '{';
00146 }
00147
00148
00149 obj >> out;
00150
00151 if (out.mFormatMode & DataOStream::FMT_TEXT)
00152 out << '}';
00153 }
00154
00155 out.mDepth--;
00156
00157 return out;
00158 }
00159
00166 DataIStream& operator>> (DataIStream& in, Object& obj) {
00167
00168 obj << in;
00169
00170 return in;
00171 }
00172
00174
00175
00176
00177
00178
00179
00180
00182
00192 Object::~Object () {
00193 }
00194
00196 ostream& Object::operator>> (ostream& out) const
00197 {
00198 return out;
00199 }
00200
00202 istream& Object::operator<< (istream& in)
00203 {
00204 return in;
00205 }
00206
00207 OStream& Object::operator>> (OStream& out) const
00208 {
00209 return out;
00210 }
00211
00216 DataOStream& Object::operator>> (DataOStream& out) const
00217 {
00218 return out;
00219 }
00220
00225 DataIStream& Object::operator<< (DataIStream& in)
00226 {
00227 MUST_OVERLOAD;
00228 return in;
00229 }
00230
00233 TextOStream& Object::operator>> (TextOStream& out) const
00234 {
00235 return out;
00236 }
00237
00242 TextIStream& Object::operator<< (TextIStream& in)
00243 {
00244 MUST_OVERLOAD;
00245 return in;
00246 }
00247
00251 Object* Object::clone () const {
00252 MUST_OVERLOAD;
00253 return NULL;
00254 }
00255
00259 void Object::check () const
00260 {
00261 }
00262
00266 bool Object::isOK () const {
00267 try {
00268 check ();
00269 } catch (...) {
00270 return false;
00271 }
00272 return true;
00273 }
00274
00278 const String& Object::getclassname () const
00279 {
00280 return getclass().getname ();
00281 }
00282
00286 int Object::is_a (const String& classname) const
00287 {
00288 return getclass().getname () == classname;
00289 }
00290
00291 bool nextNewIsObject = false;
00292
00293 #ifdef DEBUG_OBJECT_NEW
00294 #ifdef new
00295 #undef new
00296
00308 void* Object::operator new[] (size_t size, const char* filen, int lineno, const char* funcn) {
00309 nextNewIsObject = true;
00310 return ::operator new[] (size, filen, lineno, funcn);
00311 }
00312
00324 void* Object::operator new (size_t size, const char* filen, int lineno, const char* funcn) {
00325 nextNewIsObject = true;
00326 return ::operator new[] (size, filen, lineno, funcn);
00327 }
00328
00333 void* Object::operator new[] (size_t size) {
00334 nextNewIsObject = true;
00335 return ::operator new[] (size, "unknown", -1, "unknown");
00336 }
00337
00342 void* Object::operator new (size_t size) {
00343 nextNewIsObject = true;
00344 return ::operator new[] (size, "unknown", -1, "unknown");
00345 }
00346
00347 #define new DEBUG_NEW
00348 #endif
00349 #endif
00350
00351
00353
00354
00356
00357 int compareComparable (const void* a, const void* b) {
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 return (**(const Comparable**)a).compare ((**(const Comparable**)b));
00368 }
00369
00370
00371
00372
00373
00374
00376
00377 Int::Int (const String& o) {
00378 data = o.toInt();
00379 }
00380
00381 int Int::operator == (const Comparable& o) const {
00382 if (o.is_a ("Int"))
00383 return data==((const Int&)o).data;
00384
00385 return -1;
00386 }
00387
00388
00389
00391
00392
00393
00394 CPPModule::CPPModule (const char* n) {
00395 name = strdup (n);
00396 #ifdef MODULEDEBUG
00397 printf ("Module %s loading...\n", name);
00398 #endif
00399 }
00400
00401
00402
00403
00404 int rnd (int range) {
00405 return (int) (double(range)*rand()/(RAND_MAX+1.0));
00406 }
00407
00408 double frnd () {
00409 return rand()/(RAND_MAX+1.0);
00410 }
00411
00412 double gaussrnd (double stdv) {
00413 if (stdv>0.0) {
00414 double r = rand()/(RAND_MAX+1.0)-0.5;
00415 return stdv * log ((r+0.5)/(0.5-r));
00416 }
00417 return 0.0;
00418 }
00419
00420
00421
00422 Exception::Exception (const String& what_arg) : mWhat (new String (what_arg)) {
00423 }
00424
00425 Exception::Exception (const Exception& orig) : mWhat (new String (*orig.mWhat)) {
00426 }
00427
00428 Exception::~Exception () {
00429 delete mWhat;
00430 }
00431
00432
00434
00435
00436
00437
00438
00439
00440
00442
00443 int assertmode=ASSERT_THROW;
00444
00447 void assertwith (const char* filename,
00448 int lineno,
00449 const char* funcname,
00450 const char* condition,
00451 const char* message)
00452 {
00453 String errormsg = strformat("Condition '%s' violated at %s[%d]: %s()",
00454 condition, filename, lineno, funcname);
00455
00456 if (message)
00457 errormsg += strformat ("\n%%ERR: %s", message);
00458
00459 switch (assertmode) {
00460 case ASSERT_CRASH:
00461 fprintf (stderr, "\n%%ERR: %s\n", (CONSTR) errormsg);
00462 fprintf (stderr, "%%ERR: Intentional assertion crash. "
00463 "I hope you are under debugger now...\n");
00464 *((int*)NULL) = 1;
00465 break;
00466 case ASSERT_EXIT:
00467 fprintf (stderr, "\n%%ERR: %s\n", (CONSTR) errormsg);
00468 exit (1);
00469 break;
00470 case ASSERT_DONTCARE:
00471 fprintf (stderr, "\n%%ERR: %s\n", (CONSTR) errormsg);
00472 break;
00473 case ASSERT_THROW:
00474 default:
00475 throw assertion_failed (format ("%s", (CONSTR)errormsg));
00476 };
00477 }
00478
00479
00480
00489
00490 #ifndef DISABLE_ALL_MEMORY_DEBUGGING
00491 #ifdef new
00492 #undef new
00493 #endif
00494 #warning "Memory debugging enabled"
00495
00496 int dbgnewmalloced=0;
00497 mallocinfostr* lastmalloced=NULL;
00498 int newtrace_disabled = 1;
00499 char* newcomment=NULL;
00500
00501 void newComment (const char* comment) {
00502 if (newcomment)
00503 free (newcomment);
00504 newcomment = strdup(comment);
00505 }
00506
00507
00508 void* operator new[] (size_t size, const char* filename, int lineno, const char* fname)
00509 {
00510
00511
00512 if (newtrace_disabled) {
00513 void* res = malloc(size);
00514 if (!res)
00515 *((char*)0x0)=0;
00516 return res;
00517 }
00518
00519
00520 mallocinfostr* p = (mallocinfostr*) malloc (size+sizeof(mallocinfostr));
00521 if (!p)
00522 *((char*)0x0)=0;
00523
00524 strcpy (p->startsym, "MiS_S");
00525 p->size = size;
00526 p->filename = filename;
00527 p->lineno = lineno;
00528 p->funcname = fname;
00529 p->newcomment = newcomment? newcomment : NULL;
00530 newcomment = NULL;
00531 p->renewed = false;
00532 p->isObject = nextNewIsObject;
00533 nextNewIsObject = false;
00534 p->prev = lastmalloced;
00535 p->next = NULL;
00536 if (p->prev)
00537 p->prev->next = p;
00538 lastmalloced = p;
00539
00540
00541 memset (((char*)p)+sizeof (mallocinfostr), '\xcc', p->size);
00542
00543
00544 dbgnewmalloced += size + sizeof(mallocinfostr);
00545 return ((char*)p)+sizeof (mallocinfostr);
00546 }
00547
00548 void* operator new (size_t size, const char* filename, int lineno, const char* fname) {
00549 return operator new[] (size, filename, lineno, fname);
00550 }
00551
00552 void* _renew (void* p, size_t newsize, const char* filename, int lineno, const char* fname) {
00553 if (memcmp (((char*)p)-sizeof(mallocinfostr), "MiS_S", 5) || newtrace_disabled) {
00554 void* res = realloc ((char*) p, newsize);
00555
00556 if (!res)
00557 *((char*)0x0)=0;
00558 return res;
00559 } else {
00560
00561 mallocinfostr* np = (mallocinfostr*) realloc (((char*)p)-sizeof(mallocinfostr),
00562 newsize+sizeof(mallocinfostr));
00563
00564 if (!np)
00565 *((char*)0x0)=0;
00566
00567 dbgnewmalloced -= np->size;
00568 np->size = newsize;
00569 np->filename = filename;
00570 np->lineno = lineno;
00571 np->funcname = fname;
00572 if (newcomment) {
00573 free (np->newcomment);
00574 np->newcomment = newcomment;
00575 newcomment = NULL;
00576 }
00577 np->renewed = true;
00578 if (np->prev)
00579 np->prev->next = np;
00580 if (np->next)
00581 np->next->prev = np;
00582 if ((void*) (((char*)p)-sizeof(mallocinfostr)) == (void*) lastmalloced)
00583 lastmalloced = np;
00584 dbgnewmalloced += newsize;
00585 return ((char*)np)+sizeof (mallocinfostr);
00586 }
00587 }
00588
00589 void operator delete (void* p) {
00590 if (p) {
00591 if (memcmp (((char*)p)-sizeof(mallocinfostr), "MiS_S", 5)) {
00592 free (p);
00593 } else {
00594 mallocinfostr* mp=(mallocinfostr*)(((char*)p)-sizeof(mallocinfostr));
00595
00596 if (mp->next)
00597 mp->next->prev = mp->prev;
00598 if (mp->prev)
00599 mp->prev->next = mp->next;
00600 if (mp == lastmalloced)
00601 if (mp->next)
00602 while (lastmalloced->next)
00603 lastmalloced=lastmalloced->next;
00604 else
00605 lastmalloced = mp->prev;
00606 if (mp->newcomment)
00607 free (mp->newcomment);
00608 dbgnewmalloced -= mp->size + sizeof (mallocinfostr);
00609
00610
00611 memset (mp, '\xdd', mp->size + sizeof (mallocinfostr));
00612
00613 free (mp);
00614 }
00615 }
00616 }
00617
00618
00619
00620 void list_allocations (int number, FILE* out) {
00621 fprintf (out, "Dumping all reserved memory blocks:\n");
00622 int i=0;
00623 for (mallocinfostr* p=lastmalloced; p && (number==0 || i<number); p=p->prev, i++) {
00624 fprintf (out, "%9d bytes (%8x) %s at %s#%d %s",
00625 p->size, (char*) (((char*)p) + sizeof (mallocinfostr)),
00626 (p->renewed)? "renewed ":"allocated",
00627 p->filename, p->lineno, p->funcname);
00628 if (p->isObject) {
00629 Object* op = (Object*)(void*)(((char*)p)+sizeof(mallocinfostr));
00630 fprintf (out, " (%s)", (CONSTR) op->getclassname());
00631 }
00632 if (p->newcomment)
00633 fprintf (out, " : \042%s\042", (CONSTR) p->newcomment);
00634 fprintf (out, "\n");
00635 }
00636 if (number>0 && i>=number)
00637 fprintf (out, "** Only %d first items listed\n", number);
00638 fprintf (out, "Total amount of memory allocated: %d "
00639 "(including the DEBUG_NEW overhead)\n", dbgnewmalloced);
00640 }
00641
00642 #endif
00643
00644 END_NAMESPACE;
00645