PTLib
Version 2.10.4
|
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: 26785 $ 00030 * $Author: rjongbloed $ 00031 * $Date: 2011-12-08 17:41:53 -0600 (Thu, 08 Dec 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::InternalCompareObjectMemoryDirect(this, dynamic_cast<const cls *>(&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 01217 static Comparison InternalCompareObjectMemoryDirect( 01218 const PObject * obj1, 01219 const PObject * obj2, 01220 PINDEX size 01221 ); 01222 01228 bool operator==( 01229 const PObject & obj // Object to compare against. 01230 ) const { return Compare(obj) == EqualTo; } 01231 01237 bool operator!=( 01238 const PObject & obj // Object to compare against. 01239 ) const { return Compare(obj) != EqualTo; } 01240 01246 bool operator<( 01247 const PObject & obj // Object to compare against. 01248 ) const { return Compare(obj) == LessThan; } 01249 01255 bool operator>( 01256 const PObject & obj // Object to compare against. 01257 ) const { return Compare(obj) == GreaterThan; } 01258 01264 bool operator<=( 01265 const PObject & obj // Object to compare against. 01266 ) const { return Compare(obj) != GreaterThan; } 01267 01273 bool operator>=( 01274 const PObject & obj // Object to compare against. 01275 ) const { return Compare(obj) != LessThan; } 01277 01286 virtual void PrintOn( 01287 ostream &strm // Stream to print the object into. 01288 ) const; 01289 01296 virtual void ReadFrom( 01297 istream &strm // Stream to read the objects contents from. 01298 ); 01299 01300 01306 inline friend ostream & operator<<( 01307 ostream &strm, 01308 const PObject & obj 01309 ) { obj.PrintOn(strm); return strm; } 01310 01316 inline friend istream & operator>>( 01317 istream &strm, 01318 PObject & obj 01319 ) { obj.ReadFrom(strm); return strm; } 01320 01321 01336 virtual PObject * Clone() const; 01337 01349 virtual PINDEX HashFunction() const; 01351 }; 01352 01354 // Platform independent types 01355 01356 // All these classes encapsulate primitive types such that they may be 01357 // transfered in a platform independent manner. In particular it is used to 01358 // do byte swapping for little endien and big endien processor architectures 01359 // as well as accommodating structure packing rules for memory structures. 01360 01361 #define PANSI_CHAR 1 01362 #define PLITTLE_ENDIAN 2 01363 #define PBIG_ENDIAN 3 01364 01365 01366 template <typename type> 01367 struct PIntSameOrder { 01368 __inline PIntSameOrder() : data(0) { } 01369 __inline PIntSameOrder(type value) : data(value) { } 01370 __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data) { } 01371 __inline PIntSameOrder & operator=(type value) { data = value; return *this; } 01372 __inline PIntSameOrder & operator=(const PIntSameOrder & value) { data = value.data; return *this; } 01373 __inline operator type() const { return data; } 01374 __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; } 01375 __inline friend istream & operator>>(istream & s, PIntSameOrder & v) { return s >> v.data; } 01376 01377 private: 01378 type data; 01379 }; 01380 01381 01382 template <typename type> 01383 struct PIntReversedOrder { 01384 __inline PIntReversedOrder() : data(0) { } 01385 __inline PIntReversedOrder(type value) { ReverseBytes(value, data); } 01386 __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data) { } 01387 __inline PIntReversedOrder & operator=(type value) { ReverseBytes(value, data); return *this; } 01388 __inline PIntReversedOrder & operator=(const PIntReversedOrder & value) { data = value.data; return *this; } 01389 __inline operator type() const { type value; ReverseBytes(data, value); return value; } 01390 __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; } 01391 __inline friend istream & operator>>(istream & s, PIntReversedOrder & v) { type val; s >> val; v = val; return s; } 01392 01393 private: 01394 type data; 01395 01396 static __inline void ReverseBytes(const type & src, type & dst) 01397 { 01398 size_t s = sizeof(type)-1; 01399 for (size_t d = 0; d < sizeof(type); ++d,--s) 01400 ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s]; 01401 } 01402 }; 01403 01404 #ifndef PCHAR8 01405 #define PCHAR8 PANSI_CHAR 01406 #endif 01407 01408 #if PCHAR8==PANSI_CHAR 01409 typedef PIntSameOrder<char> PChar8; 01410 #endif 01411 01412 typedef PIntSameOrder<char> PInt8; 01413 01414 typedef PIntSameOrder<unsigned char> PUInt8; 01415 01416 #if PBYTE_ORDER==PLITTLE_ENDIAN 01417 typedef PIntSameOrder<PInt16> PInt16l; 01418 #elif PBYTE_ORDER==PBIG_ENDIAN 01419 typedef PIntReversedOrder<PInt16> PInt16l; 01420 #endif 01421 01422 #if PBYTE_ORDER==PLITTLE_ENDIAN 01423 typedef PIntReversedOrder<PInt16> PInt16b; 01424 #elif PBYTE_ORDER==PBIG_ENDIAN 01425 typedef PIntSameOrder<PInt16> PInt16b; 01426 #endif 01427 01428 #if PBYTE_ORDER==PLITTLE_ENDIAN 01429 typedef PIntSameOrder<WORD> PUInt16l; 01430 #elif PBYTE_ORDER==PBIG_ENDIAN 01431 typedef PIntReversedOrder<WORD> PUInt16l; 01432 #endif 01433 01434 #if PBYTE_ORDER==PLITTLE_ENDIAN 01435 typedef PIntReversedOrder<WORD> PUInt16b; 01436 #elif PBYTE_ORDER==PBIG_ENDIAN 01437 typedef PIntSameOrder<WORD> PUInt16b; 01438 #endif 01439 01440 #if PBYTE_ORDER==PLITTLE_ENDIAN 01441 typedef PIntSameOrder<PInt32> PInt32l; 01442 #elif PBYTE_ORDER==PBIG_ENDIAN 01443 typedef PIntReversedOrder<PInt32> PInt32l; 01444 #endif 01445 01446 #if PBYTE_ORDER==PLITTLE_ENDIAN 01447 typedef PIntReversedOrder<PInt32> PInt32b; 01448 #elif PBYTE_ORDER==PBIG_ENDIAN 01449 typedef PIntSameOrder<PInt32> PInt32b; 01450 #endif 01451 01452 #if PBYTE_ORDER==PLITTLE_ENDIAN 01453 typedef PIntSameOrder<DWORD> PUInt32l; 01454 #elif PBYTE_ORDER==PBIG_ENDIAN 01455 typedef PIntReversedOrder<DWORD> PUInt32l; 01456 #endif 01457 01458 #if PBYTE_ORDER==PLITTLE_ENDIAN 01459 typedef PIntReversedOrder<DWORD> PUInt32b; 01460 #elif PBYTE_ORDER==PBIG_ENDIAN 01461 typedef PIntSameOrder<DWORD> PUInt32b; 01462 #endif 01463 01464 #if PBYTE_ORDER==PLITTLE_ENDIAN 01465 typedef PIntSameOrder<PInt64> PInt64l; 01466 #elif PBYTE_ORDER==PBIG_ENDIAN 01467 typedef PIntReversedOrder<PInt64> PInt64l; 01468 #endif 01469 01470 #if PBYTE_ORDER==PLITTLE_ENDIAN 01471 typedef PIntReversedOrder<PInt64> PInt64b; 01472 #elif PBYTE_ORDER==PBIG_ENDIAN 01473 typedef PIntSameOrder<PInt64> PInt64b; 01474 #endif 01475 01476 #if PBYTE_ORDER==PLITTLE_ENDIAN 01477 typedef PIntSameOrder<PUInt64> PUInt64l; 01478 #elif PBYTE_ORDER==PBIG_ENDIAN 01479 typedef PIntReversedOrder<PUInt64> PUInt64l; 01480 #endif 01481 01482 #if PBYTE_ORDER==PLITTLE_ENDIAN 01483 typedef PIntReversedOrder<PUInt64> PUInt64b; 01484 #elif PBYTE_ORDER==PBIG_ENDIAN 01485 typedef PIntSameOrder<PUInt64> PUInt64b; 01486 #endif 01487 01488 #if PBYTE_ORDER==PLITTLE_ENDIAN 01489 typedef PIntSameOrder<float> PFloat32l; 01490 #elif PBYTE_ORDER==PBIG_ENDIAN 01491 typedef PIntReversedOrder<float> PFloat32l; 01492 #endif 01493 01494 #if PBYTE_ORDER==PLITTLE_ENDIAN 01495 typedef PIntReversedOrder<float> PFloat32b; 01496 #elif PBYTE_ORDER==PBIG_ENDIAN 01497 typedef PIntSameOrder<float> PFloat32b; 01498 #endif 01499 01500 #if PBYTE_ORDER==PLITTLE_ENDIAN 01501 typedef PIntSameOrder<double> PFloat64l; 01502 #elif PBYTE_ORDER==PBIG_ENDIAN 01503 typedef PIntReversedOrder<double> PFloat64l; 01504 #endif 01505 01506 #if PBYTE_ORDER==PLITTLE_ENDIAN 01507 typedef PIntReversedOrder<double> PFloat64b; 01508 #elif PBYTE_ORDER==PBIG_ENDIAN 01509 typedef PIntSameOrder<double> PFloat64b; 01510 #endif 01511 01512 #ifndef NO_LONG_DOUBLE // stupid OSX compiler 01513 #if PBYTE_ORDER==PLITTLE_ENDIAN 01514 typedef PIntSameOrder<long double> PFloat80l; 01515 #elif PBYTE_ORDER==PBIG_ENDIAN 01516 typedef PIntReversedOrder<long double> PFloat80l; 01517 #endif 01518 01519 #if PBYTE_ORDER==PLITTLE_ENDIAN 01520 typedef PIntReversedOrder<long double> PFloat80b; 01521 #elif PBYTE_ORDER==PBIG_ENDIAN 01522 typedef PIntSameOrder<long double> PFloat80b; 01523 #endif 01524 #endif 01525 01526 01528 // Miscellaneous 01529 01530 /*$MACRO PARRAYSIZE(array) 01531 This macro is used to calculate the number of array elements in a static 01532 array. 01533 */ 01534 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0]))) 01535 01536 /*$MACRO PMIN(v1, v2) 01537 This macro is used to calculate the minimum 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 PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2)) 01542 01543 /*$MACRO PMAX(v1, v2) 01544 This macro is used to calculate the maximum of two values. As this is a 01545 macro the expression in <code>v1</code> or <code>v2</code> is executed 01546 twice so extreme care should be made in its use. 01547 */ 01548 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2)) 01549 01550 /*$MACRO PABS(val) 01551 This macro is used to calculate an absolute value. As this is a macro the 01552 expression in <code>val</code> is executed twice so extreme care should be 01553 made in its use. 01554 */ 01555 #define PABS(v) ((v) < 0 ? -(v) : (v)) 01556 01557 01558 #endif // PTLIB_OBJECT_H 01559 01560 01561 // End Of File ///////////////////////////////////////////////////////////////