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: 28201 $
00030  * $Author: rjongbloed $
00031  * $Date: 2012-08-14 21:30:31 -0500 (Tue, 14 Aug 2012) $
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 #include <vector>
00062 #include <list>
00063 #include <map>
00064 #include <algorithm>
00065 
00066 
00067 #define P_REMOVE_VIRTUAL_INTERNAL_BASE(fn) __inline virtual struct ptlib_virtual_function_changed_or_removed ****** fn { return 0; }
00068 
00069 #if defined(_MSC_VER)
00070   #if _MSC_VER < 1310
00071     #define P_DEPRECATED
00072     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
00073   #elif _MSC_VER < 1400
00074     #define P_DEPRECATED __declspec(deprecated)
00075     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated) type fn body
00076   #else
00077     #define P_DEPRECATED __declspec(deprecated)
00078     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated("Virtual function signature changed or function deprecated")) type fn body
00079   #endif
00080 #elif defined(__GNUC__)
00081   #if __GNUC__ < 4
00082     #define P_DEPRECATED
00083     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
00084   #else
00085     #define P_DEPRECATED __attribute__((deprecated))
00086     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __attribute__((warn_unused_result)) __attribute__((deprecated)) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
00087   #endif
00088 #else
00089     #define P_DEPRECATED
00090     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
00091 #endif
00092 
00093 #define P_REMOVE_VIRTUAL_VOID(fn)       P_REMOVE_VIRTUAL_INTERNAL(void, fn, {})
00094 #define P_REMOVE_VIRTUAL(type, fn, ret) P_REMOVE_VIRTUAL_INTERNAL(type, fn, { return ret; })
00095 
00096 
00097 // P_USE_INTEGER_BOOL is the default and gives the old behaviour (it
00098 // is also used for C translation units).
00099 // without P_USE_INTEGER_BOOL, the ANSI C++ bool is used.
00100 
00101 #if defined(P_USE_INTEGER_BOOL) || !defined(__cplusplus)
00102    typedef BOOL PBoolean;
00103 #  define PTrue TRUE
00104 #  define PFalse FALSE
00105 #else
00106    typedef bool PBoolean;
00107 #  define PTrue true
00108 #  define PFalse false
00109 #endif
00110 
00111 
00113 // Disable inlines when debugging for faster compiles (the compiler doesn't
00114 // actually inline the function with debug on any way).
00115 
00116 #ifndef P_USE_INLINES
00117 #ifdef _DEBUG
00118 #define P_USE_INLINES 0
00119 #else
00120 #define P_USE_INLINES 0
00121 #endif
00122 #endif
00123 
00124 #if P_USE_INLINES
00125 #define PINLINE inline
00126 #else
00127 #define PINLINE
00128 #endif
00129 
00130 
00132 // Declare the debugging support
00133 
00134 #ifndef P_USE_ASSERTS
00135 #define P_USE_ASSERTS 1
00136 #endif
00137 
00138 #if !P_USE_ASSERTS
00139 
00140 #define PAssert(b, m) (b)
00141 #define PAssert2(b, c, m) (b)
00142 #define PAssertOS(b) (b)
00143 #define PAssertNULL(p) (p)
00144 #define PAssertAlways(m) {}
00145 #define PAssertAlways2(c, m) {}
00146 
00147 #else // P_USE_ASSERTS
00148 
00150 enum PStandardAssertMessage {
00151   PLogicError,              
00152   POutOfMemory,             
00153   PNullPointerReference,    
00154   PInvalidCast,             
00155   PInvalidArrayIndex,       
00156   PInvalidArrayElement,     
00157   PStackEmpty,              
00158   PUnimplementedFunction,   
00159   PInvalidParameter,        
00160   POperatingSystemError,    
00161   PChannelNotOpen,          
00162   PUnsupportedFeature,      
00163   PInvalidWindow,           
00164   PMaxStandardAssertMessage 
00165 };
00166 
00167 #define __CLASS__ NULL
00168 
00169 void PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
00170 void PAssertFunc(const char * file, int line, const char * className, const char * msg);
00171 void PAssertFunc(const char * full_msg);
00172 
00173 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, PStandardAssertMessage msg)
00174 {
00175   if (!b) 
00176     PAssertFunc(file, line, className, msg);
00177   return b;
00178 }
00179 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, const char * msg)
00180 {
00181   if (!b) 
00182     PAssertFunc(file, line, className, msg);
00183   return b;
00184 }
00185 
00192 #define PAssert(b, msg) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,(msg))
00193 
00201 #define PAssert2(b, cls, msg) PAssertFuncInline((b), __FILE__,__LINE__,(cls),(msg))
00202 
00209 #define PAssertOS(b) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,POperatingSystemError)
00210 
00220 #define PAssertNULL(ptr) (((ptr)!=NULL)?(ptr): \
00221                      (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(ptr)))
00222 
00229 #define PAssertAlways(msg) PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg))
00230 
00237 #define PAssertAlways2(cls, msg) PAssertFunc(__FILE__,__LINE__,(cls),(msg))
00238 
00239 #endif // P_USE_ASSERTS
00240 
00241 
00246 ostream & PGetErrorStream();
00247 
00251 void PSetErrorStream(ostream * strm  );
00252 
00267 #define PError (PGetErrorStream())
00268 
00269 
00270 
00272 // Debug and tracing
00273 
00274 #ifndef PTRACING
00275 #define PTRACING 1
00276 #endif
00277 
00278 #if PTRACING
00279 
00292 class PTrace
00293 {
00294 public:
00296   enum Options {
00302     Blocks = 1,
00304     DateAndTime = 2,
00306     Timestamp = 4,
00308     Thread = 8,
00310     TraceLevel = 16,
00312     FileAndLine = 32,
00314     ThreadAddress = 64,
00316     AppendToFile = 128,
00318     GMTTime = 256,
00320     RotateDaily = 512,
00322     RotateHourly = 1024,
00324     RotateMinutely = 2048,
00326     RotateLogMask = RotateDaily + RotateHourly + RotateMinutely,
00330     SystemLogStream = 32768
00331   };
00332 
00333 
00347   static void Initialise(
00348     unsigned level,                               
00349     const char * filename = NULL,                 
00350     unsigned options = Timestamp | Thread | Blocks 
00351   );
00352 
00363   static void Initialise(
00364     unsigned level,                                 
00365     const char * filename,                          
00366     const char * rolloverPattern,                   
00367     unsigned options = Timestamp | Thread | Blocks  
00368   );
00369 
00376   static void SetOptions(
00377     unsigned options 
00378   );
00379 
00388   static void ClearOptions(
00389     unsigned options 
00390   );
00391 
00397   static unsigned GetOptions();
00398 
00404   static void SetLevel(
00405     unsigned level 
00406   );
00407 
00413   static unsigned GetLevel();
00414 
00419   static PBoolean CanTrace(
00420     unsigned level 
00421   );
00422 
00427   static void SetStream(
00428     ostream * out 
00429   );
00430 
00446   static ostream & Begin(
00447     unsigned level,         
00448     const char * fileName,  
00449     int lineNum             
00450   );
00451 
00469   static ostream & End(
00470     ostream & strm 
00471   );
00472 
00476   static void Cleanup();
00477 
00483   class Block {
00484     public:
00486       Block(
00487         const char * fileName, 
00488         int lineNum,           
00489         const char * traceName
00491        );
00492       Block(const Block & obj)
00493         : file(obj.file), line(obj.line), name(obj.name) { }
00495       ~Block();
00496     private:
00497       Block & operator=(const Block &)
00498       { return *this; }
00499       const char * file;
00500       int          line;
00501       const char * name;
00502   };
00503 };
00504 
00505 /* Macro to conditionally declare a parameter to a function to avoid compiler
00506    warning due that parameter only being used in a <code>PTRACE()</code> */
00507 #define PTRACE_PARAM(param) param
00508 
00515 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
00516 
00520 #define PTRACE_LINE() \
00521     if (PTrace::CanTrace(1)) \
00522       PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
00523     else (void)0
00524 
00530 #define PTRACE(level, args) \
00531     if (PTrace::CanTrace(level)) \
00532       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00533     else (void)0
00534 
00542 #define PTRACE_IF(level, cond, args) \
00543     if ((PTrace::CanTrace(level) && (cond))) \
00544       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00545     else (void)0
00546 
00547 #else // PTRACING
00548 
00549 #define PTRACE_PARAM(param)
00550 #define PTRACE_BLOCK(n)
00551 #define PTRACE_LINE()
00552 #define PTRACE(level, arg)
00553 #define PTRACE_IF(level, cond, args)
00554 
00555 #endif // PTRACING
00556 
00557 
00558 
00559 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE)) 
00560 
00561 #define PMEMORY_HEAP 1
00562 
00569 class PMemoryHeap {
00570   public:
00572     PMemoryHeap();
00573 
00574     // Clear up the memory checking subsystem, dumping memory leaks.
00575     ~PMemoryHeap();
00576 
00583     static void * Allocate(
00584       size_t nSize,           
00585       const char * file,      
00586       int line,               
00587       const char * className  
00588     );
00595     static void * Allocate(
00596       size_t count,       
00597       size_t iSize,       
00598       const char * file,  
00599       int line            
00600     );
00601 
00609     static void * Reallocate(
00610       void * ptr,         
00611       size_t nSize,       
00612       const char * file,  
00613       int line            
00614     );
00615 
00621     static void Deallocate(
00622       void * ptr,             
00623       const char * className  
00624     );
00625 
00628     enum Validation {
00629       Ok, Bad, Trashed
00630     };
00638     static Validation Validate(
00639       const void * ptr,       
00640       const char * className, 
00641       ostream * error         
00642     );
00643 
00648     static PBoolean ValidateHeap(
00649       ostream * error = NULL  
00650     );
00651 
00657     static PBoolean SetIgnoreAllocations(
00658       PBoolean ignore  
00659     );
00660 
00664     static void DumpStatistics();
00668     static void DumpStatistics(ostream & strm );
00669 
00670 #if PMEMORY_CHECK
00671     struct State {
00672       DWORD allocationNumber;
00673     };
00674 #else
00675         typedef _CrtMemState State;
00676 #endif
00677 
00678     /* Get memory state.
00679       This returns a state that may be used to determine where to start dumping
00680       objects from.
00681      */
00682     static void GetState(
00683       State & state  
00684     );
00685 
00693     static void DumpObjectsSince(
00694       const State & when    
00695     );
00696 
00702     static void DumpObjectsSince(
00703       const State & when,   
00704       ostream & strm        
00705     );
00706 
00712     static void SetAllocationBreakpoint(
00713       DWORD point   
00714     );
00715 
00716 #if PMEMORY_CHECK
00717 
00718   protected:
00719     void * InternalAllocate(
00720       size_t nSize,           // Number of bytes to allocate.
00721       const char * file,      // Source file name for allocating function.
00722       int line,               // Source file line for allocating function.
00723       const char * className  // Class name for allocating function.
00724     );
00725     Validation InternalValidate(
00726       const void * ptr,       // Pointer to memory block to check
00727       const char * className, // Class name it should be.
00728       ostream * error         // Stream to receive error message (may be NULL)
00729     );
00730     void InternalDumpStatistics(ostream & strm);
00731     void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
00732 
00733     class Wrapper {
00734       public:
00735         Wrapper();
00736         ~Wrapper();
00737         PMemoryHeap * operator->() const { return instance; }
00738       private:
00739         PMemoryHeap * instance;
00740     };
00741     friend class Wrapper;
00742 
00743     enum Flags {
00744       NoLeakPrint = 1
00745     };
00746 
00747 #pragma pack(1)
00748     struct Header {
00749       enum {
00750         // Assure that the Header struct is aligned to 8 byte boundary
00751         NumGuardBytes = 16 - (sizeof(Header *) +
00752                               sizeof(Header *) +
00753                               sizeof(const char *) +
00754                               sizeof(const char *) +
00755                               sizeof(size_t) +
00756                               sizeof(DWORD) +
00757                               sizeof(WORD) +
00758                               sizeof(BYTE)
00759 #if P_PTHREADS
00760                               + sizeof(pthread_t)
00761 #endif
00762                               )%8
00763       };
00764 
00765       Header     * prev;
00766       Header     * next;
00767       const char * className;
00768       const char * fileName;
00769       size_t       size;
00770       DWORD        request;
00771       WORD         line;
00772       BYTE         flags;
00773 #if P_PTHREADS
00774       pthread_t    thread;
00775 #endif
00776       char         guard[NumGuardBytes];
00777 
00778       static char GuardBytes[NumGuardBytes];
00779     };
00780 #pragma pack()
00781 
00782     PBoolean isDestroyed;
00783 
00784     Header * listHead;
00785     Header * listTail;
00786 
00787     static DWORD allocationBreakpoint;
00788     DWORD allocationRequest;
00789     DWORD firstRealObject;
00790     BYTE  flags;
00791 
00792     char  allocFillChar;
00793     char  freeFillChar;
00794 
00795     DWORD currentMemoryUsage;
00796     DWORD peakMemoryUsage;
00797     DWORD currentObjects;
00798     DWORD peakObjects;
00799     DWORD totalObjects;
00800 
00801     ostream * leakDumpStream;
00802 
00803 #if defined(_WIN32)
00804     CRITICAL_SECTION mutex;
00805 #elif defined(P_PTHREADS)
00806     pthread_mutex_t mutex;
00807 #elif defined(P_VXWORKS)
00808     void * mutex;
00809 #endif
00810 
00811 #else
00812 
00813 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
00814     _CrtMemState initialState;
00815 
00816 #endif // PMEMORY_CHECK
00817 };
00818 
00819 
00824 inline void * runtime_malloc(size_t bytes  ) { return malloc(bytes); }
00825 
00830 inline void runtime_free(void * ptr  ) { free(ptr); }
00831 
00832 
00839 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
00840 
00847 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
00848 
00855 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
00856 
00857 
00864 #define free(p) PMemoryHeap::Deallocate(p, NULL)
00865 
00866 
00873 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
00874 
00875 
00890 #define PNEW  new (__FILE__, __LINE__)
00891 
00892 #if !defined(_MSC_VER) || _MSC_VER<1200
00893 #define PSPECIAL_DELETE_FUNCTION
00894 #else
00895 #define PSPECIAL_DELETE_FUNCTION \
00896     void operator delete(void * ptr, const char *, int) \
00897       { PMemoryHeap::Deallocate(ptr, Class()); } \
00898     void operator delete[](void * ptr, const char *, int) \
00899       { PMemoryHeap::Deallocate(ptr, Class()); }
00900 #endif
00901 
00902 #define PNEW_AND_DELETE_FUNCTIONS \
00903     void * operator new(size_t nSize, const char * file, int line) \
00904       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00905     void * operator new(size_t nSize) \
00906       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00907     void operator delete(void * ptr) \
00908       { PMemoryHeap::Deallocate(ptr, Class()); } \
00909     void * operator new(size_t, void * placement) \
00910       { return placement; } \
00911     void operator delete(void *, void *) \
00912       { } \
00913     void * operator new[](size_t nSize, const char * file, int line) \
00914       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00915     void * operator new[](size_t nSize) \
00916       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00917     void operator delete[](void * ptr) \
00918       { PMemoryHeap::Deallocate(ptr, Class()); } \
00919     PSPECIAL_DELETE_FUNCTION
00920 
00921 
00922 inline void * operator new(size_t nSize, const char * file, int line)
00923   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00924 
00925 inline void * operator new[](size_t nSize, const char * file, int line)
00926   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00927 
00928 #ifndef __GNUC__
00929 void * operator new(size_t nSize);
00930 void * operator new[](size_t nSize);
00931 
00932 void operator delete(void * ptr);
00933 void operator delete[](void * ptr);
00934 
00935 #if defined(_MSC_VER) && _MSC_VER>=1200
00936 inline void operator delete(void * ptr, const char *, int)
00937   { PMemoryHeap::Deallocate(ptr, NULL); }
00938 
00939 inline void operator delete[](void * ptr, const char *, int)
00940   { PMemoryHeap::Deallocate(ptr, NULL); }
00941 #endif
00942 #endif
00943 
00944 
00945 class PMemoryHeapIgnoreAllocationsForScope {
00946 public:
00947   PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(true)) { }
00948   ~PMemoryHeapIgnoreAllocationsForScope() { PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations); }
00949 private:
00950   PBoolean previousIgnoreAllocations;
00951 };
00952 
00953 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
00954 
00955 class PMemoryAllocationBreakpoint {
00956 public:
00957   PMemoryAllocationBreakpoint(DWORD point)
00958   {
00959     PMemoryHeap::SetAllocationBreakpoint(point);
00960   }
00961 };
00962 
00963 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
00964 
00965 
00966 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00967 
00968 #define PMEMORY_HEAP 0
00969 
00970 #define PNEW new
00971 
00972 #define PNEW_AND_DELETE_FUNCTIONS
00973 
00974 #define runtime_malloc(s) malloc(s)
00975 #define runtime_free(p) free(p)
00976 
00977 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
00978 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
00979 
00980 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00981 
00982 
00983 
00984 /*
00985  *  Implement "construct on first use" paradigm
00986  */
00987 
00988 template <class GnuAllocator, class Type>
00989 struct PAllocatorTemplate
00990 {
00991   Type * allocate(size_t v)  
00992   {
00993     return GetAllocator().allocate(v);
00994   }
00995 
00996   void deallocate(Type * p, size_t v)  
00997   {
00998     GetAllocator().deallocate(p, v);
00999   }
01000 
01001   private:
01002     static GnuAllocator & GetAllocator()
01003     {
01004       static GnuAllocator instance;
01005       return instance;
01006     }
01007 };
01008 
01009 #define GCC_VERSION (__GNUC__ * 10000 \
01010                    + __GNUC_MINOR__ * 100 \
01011                    + __GNUC_PATCHLEVEL__)
01012 
01013 // Memory pooling allocators
01014 #if defined(__GNUC__) && (GCC_VERSION > 40000) && !defined(P_MINGW) && !defined(P_MACOSX) 
01015 #include <ext/mt_allocator.h>
01016 template <class Type> struct PFixedPoolAllocator    : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
01017 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
01018 
01019 #else
01020 
01021 template <class Type> struct PFixedPoolAllocator    : public PAllocatorTemplate<std::allocator<Type>, Type> { };
01022 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<std::allocator<Type>, Type> { };
01023 #endif
01024 
01025 #define PDECLARE_POOL_ALLOCATOR() \
01026     void * operator new(size_t nSize); \
01027     void * operator new(size_t nSize, const char * file, int line); \
01028     void operator delete(void * ptr); \
01029     void operator delete(void * ptr, const char *, int)
01030 
01031 #define PDEFINE_POOL_ALLOCATOR(cls) \
01032   static PFixedPoolAllocator<cls> cls##_allocator; \
01033   void * cls::operator new(size_t)                           { return cls##_allocator.allocate(1);               } \
01034   void * cls::operator new(size_t, const char *, int)        { return cls##_allocator.allocate(1);               } \
01035   void   cls::operator delete(void * ptr)                    {        cls##_allocator.deallocate((cls *)ptr, 1); } \
01036   void   cls::operator delete(void * ptr, const char *, int) {        cls##_allocator.deallocate((cls *)ptr, 1); }
01037 
01038 
01049 #define PCLASSINFO(cls, par) \
01050   public: \
01051     typedef cls P_thisClass; \
01052     static inline const char * Class() \
01053       { return #cls; } \
01054     virtual PBoolean InternalIsDescendant(const char * clsName) const \
01055       { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
01056     virtual const char * GetClass(unsigned ancestor = 0) const \
01057       { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
01058     virtual PObject::Comparison CompareObjectMemoryDirect(const PObject & obj) const \
01059       { return PObject::InternalCompareObjectMemoryDirect(this, dynamic_cast<const cls *>(&obj), sizeof(cls)); } \
01060     PNEW_AND_DELETE_FUNCTIONS
01061 
01062 
01063 #if P_HAS_TYPEINFO
01064 
01065 #define PIsDescendant(ptr, cls)    (dynamic_cast<const cls *>(ptr) != NULL) 
01066 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str)) 
01067 
01068 #define PRemoveConst(cls, ptr)  (const_cast<cls*>(ptr))
01069 
01070 #if P_USE_ASSERTS
01071 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line) 
01072   { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
01073 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
01074 #else
01075 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
01076 #endif
01077 
01078 #include <typeinfo>
01079 
01080 #else // P_HAS_TYPEINFO
01081 
01082 #define PIsDescendant(ptr, cls)    ((ptr)->InternalIsDescendant(cls::Class()))
01083 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
01084 
01085 #define PRemoveConst(cls, ptr)  ((cls*)(ptr))
01086 
01087 #if P_USE_ASSERTS
01088 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line) 
01089   { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
01090 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
01091 #else
01092 #define PDownCast(cls, ptr) ((cls*)(ptr))
01093 #endif
01094 
01095 #endif // P_HAS_TYPEINFO
01096 
01097 
01106 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
01107 #ifdef DOC_PLUS_PLUS
01108 } Match previous opening brace in doc++
01109 #endif
01110 
01112 // The root of all evil ... umm classes
01113 
01118 class PObject {
01119 
01120   protected:
01124     PObject() { }
01125 
01126   public:
01127     /* Destructor required to get the "virtual". A PObject really has nothing
01128        to destroy.
01129      */
01130     virtual ~PObject() { }
01131 
01144     static inline const char * Class()    { return "PObject"; }
01145 
01158     virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : Class(); }
01159 
01160     PBoolean IsClass(const char * cls) const 
01161     { return strcmp(cls, GetClass()) == 0; }
01162 
01172     virtual PBoolean InternalIsDescendant(
01173       const char * clsName    // Ancestor class name to compare against.
01174     ) const
01175     { return IsClass(clsName); }
01176 
01178 
01184     enum Comparison {
01185       LessThan = -1,
01186       EqualTo = 0,
01187       GreaterThan = 1
01188     };
01189 
01201     virtual Comparison Compare(
01202       const PObject & obj   // Object to compare against.
01203     ) const;
01204     
01216     virtual Comparison CompareObjectMemoryDirect(
01217       const PObject & obj   // Object to compare against.
01218     ) const;
01219 
01221     static Comparison InternalCompareObjectMemoryDirect(
01222       const PObject * obj1,
01223       const PObject * obj2,
01224       PINDEX size
01225     );
01226 
01232     bool operator==(
01233       const PObject & obj   // Object to compare against.
01234     ) const { return Compare(obj) == EqualTo; }
01235 
01241     bool operator!=(
01242       const PObject & obj   // Object to compare against.
01243     ) const { return Compare(obj) != EqualTo; }
01244 
01250     bool operator<(
01251       const PObject & obj   // Object to compare against.
01252     ) const { return Compare(obj) == LessThan; }
01253 
01259     bool operator>(
01260       const PObject & obj   // Object to compare against.
01261     ) const { return Compare(obj) == GreaterThan; }
01262 
01268     bool operator<=(
01269       const PObject & obj   // Object to compare against.
01270     ) const { return Compare(obj) != GreaterThan; }
01271 
01277     bool operator>=(
01278       const PObject & obj   // Object to compare against.
01279     ) const { return Compare(obj) != LessThan; }
01281 
01290     virtual void PrintOn(
01291       ostream &strm   // Stream to print the object into.
01292     ) const;
01293 
01300     virtual void ReadFrom(
01301       istream &strm   // Stream to read the objects contents from.
01302     );
01303 
01304 
01310     inline friend ostream & operator<<(
01311       ostream &strm,       
01312       const PObject & obj  
01313     ) { obj.PrintOn(strm); return strm; }
01314 
01320     inline friend istream & operator>>(
01321       istream &strm,   
01322       PObject & obj    
01323     ) { obj.ReadFrom(strm); return strm; }
01324 
01325 
01340     virtual PObject * Clone() const;
01341 
01353     virtual PINDEX HashFunction() const;
01355 };
01356 
01358 // Platform independent types
01359 
01360 // All these classes encapsulate primitive types such that they may be
01361 // transfered in a platform independent manner. In particular it is used to
01362 // do byte swapping for little endien and big endien processor architectures
01363 // as well as accommodating structure packing rules for memory structures.
01364 
01365 #define PANSI_CHAR 1
01366 #define PLITTLE_ENDIAN 2
01367 #define PBIG_ENDIAN 3
01368 
01369 
01370 template <typename type>
01371 struct PIntSameOrder {
01372   __inline PIntSameOrder()                            : data(0)              { }
01373   __inline PIntSameOrder(type value)                  : data(value)          { }
01374   __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data)     { }
01375   __inline PIntSameOrder & operator=(type value)                             { data = value; return *this; }
01376   __inline PIntSameOrder & operator=(const PIntSameOrder & value)            { data = value.data; return *this; }
01377   __inline operator type() const                                             { return data; }
01378   __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
01379   __inline friend istream & operator>>(istream & s, PIntSameOrder & v)       { return s >> v.data; }
01380 
01381   private:
01382     type data;
01383 };
01384 
01385 
01386 template <typename type>
01387 struct PIntReversedOrder {
01388   __inline PIntReversedOrder()                                : data(0)              { }
01389   __inline PIntReversedOrder(type value)                                             { ReverseBytes(value, data); }
01390   __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data)     { }
01391   __inline PIntReversedOrder & operator=(type value)                                 { ReverseBytes(value, data); return *this; }
01392   __inline PIntReversedOrder & operator=(const PIntReversedOrder & value)            { data = value.data; return *this; }
01393   __inline operator type() const                                                     { type value; ReverseBytes(data, value); return value; }
01394   __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
01395   __inline friend istream & operator>>(istream & s, PIntReversedOrder & v)           { type val; s >> val; v = val; return s; }
01396 
01397   private:
01398     type data;
01399 
01400   static __inline void ReverseBytes(const type & src, type & dst)
01401   {
01402     size_t s = sizeof(type)-1;
01403     for (size_t d = 0; d < sizeof(type); ++d,--s)
01404       ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
01405   }
01406 };
01407 
01408 #ifndef PCHAR8
01409 #define PCHAR8 PANSI_CHAR
01410 #endif
01411 
01412 #if PCHAR8==PANSI_CHAR
01413 typedef PIntSameOrder<char> PChar8;
01414 #endif
01415 
01416 typedef PIntSameOrder<char> PInt8;
01417 
01418 typedef PIntSameOrder<unsigned char> PUInt8;
01419 
01420 #if PBYTE_ORDER==PLITTLE_ENDIAN
01421 typedef PIntSameOrder<PInt16> PInt16l;
01422 #elif PBYTE_ORDER==PBIG_ENDIAN
01423 typedef PIntReversedOrder<PInt16> PInt16l;
01424 #endif
01425 
01426 #if PBYTE_ORDER==PLITTLE_ENDIAN
01427 typedef PIntReversedOrder<PInt16> PInt16b;
01428 #elif PBYTE_ORDER==PBIG_ENDIAN
01429 typedef PIntSameOrder<PInt16> PInt16b;
01430 #endif
01431 
01432 #if PBYTE_ORDER==PLITTLE_ENDIAN
01433 typedef PIntSameOrder<WORD> PUInt16l;
01434 #elif PBYTE_ORDER==PBIG_ENDIAN
01435 typedef PIntReversedOrder<WORD> PUInt16l;
01436 #endif
01437 
01438 #if PBYTE_ORDER==PLITTLE_ENDIAN
01439 typedef PIntReversedOrder<WORD> PUInt16b;
01440 #elif PBYTE_ORDER==PBIG_ENDIAN
01441 typedef PIntSameOrder<WORD> PUInt16b;
01442 #endif
01443 
01444 #if PBYTE_ORDER==PLITTLE_ENDIAN
01445 typedef PIntSameOrder<PInt32> PInt32l;
01446 #elif PBYTE_ORDER==PBIG_ENDIAN
01447 typedef PIntReversedOrder<PInt32> PInt32l;
01448 #endif
01449 
01450 #if PBYTE_ORDER==PLITTLE_ENDIAN
01451 typedef PIntReversedOrder<PInt32> PInt32b;
01452 #elif PBYTE_ORDER==PBIG_ENDIAN
01453 typedef PIntSameOrder<PInt32> PInt32b;
01454 #endif
01455 
01456 #if PBYTE_ORDER==PLITTLE_ENDIAN
01457 typedef PIntSameOrder<DWORD> PUInt32l;
01458 #elif PBYTE_ORDER==PBIG_ENDIAN
01459 typedef PIntReversedOrder<DWORD> PUInt32l;
01460 #endif
01461 
01462 #if PBYTE_ORDER==PLITTLE_ENDIAN
01463 typedef PIntReversedOrder<DWORD> PUInt32b;
01464 #elif PBYTE_ORDER==PBIG_ENDIAN
01465 typedef PIntSameOrder<DWORD> PUInt32b;
01466 #endif
01467 
01468 #if PBYTE_ORDER==PLITTLE_ENDIAN
01469 typedef PIntSameOrder<PInt64> PInt64l;
01470 #elif PBYTE_ORDER==PBIG_ENDIAN
01471 typedef PIntReversedOrder<PInt64> PInt64l;
01472 #endif
01473 
01474 #if PBYTE_ORDER==PLITTLE_ENDIAN
01475 typedef PIntReversedOrder<PInt64> PInt64b;
01476 #elif PBYTE_ORDER==PBIG_ENDIAN
01477 typedef PIntSameOrder<PInt64> PInt64b;
01478 #endif
01479 
01480 #if PBYTE_ORDER==PLITTLE_ENDIAN
01481 typedef PIntSameOrder<PUInt64> PUInt64l;
01482 #elif PBYTE_ORDER==PBIG_ENDIAN
01483 typedef PIntReversedOrder<PUInt64> PUInt64l;
01484 #endif
01485 
01486 #if PBYTE_ORDER==PLITTLE_ENDIAN
01487 typedef PIntReversedOrder<PUInt64> PUInt64b;
01488 #elif PBYTE_ORDER==PBIG_ENDIAN
01489 typedef PIntSameOrder<PUInt64> PUInt64b;
01490 #endif
01491 
01492 #if PBYTE_ORDER==PLITTLE_ENDIAN
01493 typedef PIntSameOrder<float> PFloat32l;
01494 #elif PBYTE_ORDER==PBIG_ENDIAN
01495 typedef PIntReversedOrder<float> PFloat32l;
01496 #endif
01497 
01498 #if PBYTE_ORDER==PLITTLE_ENDIAN
01499 typedef PIntReversedOrder<float> PFloat32b;
01500 #elif PBYTE_ORDER==PBIG_ENDIAN
01501 typedef PIntSameOrder<float> PFloat32b;
01502 #endif
01503 
01504 #if PBYTE_ORDER==PLITTLE_ENDIAN
01505 typedef PIntSameOrder<double> PFloat64l;
01506 #elif PBYTE_ORDER==PBIG_ENDIAN
01507 typedef PIntReversedOrder<double> PFloat64l;
01508 #endif
01509 
01510 #if PBYTE_ORDER==PLITTLE_ENDIAN
01511 typedef PIntReversedOrder<double> PFloat64b;
01512 #elif PBYTE_ORDER==PBIG_ENDIAN
01513 typedef PIntSameOrder<double> PFloat64b;
01514 #endif
01515 
01516 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
01517 #if PBYTE_ORDER==PLITTLE_ENDIAN
01518 typedef PIntSameOrder<long double> PFloat80l;
01519 #elif PBYTE_ORDER==PBIG_ENDIAN
01520 typedef PIntReversedOrder<long double> PFloat80l;
01521 #endif
01522 
01523 #if PBYTE_ORDER==PLITTLE_ENDIAN
01524 typedef PIntReversedOrder<long double> PFloat80b;
01525 #elif PBYTE_ORDER==PBIG_ENDIAN
01526 typedef PIntSameOrder<long double> PFloat80b;
01527 #endif
01528 #endif
01529 
01530 
01532 // Miscellaneous
01533 
01534 /*$MACRO PARRAYSIZE(array)
01535    This macro is used to calculate the number of array elements in a static
01536    array.
01537  */
01538 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01539 
01540 /*$MACRO PMIN(v1, v2)
01541    This macro is used to calculate the minimum of two values. As this is a
01542    macro the expression in <code>v1</code> or <code>v2</code> is executed
01543    twice so extreme care should be made in its use.
01544  */
01545 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01546 
01547 /*$MACRO PMAX(v1, v2)
01548    This macro is used to calculate the maximum of two values. As this is a
01549    macro the expression in <code>v1</code> or <code>v2</code> is executed
01550    twice so extreme care should be made in its use.
01551  */
01552 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01553 
01554 /*$MACRO PABS(val)
01555    This macro is used to calculate an absolute value. As this is a macro the
01556    expression in <code>val</code> is executed twice so extreme care should be
01557    made in its use.
01558  */
01559 #define PABS(v) ((v) < 0 ? -(v) : (v))
01560 
01561 
01562 #endif // PTLIB_OBJECT_H
01563 
01564 
01565 // End Of File ///////////////////////////////////////////////////////////////

Generated on Fri Feb 15 20:58:31 2013 for PTLib by  doxygen 1.4.7