PTLib Version 2.10.2
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: 26129 $
00030  * $Author: rjongbloed $
00031  * $Date: 2011-07-07 21:42:50 -0500 (Thu, 07 Jul 2011) $
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 
00980 /*
00981  *  Implement "construct on first use" paradigm
00982  */
00983 
00984 template <class GnuAllocator, class Type>
00985 struct PAllocatorTemplate
00986 {
00987   Type * allocate(size_t v)  
00988   {
00989     return GetAllocator().allocate(v);
00990   }
00991 
00992   void deallocate(Type * p, size_t v)  
00993   {
00994     GetAllocator().deallocate(p, v);
00995   }
00996 
00997   private:
00998     static GnuAllocator & GetAllocator()
00999     {
01000       static GnuAllocator instance;
01001       return instance;
01002     }
01003 };
01004 
01005 #define GCC_VERSION (__GNUC__ * 10000 \
01006                    + __GNUC_MINOR__ * 100 \
01007                    + __GNUC_PATCHLEVEL__)
01008 
01009 // Memory pooling allocators
01010 #if defined(__GNUC__) && (GCC_VERSION > 40000) && !defined(P_MINGW) && !defined(P_MACOSX) 
01011 #include <ext/mt_allocator.h>
01012 template <class Type> struct PFixedPoolAllocator    : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
01013 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
01014 
01015 #else
01016 
01017 template <class Type> struct PFixedPoolAllocator    : public PAllocatorTemplate<std::allocator<Type>, Type> { };
01018 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<std::allocator<Type>, Type> { };
01019 #endif
01020 
01021 #define PDECLARE_POOL_ALLOCATOR() \
01022     void * operator new(size_t nSize); \
01023     void * operator new(size_t nSize, const char * file, int line); \
01024     void operator delete(void * ptr); \
01025     void operator delete(void * ptr, const char *, int)
01026 
01027 #define PDEFINE_POOL_ALLOCATOR(cls) \
01028   static PFixedPoolAllocator<cls> cls##_allocator; \
01029   void * cls::operator new(size_t)                           { return cls##_allocator.allocate(1);               } \
01030   void * cls::operator new(size_t, const char *, int)        { return cls##_allocator.allocate(1);               } \
01031   void   cls::operator delete(void * ptr)                    {        cls##_allocator.deallocate((cls *)ptr, 1); } \
01032   void   cls::operator delete(void * ptr, const char *, int) {        cls##_allocator.deallocate((cls *)ptr, 1); }
01033 
01034 
01045 #define PCLASSINFO(cls, par) \
01046   public: \
01047     typedef cls P_thisClass; \
01048     static inline const char * Class() \
01049       { return #cls; } \
01050     virtual PBoolean InternalIsDescendant(const char * clsName) const \
01051       { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
01052     virtual const char * GetClass(unsigned ancestor = 0) const \
01053       { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
01054     virtual PObject::Comparison CompareObjectMemoryDirect(const PObject & _obj) const \
01055       { return (PObject::Comparison)memcmp(this, &_obj, sizeof(cls)); } \
01056     PNEW_AND_DELETE_FUNCTIONS
01057 
01058 
01059 #if P_HAS_TYPEINFO
01060 
01061 #define PIsDescendant(ptr, cls)    (dynamic_cast<const cls *>(ptr) != NULL) 
01062 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str)) 
01063 
01064 #define PRemoveConst(cls, ptr)  (const_cast<cls*>(ptr))
01065 
01066 #if P_USE_ASSERTS
01067 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line) 
01068   { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
01069 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
01070 #else
01071 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
01072 #endif
01073 
01074 #include <typeinfo>
01075 
01076 #else // P_HAS_TYPEINFO
01077 
01078 #define PIsDescendant(ptr, cls)    ((ptr)->InternalIsDescendant(cls::Class()))
01079 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
01080 
01081 #define PRemoveConst(cls, ptr)  ((cls*)(ptr))
01082 
01083 #if P_USE_ASSERTS
01084 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line) 
01085   { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
01086 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
01087 #else
01088 #define PDownCast(cls, ptr) ((cls*)(ptr))
01089 #endif
01090 
01091 #endif // P_HAS_TYPEINFO
01092 
01093 
01102 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
01103 #ifdef DOC_PLUS_PLUS
01104 } Match previous opening brace in doc++
01105 #endif
01106 
01108 // The root of all evil ... umm classes
01109 
01114 class PObject {
01115 
01116   protected:
01120     PObject() { }
01121 
01122   public:
01123     /* Destructor required to get the "virtual". A PObject really has nothing
01124        to destroy.
01125      */
01126     virtual ~PObject() { }
01127 
01140     static inline const char * Class()    { return "PObject"; }
01141 
01154     virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : Class(); }
01155 
01156     PBoolean IsClass(const char * cls) const 
01157     { return strcmp(cls, GetClass()) == 0; }
01158 
01168     virtual PBoolean InternalIsDescendant(
01169       const char * clsName    // Ancestor class name to compare against.
01170     ) const
01171     { return IsClass(clsName); }
01172 
01174 
01180     enum Comparison {
01181       LessThan = -1,
01182       EqualTo = 0,
01183       GreaterThan = 1
01184     };
01185 
01197     virtual Comparison Compare(
01198       const PObject & obj   // Object to compare against.
01199     ) const;
01200     
01212     virtual Comparison CompareObjectMemoryDirect(
01213       const PObject & obj   // Object to compare against.
01214     ) const;
01215 
01221     bool operator==(
01222       const PObject & obj   // Object to compare against.
01223     ) const { return Compare(obj) == EqualTo; }
01224 
01230     bool operator!=(
01231       const PObject & obj   // Object to compare against.
01232     ) const { return Compare(obj) != EqualTo; }
01233 
01239     bool operator<(
01240       const PObject & obj   // Object to compare against.
01241     ) const { return Compare(obj) == LessThan; }
01242 
01248     bool operator>(
01249       const PObject & obj   // Object to compare against.
01250     ) const { return Compare(obj) == GreaterThan; }
01251 
01257     bool operator<=(
01258       const PObject & obj   // Object to compare against.
01259     ) const { return Compare(obj) != GreaterThan; }
01260 
01266     bool operator>=(
01267       const PObject & obj   // Object to compare against.
01268     ) const { return Compare(obj) != LessThan; }
01270 
01279     virtual void PrintOn(
01280       ostream &strm   // Stream to print the object into.
01281     ) const;
01282 
01289     virtual void ReadFrom(
01290       istream &strm   // Stream to read the objects contents from.
01291     );
01292 
01293 
01299     inline friend ostream & operator<<(
01300       ostream &strm,       
01301       const PObject & obj  
01302     ) { obj.PrintOn(strm); return strm; }
01303 
01309     inline friend istream & operator>>(
01310       istream &strm,   
01311       PObject & obj    
01312     ) { obj.ReadFrom(strm); return strm; }
01313 
01314 
01329     virtual PObject * Clone() const;
01330 
01342     virtual PINDEX HashFunction() const;
01344 };
01345 
01347 // Platform independent types
01348 
01349 // All these classes encapsulate primitive types such that they may be
01350 // transfered in a platform independent manner. In particular it is used to
01351 // do byte swapping for little endien and big endien processor architectures
01352 // as well as accommodating structure packing rules for memory structures.
01353 
01354 #define PANSI_CHAR 1
01355 #define PLITTLE_ENDIAN 2
01356 #define PBIG_ENDIAN 3
01357 
01358 
01359 template <typename type>
01360 struct PIntSameOrder {
01361   __inline PIntSameOrder()                            : data(0)              { }
01362   __inline PIntSameOrder(type value)                  : data(value)          { }
01363   __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data)     { }
01364   __inline PIntSameOrder & operator=(type value)                             { data = value; return *this; }
01365   __inline PIntSameOrder & operator=(const PIntSameOrder & value)            { data = value.data; return *this; }
01366   __inline operator type() const                                             { return data; }
01367   __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
01368   __inline friend istream & operator>>(istream & s, PIntSameOrder & v)       { return s >> v.data; }
01369 
01370   private:
01371     type data;
01372 };
01373 
01374 
01375 template <typename type>
01376 struct PIntReversedOrder {
01377   __inline PIntReversedOrder()                                : data(0)              { }
01378   __inline PIntReversedOrder(type value)                                             { ReverseBytes(value, data); }
01379   __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data)     { }
01380   __inline PIntReversedOrder & operator=(type value)                                 { ReverseBytes(value, data); return *this; }
01381   __inline PIntReversedOrder & operator=(const PIntReversedOrder & value)            { data = value.data; return *this; }
01382   __inline operator type() const                                                     { type value; ReverseBytes(data, value); return value; }
01383   __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
01384   __inline friend istream & operator>>(istream & s, PIntReversedOrder & v)           { type val; s >> val; v = val; return s; }
01385 
01386   private:
01387     type data;
01388 
01389   static __inline void ReverseBytes(const type & src, type & dst)
01390   {
01391     size_t s = sizeof(type)-1;
01392     for (size_t d = 0; d < sizeof(type); ++d,--s)
01393       ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
01394   }
01395 };
01396 
01397 #ifndef PCHAR8
01398 #define PCHAR8 PANSI_CHAR
01399 #endif
01400 
01401 #if PCHAR8==PANSI_CHAR
01402 typedef PIntSameOrder<char> PChar8;
01403 #endif
01404 
01405 typedef PIntSameOrder<char> PInt8;
01406 
01407 typedef PIntSameOrder<unsigned char> PUInt8;
01408 
01409 #if PBYTE_ORDER==PLITTLE_ENDIAN
01410 typedef PIntSameOrder<PInt16> PInt16l;
01411 #elif PBYTE_ORDER==PBIG_ENDIAN
01412 typedef PIntReversedOrder<PInt16> PInt16l;
01413 #endif
01414 
01415 #if PBYTE_ORDER==PLITTLE_ENDIAN
01416 typedef PIntReversedOrder<PInt16> PInt16b;
01417 #elif PBYTE_ORDER==PBIG_ENDIAN
01418 typedef PIntSameOrder<PInt16> PInt16b;
01419 #endif
01420 
01421 #if PBYTE_ORDER==PLITTLE_ENDIAN
01422 typedef PIntSameOrder<WORD> PUInt16l;
01423 #elif PBYTE_ORDER==PBIG_ENDIAN
01424 typedef PIntReversedOrder<WORD> PUInt16l;
01425 #endif
01426 
01427 #if PBYTE_ORDER==PLITTLE_ENDIAN
01428 typedef PIntReversedOrder<WORD> PUInt16b;
01429 #elif PBYTE_ORDER==PBIG_ENDIAN
01430 typedef PIntSameOrder<WORD> PUInt16b;
01431 #endif
01432 
01433 #if PBYTE_ORDER==PLITTLE_ENDIAN
01434 typedef PIntSameOrder<PInt32> PInt32l;
01435 #elif PBYTE_ORDER==PBIG_ENDIAN
01436 typedef PIntReversedOrder<PInt32> PInt32l;
01437 #endif
01438 
01439 #if PBYTE_ORDER==PLITTLE_ENDIAN
01440 typedef PIntReversedOrder<PInt32> PInt32b;
01441 #elif PBYTE_ORDER==PBIG_ENDIAN
01442 typedef PIntSameOrder<PInt32> PInt32b;
01443 #endif
01444 
01445 #if PBYTE_ORDER==PLITTLE_ENDIAN
01446 typedef PIntSameOrder<DWORD> PUInt32l;
01447 #elif PBYTE_ORDER==PBIG_ENDIAN
01448 typedef PIntReversedOrder<DWORD> PUInt32l;
01449 #endif
01450 
01451 #if PBYTE_ORDER==PLITTLE_ENDIAN
01452 typedef PIntReversedOrder<DWORD> PUInt32b;
01453 #elif PBYTE_ORDER==PBIG_ENDIAN
01454 typedef PIntSameOrder<DWORD> PUInt32b;
01455 #endif
01456 
01457 #if PBYTE_ORDER==PLITTLE_ENDIAN
01458 typedef PIntSameOrder<PInt64> PInt64l;
01459 #elif PBYTE_ORDER==PBIG_ENDIAN
01460 typedef PIntReversedOrder<PInt64> PInt64l;
01461 #endif
01462 
01463 #if PBYTE_ORDER==PLITTLE_ENDIAN
01464 typedef PIntReversedOrder<PInt64> PInt64b;
01465 #elif PBYTE_ORDER==PBIG_ENDIAN
01466 typedef PIntSameOrder<PInt64> PInt64b;
01467 #endif
01468 
01469 #if PBYTE_ORDER==PLITTLE_ENDIAN
01470 typedef PIntSameOrder<PUInt64> PUInt64l;
01471 #elif PBYTE_ORDER==PBIG_ENDIAN
01472 typedef PIntReversedOrder<PUInt64> PUInt64l;
01473 #endif
01474 
01475 #if PBYTE_ORDER==PLITTLE_ENDIAN
01476 typedef PIntReversedOrder<PUInt64> PUInt64b;
01477 #elif PBYTE_ORDER==PBIG_ENDIAN
01478 typedef PIntSameOrder<PUInt64> PUInt64b;
01479 #endif
01480 
01481 #if PBYTE_ORDER==PLITTLE_ENDIAN
01482 typedef PIntSameOrder<float> PFloat32l;
01483 #elif PBYTE_ORDER==PBIG_ENDIAN
01484 typedef PIntReversedOrder<float> PFloat32l;
01485 #endif
01486 
01487 #if PBYTE_ORDER==PLITTLE_ENDIAN
01488 typedef PIntReversedOrder<float> PFloat32b;
01489 #elif PBYTE_ORDER==PBIG_ENDIAN
01490 typedef PIntSameOrder<float> PFloat32b;
01491 #endif
01492 
01493 #if PBYTE_ORDER==PLITTLE_ENDIAN
01494 typedef PIntSameOrder<double> PFloat64l;
01495 #elif PBYTE_ORDER==PBIG_ENDIAN
01496 typedef PIntReversedOrder<double> PFloat64l;
01497 #endif
01498 
01499 #if PBYTE_ORDER==PLITTLE_ENDIAN
01500 typedef PIntReversedOrder<double> PFloat64b;
01501 #elif PBYTE_ORDER==PBIG_ENDIAN
01502 typedef PIntSameOrder<double> PFloat64b;
01503 #endif
01504 
01505 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
01506 #if PBYTE_ORDER==PLITTLE_ENDIAN
01507 typedef PIntSameOrder<long double> PFloat80l;
01508 #elif PBYTE_ORDER==PBIG_ENDIAN
01509 typedef PIntReversedOrder<long double> PFloat80l;
01510 #endif
01511 
01512 #if PBYTE_ORDER==PLITTLE_ENDIAN
01513 typedef PIntReversedOrder<long double> PFloat80b;
01514 #elif PBYTE_ORDER==PBIG_ENDIAN
01515 typedef PIntSameOrder<long double> PFloat80b;
01516 #endif
01517 #endif
01518 
01519 
01521 // Miscellaneous
01522 
01523 /*$MACRO PARRAYSIZE(array)
01524    This macro is used to calculate the number of array elements in a static
01525    array.
01526  */
01527 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01528 
01529 /*$MACRO PMIN(v1, v2)
01530    This macro is used to calculate the minimum of two values. As this is a
01531    macro the expression in <code>v1</code> or <code>v2</code> is executed
01532    twice so extreme care should be made in its use.
01533  */
01534 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01535 
01536 /*$MACRO PMAX(v1, v2)
01537    This macro is used to calculate the maximum of two values. As this is a
01538    macro the expression in <code>v1</code> or <code>v2</code> is executed
01539    twice so extreme care should be made in its use.
01540  */
01541 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01542 
01543 /*$MACRO PABS(val)
01544    This macro is used to calculate an absolute value. As this is a macro the
01545    expression in <code>val</code> is executed twice so extreme care should be
01546    made in its use.
01547  */
01548 #define PABS(v) ((v) < 0 ? -(v) : (v))
01549 
01550 
01551 #endif // PTLIB_OBJECT_H
01552 
01553 
01554 // End Of File ///////////////////////////////////////////////////////////////
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines