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: 24234 $
00030  * $Author: csoutheren $
00031  * $Date: 2010-04-12 07:02:21 -0500 (Mon, 12 Apr 2010) $
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, msg) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,(msg))
00189 
00197 #define PAssert2(b, cls, msg) PAssertFuncInline((b), __FILE__,__LINE__,(cls),(msg))
00198 
00205 #define PAssertOS(b) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,POperatingSystemError)
00206 
00216 #define PAssertNULL(ptr) (((ptr)!=NULL)?(ptr): \
00217                      (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(ptr)))
00218 
00225 #define PAssertAlways(msg) PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg))
00226 
00233 #define PAssertAlways2(cls, msg) PAssertFunc(__FILE__,__LINE__,(cls),(msg))
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 
00288 class PTrace
00289 {
00290 public:
00292   enum Options {
00298     Blocks = 1,
00300     DateAndTime = 2,
00302     Timestamp = 4,
00304     Thread = 8,
00306     TraceLevel = 16,
00308     FileAndLine = 32,
00310     ThreadAddress = 64,
00312     AppendToFile = 128,
00314     GMTTime = 256,
00316     RotateDaily = 512,
00318     RotateHourly = 1024,
00320     RotateMinutely = 2048,
00322     RotateLogMask = RotateDaily + RotateHourly + RotateMinutely,
00326     SystemLogStream = 32768
00327   };
00328 
00329 
00343   static void Initialise(
00344     unsigned level,                               
00345     const char * filename = NULL,                 
00346     unsigned options = Timestamp | Thread | Blocks 
00347   );
00348 
00359   static void Initialise(
00360     unsigned level,                                 
00361     const char * filename,                          
00362     const char * rolloverPattern,                   
00363     unsigned options = Timestamp | Thread | Blocks  
00364   );
00365 
00372   static void SetOptions(
00373     unsigned options 
00374   );
00375 
00384   static void ClearOptions(
00385     unsigned options 
00386   );
00387 
00393   static unsigned GetOptions();
00394 
00400   static void SetLevel(
00401     unsigned level 
00402   );
00403 
00409   static unsigned GetLevel();
00410 
00415   static PBoolean CanTrace(
00416     unsigned level 
00417   );
00418 
00423   static void SetStream(
00424     ostream * out 
00425   );
00426 
00442   static ostream & Begin(
00443     unsigned level,         
00444     const char * fileName,  
00445     int lineNum             
00446   );
00447 
00465   static ostream & End(
00466     ostream & strm 
00467   );
00468 
00472   static void Cleanup();
00473 
00479   class Block {
00480     public:
00482       Block(
00483         const char * fileName, 
00484         int lineNum,           
00485         const char * traceName
00487        );
00488       Block(const Block & obj)
00489         : file(obj.file), line(obj.line), name(obj.name) { }
00491       ~Block();
00492     private:
00493       Block & operator=(const Block &)
00494       { return *this; }
00495       const char * file;
00496       int          line;
00497       const char * name;
00498   };
00499 };
00500 
00501 /* Macro to conditionally declare a parameter to a function to avoid compiler
00502    warning due that parameter only being used in a <code>PTRACE()</code> */
00503 #define PTRACE_PARAM(param) param
00504 
00511 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
00512 
00516 #define PTRACE_LINE() \
00517     if (PTrace::CanTrace(1)) \
00518       PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
00519     else (void)0
00520 
00526 #define PTRACE(level, args) \
00527     if (PTrace::CanTrace(level)) \
00528       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00529     else (void)0
00530 
00538 #define PTRACE_IF(level, cond, args) \
00539     if ((PTrace::CanTrace(level) && (cond))) \
00540       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00541     else (void)0
00542 
00543 #else // PTRACING
00544 
00545 #define PTRACE_PARAM(param)
00546 #define PTRACE_BLOCK(n)
00547 #define PTRACE_LINE()
00548 #define PTRACE(level, arg)
00549 #define PTRACE_IF(level, cond, args)
00550 
00551 #endif // PTRACING
00552 
00553 
00554 
00555 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE)) 
00556 
00557 #define PMEMORY_HEAP 1
00558 
00565 class PMemoryHeap {
00566   public:
00568     PMemoryHeap();
00569 
00570     // Clear up the memory checking subsystem, dumping memory leaks.
00571     ~PMemoryHeap();
00572 
00579     static void * Allocate(
00580       size_t nSize,           
00581       const char * file,      
00582       int line,               
00583       const char * className  
00584     );
00591     static void * Allocate(
00592       size_t count,       
00593       size_t iSize,       
00594       const char * file,  
00595       int line            
00596     );
00597 
00605     static void * Reallocate(
00606       void * ptr,         
00607       size_t nSize,       
00608       const char * file,  
00609       int line            
00610     );
00611 
00617     static void Deallocate(
00618       void * ptr,             
00619       const char * className  
00620     );
00621 
00624     enum Validation {
00625       Ok, Bad, Trashed
00626     };
00634     static Validation Validate(
00635       const void * ptr,       
00636       const char * className, 
00637       ostream * error         
00638     );
00639 
00644     static PBoolean ValidateHeap(
00645       ostream * error = NULL  
00646     );
00647 
00653     static PBoolean SetIgnoreAllocations(
00654       PBoolean ignore  
00655     );
00656 
00660     static void DumpStatistics();
00664     static void DumpStatistics(ostream & strm );
00665 
00666 #if PMEMORY_CHECK
00667     struct State {
00668       DWORD allocationNumber;
00669     };
00670 #else
00671         typedef _CrtMemState State;
00672 #endif
00673 
00674     /* Get memory state.
00675       This returns a state that may be used to determine where to start dumping
00676       objects from.
00677      */
00678     static void GetState(
00679       State & state  
00680     );
00681 
00689     static void DumpObjectsSince(
00690       const State & when    
00691     );
00692 
00698     static void DumpObjectsSince(
00699       const State & when,   
00700       ostream & strm        
00701     );
00702 
00708     static void SetAllocationBreakpoint(
00709       DWORD point   
00710     );
00711 
00712 #if PMEMORY_CHECK
00713 
00714   protected:
00715     void * InternalAllocate(
00716       size_t nSize,           // Number of bytes to allocate.
00717       const char * file,      // Source file name for allocating function.
00718       int line,               // Source file line for allocating function.
00719       const char * className  // Class name for allocating function.
00720     );
00721     Validation InternalValidate(
00722       const void * ptr,       // Pointer to memory block to check
00723       const char * className, // Class name it should be.
00724       ostream * error         // Stream to receive error message (may be NULL)
00725     );
00726     void InternalDumpStatistics(ostream & strm);
00727     void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
00728 
00729     class Wrapper {
00730       public:
00731         Wrapper();
00732         ~Wrapper();
00733         PMemoryHeap * operator->() const { return instance; }
00734       private:
00735         PMemoryHeap * instance;
00736     };
00737     friend class Wrapper;
00738 
00739     enum Flags {
00740       NoLeakPrint = 1
00741     };
00742 
00743 #pragma pack(1)
00744     struct Header {
00745       enum {
00746         // Assure that the Header struct is aligned to 8 byte boundary
00747         NumGuardBytes = 16 - (sizeof(Header *) +
00748                               sizeof(Header *) +
00749                               sizeof(const char *) +
00750                               sizeof(const char *) +
00751                               sizeof(size_t) +
00752                               sizeof(DWORD) +
00753                               sizeof(WORD) +
00754                               sizeof(BYTE)
00755 #ifdef P_LINUX
00756                               + sizeof(pthread_t)
00757 #endif
00758                               )%8
00759       };
00760 
00761       Header     * prev;
00762       Header     * next;
00763       const char * className;
00764       const char * fileName;
00765       size_t       size;
00766       DWORD        request;
00767       WORD         line;
00768       BYTE         flags;
00769 #ifdef P_LINUX
00770       pthread_t    thread;
00771 #endif
00772       char         guard[NumGuardBytes];
00773 
00774       static char GuardBytes[NumGuardBytes];
00775     };
00776 #pragma pack()
00777 
00778     PBoolean isDestroyed;
00779 
00780     Header * listHead;
00781     Header * listTail;
00782 
00783     static DWORD allocationBreakpoint;
00784     DWORD allocationRequest;
00785     DWORD firstRealObject;
00786     BYTE  flags;
00787 
00788     char  allocFillChar;
00789     char  freeFillChar;
00790 
00791     DWORD currentMemoryUsage;
00792     DWORD peakMemoryUsage;
00793     DWORD currentObjects;
00794     DWORD peakObjects;
00795     DWORD totalObjects;
00796 
00797     ostream * leakDumpStream;
00798 
00799 #if defined(_WIN32)
00800     CRITICAL_SECTION mutex;
00801 #elif defined(P_PTHREADS)
00802     pthread_mutex_t mutex;
00803 #elif defined(P_VXWORKS)
00804     void * mutex;
00805 #endif
00806 
00807 #else
00808 
00809 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
00810     _CrtMemState initialState;
00811 
00812 #endif // PMEMORY_CHECK
00813 };
00814 
00815 
00820 inline void * runtime_malloc(size_t bytes  ) { return malloc(bytes); }
00821 
00826 inline void runtime_free(void * ptr  ) { free(ptr); }
00827 
00828 
00835 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
00836 
00843 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
00844 
00851 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
00852 
00853 
00860 #define free(p) PMemoryHeap::Deallocate(p, NULL)
00861 
00862 
00869 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
00870 
00871 
00886 #define PNEW  new (__FILE__, __LINE__)
00887 
00888 #if !defined(_MSC_VER) || _MSC_VER<1200
00889 #define PSPECIAL_DELETE_FUNCTION
00890 #else
00891 #define PSPECIAL_DELETE_FUNCTION \
00892     void operator delete(void * ptr, const char *, int) \
00893       { PMemoryHeap::Deallocate(ptr, Class()); } \
00894     void operator delete[](void * ptr, const char *, int) \
00895       { PMemoryHeap::Deallocate(ptr, Class()); }
00896 #endif
00897 
00898 #define PNEW_AND_DELETE_FUNCTIONS \
00899     void * operator new(size_t nSize, const char * file, int line) \
00900       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00901     void * operator new(size_t nSize) \
00902       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00903     void operator delete(void * ptr) \
00904       { PMemoryHeap::Deallocate(ptr, Class()); } \
00905     void * operator new(size_t, void * placement) \
00906       { return placement; } \
00907     void operator delete(void *, void *) \
00908       { } \
00909     void * operator new[](size_t nSize, const char * file, int line) \
00910       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00911     void * operator new[](size_t nSize) \
00912       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00913     void operator delete[](void * ptr) \
00914       { PMemoryHeap::Deallocate(ptr, Class()); } \
00915     PSPECIAL_DELETE_FUNCTION
00916 
00917 
00918 inline void * operator new(size_t nSize, const char * file, int line)
00919   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00920 
00921 inline void * operator new[](size_t nSize, const char * file, int line)
00922   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00923 
00924 #ifndef __GNUC__
00925 void * operator new(size_t nSize);
00926 void * operator new[](size_t nSize);
00927 
00928 void operator delete(void * ptr);
00929 void operator delete[](void * ptr);
00930 
00931 #if defined(_MSC_VER) && _MSC_VER>=1200
00932 inline void operator delete(void * ptr, const char *, int)
00933   { PMemoryHeap::Deallocate(ptr, NULL); }
00934 
00935 inline void operator delete[](void * ptr, const char *, int)
00936   { PMemoryHeap::Deallocate(ptr, NULL); }
00937 #endif
00938 #endif
00939 
00940 
00941 class PMemoryHeapIgnoreAllocationsForScope {
00942 public:
00943   PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(true)) { }
00944   ~PMemoryHeapIgnoreAllocationsForScope() { PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations); }
00945 private:
00946   PBoolean previousIgnoreAllocations;
00947 };
00948 
00949 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
00950 
00951 class PMemoryAllocationBreakpoint {
00952 public:
00953   PMemoryAllocationBreakpoint(DWORD point)
00954   {
00955     PMemoryHeap::SetAllocationBreakpoint(point);
00956   }
00957 };
00958 
00959 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
00960 
00961 
00962 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00963 
00964 #define PMEMORY_HEAP 0
00965 
00966 #define PNEW new
00967 
00968 #define PNEW_AND_DELETE_FUNCTIONS
00969 
00970 #define runtime_malloc(s) malloc(s)
00971 #define runtime_free(p) free(p)
00972 
00973 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
00974 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
00975 
00976 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00977 
00978 
00979 // Memory pooling allocators
00980 #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(P_MINGW) && !defined(P_MACOSX)
00981 #include <ext/bitmap_allocator.h>
00982 template <class Type> class PFixedPoolAllocator    : public __gnu_cxx::bitmap_allocator<Type> { };
00983 #include <ext/mt_allocator.h>
00984 template <class Type> class PVariablePoolAllocator : public __gnu_cxx::__mt_alloc<Type>   { };
00985 #else
00986 template <class Type> class PFixedPoolAllocator    : public std::allocator<Type> { };
00987 template <class Type> class PVariablePoolAllocator : public std::allocator<Type> { };
00988 #endif
00989 
00990 #define PDECLARE_POOL_ALLOCATOR() \
00991     void * operator new(size_t nSize); \
00992     void * operator new(size_t nSize, const char * file, int line); \
00993     void operator delete(void * ptr); \
00994     void operator delete(void * ptr, const char *, int)
00995 
00996 #define PDEFINE_POOL_ALLOCATOR(cls) \
00997   static PFixedPoolAllocator<cls> cls##_allocator; \
00998   void * cls::operator new(size_t)                           { return cls##_allocator.allocate(1);               } \
00999   void * cls::operator new(size_t, const char *, int)        { return cls##_allocator.allocate(1);               } \
01000   void   cls::operator delete(void * ptr)                    {        cls##_allocator.deallocate((cls *)ptr, 1); } \
01001   void   cls::operator delete(void * ptr, const char *, int) {        cls##_allocator.deallocate((cls *)ptr, 1); }
01002 
01003 
01004 
01015 #define PCLASSINFO(cls, par) \
01016   public: \
01017     typedef cls P_thisClass; \
01018     static inline const char * Class() \
01019       { return #cls; } \
01020     virtual PBoolean InternalIsDescendant(const char * clsName) const \
01021       { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
01022     virtual const char * GetClass(unsigned ancestor = 0) const \
01023       { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
01024     virtual Comparison CompareObjectMemoryDirect(const PObject & _obj) const \
01025       { return (Comparison)memcmp(this, &_obj, sizeof(cls)); } \
01026     PNEW_AND_DELETE_FUNCTIONS
01027 
01028 
01029 #if P_HAS_TYPEINFO
01030 
01031 #define PIsDescendant(ptr, cls)    (dynamic_cast<const cls *>(ptr) != NULL) 
01032 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str)) 
01033 
01034 #define PRemoveConst(cls, ptr)  (const_cast<cls*>(ptr))
01035 
01036 #if P_USE_ASSERTS
01037 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line) 
01038   { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
01039 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
01040 #else
01041 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
01042 #endif
01043 
01044 #include <typeinfo>
01045 
01046 #else // P_HAS_TYPEINFO
01047 
01048 #define PIsDescendant(ptr, cls)    ((ptr)->InternalIsDescendant(cls::Class()))
01049 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
01050 
01051 #define PRemoveConst(cls, ptr)  ((cls*)(ptr))
01052 
01053 #if P_USE_ASSERTS
01054 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line) 
01055   { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
01056 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
01057 #else
01058 #define PDownCast(cls, ptr) ((cls*)(ptr))
01059 #endif
01060 
01061 #endif // P_HAS_TYPEINFO
01062 
01063 
01072 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
01073 #ifdef DOC_PLUS_PLUS
01074 } Match previous opening brace in doc++
01075 #endif
01076 
01078 // The root of all evil ... umm classes
01079 
01084 class PObject {
01085 
01086   protected:
01090     PObject() { }
01091 
01092   public:
01093     /* Destructor required to get the "virtual". A PObject really has nothing
01094        to destroy.
01095      */
01096     virtual ~PObject() { }
01097 
01110     static inline const char * Class()    { return "PObject"; }
01111 
01124     virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : Class(); }
01125 
01126     PBoolean IsClass(const char * cls) const 
01127     { return strcmp(cls, GetClass()) == 0; }
01128 
01138     virtual PBoolean InternalIsDescendant(
01139       const char * clsName    // Ancestor class name to compare against.
01140     ) const
01141     { return IsClass(clsName); }
01142 
01144 
01150     enum Comparison {
01151       LessThan = -1,
01152       EqualTo = 0,
01153       GreaterThan = 1
01154     };
01155 
01167     virtual Comparison Compare(
01168       const PObject & obj   // Object to compare against.
01169     ) const;
01170     
01182     virtual Comparison CompareObjectMemoryDirect(
01183       const PObject & obj   // Object to compare against.
01184     ) const;
01185 
01191     bool operator==(
01192       const PObject & obj   // Object to compare against.
01193     ) const { return Compare(obj) == EqualTo; }
01194 
01200     bool operator!=(
01201       const PObject & obj   // Object to compare against.
01202     ) const { return Compare(obj) != EqualTo; }
01203 
01209     bool operator<(
01210       const PObject & obj   // Object to compare against.
01211     ) const { return Compare(obj) == LessThan; }
01212 
01218     bool operator>(
01219       const PObject & obj   // Object to compare against.
01220     ) const { return Compare(obj) == GreaterThan; }
01221 
01227     bool operator<=(
01228       const PObject & obj   // Object to compare against.
01229     ) const { return Compare(obj) != GreaterThan; }
01230 
01236     bool operator>=(
01237       const PObject & obj   // Object to compare against.
01238     ) const { return Compare(obj) != LessThan; }
01240 
01249     virtual void PrintOn(
01250       ostream &strm   // Stream to print the object into.
01251     ) const;
01252 
01259     virtual void ReadFrom(
01260       istream &strm   // Stream to read the objects contents from.
01261     );
01262 
01263 
01269     inline friend ostream & operator<<(
01270       ostream &strm,       
01271       const PObject & obj  
01272     ) { obj.PrintOn(strm); return strm; }
01273 
01279     inline friend istream & operator>>(
01280       istream &strm,   
01281       PObject & obj    
01282     ) { obj.ReadFrom(strm); return strm; }
01283 
01284 
01299     virtual PObject * Clone() const;
01300 
01312     virtual PINDEX HashFunction() const;
01314 };
01315 
01317 // Platform independent types
01318 
01319 // All these classes encapsulate primitive types such that they may be
01320 // transfered in a platform independent manner. In particular it is used to
01321 // do byte swapping for little endien and big endien processor architectures
01322 // as well as accommodating structure packing rules for memory structures.
01323 
01324 #define PANSI_CHAR 1
01325 #define PLITTLE_ENDIAN 2
01326 #define PBIG_ENDIAN 3
01327 
01328 
01329 template <typename type>
01330 struct PIntSameOrder {
01331   __inline PIntSameOrder()                            : data(0)              { }
01332   __inline PIntSameOrder(type value)                  : data(value)          { }
01333   __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data)     { }
01334   __inline PIntSameOrder & operator=(type value)                             { data = value; return *this; }
01335   __inline PIntSameOrder & operator=(const PIntSameOrder & value)            { data = value.data; return *this; }
01336   __inline operator type() const                                             { return data; }
01337   __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
01338   __inline friend istream & operator>>(istream & s, PIntSameOrder & v)       { return s >> v.data; }
01339 
01340   private:
01341     type data;
01342 };
01343 
01344 
01345 template <typename type>
01346 struct PIntReversedOrder {
01347   __inline PIntReversedOrder()                                : data(0)              { }
01348   __inline PIntReversedOrder(type value)                                             { ReverseBytes(value, data); }
01349   __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data)     { }
01350   __inline PIntReversedOrder & operator=(type value)                                 { ReverseBytes(value, data); return *this; }
01351   __inline PIntReversedOrder & operator=(const PIntReversedOrder & value)            { data = value.data; return *this; }
01352   __inline operator type() const                                                     { type value; ReverseBytes(data, value); return value; }
01353   __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
01354   __inline friend istream & operator>>(istream & s, PIntReversedOrder & v)           { type val; s >> val; v = val; return s; }
01355 
01356   private:
01357     type data;
01358 
01359   static __inline void ReverseBytes(const type & src, type & dst)
01360   {
01361     size_t s = sizeof(type)-1;
01362     for (size_t d = 0; d < sizeof(type); ++d,--s)
01363       ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
01364   }
01365 };
01366 
01367 #ifndef PCHAR8
01368 #define PCHAR8 PANSI_CHAR
01369 #endif
01370 
01371 #if PCHAR8==PANSI_CHAR
01372 typedef PIntSameOrder<char> PChar8;
01373 #endif
01374 
01375 typedef PIntSameOrder<char> PInt8;
01376 
01377 typedef PIntSameOrder<unsigned char> PUInt8;
01378 
01379 #if PBYTE_ORDER==PLITTLE_ENDIAN
01380 typedef PIntSameOrder<PInt16> PInt16l;
01381 #elif PBYTE_ORDER==PBIG_ENDIAN
01382 typedef PIntReversedOrder<PInt16> PInt16l;
01383 #endif
01384 
01385 #if PBYTE_ORDER==PLITTLE_ENDIAN
01386 typedef PIntReversedOrder<PInt16> PInt16b;
01387 #elif PBYTE_ORDER==PBIG_ENDIAN
01388 typedef PIntSameOrder<PInt16> PInt16b;
01389 #endif
01390 
01391 #if PBYTE_ORDER==PLITTLE_ENDIAN
01392 typedef PIntSameOrder<WORD> PUInt16l;
01393 #elif PBYTE_ORDER==PBIG_ENDIAN
01394 typedef PIntReversedOrder<WORD> PUInt16l;
01395 #endif
01396 
01397 #if PBYTE_ORDER==PLITTLE_ENDIAN
01398 typedef PIntReversedOrder<WORD> PUInt16b;
01399 #elif PBYTE_ORDER==PBIG_ENDIAN
01400 typedef PIntSameOrder<WORD> PUInt16b;
01401 #endif
01402 
01403 #if PBYTE_ORDER==PLITTLE_ENDIAN
01404 typedef PIntSameOrder<PInt32> PInt32l;
01405 #elif PBYTE_ORDER==PBIG_ENDIAN
01406 typedef PIntReversedOrder<PInt32> PInt32l;
01407 #endif
01408 
01409 #if PBYTE_ORDER==PLITTLE_ENDIAN
01410 typedef PIntReversedOrder<PInt32> PInt32b;
01411 #elif PBYTE_ORDER==PBIG_ENDIAN
01412 typedef PIntSameOrder<PInt32> PInt32b;
01413 #endif
01414 
01415 #if PBYTE_ORDER==PLITTLE_ENDIAN
01416 typedef PIntSameOrder<DWORD> PUInt32l;
01417 #elif PBYTE_ORDER==PBIG_ENDIAN
01418 typedef PIntReversedOrder<DWORD> PUInt32l;
01419 #endif
01420 
01421 #if PBYTE_ORDER==PLITTLE_ENDIAN
01422 typedef PIntReversedOrder<DWORD> PUInt32b;
01423 #elif PBYTE_ORDER==PBIG_ENDIAN
01424 typedef PIntSameOrder<DWORD> PUInt32b;
01425 #endif
01426 
01427 #if PBYTE_ORDER==PLITTLE_ENDIAN
01428 typedef PIntSameOrder<PInt64> PInt64l;
01429 #elif PBYTE_ORDER==PBIG_ENDIAN
01430 typedef PIntReversedOrder<PInt64> PInt64l;
01431 #endif
01432 
01433 #if PBYTE_ORDER==PLITTLE_ENDIAN
01434 typedef PIntReversedOrder<PInt64> PInt64b;
01435 #elif PBYTE_ORDER==PBIG_ENDIAN
01436 typedef PIntSameOrder<PInt64> PInt64b;
01437 #endif
01438 
01439 #if PBYTE_ORDER==PLITTLE_ENDIAN
01440 typedef PIntSameOrder<PUInt64> PUInt64l;
01441 #elif PBYTE_ORDER==PBIG_ENDIAN
01442 typedef PIntReversedOrder<PUInt64> PUInt64l;
01443 #endif
01444 
01445 #if PBYTE_ORDER==PLITTLE_ENDIAN
01446 typedef PIntReversedOrder<PUInt64> PUInt64b;
01447 #elif PBYTE_ORDER==PBIG_ENDIAN
01448 typedef PIntSameOrder<PUInt64> PUInt64b;
01449 #endif
01450 
01451 #if PBYTE_ORDER==PLITTLE_ENDIAN
01452 typedef PIntSameOrder<float> PFloat32l;
01453 #elif PBYTE_ORDER==PBIG_ENDIAN
01454 typedef PIntReversedOrder<float> PFloat32l;
01455 #endif
01456 
01457 #if PBYTE_ORDER==PLITTLE_ENDIAN
01458 typedef PIntReversedOrder<float> PFloat32b;
01459 #elif PBYTE_ORDER==PBIG_ENDIAN
01460 typedef PIntSameOrder<float> PFloat32b;
01461 #endif
01462 
01463 #if PBYTE_ORDER==PLITTLE_ENDIAN
01464 typedef PIntSameOrder<double> PFloat64l;
01465 #elif PBYTE_ORDER==PBIG_ENDIAN
01466 typedef PIntReversedOrder<double> PFloat64l;
01467 #endif
01468 
01469 #if PBYTE_ORDER==PLITTLE_ENDIAN
01470 typedef PIntReversedOrder<double> PFloat64b;
01471 #elif PBYTE_ORDER==PBIG_ENDIAN
01472 typedef PIntSameOrder<double> PFloat64b;
01473 #endif
01474 
01475 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
01476 #if PBYTE_ORDER==PLITTLE_ENDIAN
01477 typedef PIntSameOrder<long double> PFloat80l;
01478 #elif PBYTE_ORDER==PBIG_ENDIAN
01479 typedef PIntReversedOrder<long double> PFloat80l;
01480 #endif
01481 
01482 #if PBYTE_ORDER==PLITTLE_ENDIAN
01483 typedef PIntReversedOrder<long double> PFloat80b;
01484 #elif PBYTE_ORDER==PBIG_ENDIAN
01485 typedef PIntSameOrder<long double> PFloat80b;
01486 #endif
01487 #endif
01488 
01489 
01491 // Miscellaneous
01492 
01493 /*$MACRO PARRAYSIZE(array)
01494    This macro is used to calculate the number of array elements in a static
01495    array.
01496  */
01497 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01498 
01499 /*$MACRO PMIN(v1, v2)
01500    This macro is used to calculate the minimum of two values. As this is a
01501    macro the expression in <code>v1</code> or <code>v2</code> is executed
01502    twice so extreme care should be made in its use.
01503  */
01504 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01505 
01506 /*$MACRO PMAX(v1, v2)
01507    This macro is used to calculate the maximum of two values. As this is a
01508    macro the expression in <code>v1</code> or <code>v2</code> is executed
01509    twice so extreme care should be made in its use.
01510  */
01511 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01512 
01513 /*$MACRO PABS(val)
01514    This macro is used to calculate an absolute value. As this is a macro the
01515    expression in <code>val</code> is executed twice so extreme care should be
01516    made in its use.
01517  */
01518 #define PABS(v) ((v) < 0 ? -(v) : (v))
01519 
01520 
01521 #endif // PTLIB_OBJECT_H
01522 
01523 
01524 // End Of File ///////////////////////////////////////////////////////////////

Generated on Fri Oct 14 01:44:09 2011 for PTLib by  doxygen 1.4.7