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, 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
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
00472
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
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
00645
00646
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,
00687 const char * file,
00688 int line,
00689 const char * className
00690 );
00691 Validation InternalValidate(
00692 const void * ptr,
00693 const char * className,
00694 ostream * error
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
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
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
01048
01053 class PObject {
01054
01055 protected:
01059 PObject() { }
01060
01061 public:
01062
01063
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
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
01138 ) const;
01139
01151 virtual Comparison CompareObjectMemoryDirect(
01152 const PObject & obj
01153 ) const;
01154
01160 bool operator==(
01161 const PObject & obj
01162 ) const { return Compare(obj) == EqualTo; }
01163
01169 bool operator!=(
01170 const PObject & obj
01171 ) const { return Compare(obj) != EqualTo; }
01172
01178 bool operator<(
01179 const PObject & obj
01180 ) const { return Compare(obj) == LessThan; }
01181
01187 bool operator>(
01188 const PObject & obj
01189 ) const { return Compare(obj) == GreaterThan; }
01190
01196 bool operator<=(
01197 const PObject & obj
01198 ) const { return Compare(obj) != GreaterThan; }
01199
01205 bool operator>=(
01206 const PObject & obj
01207 ) const { return Compare(obj) != LessThan; }
01209
01218 virtual void PrintOn(
01219 ostream &strm
01220 ) const;
01221
01228 virtual void ReadFrom(
01229 istream &strm
01230 );
01231
01232
01238 inline friend ostream & operator<<(
01239 ostream &strm,
01240 const PObject & obj
01241 ) { obj.PrintOn(strm); return strm; }
01242
01248 inline friend istream & operator>>(
01249 istream &strm,
01250 PObject & obj
01251 ) { obj.ReadFrom(strm); return strm; }
01252
01253
01268 virtual PObject * Clone() const;
01269
01281 virtual PINDEX HashFunction() const;
01283 };
01284
01286
01287
01288
01289
01290
01291
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
01461
01462
01463
01464
01465
01466 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01467
01468
01469
01470
01471
01472
01473 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01474
01475
01476
01477
01478
01479
01480 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01481
01482
01483
01484
01485
01486
01487 #define PABS(v) ((v) < 0 ? -(v) : (v))
01488
01489
01490 #endif // PTLIB_OBJECT_H
01491
01492
01493