object.h

Go to the documentation of this file.
00001 /*
00002  * object.h
00003  *
00004  * Mother of all ancestor classes.
00005  *
00006  * Portable Tools Library
00007  *
00008  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Portable Windows Library.
00021  *
00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00023  *
00024  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
00025  * All Rights Reserved.
00026  *
00027  * Contributor(s): ______________________________________.
00028  *
00029  * $Revision: 22742 $
00030  * $Author: rjongbloed $
00031  * $Date: 2009-05-27 19:13:15 -0500 (Wed, 27 May 2009) $
00032  */
00033 
00034 #ifndef PTLIB_OBJECT_H
00035 #define PTLIB_OBJECT_H
00036 
00037 #ifdef P_USE_PRAGMA
00038 #pragma interface
00039 #endif
00040 
00041 #if defined(_WIN32) || defined(_WIN32_WCE)
00042 #include "msos/ptlib/contain.h"
00043 #else
00044 #include "unix/ptlib/contain.h"
00045 #endif
00046 
00047 #if defined(P_VXWORKS)
00048 #include <private/stdiop.h>
00049 #endif
00050 
00051 #include <stdio.h>
00052 #include <stdarg.h>
00053 #include <stdlib.h>
00054 
00055 #include <string.h>
00056 
00057 #include <string>
00058 #include <iomanip>
00059 #include <iostream>
00060 #include <sstream>
00061 
00062 
00063 #define P_REMOVE_VIRTUAL_INTERNAL_BASE(fn) __inline virtual struct ptlib_virtual_function_changed_or_removed ****** fn { return 0; }
00064 
00065 #if defined(_MSC_VER)
00066   #if _MSC_VER < 1310
00067     #define P_DEPRECATED
00068     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
00069   #elif _MSC_VER < 1400
00070     #define P_DEPRECATED __declspec(deprecated)
00071     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated) type fn body
00072   #else
00073     #define P_DEPRECATED __declspec(deprecated)
00074     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated("Virtual function signature changed or function deprecated")) type fn body
00075   #endif
00076 #elif defined(__GNUC__)
00077   #if __GNUC__ < 4
00078     #define P_DEPRECATED
00079     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
00080   #else
00081     #define P_DEPRECATED __attribute__((deprecated))
00082     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __attribute__((warn_unused_result)) __attribute__((deprecated)) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
00083   #endif
00084 #else
00085     #define P_DEPRECATED
00086     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
00087 #endif
00088 
00089 #define P_REMOVE_VIRTUAL_VOID(fn)       P_REMOVE_VIRTUAL_INTERNAL(void, fn, {})
00090 #define P_REMOVE_VIRTUAL(type, fn, ret) P_REMOVE_VIRTUAL_INTERNAL(type, fn, { return ret; })
00091 
00092 
00093 // P_USE_INTEGER_BOOL is the default and gives the old behaviour (it
00094 // is also used for C translation units).
00095 // without P_USE_INTEGER_BOOL, the ANSI C++ bool is used.
00096 
00097 #if defined(P_USE_INTEGER_BOOL) || !defined(__cplusplus)
00098    typedef BOOL PBoolean;
00099 #  define PTrue TRUE
00100 #  define PFalse FALSE
00101 #else
00102    typedef bool PBoolean;
00103 #  define PTrue true
00104 #  define PFalse false
00105 #endif
00106 
00107 
00109 // Disable inlines when debugging for faster compiles (the compiler doesn't
00110 // actually inline the function with debug on any way).
00111 
00112 #ifndef P_USE_INLINES
00113 #ifdef _DEBUG
00114 #define P_USE_INLINES 0
00115 #else
00116 #define P_USE_INLINES 0
00117 #endif
00118 #endif
00119 
00120 #if P_USE_INLINES
00121 #define PINLINE inline
00122 #else
00123 #define PINLINE
00124 #endif
00125 
00126 
00128 // Declare the debugging support
00129 
00130 #ifndef P_USE_ASSERTS
00131 #define P_USE_ASSERTS 1
00132 #endif
00133 
00134 #if !P_USE_ASSERTS
00135 
00136 #define PAssert(b, m) (b)
00137 #define PAssert2(b, c, m) (b)
00138 #define PAssertOS(b) (b)
00139 #define PAssertNULL(p) (p)
00140 #define PAssertAlways(m) {}
00141 #define PAssertAlways2(c, m) {}
00142 
00143 #else // P_USE_ASSERTS
00144 
00146 enum PStandardAssertMessage {
00147   PLogicError,              
00148   POutOfMemory,             
00149   PNullPointerReference,    
00150   PInvalidCast,             
00151   PInvalidArrayIndex,       
00152   PInvalidArrayElement,     
00153   PStackEmpty,              
00154   PUnimplementedFunction,   
00155   PInvalidParameter,        
00156   POperatingSystemError,    
00157   PChannelNotOpen,          
00158   PUnsupportedFeature,      
00159   PInvalidWindow,           
00160   PMaxStandardAssertMessage 
00161 };
00162 
00163 #define __CLASS__ NULL
00164 
00165 void PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
00166 void PAssertFunc(const char * file, int line, const char * className, const char * msg);
00167 void PAssertFunc(const char * full_msg);
00168 
00169 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, PStandardAssertMessage msg)
00170 {
00171   if (!b) 
00172     PAssertFunc(file, line, className, msg);
00173   return b;
00174 }
00175 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, const char * msg)
00176 {
00177   if (!b) 
00178     PAssertFunc(file, line, className, msg);
00179   return b;
00180 }
00181 
00188 #define PAssert(b, m) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,(m))
00189 
00197 #define PAssert2(b, c, m) PAssertFuncInline((b), __FILE__,__LINE__,(c),(m))
00198 
00205 #define PAssertOS(b) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,POperatingSystemError)
00206 
00216 #define PAssertNULL(p) (((p)!=NULL)?(p): \
00217                      (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(p)))
00218 
00225 #define PAssertAlways(m) PAssertFunc(__FILE__,__LINE__,__CLASS__,(m))
00226 
00233 #define PAssertAlways2(c, m) PAssertFunc(__FILE__,__LINE__,(c),(m))
00234 
00235 #endif // P_USE_ASSERTS
00236 
00237 
00242 ostream & PGetErrorStream();
00243 
00247 void PSetErrorStream(ostream * strm  );
00248 
00263 #define PError (PGetErrorStream())
00264 
00265 
00266 
00268 // Debug and tracing
00269 
00270 #ifndef PTRACING
00271 #define PTRACING 1
00272 #endif
00273 
00274 #if PTRACING
00275 
00280 class PTrace
00281 {
00282 public:
00284   enum Options {
00290     Blocks = 1,
00292     DateAndTime = 2,
00294     Timestamp = 4,
00296     Thread = 8,
00298     TraceLevel = 16,
00300     FileAndLine = 32,
00302     ThreadAddress = 64,
00304     AppendToFile = 128,
00307     GMTTime = 256,
00310     RotateDaily = 512,
00311     RotateHourly = 1024,
00312     RotateMinutely = 2048,
00313     RotateLogMask = RotateDaily + RotateHourly + RotateMinutely,
00317     SystemLogStream = 32768
00318   };
00319 
00320 
00328   static void Initialise(
00329     unsigned level,
00330     const char * filename = NULL,
00331     unsigned options = Timestamp | Thread | Blocks
00332   );
00333 
00344   static void Initialise(
00345     unsigned level,
00346     const char * filename,
00347     const char * rolloverPattern,
00348     unsigned options = Timestamp | Thread | Blocks
00349   );
00350 
00357   static void SetOptions(unsigned options  );
00358 
00366   static void ClearOptions(unsigned options  );
00367 
00372   static unsigned GetOptions();
00373 
00379   static void SetLevel(unsigned level  );
00380 
00386   static unsigned GetLevel();
00387 
00392   static PBoolean CanTrace(unsigned level );
00393 
00398   static void SetStream(ostream * out  );
00399 
00415   static ostream & Begin(
00416     unsigned level,         
00417     const char * fileName,  
00418     int lineNum             
00419   );
00420 
00437   static ostream & End(ostream & strm );
00438 
00442   static void Cleanup();
00443 
00449   class Block {
00450     public:
00452       Block(
00453         const char * fileName, 
00454         int lineNum,           
00455         const char * traceName
00457        );
00458       Block(const Block & obj)
00459         : file(obj.file), line(obj.line), name(obj.name) { }
00461       ~Block();
00462     private:
00463       Block & operator=(const Block &)
00464       { return *this; }
00465       const char * file;
00466       int          line;
00467       const char * name;
00468   };
00469 };
00470 
00471 /* Macro to conditionally declare a parameter to a function to avoid compiler
00472    warning due that parameter only being used in a #PTRACE */
00473 #define PTRACE_PARAM(param) param
00474 
00481 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
00482 
00486 #define PTRACE_LINE() \
00487     if (PTrace::CanTrace(1)) \
00488       PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
00489     else (void)0
00490 
00496 #define PTRACE(level, args) \
00497     if (PTrace::CanTrace(level)) \
00498       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00499     else (void)0
00500 
00508 #define PTRACE_IF(level, cond, args) \
00509     if ((PTrace::CanTrace(level) && (cond))) \
00510       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00511     else (void)0
00512 
00513 #else // PTRACING
00514 
00515 #define PTRACE_PARAM(param)
00516 #define PTRACE_BLOCK(n)
00517 #define PTRACE_LINE()
00518 #define PTRACE(level, arg)
00519 #define PTRACE_IF(level, cond, args)
00520 
00521 #endif // PTRACING
00522 
00523 
00524 
00525 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE)) 
00526 
00527 #define PMEMORY_HEAP 1
00528 
00535 class PMemoryHeap {
00536   public:
00538     PMemoryHeap();
00539 
00540     // Clear up the memory checking subsystem, dumping memory leaks.
00541     ~PMemoryHeap();
00542 
00549     static void * Allocate(
00550       size_t nSize,           
00551       const char * file,      
00552       int line,               
00553       const char * className  
00554     );
00561     static void * Allocate(
00562       size_t count,       
00563       size_t iSize,       
00564       const char * file,  
00565       int line            
00566     );
00567 
00575     static void * Reallocate(
00576       void * ptr,         
00577       size_t nSize,       
00578       const char * file,  
00579       int line            
00580     );
00581 
00587     static void Deallocate(
00588       void * ptr,             
00589       const char * className  
00590     );
00591 
00594     enum Validation {
00595       Ok, Bad, Trashed
00596     };
00604     static Validation Validate(
00605       const void * ptr,       
00606       const char * className, 
00607       ostream * error         
00608     );
00609 
00614     static PBoolean ValidateHeap(
00615       ostream * error = NULL  
00616     );
00617 
00623     static PBoolean SetIgnoreAllocations(
00624       PBoolean ignore  
00625     );
00626 
00630     static void DumpStatistics();
00634     static void DumpStatistics(ostream & strm );
00635 
00636 #if PMEMORY_CHECK
00637     struct State {
00638       DWORD allocationNumber;
00639     };
00640 #else
00641         typedef _CrtMemState State;
00642 #endif
00643 
00644     /* Get memory state.
00645       This returns a state that may be used to determine where to start dumping
00646       objects from.
00647      */
00648     static void GetState(
00649       State & state  
00650     );
00651 
00659     static void DumpObjectsSince(
00660       const State & when    
00661     );
00662 
00668     static void DumpObjectsSince(
00669       const State & when,   
00670       ostream & strm        
00671     );
00672 
00678     static void SetAllocationBreakpoint(
00679       DWORD point   
00680     );
00681 
00682 #if PMEMORY_CHECK
00683 
00684   protected:
00685     void * InternalAllocate(
00686       size_t nSize,           // Number of bytes to allocate.
00687       const char * file,      // Source file name for allocating function.
00688       int line,               // Source file line for allocating function.
00689       const char * className  // Class name for allocating function.
00690     );
00691     Validation InternalValidate(
00692       const void * ptr,       // Pointer to memory block to check
00693       const char * className, // Class name it should be.
00694       ostream * error         // Stream to receive error message (may be NULL)
00695     );
00696     void InternalDumpStatistics(ostream & strm);
00697     void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
00698 
00699     class Wrapper {
00700       public:
00701         Wrapper();
00702         ~Wrapper();
00703         PMemoryHeap * operator->() const { return instance; }
00704       private:
00705         PMemoryHeap * instance;
00706     };
00707     friend class Wrapper;
00708 
00709     enum Flags {
00710       NoLeakPrint = 1
00711     };
00712 
00713 #pragma pack(1)
00714     struct Header {
00715       enum {
00716         // Assure that the Header struct is aligned to 8 byte boundary
00717         NumGuardBytes = 16 - (sizeof(Header *) +
00718                               sizeof(Header *) +
00719                               sizeof(const char *) +
00720                               sizeof(const char *) +
00721                               sizeof(size_t) +
00722                               sizeof(DWORD) +
00723                               sizeof(WORD) +
00724                               sizeof(BYTE)
00725 #ifdef P_LINUX
00726                               + sizeof(pthread_t)
00727 #endif
00728                               )%8
00729       };
00730 
00731       Header     * prev;
00732       Header     * next;
00733       const char * className;
00734       const char * fileName;
00735       size_t       size;
00736       DWORD        request;
00737       WORD         line;
00738       BYTE         flags;
00739 #ifdef P_LINUX
00740       pthread_t    thread;
00741 #endif
00742       char         guard[NumGuardBytes];
00743 
00744       static char GuardBytes[NumGuardBytes];
00745     };
00746 #pragma pack()
00747 
00748     PBoolean isDestroyed;
00749 
00750     Header * listHead;
00751     Header * listTail;
00752 
00753     static DWORD allocationBreakpoint;
00754     DWORD allocationRequest;
00755     DWORD firstRealObject;
00756     BYTE  flags;
00757 
00758     char  allocFillChar;
00759     char  freeFillChar;
00760 
00761     DWORD currentMemoryUsage;
00762     DWORD peakMemoryUsage;
00763     DWORD currentObjects;
00764     DWORD peakObjects;
00765     DWORD totalObjects;
00766 
00767     ostream * leakDumpStream;
00768 
00769 #if defined(_WIN32)
00770     CRITICAL_SECTION mutex;
00771 #elif defined(P_PTHREADS)
00772     pthread_mutex_t mutex;
00773 #elif defined(P_VXWORKS)
00774     void * mutex;
00775 #endif
00776 
00777 #else
00778 
00779 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
00780     _CrtMemState initialState;
00781 
00782 #endif // PMEMORY_CHECK
00783 };
00784 
00785 
00790 inline void * runtime_malloc(size_t bytes  ) { return malloc(bytes); }
00791 
00796 inline void runtime_free(void * ptr  ) { free(ptr); }
00797 
00798 
00805 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
00806 
00813 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
00814 
00821 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
00822 
00823 
00830 #define free(p) PMemoryHeap::Deallocate(p, NULL)
00831 
00832 
00839 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
00840 
00841 
00856 #define PNEW  new (__FILE__, __LINE__)
00857 
00858 #if !defined(_MSC_VER) || _MSC_VER<1200
00859 #define PSPECIAL_DELETE_FUNCTION
00860 #else
00861 #define PSPECIAL_DELETE_FUNCTION \
00862     void operator delete(void * ptr, const char *, int) \
00863       { PMemoryHeap::Deallocate(ptr, Class()); } \
00864     void operator delete[](void * ptr, const char *, int) \
00865       { PMemoryHeap::Deallocate(ptr, Class()); }
00866 #endif
00867 
00868 #define PNEW_AND_DELETE_FUNCTIONS \
00869     void * operator new(size_t nSize, const char * file, int line) \
00870       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00871     void * operator new(size_t nSize) \
00872       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00873     void operator delete(void * ptr) \
00874       { PMemoryHeap::Deallocate(ptr, Class()); } \
00875     void * operator new(size_t, void * placement) \
00876       { return placement; } \
00877     void operator delete(void *, void *) \
00878       { } \
00879     void * operator new[](size_t nSize, const char * file, int line) \
00880       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00881     void * operator new[](size_t nSize) \
00882       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00883     void operator delete[](void * ptr) \
00884       { PMemoryHeap::Deallocate(ptr, Class()); } \
00885     PSPECIAL_DELETE_FUNCTION
00886 
00887 
00888 inline void * operator new(size_t nSize, const char * file, int line)
00889   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00890 
00891 inline void * operator new[](size_t nSize, const char * file, int line)
00892   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00893 
00894 #ifndef __GNUC__
00895 void * operator new(size_t nSize);
00896 void * operator new[](size_t nSize);
00897 
00898 void operator delete(void * ptr);
00899 void operator delete[](void * ptr);
00900 
00901 #if defined(_MSC_VER) && _MSC_VER>=1200
00902 inline void operator delete(void * ptr, const char *, int)
00903   { PMemoryHeap::Deallocate(ptr, NULL); }
00904 
00905 inline void operator delete[](void * ptr, const char *, int)
00906   { PMemoryHeap::Deallocate(ptr, NULL); }
00907 #endif
00908 #endif
00909 
00910 
00911 class PMemoryHeapIgnoreAllocationsForScope {
00912 public:
00913   PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(PTrue)) { }
00914   ~PMemoryHeapIgnoreAllocationsForScope() { PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations); }
00915 private:
00916   PBoolean previousIgnoreAllocations;
00917 };
00918 
00919 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
00920 
00921 class PMemoryAllocationBreakpoint {
00922 public:
00923   PMemoryAllocationBreakpoint(DWORD point)
00924   {
00925     PMemoryHeap::SetAllocationBreakpoint(point);
00926   }
00927 };
00928 
00929 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
00930 
00931 
00932 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00933 
00934 #define PMEMORY_HEAP 0
00935 
00936 #define PNEW new
00937 
00938 #define PNEW_AND_DELETE_FUNCTIONS
00939 
00940 #define runtime_malloc(s) malloc(s)
00941 #define runtime_free(p) free(p)
00942 
00943 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
00944 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
00945 
00946 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00947 
00948 
00959 #define PCLASSINFO(cls, par) \
00960   public: \
00961     static inline const char * Class() \
00962       { return #cls; } \
00963     virtual PBoolean InternalIsDescendant(const char * clsName) const \
00964       { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
00965     virtual const char * GetClass(unsigned ancestor = 0) const \
00966       { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
00967     virtual Comparison CompareObjectMemoryDirect(const PObject & _obj) const \
00968       { return (Comparison)memcmp(this, &_obj, sizeof(cls)); } \
00969     PNEW_AND_DELETE_FUNCTIONS
00970 
00971 
00972 #if P_HAS_TYPEINFO
00973 
00974 #define PIsDescendant(ptr, cls)    (dynamic_cast<const cls *>(ptr) != NULL) 
00975 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str)) 
00976 
00977 #define PRemoveConst(cls, ptr)  (const_cast<cls*>(ptr))
00978 
00979 #if P_USE_ASSERTS
00980 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line) 
00981   { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
00982 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
00983 #else
00984 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
00985 #endif
00986 
00987 #include <typeinfo>
00988 
00989 #else // P_HAS_TYPEINFO
00990 
00991 #define PIsDescendant(ptr, cls)    ((ptr)->InternalIsDescendant(cls::Class()))
00992 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
00993 
00994 #define PRemoveConst(cls, ptr)  ((cls*)(ptr))
00995 
00996 #if P_USE_ASSERTS
00997 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line) 
00998   { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
00999 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
01000 #else
01001 #define PDownCast(cls, ptr) ((cls*)(ptr))
01002 #endif
01003 
01004 #endif // P_HAS_TYPEINFO
01005 
01006 
01015 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
01016 #ifdef DOC_PLUS_PLUS
01017 } Match previous opening brace in doc++
01018 #endif
01019 
01021 // The root of all evil ... umm classes
01022 
01027 class PObject {
01028 
01029   protected:
01033     PObject() { }
01034 
01035   public:
01036     /* Destructor required to get the "virtual". A PObject really has nothing
01037        to destroy.
01038      */
01039     virtual ~PObject() { }
01040 
01053     static inline const char * Class()    { return "PObject"; }
01054 
01067     virtual const char * GetClass(unsigned /*ancestor*/ = 0) const { return Class(); }
01068 
01069     PBoolean IsClass(const char * cls) const 
01070     { return strcmp(cls, GetClass()) == 0; }
01071 
01081     virtual PBoolean InternalIsDescendant(
01082       const char * clsName    // Ancestor class name to compare against.
01083     ) const
01084     { return IsClass(clsName); }
01085 
01087 
01093     enum Comparison {
01094       LessThan = -1,
01095       EqualTo = 0,
01096       GreaterThan = 1
01097     };
01098 
01110     virtual Comparison Compare(
01111       const PObject & obj   // Object to compare against.
01112     ) const;
01113     
01125     virtual Comparison CompareObjectMemoryDirect(
01126       const PObject & obj   // Object to compare against.
01127     ) const;
01128 
01134     bool operator==(
01135       const PObject & obj   // Object to compare against.
01136     ) const { return Compare(obj) == EqualTo; }
01137 
01143     bool operator!=(
01144       const PObject & obj   // Object to compare against.
01145     ) const { return Compare(obj) != EqualTo; }
01146 
01152     bool operator<(
01153       const PObject & obj   // Object to compare against.
01154     ) const { return Compare(obj) == LessThan; }
01155 
01161     bool operator>(
01162       const PObject & obj   // Object to compare against.
01163     ) const { return Compare(obj) == GreaterThan; }
01164 
01170     bool operator<=(
01171       const PObject & obj   // Object to compare against.
01172     ) const { return Compare(obj) != GreaterThan; }
01173 
01179     bool operator>=(
01180       const PObject & obj   // Object to compare against.
01181     ) const { return Compare(obj) != LessThan; }
01183 
01192     virtual void PrintOn(
01193       ostream &strm   // Stream to print the object into.
01194     ) const;
01195 
01202     virtual void ReadFrom(
01203       istream &strm   // Stream to read the objects contents from.
01204     );
01205 
01206 
01212     inline friend ostream & operator<<(
01213       ostream &strm,       // Stream to print the object into.
01214       const PObject & obj  // Object to print to the stream.
01215     ) { obj.PrintOn(strm); return strm; }
01216 
01222     inline friend istream & operator>>(
01223       istream &strm,   // Stream to read the objects contents from.
01224       PObject & obj    // Object to read inormation into.
01225     ) { obj.ReadFrom(strm); return strm; }
01226 
01227 
01242     virtual PObject * Clone() const;
01243 
01255     virtual PINDEX HashFunction() const;
01257 };
01258 
01260 // Platform independent types
01261 
01262 // All these classes encapsulate primitive types such that they may be
01263 // transfered in a platform independent manner. In particular it is used to
01264 // do byte swapping for little endien and big endien processor architectures
01265 // as well as accommodating structure packing rules for memory structures.
01266 
01267 #define PANSI_CHAR 1
01268 #define PLITTLE_ENDIAN 2
01269 #define PBIG_ENDIAN 3
01270 
01271 
01272 #if 0
01273 class PStandardType
01274 /* Encapsulate a standard 8 bit character into a portable format. This would
01275    rarely need to do translation, only if the target platform uses EBCDIC
01276    would it do anything.
01277 
01278    The platform independent form here is always 8 bit ANSI.
01279  */
01280 {
01281   public:
01282     PStandardType(
01283       type newVal   // Value to initialise data in platform dependent form.
01284     ) { data = newVal; }
01285     /* Create a new instance of the platform independent type using platform
01286        dependent data, or platform independent streams.
01287      */
01288 
01289     operator type() { return data; }
01290     /* Get the platform dependent value for the type.
01291 
01292        @return
01293        data for instance.
01294      */
01295 
01296     friend ostream & operator<<(ostream & strm, const PStandardType & val)
01297       { return strm << (type)val; }
01298     /* Output the platform dependent value for the type to the stream.
01299 
01300        @return
01301        the stream output was made to.
01302      */
01303 
01304     friend istream & operator>>(istream & strm, PStandardType & val)
01305       { type data; strm >> data; val = PStandardType(data); return strm; }
01306     /* Input the platform dependent value for the type from the stream.
01307 
01308        @return
01309        the stream input was made from.
01310      */
01311 
01312 
01313   private:
01314     type data;
01315 };
01316 #endif
01317 
01318 
01319 #define PI_SAME(name, type) \
01320   struct name { \
01321     name() : data(0) { } \
01322     name(type value) : data(value) { } \
01323     name(const name & value) : data(value.data) { } \
01324     name & operator =(type value) { data = value; return *this; } \
01325     name & operator =(const name & value) { data = value.data; return *this; } \
01326     operator type() const { return data; } \
01327     friend ostream & operator<<(ostream & s, const name & v) { return s << v.data; } \
01328     friend istream & operator>>(istream & s, name & v) { return s >> v.data; } \
01329     private: type data; \
01330   }
01331 
01332 #define PI_LOOP(src, dst) \
01333     BYTE *s = ((BYTE *)&src)+sizeof(src); BYTE *d = (BYTE *)&dst; \
01334     while (s != (BYTE *)&src) *d++ = *--s;
01335 
01336 #define PI_DIFF(name, type) \
01337   struct name { \
01338     name() : data(0) { } \
01339     name(type value) : data(0) { operator=(value); } \
01340     name(const name & value) : data(value.data) { } \
01341     name & operator =(type value) { PI_LOOP(value, data); return *this; } \
01342     name & operator =(const name & value) { data = value.data; return *this; } \
01343     operator type() const { type value; PI_LOOP(data, value); return value; } \
01344     friend ostream & operator<<(ostream & s, const name & value) { return s << (type)value; } \
01345     friend istream & operator>>(istream & s, name & v) { type val; s >> val; v = val; return s; } \
01346     private: type data; \
01347   }
01348 
01349 #ifndef PCHAR8
01350 #define PCHAR8 PANSI_CHAR
01351 #endif
01352 
01353 #if PCHAR8==PANSI_CHAR
01354 PI_SAME(PChar8, char);
01355 #endif
01356 
01357 PI_SAME(PInt8, char);
01358 
01359 PI_SAME(PUInt8, unsigned char);
01360 
01361 #if PBYTE_ORDER==PLITTLE_ENDIAN
01362 PI_SAME(PInt16l, PInt16);
01363 #elif PBYTE_ORDER==PBIG_ENDIAN
01364 PI_DIFF(PInt16l, PInt16);
01365 #endif
01366 
01367 #if PBYTE_ORDER==PLITTLE_ENDIAN
01368 PI_DIFF(PInt16b, PInt16);
01369 #elif PBYTE_ORDER==PBIG_ENDIAN
01370 PI_SAME(PInt16b, PInt16);
01371 #endif
01372 
01373 #if PBYTE_ORDER==PLITTLE_ENDIAN
01374 PI_SAME(PUInt16l, WORD);
01375 #elif PBYTE_ORDER==PBIG_ENDIAN
01376 PI_DIFF(PUInt16l, WORD);
01377 #endif
01378 
01379 #if PBYTE_ORDER==PLITTLE_ENDIAN
01380 PI_DIFF(PUInt16b, WORD);
01381 #elif PBYTE_ORDER==PBIG_ENDIAN
01382 PI_SAME(PUInt16b, WORD);
01383 #endif
01384 
01385 #if PBYTE_ORDER==PLITTLE_ENDIAN
01386 PI_SAME(PInt32l, PInt32);
01387 #elif PBYTE_ORDER==PBIG_ENDIAN
01388 PI_DIFF(PInt32l, PInt32);
01389 #endif
01390 
01391 #if PBYTE_ORDER==PLITTLE_ENDIAN
01392 PI_DIFF(PInt32b, PInt32);
01393 #elif PBYTE_ORDER==PBIG_ENDIAN
01394 PI_SAME(PInt32b, PInt32);
01395 #endif
01396 
01397 #if PBYTE_ORDER==PLITTLE_ENDIAN
01398 PI_SAME(PUInt32l, DWORD);
01399 #elif PBYTE_ORDER==PBIG_ENDIAN
01400 PI_DIFF(PUInt32l, DWORD);
01401 #endif
01402 
01403 #if PBYTE_ORDER==PLITTLE_ENDIAN
01404 PI_DIFF(PUInt32b, DWORD);
01405 #elif PBYTE_ORDER==PBIG_ENDIAN
01406 PI_SAME(PUInt32b, DWORD);
01407 #endif
01408 
01409 #if PBYTE_ORDER==PLITTLE_ENDIAN
01410 PI_SAME(PInt64l, PInt64);
01411 #elif PBYTE_ORDER==PBIG_ENDIAN
01412 PI_DIFF(PInt64l, PInt64);
01413 #endif
01414 
01415 #if PBYTE_ORDER==PLITTLE_ENDIAN
01416 PI_DIFF(PInt64b, PInt64);
01417 #elif PBYTE_ORDER==PBIG_ENDIAN
01418 PI_SAME(PInt64b, PInt64);
01419 #endif
01420 
01421 #if PBYTE_ORDER==PLITTLE_ENDIAN
01422 PI_SAME(PUInt64l, PUInt64);
01423 #elif PBYTE_ORDER==PBIG_ENDIAN
01424 PI_DIFF(PUInt64l, PUInt64);
01425 #endif
01426 
01427 #if PBYTE_ORDER==PLITTLE_ENDIAN
01428 PI_DIFF(PUInt64b, PUInt64);
01429 #elif PBYTE_ORDER==PBIG_ENDIAN
01430 PI_SAME(PUInt64b, PUInt64);
01431 #endif
01432 
01433 #if PBYTE_ORDER==PLITTLE_ENDIAN
01434 PI_SAME(PFloat32l, float);
01435 #elif PBYTE_ORDER==PBIG_ENDIAN
01436 PI_DIFF(PFloat32l, float);
01437 #endif
01438 
01439 #if PBYTE_ORDER==PLITTLE_ENDIAN
01440 PI_DIFF(PFloat32b, float);
01441 #elif PBYTE_ORDER==PBIG_ENDIAN
01442 PI_SAME(PFloat32b, float);
01443 #endif
01444 
01445 #if PBYTE_ORDER==PLITTLE_ENDIAN
01446 PI_SAME(PFloat64l, double);
01447 #elif PBYTE_ORDER==PBIG_ENDIAN
01448 PI_DIFF(PFloat64l, double);
01449 #endif
01450 
01451 #if PBYTE_ORDER==PLITTLE_ENDIAN
01452 PI_DIFF(PFloat64b, double);
01453 #elif PBYTE_ORDER==PBIG_ENDIAN
01454 PI_SAME(PFloat64b, double);
01455 #endif
01456 
01457 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
01458 #if PBYTE_ORDER==PLITTLE_ENDIAN
01459 PI_SAME(PFloat80l, long double);
01460 #elif PBYTE_ORDER==PBIG_ENDIAN
01461 PI_DIFF(PFloat80l, long double);
01462 #endif
01463 
01464 #if PBYTE_ORDER==PLITTLE_ENDIAN
01465 PI_DIFF(PFloat80b, long double);
01466 #elif PBYTE_ORDER==PBIG_ENDIAN
01467 PI_SAME(PFloat80b, long double);
01468 #endif
01469 #endif
01470 
01471 #undef PI_LOOP
01472 #undef PI_SAME
01473 #undef PI_DIFF
01474 
01475 
01477 // Miscellaneous
01478 
01479 /*$MACRO PARRAYSIZE(array)
01480    This macro is used to calculate the number of array elements in a static
01481    array.
01482  */
01483 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01484 
01485 /*$MACRO PMIN(v1, v2)
01486    This macro is used to calculate the minimum of two values. As this is a
01487    macro the expression in #v1 or #v2 is executed
01488    twice so extreme care should be made in its use.
01489  */
01490 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01491 
01492 /*$MACRO PMAX(v1, v2)
01493    This macro is used to calculate the maximum of two values. As this is a
01494    macro the expression in #v1 or #v2 is executed
01495    twice so extreme care should be made in its use.
01496  */
01497 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01498 
01499 /*$MACRO PABS(val)
01500    This macro is used to calculate an absolute value. As this is a macro the
01501    expression in #val is executed twice so extreme care should be
01502    made in its use.
01503  */
01504 #define PABS(v) ((v) < 0 ? -(v) : (v))
01505 
01506 
01507 #endif // PTLIB_OBJECT_H
01508 
01509 
01510 // End Of File ///////////////////////////////////////////////////////////////

Generated on Thu May 27 01:36:48 2010 for PTLib by  doxygen 1.4.7