Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

mobject.cc

Go to the documentation of this file.
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 //- Standard object.hierarchy<BR>
00040 //- Käytetty seuraavissa käyttöympäristöissä, vaikkakaan yhteensopivuus
00041 //- ei välttämättä ole täysin ajan tasalla:
00042 //-      MSDOS Borland C++ 3.0
00043 //-      Unix gcc 2.7.0 C++ (Solaris, Linux)
00044 //-      Unix egcs C++ (Solaris, Linux)
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 //  ----                                            | o                     o            //
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++; // Grow indentation depth
00125 
00126     if (out.mFormatMode & DataOStream::FMT_RECORD) {
00127         // With FMT_RECORD, we do not actually print anything,
00128         // but just store the attributes.
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             //      , out.print ("::");
00139 
00140             if (!out.mNextName.isEmpty()) {
00141                 out << out.nextName();
00142                 out << '=';
00143                 out.name ("");  // NULL originally, but causes ambiquity with some compilers
00144             }
00145             out << '{';
00146         }
00147 
00148         // Let the object output its members, recursively.
00149         obj >> out;
00150 
00151         if (out.mFormatMode & DataOStream::FMT_TEXT)
00152             out << '}';
00153     }
00154     
00155     out.mDepth--; // Lesser indentation depth
00156 
00157     return out;
00158 }
00159 
00166 DataIStream& operator>> (DataIStream& in, Object& obj) {
00167     // in.depth++;
00168     obj << in;
00169     // in.depth--;
00170     return in;
00171 }
00172 
00174 //                                                                           //
00175 //                       ___          o                                      //
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       // :WEIRDNESS: The code below crashes... What's the difference
00360       ASSERT (a);
00361       ASSERT (b);
00362       const Comparable& ac = *static_cast<const Comparable*> (a);
00363       const Comparable& bc = *static_cast<const Comparable*> (b);
00364       return ac.compare (bc);
00365       */
00366 
00367     return (**(const Comparable**)a).compare ((**(const Comparable**)b));
00368 }
00369 /*
00370 int compareComparable   (const void* a, const void* b) {
00371     return (**(const Comparable**)a).compare ((**(const Comparable**)b));
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; // Undefined value. Should we throw an exception?
00386 }
00387 
00388 
00389 
00391 // Apufunktioita
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 // From mmagisupp.h
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 //              _                             o                             //
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; // So you're under debugger. Ok, now just backtrace
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     // fprintf (stderr, "filename=%s, lineno=%d, fname=%s\n", filename, lineno, fname);
00511 
00512     if (newtrace_disabled) {
00513         void* res = malloc(size);
00514         if (!res)
00515             *((char*)0x0)=0;
00516         return res;
00517     }
00518 
00519     // Reserve the memory block PLUS space for the info structure
00520     mallocinfostr* p = (mallocinfostr*) malloc (size+sizeof(mallocinfostr));
00521     if (!p)
00522         *((char*)0x0)=0;
00523 
00524     strcpy (p->startsym, "MiS_S");  // Set a recognition label
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     // Fill with 0x00
00541     memset (((char*)p)+sizeof (mallocinfostr), '\xcc', p->size);
00542 
00543     // Add to global counter
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         // Again, should not be null
00556         if (!res)
00557             *((char*)0x0)=0;
00558         return res;
00559     } else {
00560         // Realloc the memory block PLUS space for the info structure
00561         mallocinfostr* np = (mallocinfostr*) realloc (((char*)p)-sizeof(mallocinfostr),
00562                                                       newsize+sizeof(mallocinfostr));
00563         // Again, should not be null
00564         if (!np)
00565             *((char*)0x0)=0;
00566         
00567         dbgnewmalloced -= np->size; // Substract old size from total size register
00568         np->size = newsize;         // Refresh
00569         np->filename = filename;    // Refresh
00570         np->lineno = lineno;        // Refresh
00571         np->funcname = fname;       // Refresh
00572         if (newcomment) {           // Refresh
00573             free (np->newcomment);
00574             np->newcomment = newcomment;
00575             newcomment = NULL;
00576         }
00577         np->renewed = true;         // Now we have been renewed
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;  // Add new size to total size register
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); // Allocated with ordinary malloc or new
00593         } else {
00594             mallocinfostr* mp=(mallocinfostr*)(((char*)p)-sizeof(mallocinfostr));
00595             //TRACE3 ("%d, %s, %d", mp->size, mp->filename, mp->lineno);
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             // Fill the block with 0xdd
00611             memset (mp, '\xdd', mp->size + sizeof (mallocinfostr));
00612 
00613             free (mp);
00614         }
00615     }
00616 }
00617 
00618 // int listAllocationsLimit=100;
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 

Generated on Thu Feb 10 20:06:42 2005 for LibMagiC by doxygen1.2.18