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 _POBJECT_H
00035 #define _POBJECT_H
00036
00037 #ifdef P_USE_PRAGMA
00038 #pragma interface
00039 #endif
00040
00041 #ifdef _WIN32
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 #ifdef __USE_STL__
00058 #include <string>
00059 #include <iomanip>
00060 #include <iostream>
00061 #if (__GNUC__ >= 3)
00062 #include <sstream>
00063 typedef std::ostringstream ostrstream;
00064 #else
00065 #include <strstream>
00066 #endif
00067
00068 #ifdef _STLP_IOS_BASE_H
00069 typedef std::ios_base::fmtflags _Ios_Fmtflags;
00070 #endif
00071 #else
00072 #if (__GNUC__ >= 3)
00073 #include <iosfwd>
00074 #ifndef __MWERKS__
00075 #include <iomanip>
00076 #endif
00077 #else
00078 #include <iosfwd>
00079 #ifdef __GNUC__
00080 #include <strstream.h>
00081 #else
00082 #include <strstrea.h>
00083 #endif
00084 #ifndef __MWERKS__
00085 #include <iomanip.h>
00086 #endif
00087 #endif
00088 #endif
00089
00090 #if (__GNUC__ < 3) && !defined(_STLP_IOS_BASE_H)
00091 typedef long _Ios_Fmtflags;
00092 #endif
00093
00094 #if _MSC_VER<1300
00095 #define _BADOFF -1
00096 #endif
00097
00098
00099
00100
00101
00102
00103 #if defined(P_USE_INTEGER_BOOL) || !defined(__cplusplus)
00104 typedef BOOL PBoolean;
00105 # define PTrue TRUE
00106 # define PFalse FALSE
00107 #else
00108 typedef bool PBoolean;
00109 # define PTrue true
00110 # define PFalse false
00111 #endif
00112
00113
00115
00116
00117
00118 #ifndef P_USE_INLINES
00119 #ifdef _DEBUG
00120 #define P_USE_INLINES 0
00121 #else
00122 #define P_USE_INLINES 0
00123 #endif
00124 #endif
00125
00126 #if P_USE_INLINES
00127 #define PINLINE inline
00128 #else
00129 #define PINLINE
00130 #endif
00131
00132
00134
00135
00136 #ifndef P_USE_ASSERTS
00137 #define P_USE_ASSERTS 1
00138 #endif
00139
00140 #if !P_USE_ASSERTS
00141
00142 #define PAssert(b, m) (b)
00143 #define PAssert2(b, c, m) (b)
00144 #define PAssertOS(b) (b)
00145 #define PAssertNULL(p) (p)
00146 #define PAssertAlways(m)
00147 #define PAssertAlways2(c, m)
00148
00149 #else // P_USE_ASSERTS
00150
00152 enum PStandardAssertMessage {
00153 PLogicError,
00154 POutOfMemory,
00155 PNullPointerReference,
00156 PInvalidCast,
00157 PInvalidArrayIndex,
00158 PInvalidArrayElement,
00159 PStackEmpty,
00160 PUnimplementedFunction,
00161 PInvalidParameter,
00162 POperatingSystemError,
00163 PChannelNotOpen,
00164 PUnsupportedFeature,
00165 PInvalidWindow,
00166 PMaxStandardAssertMessage
00167 };
00168
00169 #define __CLASS__ NULL
00170
00171 void PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
00172 void PAssertFunc(const char * file, int line, const char * className, const char * msg);
00173 void PAssertFunc(const char * full_msg);
00174
00175 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, PStandardAssertMessage msg)
00176 {
00177 if (!b)
00178 PAssertFunc(file, line, className, msg);
00179 return b;
00180 }
00181 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, const char * msg)
00182 {
00183 if (!b)
00184 PAssertFunc(file, line, className, msg);
00185 return b;
00186 }
00187
00194 #define PAssert(b, m) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,(m))
00195
00203 #define PAssert2(b, c, m) PAssertFuncInline((b), __FILE__,__LINE__,(c),(m))
00204
00211 #define PAssertOS(b) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,POperatingSystemError)
00212
00222 #define PAssertNULL(p) (((p)!=NULL)?(p): \
00223 (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(p)))
00224
00231 #define PAssertAlways(m) PAssertFunc(__FILE__,__LINE__,__CLASS__,(m))
00232
00239 #define PAssertAlways2(c, m) PAssertFunc(__FILE__,__LINE__,(c),(m))
00240
00241 #endif // P_USE_ASSERTS
00242
00243
00248 ostream & PGetErrorStream();
00249
00253 void PSetErrorStream(ostream * strm );
00254
00269 #define PError (PGetErrorStream())
00270
00271
00272
00274
00275
00276 #ifndef PTRACING
00277 #define PTRACING 1
00278 #endif
00279
00280 #if PTRACING
00281
00286 class PTrace
00287 {
00288 public:
00290 enum Options {
00296 Blocks = 1,
00298 DateAndTime = 2,
00300 Timestamp = 4,
00302 Thread = 8,
00304 TraceLevel = 16,
00306 FileAndLine = 32,
00308 ThreadAddress = 64,
00310 AppendToFile = 128,
00313 GMTTime = 256,
00316 RotateDaily = 512,
00320 SystemLogStream = 32768
00321 };
00322
00330 static void Initialise(
00331 unsigned level,
00332 const char * filename = NULL,
00333 unsigned options = Timestamp | Thread | Blocks
00334 );
00335
00346 static void Initialise(
00347 unsigned level,
00348 const char * filename,
00349 const char * rolloverPattern,
00350 unsigned options = Timestamp | Thread | Blocks
00351 );
00352
00359 static void SetOptions(unsigned options );
00360
00368 static void ClearOptions(unsigned options );
00369
00374 static unsigned GetOptions();
00375
00381 static void SetLevel(unsigned level );
00382
00388 static unsigned GetLevel();
00389
00394 static PBoolean CanTrace(unsigned level );
00395
00400 static void SetStream(ostream * out );
00401
00417 static ostream & Begin(
00418 unsigned level,
00419 const char * fileName,
00420 int lineNum
00421 );
00422
00439 static ostream & End(ostream & strm );
00440
00441
00447 class Block {
00448 public:
00450 Block(
00451 const char * fileName,
00452 int lineNum,
00453 const char * traceName
00455 );
00456 Block(const Block & obj)
00457 : file(obj.file), line(obj.line), name(obj.name) { }
00459 ~Block();
00460 private:
00461 Block & operator=(const Block &)
00462 { return *this; }
00463 const char * file;
00464 int line;
00465 const char * name;
00466 };
00467 };
00468
00469
00470
00471 #define PTRACE_PARAM(param) param
00472
00479 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
00480
00484 #define PTRACE_LINE() \
00485 if (!PTrace::CanTrace(1)) ; else \
00486 PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End
00487
00493 #define PTRACE(level, args) \
00494 if (!PTrace::CanTrace(level)) ; else \
00495 PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End
00496
00504 #define PTRACE_IF(level, cond, args) \
00505 if (!(PTrace::CanTrace(level) && (cond))) ; else \
00506 PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End
00507
00508 #else // PTRACING
00509
00510 #define PTRACE_PARAM(param)
00511 #define PTRACE_BLOCK(n)
00512 #define PTRACE_LINE()
00513 #define PTRACE(level, arg)
00514 #define PTRACE_IF(level, cond, args)
00515
00516 #endif // PTRACING
00517
00518
00519
00520 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE))
00521
00522 #define PMEMORY_HEAP 1
00523
00530 class PMemoryHeap {
00531 public:
00533 PMemoryHeap();
00534
00535
00536 ~PMemoryHeap();
00537
00544 static void * Allocate(
00545 size_t nSize,
00546 const char * file,
00547 int line,
00548 const char * className
00549 );
00556 static void * Allocate(
00557 size_t count,
00558 size_t iSize,
00559 const char * file,
00560 int line
00561 );
00562
00570 static void * Reallocate(
00571 void * ptr,
00572 size_t nSize,
00573 const char * file,
00574 int line
00575 );
00576
00582 static void Deallocate(
00583 void * ptr,
00584 const char * className
00585 );
00586
00589 enum Validation {
00590 Ok, Bad, Trashed
00591 };
00599 static Validation Validate(
00600 const void * ptr,
00601 const char * className,
00602 ostream * error
00603 );
00604
00609 static PBoolean ValidateHeap(
00610 ostream * error = NULL
00611 );
00612
00618 static PBoolean SetIgnoreAllocations(
00619 PBoolean ignore
00620 );
00621
00625 static void DumpStatistics();
00629 static void DumpStatistics(ostream & strm );
00630
00631 #if PMEMORY_CHECK
00632 struct State {
00633 DWORD allocationNumber;
00634 };
00635 #else
00636 typedef _CrtMemState State;
00637 #endif
00638
00639
00640
00641
00642
00643 static void GetState(
00644 State & state
00645 );
00646
00654 static void DumpObjectsSince(
00655 const State & when
00656 );
00657
00663 static void DumpObjectsSince(
00664 const State & when,
00665 ostream & strm
00666 );
00667
00673 static void SetAllocationBreakpoint(
00674 DWORD point
00675 );
00676
00677 #if PMEMORY_CHECK
00678
00679 protected:
00680 void * InternalAllocate(
00681 size_t nSize,
00682 const char * file,
00683 int line,
00684 const char * className
00685 );
00686 Validation InternalValidate(
00687 const void * ptr,
00688 const char * className,
00689 ostream * error
00690 );
00691 void InternalDumpStatistics(ostream & strm);
00692 void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
00693
00694 class Wrapper {
00695 public:
00696 Wrapper();
00697 ~Wrapper();
00698 PMemoryHeap * operator->() const { return instance; }
00699 private:
00700 PMemoryHeap * instance;
00701 };
00702 friend class Wrapper;
00703
00704 enum Flags {
00705 NoLeakPrint = 1
00706 };
00707
00708 #pragma pack(1)
00709 struct Header {
00710 enum {
00711
00712 NumGuardBytes = 16 - (sizeof(Header *) +
00713 sizeof(Header *) +
00714 sizeof(const char *) +
00715 sizeof(const char *) +
00716 sizeof(size_t) +
00717 sizeof(DWORD) +
00718 sizeof(WORD) +
00719 sizeof(BYTE)
00720 #ifdef P_LINUX
00721 + sizeof(pthread_t)
00722 #endif
00723 )%8
00724 };
00725
00726 Header * prev;
00727 Header * next;
00728 const char * className;
00729 const char * fileName;
00730 size_t size;
00731 DWORD request;
00732 WORD line;
00733 BYTE flags;
00734 #ifdef P_LINUX
00735 pthread_t thread;
00736 #endif
00737 char guard[NumGuardBytes];
00738
00739 static char GuardBytes[NumGuardBytes];
00740 };
00741 #pragma pack()
00742
00743 PBoolean isDestroyed;
00744
00745 Header * listHead;
00746 Header * listTail;
00747
00748 static DWORD allocationBreakpoint;
00749 DWORD allocationRequest;
00750 DWORD firstRealObject;
00751 BYTE flags;
00752
00753 char allocFillChar;
00754 char freeFillChar;
00755
00756 DWORD currentMemoryUsage;
00757 DWORD peakMemoryUsage;
00758 DWORD currentObjects;
00759 DWORD peakObjects;
00760 DWORD totalObjects;
00761
00762 ostream * leakDumpStream;
00763
00764 #if defined(_WIN32)
00765 CRITICAL_SECTION mutex;
00766 #elif defined(P_PTHREADS)
00767 pthread_mutex_t mutex;
00768 #elif defined(P_VXWORKS)
00769 void * mutex;
00770 #endif
00771
00772 #else
00773
00774 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
00775 _CrtMemState initialState;
00776
00777 #endif // PMEMORY_CHECK
00778 };
00779
00780
00785 inline void * runtime_malloc(size_t bytes ) { return malloc(bytes); }
00786
00791 inline void runtime_free(void * ptr ) { free(ptr); }
00792
00793
00800 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
00801
00808 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
00809
00816 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
00817
00818
00825 #define free(p) PMemoryHeap::Deallocate(p, NULL)
00826
00827
00834 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
00835
00836
00851 #define PNEW new (__FILE__, __LINE__)
00852
00853 #if !defined(_MSC_VER) || _MSC_VER<1200
00854 #define PSPECIAL_DELETE_FUNCTION
00855 #else
00856 #define PSPECIAL_DELETE_FUNCTION \
00857 void operator delete(void * ptr, const char *, int) \
00858 { PMemoryHeap::Deallocate(ptr, Class()); } \
00859 void operator delete[](void * ptr, const char *, int) \
00860 { PMemoryHeap::Deallocate(ptr, Class()); }
00861 #endif
00862
00863 #define PNEW_AND_DELETE_FUNCTIONS \
00864 void * operator new(size_t nSize, const char * file, int line) \
00865 { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00866 void * operator new(size_t nSize) \
00867 { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00868 void operator delete(void * ptr) \
00869 { PMemoryHeap::Deallocate(ptr, Class()); } \
00870 void * operator new(size_t, void * placement) \
00871 { return placement; } \
00872 void operator delete(void *, void *) \
00873 { } \
00874 void * operator new[](size_t nSize, const char * file, int line) \
00875 { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00876 void * operator new[](size_t nSize) \
00877 { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00878 void operator delete[](void * ptr) \
00879 { PMemoryHeap::Deallocate(ptr, Class()); } \
00880 PSPECIAL_DELETE_FUNCTION
00881
00882
00883 inline void * operator new(size_t nSize, const char * file, int line)
00884 { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00885
00886 inline void * operator new[](size_t nSize, const char * file, int line)
00887 { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00888
00889 #ifndef __GNUC__
00890 void * operator new(size_t nSize);
00891 void * operator new[](size_t nSize);
00892
00893 void operator delete(void * ptr);
00894 void operator delete[](void * ptr);
00895
00896 #if defined(_MSC_VER) && _MSC_VER>=1200
00897 inline void operator delete(void * ptr, const char *, int)
00898 { PMemoryHeap::Deallocate(ptr, NULL); }
00899
00900 inline void operator delete[](void * ptr, const char *, int)
00901 { PMemoryHeap::Deallocate(ptr, NULL); }
00902 #endif
00903 #endif
00904
00905
00906 class PMemoryHeapIgnoreAllocationsForScope {
00907 public:
00908 PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(PTrue)) { }
00909 ~PMemoryHeapIgnoreAllocationsForScope() { PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations); }
00910 private:
00911 PBoolean previousIgnoreAllocations;
00912 };
00913
00914 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
00915
00916 class PMemoryAllocationBreakpoint {
00917 public:
00918 PMemoryAllocationBreakpoint(DWORD point)
00919 {
00920 PMemoryHeap::SetAllocationBreakpoint(point);
00921 }
00922 };
00923
00924 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
00925
00926
00927 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00928
00929 #define PMEMORY_HEAP 0
00930
00931 #define PNEW new
00932
00933 #define PNEW_AND_DELETE_FUNCTIONS
00934
00935 #define runtime_malloc(s) malloc(s)
00936 #define runtime_free(p) free(p)
00937
00938 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
00939 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
00940
00941 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00942
00943
00954 #define PCLASSINFO(cls, par) \
00955 public: \
00956 static inline const char * Class() \
00957 { return #cls; } \
00958 virtual PBoolean InternalIsDescendant(const char * clsName) const \
00959 { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
00960 virtual const char * GetClass(unsigned ancestor = 0) const \
00961 { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
00962 virtual Comparison CompareObjectMemoryDirect(const PObject & _obj) const \
00963 { return (Comparison)memcmp(this, &_obj, sizeof(cls)); } \
00964 PNEW_AND_DELETE_FUNCTIONS
00965
00966
00967 #if P_HAS_TYPEINFO
00968
00969 #define PIsDescendant(ptr, cls) (dynamic_cast<const cls *>(ptr) != NULL)
00970 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
00971
00972 #define PRemoveConst(cls, ptr) (const_cast<cls*>(ptr))
00973
00974 #if P_USE_ASSERTS
00975 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line)
00976 { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
00977 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
00978 #else
00979 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
00980 #endif
00981
00982 #include <typeinfo>
00983
00984 #else // P_HAS_TYPEINFO
00985
00986 #define PIsDescendant(ptr, cls) ((ptr)->InternalIsDescendant(cls::Class()))
00987 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
00988
00989 #define PRemoveConst(cls, ptr) ((cls*)(ptr))
00990
00991 #if P_USE_ASSERTS
00992 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line)
00993 { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
00994 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
00995 #else
00996 #define PDownCast(cls, ptr) ((cls*)(ptr))
00997 #endif
00998
00999 #endif // P_HAS_TYPEINFO
01000
01001
01010 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
01011 #ifdef DOC_PLUS_PLUS
01012 } Match previous opening brace in doc++
01013 #endif
01014
01016
01017
01022 class PObject {
01023
01024 protected:
01028 PObject() { }
01029
01030 public:
01031
01032
01033
01034 virtual ~PObject() { }
01035
01048 static inline const char * Class() { return "PObject"; }
01049
01062 virtual const char * GetClass(unsigned = 0) const { return Class(); }
01063
01064 PBoolean IsClass(const char * cls) const
01065 { return strcmp(cls, GetClass()) == 0; }
01066
01076 virtual PBoolean InternalIsDescendant(
01077 const char * clsName
01078 ) const
01079 { return IsClass(clsName); }
01080
01082
01088 enum Comparison {
01089 LessThan = -1,
01090 EqualTo = 0,
01091 GreaterThan = 1
01092 };
01093
01105 virtual Comparison Compare(
01106 const PObject & obj
01107 ) const;
01108
01120 virtual Comparison CompareObjectMemoryDirect(
01121 const PObject & obj
01122 ) const;
01123
01129 bool operator==(
01130 const PObject & obj
01131 ) const { return Compare(obj) == EqualTo; }
01132
01138 bool operator!=(
01139 const PObject & obj
01140 ) const { return Compare(obj) != EqualTo; }
01141
01147 bool operator<(
01148 const PObject & obj
01149 ) const { return Compare(obj) == LessThan; }
01150
01156 bool operator>(
01157 const PObject & obj
01158 ) const { return Compare(obj) == GreaterThan; }
01159
01165 bool operator<=(
01166 const PObject & obj
01167 ) const { return Compare(obj) != GreaterThan; }
01168
01174 bool operator>=(
01175 const PObject & obj
01176 ) const { return Compare(obj) != LessThan; }
01178
01187 virtual void PrintOn(
01188 ostream &strm
01189 ) const;
01190
01197 virtual void ReadFrom(
01198 istream &strm
01199 );
01200
01201
01207 inline friend ostream & operator<<(
01208 ostream &strm,
01209 const PObject & obj
01210 ) { obj.PrintOn(strm); return strm; }
01211
01217 inline friend istream & operator>>(
01218 istream &strm,
01219 PObject & obj
01220 ) { obj.ReadFrom(strm); return strm; }
01221
01222
01237 virtual PObject * Clone() const;
01238
01250 virtual PINDEX HashFunction() const;
01252 };
01253
01255
01256
01257
01258
01259
01260
01261
01262 #define PANSI_CHAR 1
01263 #define PLITTLE_ENDIAN 2
01264 #define PBIG_ENDIAN 3
01265
01266
01267 #if 0
01268 class PStandardType
01269
01270
01271
01272
01273
01274
01275 {
01276 public:
01277 PStandardType(
01278 type newVal
01279 ) { data = newVal; }
01280
01281
01282
01283
01284 operator type() { return data; }
01285
01286
01287
01288
01289
01290
01291 friend ostream & operator<<(ostream & strm, const PStandardType & val)
01292 { return strm << (type)val; }
01293
01294
01295
01296
01297
01298
01299 friend istream & operator>>(istream & strm, PStandardType & val)
01300 { type data; strm >> data; val = PStandardType(data); return strm; }
01301
01302
01303
01304
01305
01306
01307
01308 private:
01309 type data;
01310 };
01311 #endif
01312
01313
01314 #define PI_SAME(name, type) \
01315 struct name { \
01316 name() : data(0) { } \
01317 name(type value) : data(value) { } \
01318 name(const name & value) : data(value.data) { } \
01319 name & operator =(type value) { data = value; return *this; } \
01320 name & operator =(const name & value) { data = value.data; return *this; } \
01321 operator type() const { return data; } \
01322 friend ostream & operator<<(ostream & s, const name & v) { return s << v.data; } \
01323 friend istream & operator>>(istream & s, name & v) { return s >> v.data; } \
01324 private: type data; \
01325 }
01326
01327 #define PI_LOOP(src, dst) \
01328 BYTE *s = ((BYTE *)&src)+sizeof(src); BYTE *d = (BYTE *)&dst; \
01329 while (s != (BYTE *)&src) *d++ = *--s;
01330
01331 #define PI_DIFF(name, type) \
01332 struct name { \
01333 name() : data(0) { } \
01334 name(type value) : data(0) { operator=(value); } \
01335 name(const name & value) : data(value.data) { } \
01336 name & operator =(type value) { PI_LOOP(value, data); return *this; } \
01337 name & operator =(const name & value) { data = value.data; return *this; } \
01338 operator type() const { type value; PI_LOOP(data, value); return value; } \
01339 friend ostream & operator<<(ostream & s, const name & value) { return s << (type)value; } \
01340 friend istream & operator>>(istream & s, name & v) { type val; s >> val; v = val; return s; } \
01341 private: type data; \
01342 }
01343
01344 #ifndef PCHAR8
01345 #define PCHAR8 PANSI_CHAR
01346 #endif
01347
01348 #if PCHAR8==PANSI_CHAR
01349 PI_SAME(PChar8, char);
01350 #endif
01351
01352 PI_SAME(PInt8, signed char);
01353
01354 PI_SAME(PUInt8, unsigned char);
01355
01356 #if PBYTE_ORDER==PLITTLE_ENDIAN
01357 PI_SAME(PInt16l, PInt16);
01358 #elif PBYTE_ORDER==PBIG_ENDIAN
01359 PI_DIFF(PInt16l, PInt16);
01360 #endif
01361
01362 #if PBYTE_ORDER==PLITTLE_ENDIAN
01363 PI_DIFF(PInt16b, PInt16);
01364 #elif PBYTE_ORDER==PBIG_ENDIAN
01365 PI_SAME(PInt16b, PInt16);
01366 #endif
01367
01368 #if PBYTE_ORDER==PLITTLE_ENDIAN
01369 PI_SAME(PUInt16l, WORD);
01370 #elif PBYTE_ORDER==PBIG_ENDIAN
01371 PI_DIFF(PUInt16l, WORD);
01372 #endif
01373
01374 #if PBYTE_ORDER==PLITTLE_ENDIAN
01375 PI_DIFF(PUInt16b, WORD);
01376 #elif PBYTE_ORDER==PBIG_ENDIAN
01377 PI_SAME(PUInt16b, WORD);
01378 #endif
01379
01380 #if PBYTE_ORDER==PLITTLE_ENDIAN
01381 PI_SAME(PInt32l, PInt32);
01382 #elif PBYTE_ORDER==PBIG_ENDIAN
01383 PI_DIFF(PInt32l, PInt32);
01384 #endif
01385
01386 #if PBYTE_ORDER==PLITTLE_ENDIAN
01387 PI_DIFF(PInt32b, PInt32);
01388 #elif PBYTE_ORDER==PBIG_ENDIAN
01389 PI_SAME(PInt32b, PInt32);
01390 #endif
01391
01392 #if PBYTE_ORDER==PLITTLE_ENDIAN
01393 PI_SAME(PUInt32l, DWORD);
01394 #elif PBYTE_ORDER==PBIG_ENDIAN
01395 PI_DIFF(PUInt32l, DWORD);
01396 #endif
01397
01398 #if PBYTE_ORDER==PLITTLE_ENDIAN
01399 PI_DIFF(PUInt32b, DWORD);
01400 #elif PBYTE_ORDER==PBIG_ENDIAN
01401 PI_SAME(PUInt32b, DWORD);
01402 #endif
01403
01404 #if PBYTE_ORDER==PLITTLE_ENDIAN
01405 PI_SAME(PInt64l, PInt64);
01406 #elif PBYTE_ORDER==PBIG_ENDIAN
01407 PI_DIFF(PInt64l, PInt64);
01408 #endif
01409
01410 #if PBYTE_ORDER==PLITTLE_ENDIAN
01411 PI_DIFF(PInt64b, PInt64);
01412 #elif PBYTE_ORDER==PBIG_ENDIAN
01413 PI_SAME(PInt64b, PInt64);
01414 #endif
01415
01416 #if PBYTE_ORDER==PLITTLE_ENDIAN
01417 PI_SAME(PUInt64l, PUInt64);
01418 #elif PBYTE_ORDER==PBIG_ENDIAN
01419 PI_DIFF(PUInt64l, PUInt64);
01420 #endif
01421
01422 #if PBYTE_ORDER==PLITTLE_ENDIAN
01423 PI_DIFF(PUInt64b, PUInt64);
01424 #elif PBYTE_ORDER==PBIG_ENDIAN
01425 PI_SAME(PUInt64b, PUInt64);
01426 #endif
01427
01428 #if PBYTE_ORDER==PLITTLE_ENDIAN
01429 PI_SAME(PFloat32l, float);
01430 #elif PBYTE_ORDER==PBIG_ENDIAN
01431 PI_DIFF(PFloat32l, float);
01432 #endif
01433
01434 #if PBYTE_ORDER==PLITTLE_ENDIAN
01435 PI_DIFF(PFloat32b, float);
01436 #elif PBYTE_ORDER==PBIG_ENDIAN
01437 PI_SAME(PFloat32b, float);
01438 #endif
01439
01440 #if PBYTE_ORDER==PLITTLE_ENDIAN
01441 PI_SAME(PFloat64l, double);
01442 #elif PBYTE_ORDER==PBIG_ENDIAN
01443 PI_DIFF(PFloat64l, double);
01444 #endif
01445
01446 #if PBYTE_ORDER==PLITTLE_ENDIAN
01447 PI_DIFF(PFloat64b, double);
01448 #elif PBYTE_ORDER==PBIG_ENDIAN
01449 PI_SAME(PFloat64b, double);
01450 #endif
01451
01452 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
01453 #if PBYTE_ORDER==PLITTLE_ENDIAN
01454 PI_SAME(PFloat80l, long double);
01455 #elif PBYTE_ORDER==PBIG_ENDIAN
01456 PI_DIFF(PFloat80l, long double);
01457 #endif
01458
01459 #if PBYTE_ORDER==PLITTLE_ENDIAN
01460 PI_DIFF(PFloat80b, long double);
01461 #elif PBYTE_ORDER==PBIG_ENDIAN
01462 PI_SAME(PFloat80b, long double);
01463 #endif
01464 #endif
01465
01466 #undef PI_LOOP
01467 #undef PI_SAME
01468 #undef PI_DIFF
01469
01470
01472
01473
01474
01475
01476
01477
01478 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01479
01480
01481
01482
01483
01484
01485 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01486
01487
01488
01489
01490
01491
01492 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01493
01494
01495
01496
01497
01498
01499 #define PABS(v) ((v) < 0 ? -(v) : (v))
01500
01501 #endif // _POBJECT_H
01502
01503