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
00959 #define PCLASSINFO(cls, par) \
00960 public: \
00961 static inline const char * Class() \
00962 { return #cls; } \
00963 virtual PBoolean InternalIsDescendant(const char * clsName) const \
00964 { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
00965 virtual const char * GetClass(unsigned ancestor = 0) const \
00966 { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
00967 virtual Comparison CompareObjectMemoryDirect(const PObject & _obj) const \
00968 { return (Comparison)memcmp(this, &_obj, sizeof(cls)); } \
00969 PNEW_AND_DELETE_FUNCTIONS
00970
00971
00972 #if P_HAS_TYPEINFO
00973
00974 #define PIsDescendant(ptr, cls) (dynamic_cast<const cls *>(ptr) != NULL)
00975 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
00976
00977 #define PRemoveConst(cls, ptr) (const_cast<cls*>(ptr))
00978
00979 #if P_USE_ASSERTS
00980 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line)
00981 { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
00982 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
00983 #else
00984 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
00985 #endif
00986
00987 #include <typeinfo>
00988
00989 #else // P_HAS_TYPEINFO
00990
00991 #define PIsDescendant(ptr, cls) ((ptr)->InternalIsDescendant(cls::Class()))
00992 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
00993
00994 #define PRemoveConst(cls, ptr) ((cls*)(ptr))
00995
00996 #if P_USE_ASSERTS
00997 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line)
00998 { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
00999 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
01000 #else
01001 #define PDownCast(cls, ptr) ((cls*)(ptr))
01002 #endif
01003
01004 #endif // P_HAS_TYPEINFO
01005
01006
01015 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
01016 #ifdef DOC_PLUS_PLUS
01017 } Match previous opening brace in doc++
01018 #endif
01019
01021
01022
01027 class PObject {
01028
01029 protected:
01033 PObject() { }
01034
01035 public:
01036
01037
01038
01039 virtual ~PObject() { }
01040
01053 static inline const char * Class() { return "PObject"; }
01054
01067 virtual const char * GetClass(unsigned = 0) const { return Class(); }
01068
01069 PBoolean IsClass(const char * cls) const
01070 { return strcmp(cls, GetClass()) == 0; }
01071
01081 virtual PBoolean InternalIsDescendant(
01082 const char * clsName
01083 ) const
01084 { return IsClass(clsName); }
01085
01087
01093 enum Comparison {
01094 LessThan = -1,
01095 EqualTo = 0,
01096 GreaterThan = 1
01097 };
01098
01110 virtual Comparison Compare(
01111 const PObject & obj
01112 ) const;
01113
01125 virtual Comparison CompareObjectMemoryDirect(
01126 const PObject & obj
01127 ) const;
01128
01134 bool operator==(
01135 const PObject & obj
01136 ) const { return Compare(obj) == EqualTo; }
01137
01143 bool operator!=(
01144 const PObject & obj
01145 ) const { return Compare(obj) != EqualTo; }
01146
01152 bool operator<(
01153 const PObject & obj
01154 ) const { return Compare(obj) == LessThan; }
01155
01161 bool operator>(
01162 const PObject & obj
01163 ) const { return Compare(obj) == GreaterThan; }
01164
01170 bool operator<=(
01171 const PObject & obj
01172 ) const { return Compare(obj) != GreaterThan; }
01173
01179 bool operator>=(
01180 const PObject & obj
01181 ) const { return Compare(obj) != LessThan; }
01183
01192 virtual void PrintOn(
01193 ostream &strm
01194 ) const;
01195
01202 virtual void ReadFrom(
01203 istream &strm
01204 );
01205
01206
01212 inline friend ostream & operator<<(
01213 ostream &strm,
01214 const PObject & obj
01215 ) { obj.PrintOn(strm); return strm; }
01216
01222 inline friend istream & operator>>(
01223 istream &strm,
01224 PObject & obj
01225 ) { obj.ReadFrom(strm); return strm; }
01226
01227
01242 virtual PObject * Clone() const;
01243
01255 virtual PINDEX HashFunction() const;
01257 };
01258
01260
01261
01262
01263
01264
01265
01266
01267 #define PANSI_CHAR 1
01268 #define PLITTLE_ENDIAN 2
01269 #define PBIG_ENDIAN 3
01270
01271
01272 #if 0
01273 class PStandardType
01274
01275
01276
01277
01278
01279
01280 {
01281 public:
01282 PStandardType(
01283 type newVal
01284 ) { data = newVal; }
01285
01286
01287
01288
01289 operator type() { return data; }
01290
01291
01292
01293
01294
01295
01296 friend ostream & operator<<(ostream & strm, const PStandardType & val)
01297 { return strm << (type)val; }
01298
01299
01300
01301
01302
01303
01304 friend istream & operator>>(istream & strm, PStandardType & val)
01305 { type data; strm >> data; val = PStandardType(data); return strm; }
01306
01307
01308
01309
01310
01311
01312
01313 private:
01314 type data;
01315 };
01316 #endif
01317
01318
01319 #define PI_SAME(name, type) \
01320 struct name { \
01321 name() : data(0) { } \
01322 name(type value) : data(value) { } \
01323 name(const name & value) : data(value.data) { } \
01324 name & operator =(type value) { data = value; return *this; } \
01325 name & operator =(const name & value) { data = value.data; return *this; } \
01326 operator type() const { return data; } \
01327 friend ostream & operator<<(ostream & s, const name & v) { return s << v.data; } \
01328 friend istream & operator>>(istream & s, name & v) { return s >> v.data; } \
01329 private: type data; \
01330 }
01331
01332 #define PI_LOOP(src, dst) \
01333 BYTE *s = ((BYTE *)&src)+sizeof(src); BYTE *d = (BYTE *)&dst; \
01334 while (s != (BYTE *)&src) *d++ = *--s;
01335
01336 #define PI_DIFF(name, type) \
01337 struct name { \
01338 name() : data(0) { } \
01339 name(type value) : data(0) { operator=(value); } \
01340 name(const name & value) : data(value.data) { } \
01341 name & operator =(type value) { PI_LOOP(value, data); return *this; } \
01342 name & operator =(const name & value) { data = value.data; return *this; } \
01343 operator type() const { type value; PI_LOOP(data, value); return value; } \
01344 friend ostream & operator<<(ostream & s, const name & value) { return s << (type)value; } \
01345 friend istream & operator>>(istream & s, name & v) { type val; s >> val; v = val; return s; } \
01346 private: type data; \
01347 }
01348
01349 #ifndef PCHAR8
01350 #define PCHAR8 PANSI_CHAR
01351 #endif
01352
01353 #if PCHAR8==PANSI_CHAR
01354 PI_SAME(PChar8, char);
01355 #endif
01356
01357 PI_SAME(PInt8, char);
01358
01359 PI_SAME(PUInt8, unsigned char);
01360
01361 #if PBYTE_ORDER==PLITTLE_ENDIAN
01362 PI_SAME(PInt16l, PInt16);
01363 #elif PBYTE_ORDER==PBIG_ENDIAN
01364 PI_DIFF(PInt16l, PInt16);
01365 #endif
01366
01367 #if PBYTE_ORDER==PLITTLE_ENDIAN
01368 PI_DIFF(PInt16b, PInt16);
01369 #elif PBYTE_ORDER==PBIG_ENDIAN
01370 PI_SAME(PInt16b, PInt16);
01371 #endif
01372
01373 #if PBYTE_ORDER==PLITTLE_ENDIAN
01374 PI_SAME(PUInt16l, WORD);
01375 #elif PBYTE_ORDER==PBIG_ENDIAN
01376 PI_DIFF(PUInt16l, WORD);
01377 #endif
01378
01379 #if PBYTE_ORDER==PLITTLE_ENDIAN
01380 PI_DIFF(PUInt16b, WORD);
01381 #elif PBYTE_ORDER==PBIG_ENDIAN
01382 PI_SAME(PUInt16b, WORD);
01383 #endif
01384
01385 #if PBYTE_ORDER==PLITTLE_ENDIAN
01386 PI_SAME(PInt32l, PInt32);
01387 #elif PBYTE_ORDER==PBIG_ENDIAN
01388 PI_DIFF(PInt32l, PInt32);
01389 #endif
01390
01391 #if PBYTE_ORDER==PLITTLE_ENDIAN
01392 PI_DIFF(PInt32b, PInt32);
01393 #elif PBYTE_ORDER==PBIG_ENDIAN
01394 PI_SAME(PInt32b, PInt32);
01395 #endif
01396
01397 #if PBYTE_ORDER==PLITTLE_ENDIAN
01398 PI_SAME(PUInt32l, DWORD);
01399 #elif PBYTE_ORDER==PBIG_ENDIAN
01400 PI_DIFF(PUInt32l, DWORD);
01401 #endif
01402
01403 #if PBYTE_ORDER==PLITTLE_ENDIAN
01404 PI_DIFF(PUInt32b, DWORD);
01405 #elif PBYTE_ORDER==PBIG_ENDIAN
01406 PI_SAME(PUInt32b, DWORD);
01407 #endif
01408
01409 #if PBYTE_ORDER==PLITTLE_ENDIAN
01410 PI_SAME(PInt64l, PInt64);
01411 #elif PBYTE_ORDER==PBIG_ENDIAN
01412 PI_DIFF(PInt64l, PInt64);
01413 #endif
01414
01415 #if PBYTE_ORDER==PLITTLE_ENDIAN
01416 PI_DIFF(PInt64b, PInt64);
01417 #elif PBYTE_ORDER==PBIG_ENDIAN
01418 PI_SAME(PInt64b, PInt64);
01419 #endif
01420
01421 #if PBYTE_ORDER==PLITTLE_ENDIAN
01422 PI_SAME(PUInt64l, PUInt64);
01423 #elif PBYTE_ORDER==PBIG_ENDIAN
01424 PI_DIFF(PUInt64l, PUInt64);
01425 #endif
01426
01427 #if PBYTE_ORDER==PLITTLE_ENDIAN
01428 PI_DIFF(PUInt64b, PUInt64);
01429 #elif PBYTE_ORDER==PBIG_ENDIAN
01430 PI_SAME(PUInt64b, PUInt64);
01431 #endif
01432
01433 #if PBYTE_ORDER==PLITTLE_ENDIAN
01434 PI_SAME(PFloat32l, float);
01435 #elif PBYTE_ORDER==PBIG_ENDIAN
01436 PI_DIFF(PFloat32l, float);
01437 #endif
01438
01439 #if PBYTE_ORDER==PLITTLE_ENDIAN
01440 PI_DIFF(PFloat32b, float);
01441 #elif PBYTE_ORDER==PBIG_ENDIAN
01442 PI_SAME(PFloat32b, float);
01443 #endif
01444
01445 #if PBYTE_ORDER==PLITTLE_ENDIAN
01446 PI_SAME(PFloat64l, double);
01447 #elif PBYTE_ORDER==PBIG_ENDIAN
01448 PI_DIFF(PFloat64l, double);
01449 #endif
01450
01451 #if PBYTE_ORDER==PLITTLE_ENDIAN
01452 PI_DIFF(PFloat64b, double);
01453 #elif PBYTE_ORDER==PBIG_ENDIAN
01454 PI_SAME(PFloat64b, double);
01455 #endif
01456
01457 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
01458 #if PBYTE_ORDER==PLITTLE_ENDIAN
01459 PI_SAME(PFloat80l, long double);
01460 #elif PBYTE_ORDER==PBIG_ENDIAN
01461 PI_DIFF(PFloat80l, long double);
01462 #endif
01463
01464 #if PBYTE_ORDER==PLITTLE_ENDIAN
01465 PI_DIFF(PFloat80b, long double);
01466 #elif PBYTE_ORDER==PBIG_ENDIAN
01467 PI_SAME(PFloat80b, long double);
01468 #endif
01469 #endif
01470
01471 #undef PI_LOOP
01472 #undef PI_SAME
01473 #undef PI_DIFF
01474
01475
01477
01478
01479
01480
01481
01482
01483 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01484
01485
01486
01487
01488
01489
01490 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01491
01492
01493
01494
01495
01496
01497 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01498
01499
01500
01501
01502
01503
01504 #define PABS(v) ((v) < 0 ? -(v) : (v))
01505
01506
01507 #endif // PTLIB_OBJECT_H
01508
01509
01510