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

Generated on Mon Feb 21 20:10:42 2011 for PTLib by  doxygen 1.4.7