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
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
00094
00095
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
00110
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
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
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
00502
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
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
00675
00676
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,
00717 const char * file,
00718 int line,
00719 const char * className
00720 );
00721 Validation InternalValidate(
00722 const void * ptr,
00723 const char * className,
00724 ostream * error
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
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 #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(P_MINGW) && !defined(P_MACOSX)
00981 #include <ext/bitmap_allocator.h>
00982 template <class Type> class PFixedPoolAllocator : public __gnu_cxx::bitmap_allocator<Type> { };
00983 #include <ext/mt_allocator.h>
00984 template <class Type> class PVariablePoolAllocator : public __gnu_cxx::__mt_alloc<Type> { };
00985 #else
00986 template <class Type> class PFixedPoolAllocator : public std::allocator<Type> { };
00987 template <class Type> class PVariablePoolAllocator : public std::allocator<Type> { };
00988 #endif
00989
00990 #define PDECLARE_POOL_ALLOCATOR() \
00991 void * operator new(size_t nSize); \
00992 void * operator new(size_t nSize, const char * file, int line); \
00993 void operator delete(void * ptr); \
00994 void operator delete(void * ptr, const char *, int)
00995
00996 #define PDEFINE_POOL_ALLOCATOR(cls) \
00997 static PFixedPoolAllocator<cls> cls##_allocator; \
00998 void * cls::operator new(size_t) { return cls##_allocator.allocate(1); } \
00999 void * cls::operator new(size_t, const char *, int) { return cls##_allocator.allocate(1); } \
01000 void cls::operator delete(void * ptr) { cls##_allocator.deallocate((cls *)ptr, 1); } \
01001 void cls::operator delete(void * ptr, const char *, int) { cls##_allocator.deallocate((cls *)ptr, 1); }
01002
01003
01004
01015 #define PCLASSINFO(cls, par) \
01016 public: \
01017 typedef cls P_thisClass; \
01018 static inline const char * Class() \
01019 { return #cls; } \
01020 virtual PBoolean InternalIsDescendant(const char * clsName) const \
01021 { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
01022 virtual const char * GetClass(unsigned ancestor = 0) const \
01023 { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
01024 virtual Comparison CompareObjectMemoryDirect(const PObject & _obj) const \
01025 { return (Comparison)memcmp(this, &_obj, sizeof(cls)); } \
01026 PNEW_AND_DELETE_FUNCTIONS
01027
01028
01029 #if P_HAS_TYPEINFO
01030
01031 #define PIsDescendant(ptr, cls) (dynamic_cast<const cls *>(ptr) != NULL)
01032 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
01033
01034 #define PRemoveConst(cls, ptr) (const_cast<cls*>(ptr))
01035
01036 #if P_USE_ASSERTS
01037 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line)
01038 { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
01039 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
01040 #else
01041 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
01042 #endif
01043
01044 #include <typeinfo>
01045
01046 #else // P_HAS_TYPEINFO
01047
01048 #define PIsDescendant(ptr, cls) ((ptr)->InternalIsDescendant(cls::Class()))
01049 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
01050
01051 #define PRemoveConst(cls, ptr) ((cls*)(ptr))
01052
01053 #if P_USE_ASSERTS
01054 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line)
01055 { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
01056 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
01057 #else
01058 #define PDownCast(cls, ptr) ((cls*)(ptr))
01059 #endif
01060
01061 #endif // P_HAS_TYPEINFO
01062
01063
01072 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
01073 #ifdef DOC_PLUS_PLUS
01074 } Match previous opening brace in doc++
01075 #endif
01076
01078
01079
01084 class PObject {
01085
01086 protected:
01090 PObject() { }
01091
01092 public:
01093
01094
01095
01096 virtual ~PObject() { }
01097
01110 static inline const char * Class() { return "PObject"; }
01111
01124 virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : Class(); }
01125
01126 PBoolean IsClass(const char * cls) const
01127 { return strcmp(cls, GetClass()) == 0; }
01128
01138 virtual PBoolean InternalIsDescendant(
01139 const char * clsName
01140 ) const
01141 { return IsClass(clsName); }
01142
01144
01150 enum Comparison {
01151 LessThan = -1,
01152 EqualTo = 0,
01153 GreaterThan = 1
01154 };
01155
01167 virtual Comparison Compare(
01168 const PObject & obj
01169 ) const;
01170
01182 virtual Comparison CompareObjectMemoryDirect(
01183 const PObject & obj
01184 ) const;
01185
01191 bool operator==(
01192 const PObject & obj
01193 ) const { return Compare(obj) == EqualTo; }
01194
01200 bool operator!=(
01201 const PObject & obj
01202 ) const { return Compare(obj) != EqualTo; }
01203
01209 bool operator<(
01210 const PObject & obj
01211 ) const { return Compare(obj) == LessThan; }
01212
01218 bool operator>(
01219 const PObject & obj
01220 ) const { return Compare(obj) == GreaterThan; }
01221
01227 bool operator<=(
01228 const PObject & obj
01229 ) const { return Compare(obj) != GreaterThan; }
01230
01236 bool operator>=(
01237 const PObject & obj
01238 ) const { return Compare(obj) != LessThan; }
01240
01249 virtual void PrintOn(
01250 ostream &strm
01251 ) const;
01252
01259 virtual void ReadFrom(
01260 istream &strm
01261 );
01262
01263
01269 inline friend ostream & operator<<(
01270 ostream &strm,
01271 const PObject & obj
01272 ) { obj.PrintOn(strm); return strm; }
01273
01279 inline friend istream & operator>>(
01280 istream &strm,
01281 PObject & obj
01282 ) { obj.ReadFrom(strm); return strm; }
01283
01284
01299 virtual PObject * Clone() const;
01300
01312 virtual PINDEX HashFunction() const;
01314 };
01315
01317
01318
01319
01320
01321
01322
01323
01324 #define PANSI_CHAR 1
01325 #define PLITTLE_ENDIAN 2
01326 #define PBIG_ENDIAN 3
01327
01328
01329 template <typename type>
01330 struct PIntSameOrder {
01331 __inline PIntSameOrder() : data(0) { }
01332 __inline PIntSameOrder(type value) : data(value) { }
01333 __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data) { }
01334 __inline PIntSameOrder & operator=(type value) { data = value; return *this; }
01335 __inline PIntSameOrder & operator=(const PIntSameOrder & value) { data = value.data; return *this; }
01336 __inline operator type() const { return data; }
01337 __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
01338 __inline friend istream & operator>>(istream & s, PIntSameOrder & v) { return s >> v.data; }
01339
01340 private:
01341 type data;
01342 };
01343
01344
01345 template <typename type>
01346 struct PIntReversedOrder {
01347 __inline PIntReversedOrder() : data(0) { }
01348 __inline PIntReversedOrder(type value) { ReverseBytes(value, data); }
01349 __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data) { }
01350 __inline PIntReversedOrder & operator=(type value) { ReverseBytes(value, data); return *this; }
01351 __inline PIntReversedOrder & operator=(const PIntReversedOrder & value) { data = value.data; return *this; }
01352 __inline operator type() const { type value; ReverseBytes(data, value); return value; }
01353 __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
01354 __inline friend istream & operator>>(istream & s, PIntReversedOrder & v) { type val; s >> val; v = val; return s; }
01355
01356 private:
01357 type data;
01358
01359 static __inline void ReverseBytes(const type & src, type & dst)
01360 {
01361 size_t s = sizeof(type)-1;
01362 for (size_t d = 0; d < sizeof(type); ++d,--s)
01363 ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
01364 }
01365 };
01366
01367 #ifndef PCHAR8
01368 #define PCHAR8 PANSI_CHAR
01369 #endif
01370
01371 #if PCHAR8==PANSI_CHAR
01372 typedef PIntSameOrder<char> PChar8;
01373 #endif
01374
01375 typedef PIntSameOrder<char> PInt8;
01376
01377 typedef PIntSameOrder<unsigned char> PUInt8;
01378
01379 #if PBYTE_ORDER==PLITTLE_ENDIAN
01380 typedef PIntSameOrder<PInt16> PInt16l;
01381 #elif PBYTE_ORDER==PBIG_ENDIAN
01382 typedef PIntReversedOrder<PInt16> PInt16l;
01383 #endif
01384
01385 #if PBYTE_ORDER==PLITTLE_ENDIAN
01386 typedef PIntReversedOrder<PInt16> PInt16b;
01387 #elif PBYTE_ORDER==PBIG_ENDIAN
01388 typedef PIntSameOrder<PInt16> PInt16b;
01389 #endif
01390
01391 #if PBYTE_ORDER==PLITTLE_ENDIAN
01392 typedef PIntSameOrder<WORD> PUInt16l;
01393 #elif PBYTE_ORDER==PBIG_ENDIAN
01394 typedef PIntReversedOrder<WORD> PUInt16l;
01395 #endif
01396
01397 #if PBYTE_ORDER==PLITTLE_ENDIAN
01398 typedef PIntReversedOrder<WORD> PUInt16b;
01399 #elif PBYTE_ORDER==PBIG_ENDIAN
01400 typedef PIntSameOrder<WORD> PUInt16b;
01401 #endif
01402
01403 #if PBYTE_ORDER==PLITTLE_ENDIAN
01404 typedef PIntSameOrder<PInt32> PInt32l;
01405 #elif PBYTE_ORDER==PBIG_ENDIAN
01406 typedef PIntReversedOrder<PInt32> PInt32l;
01407 #endif
01408
01409 #if PBYTE_ORDER==PLITTLE_ENDIAN
01410 typedef PIntReversedOrder<PInt32> PInt32b;
01411 #elif PBYTE_ORDER==PBIG_ENDIAN
01412 typedef PIntSameOrder<PInt32> PInt32b;
01413 #endif
01414
01415 #if PBYTE_ORDER==PLITTLE_ENDIAN
01416 typedef PIntSameOrder<DWORD> PUInt32l;
01417 #elif PBYTE_ORDER==PBIG_ENDIAN
01418 typedef PIntReversedOrder<DWORD> PUInt32l;
01419 #endif
01420
01421 #if PBYTE_ORDER==PLITTLE_ENDIAN
01422 typedef PIntReversedOrder<DWORD> PUInt32b;
01423 #elif PBYTE_ORDER==PBIG_ENDIAN
01424 typedef PIntSameOrder<DWORD> PUInt32b;
01425 #endif
01426
01427 #if PBYTE_ORDER==PLITTLE_ENDIAN
01428 typedef PIntSameOrder<PInt64> PInt64l;
01429 #elif PBYTE_ORDER==PBIG_ENDIAN
01430 typedef PIntReversedOrder<PInt64> PInt64l;
01431 #endif
01432
01433 #if PBYTE_ORDER==PLITTLE_ENDIAN
01434 typedef PIntReversedOrder<PInt64> PInt64b;
01435 #elif PBYTE_ORDER==PBIG_ENDIAN
01436 typedef PIntSameOrder<PInt64> PInt64b;
01437 #endif
01438
01439 #if PBYTE_ORDER==PLITTLE_ENDIAN
01440 typedef PIntSameOrder<PUInt64> PUInt64l;
01441 #elif PBYTE_ORDER==PBIG_ENDIAN
01442 typedef PIntReversedOrder<PUInt64> PUInt64l;
01443 #endif
01444
01445 #if PBYTE_ORDER==PLITTLE_ENDIAN
01446 typedef PIntReversedOrder<PUInt64> PUInt64b;
01447 #elif PBYTE_ORDER==PBIG_ENDIAN
01448 typedef PIntSameOrder<PUInt64> PUInt64b;
01449 #endif
01450
01451 #if PBYTE_ORDER==PLITTLE_ENDIAN
01452 typedef PIntSameOrder<float> PFloat32l;
01453 #elif PBYTE_ORDER==PBIG_ENDIAN
01454 typedef PIntReversedOrder<float> PFloat32l;
01455 #endif
01456
01457 #if PBYTE_ORDER==PLITTLE_ENDIAN
01458 typedef PIntReversedOrder<float> PFloat32b;
01459 #elif PBYTE_ORDER==PBIG_ENDIAN
01460 typedef PIntSameOrder<float> PFloat32b;
01461 #endif
01462
01463 #if PBYTE_ORDER==PLITTLE_ENDIAN
01464 typedef PIntSameOrder<double> PFloat64l;
01465 #elif PBYTE_ORDER==PBIG_ENDIAN
01466 typedef PIntReversedOrder<double> PFloat64l;
01467 #endif
01468
01469 #if PBYTE_ORDER==PLITTLE_ENDIAN
01470 typedef PIntReversedOrder<double> PFloat64b;
01471 #elif PBYTE_ORDER==PBIG_ENDIAN
01472 typedef PIntSameOrder<double> PFloat64b;
01473 #endif
01474
01475 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
01476 #if PBYTE_ORDER==PLITTLE_ENDIAN
01477 typedef PIntSameOrder<long double> PFloat80l;
01478 #elif PBYTE_ORDER==PBIG_ENDIAN
01479 typedef PIntReversedOrder<long double> PFloat80l;
01480 #endif
01481
01482 #if PBYTE_ORDER==PLITTLE_ENDIAN
01483 typedef PIntReversedOrder<long double> PFloat80b;
01484 #elif PBYTE_ORDER==PBIG_ENDIAN
01485 typedef PIntSameOrder<long double> PFloat80b;
01486 #endif
01487 #endif
01488
01489
01491
01492
01493
01494
01495
01496
01497 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01498
01499
01500
01501
01502
01503
01504 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01505
01506
01507
01508
01509
01510
01511 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01512
01513
01514
01515
01516
01517
01518 #define PABS(v) ((v) < 0 ? -(v) : (v))
01519
01520
01521 #endif // PTLIB_OBJECT_H
01522
01523
01524