00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
00098
00099
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
00114
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
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
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
00506
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
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
00679
00680
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,
00721 const char * file,
00722 int line,
00723 const char * className
00724 );
00725 Validation InternalValidate(
00726 const void * ptr,
00727 const char * className,
00728 ostream * error
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
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
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
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
01113
01118 class PObject {
01119
01120 protected:
01124 PObject() { }
01125
01126 public:
01127
01128
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
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
01203 ) const;
01204
01216 virtual Comparison CompareObjectMemoryDirect(
01217 const PObject & obj
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
01234 ) const { return Compare(obj) == EqualTo; }
01235
01241 bool operator!=(
01242 const PObject & obj
01243 ) const { return Compare(obj) != EqualTo; }
01244
01250 bool operator<(
01251 const PObject & obj
01252 ) const { return Compare(obj) == LessThan; }
01253
01259 bool operator>(
01260 const PObject & obj
01261 ) const { return Compare(obj) == GreaterThan; }
01262
01268 bool operator<=(
01269 const PObject & obj
01270 ) const { return Compare(obj) != GreaterThan; }
01271
01277 bool operator>=(
01278 const PObject & obj
01279 ) const { return Compare(obj) != LessThan; }
01281
01290 virtual void PrintOn(
01291 ostream &strm
01292 ) const;
01293
01300 virtual void ReadFrom(
01301 istream &strm
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
01359
01360
01361
01362
01363
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
01533
01534
01535
01536
01537
01538 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01539
01540
01541
01542
01543
01544
01545 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01546
01547
01548
01549
01550
01551
01552 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01553
01554
01555
01556
01557
01558
01559 #define PABS(v) ((v) < 0 ? -(v) : (v))
01560
01561
01562 #endif // PTLIB_OBJECT_H
01563
01564
01565