object.h

Go to the documentation of this file.
00001 /*
00002  * object.h
00003  *
00004  * Mother of all ancestor classes.
00005  *
00006  * Portable Tools Library
00007  *
00008  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Portable Windows Library.
00021  *
00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00023  *
00024  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
00025  * All Rights Reserved.
00026  *
00027  * Contributor(s): ______________________________________.
00028  *
00029  * $Revision: 21160 $
00030  * $Author: rjongbloed $
00031  * $Date: 2008-09-25 03:17:12 +0000 (Thu, 25 Sep 2008) $
00032  */
00033 
00034 #ifndef _POBJECT_H
00035 #define _POBJECT_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 // P_USE_INTEGER_BOOL is the default and gives the old behaviour (it
00064 // is also used for C translation units).
00065 // without P_USE_INTEGER_BOOL, the ANSI C++ bool is used.
00066 
00067 #if defined(P_USE_INTEGER_BOOL) || !defined(__cplusplus)
00068    typedef BOOL PBoolean;
00069 #  define PTrue TRUE
00070 #  define PFalse FALSE
00071 #else
00072    typedef bool PBoolean;
00073 #  define PTrue true
00074 #  define PFalse false
00075 #endif
00076 
00077 
00079 // Disable inlines when debugging for faster compiles (the compiler doesn't
00080 // actually inline the function with debug on any way).
00081 
00082 #ifndef P_USE_INLINES
00083 #ifdef _DEBUG
00084 #define P_USE_INLINES 0
00085 #else
00086 #define P_USE_INLINES 0
00087 #endif
00088 #endif
00089 
00090 #if P_USE_INLINES
00091 #define PINLINE inline
00092 #else
00093 #define PINLINE
00094 #endif
00095 
00096 
00098 // Declare the debugging support
00099 
00100 #ifndef P_USE_ASSERTS
00101 #define P_USE_ASSERTS 1
00102 #endif
00103 
00104 #if !P_USE_ASSERTS
00105 
00106 #define PAssert(b, m) (b)
00107 #define PAssert2(b, c, m) (b)
00108 #define PAssertOS(b) (b)
00109 #define PAssertNULL(p) (p)
00110 #define PAssertAlways(m)
00111 #define PAssertAlways2(c, m)
00112 
00113 #else // P_USE_ASSERTS
00114 
00116 enum PStandardAssertMessage {
00117   PLogicError,              
00118   POutOfMemory,             
00119   PNullPointerReference,    
00120   PInvalidCast,             
00121   PInvalidArrayIndex,       
00122   PInvalidArrayElement,     
00123   PStackEmpty,              
00124   PUnimplementedFunction,   
00125   PInvalidParameter,        
00126   POperatingSystemError,    
00127   PChannelNotOpen,          
00128   PUnsupportedFeature,      
00129   PInvalidWindow,           
00130   PMaxStandardAssertMessage 
00131 };
00132 
00133 #define __CLASS__ NULL
00134 
00135 void PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
00136 void PAssertFunc(const char * file, int line, const char * className, const char * msg);
00137 void PAssertFunc(const char * full_msg);
00138 
00139 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, PStandardAssertMessage msg)
00140 {
00141   if (!b) 
00142     PAssertFunc(file, line, className, msg);
00143   return b;
00144 }
00145 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, const char * msg)
00146 {
00147   if (!b) 
00148     PAssertFunc(file, line, className, msg);
00149   return b;
00150 }
00151 
00158 #define PAssert(b, m) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,(m))
00159 
00167 #define PAssert2(b, c, m) PAssertFuncInline((b), __FILE__,__LINE__,(c),(m))
00168 
00175 #define PAssertOS(b) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,POperatingSystemError)
00176 
00186 #define PAssertNULL(p) (((p)!=NULL)?(p): \
00187                      (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(p)))
00188 
00195 #define PAssertAlways(m) PAssertFunc(__FILE__,__LINE__,__CLASS__,(m))
00196 
00203 #define PAssertAlways2(c, m) PAssertFunc(__FILE__,__LINE__,(c),(m))
00204 
00205 #endif // P_USE_ASSERTS
00206 
00207 
00212 ostream & PGetErrorStream();
00213 
00217 void PSetErrorStream(ostream * strm  );
00218 
00233 #define PError (PGetErrorStream())
00234 
00235 
00236 
00238 // Debug and tracing
00239 
00240 #ifndef PTRACING
00241 #define PTRACING 1
00242 #endif
00243 
00244 #if PTRACING
00245 
00250 class PTrace
00251 {
00252 public:
00254   enum Options {
00260     Blocks = 1,
00262     DateAndTime = 2,
00264     Timestamp = 4,
00266     Thread = 8,
00268     TraceLevel = 16,
00270     FileAndLine = 32,
00272     ThreadAddress = 64,
00274     AppendToFile = 128,
00277     GMTTime = 256,
00280     RotateDaily = 512,
00281     RotateHourly = 1024,
00282     RotateMinutely = 2048,
00283     RotateLogMask = RotateDaily + RotateHourly + RotateMinutely,
00287     SystemLogStream = 32768
00288   };
00289 
00290 
00298   static void Initialise(
00299     unsigned level,
00300     const char * filename = NULL,
00301     unsigned options = Timestamp | Thread | Blocks
00302   );
00303 
00314   static void Initialise(
00315     unsigned level,
00316     const char * filename,
00317     const char * rolloverPattern,
00318     unsigned options = Timestamp | Thread | Blocks
00319   );
00320 
00327   static void SetOptions(unsigned options  );
00328 
00336   static void ClearOptions(unsigned options  );
00337 
00342   static unsigned GetOptions();
00343 
00349   static void SetLevel(unsigned level  );
00350 
00356   static unsigned GetLevel();
00357 
00362   static PBoolean CanTrace(unsigned level );
00363 
00368   static void SetStream(ostream * out  );
00369 
00385   static ostream & Begin(
00386     unsigned level,         
00387     const char * fileName,  
00388     int lineNum             
00389   );
00390 
00407   static ostream & End(ostream & strm );
00408 
00412   static void Cleanup();
00413 
00419   class Block {
00420     public:
00422       Block(
00423         const char * fileName, 
00424         int lineNum,           
00425         const char * traceName
00427        );
00428       Block(const Block & obj)
00429         : file(obj.file), line(obj.line), name(obj.name) { }
00431       ~Block();
00432     private:
00433       Block & operator=(const Block &)
00434       { return *this; }
00435       const char * file;
00436       int          line;
00437       const char * name;
00438   };
00439 };
00440 
00441 /* Macro to conditionally declare a parameter to a function to avoid compiler
00442    warning due that parameter only being used in a #PTRACE */
00443 #define PTRACE_PARAM(param) param
00444 
00451 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
00452 
00456 #define PTRACE_LINE() \
00457     if (PTrace::CanTrace(1)) \
00458       PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
00459     else (void)0
00460 
00466 #define PTRACE(level, args) \
00467     if (PTrace::CanTrace(level)) \
00468       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00469     else (void)0
00470 
00478 #define PTRACE_IF(level, cond, args) \
00479     if ((PTrace::CanTrace(level) && (cond))) \
00480       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00481     else (void)0
00482 
00483 #else // PTRACING
00484 
00485 #define PTRACE_PARAM(param)
00486 #define PTRACE_BLOCK(n)
00487 #define PTRACE_LINE()
00488 #define PTRACE(level, arg)
00489 #define PTRACE_IF(level, cond, args)
00490 
00491 #endif // PTRACING
00492 
00493 
00494 
00495 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE)) 
00496 
00497 #define PMEMORY_HEAP 1
00498 
00505 class PMemoryHeap {
00506   public:
00508     PMemoryHeap();
00509 
00510     // Clear up the memory checking subsystem, dumping memory leaks.
00511     ~PMemoryHeap();
00512 
00519     static void * Allocate(
00520       size_t nSize,           
00521       const char * file,      
00522       int line,               
00523       const char * className  
00524     );
00531     static void * Allocate(
00532       size_t count,       
00533       size_t iSize,       
00534       const char * file,  
00535       int line            
00536     );
00537 
00545     static void * Reallocate(
00546       void * ptr,         
00547       size_t nSize,       
00548       const char * file,  
00549       int line            
00550     );
00551 
00557     static void Deallocate(
00558       void * ptr,             
00559       const char * className  
00560     );
00561 
00564     enum Validation {
00565       Ok, Bad, Trashed
00566     };
00574     static Validation Validate(
00575       const void * ptr,       
00576       const char * className, 
00577       ostream * error         
00578     );
00579 
00584     static PBoolean ValidateHeap(
00585       ostream * error = NULL  
00586     );
00587 
00593     static PBoolean SetIgnoreAllocations(
00594       PBoolean ignore  
00595     );
00596 
00600     static void DumpStatistics();
00604     static void DumpStatistics(ostream & strm );
00605 
00606 #if PMEMORY_CHECK
00607     struct State {
00608       DWORD allocationNumber;
00609     };
00610 #else
00611         typedef _CrtMemState State;
00612 #endif
00613 
00614     /* Get memory state.
00615       This returns a state that may be used to determine where to start dumping
00616       objects from.
00617      */
00618     static void GetState(
00619       State & state  
00620     );
00621 
00629     static void DumpObjectsSince(
00630       const State & when    
00631     );
00632 
00638     static void DumpObjectsSince(
00639       const State & when,   
00640       ostream & strm        
00641     );
00642 
00648     static void SetAllocationBreakpoint(
00649       DWORD point   
00650     );
00651 
00652 #if PMEMORY_CHECK
00653 
00654   protected:
00655     void * InternalAllocate(
00656       size_t nSize,           // Number of bytes to allocate.
00657       const char * file,      // Source file name for allocating function.
00658       int line,               // Source file line for allocating function.
00659       const char * className  // Class name for allocating function.
00660     );
00661     Validation InternalValidate(
00662       const void * ptr,       // Pointer to memory block to check
00663       const char * className, // Class name it should be.
00664       ostream * error         // Stream to receive error message (may be NULL)
00665     );
00666     void InternalDumpStatistics(ostream & strm);
00667     void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
00668 
00669     class Wrapper {
00670       public:
00671         Wrapper();
00672         ~Wrapper();
00673         PMemoryHeap * operator->() const { return instance; }
00674       private:
00675         PMemoryHeap * instance;
00676     };
00677     friend class Wrapper;
00678 
00679     enum Flags {
00680       NoLeakPrint = 1
00681     };
00682 
00683 #pragma pack(1)
00684     struct Header {
00685       enum {
00686         // Assure that the Header struct is aligned to 8 byte boundary
00687         NumGuardBytes = 16 - (sizeof(Header *) +
00688                               sizeof(Header *) +
00689                               sizeof(const char *) +
00690                               sizeof(const char *) +
00691                               sizeof(size_t) +
00692                               sizeof(DWORD) +
00693                               sizeof(WORD) +
00694                               sizeof(BYTE)
00695 #ifdef P_LINUX
00696                               + sizeof(pthread_t)
00697 #endif
00698                               )%8
00699       };
00700 
00701       Header     * prev;
00702       Header     * next;
00703       const char * className;
00704       const char * fileName;
00705       size_t       size;
00706       DWORD        request;
00707       WORD         line;
00708       BYTE         flags;
00709 #ifdef P_LINUX
00710       pthread_t    thread;
00711 #endif
00712       char         guard[NumGuardBytes];
00713 
00714       static char GuardBytes[NumGuardBytes];
00715     };
00716 #pragma pack()
00717 
00718     PBoolean isDestroyed;
00719 
00720     Header * listHead;
00721     Header * listTail;
00722 
00723     static DWORD allocationBreakpoint;
00724     DWORD allocationRequest;
00725     DWORD firstRealObject;
00726     BYTE  flags;
00727 
00728     char  allocFillChar;
00729     char  freeFillChar;
00730 
00731     DWORD currentMemoryUsage;
00732     DWORD peakMemoryUsage;
00733     DWORD currentObjects;
00734     DWORD peakObjects;
00735     DWORD totalObjects;
00736 
00737     ostream * leakDumpStream;
00738 
00739 #if defined(_WIN32)
00740     CRITICAL_SECTION mutex;
00741 #elif defined(P_PTHREADS)
00742     pthread_mutex_t mutex;
00743 #elif defined(P_VXWORKS)
00744     void * mutex;
00745 #endif
00746 
00747 #else
00748 
00749 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
00750     _CrtMemState initialState;
00751 
00752 #endif // PMEMORY_CHECK
00753 };
00754 
00755 
00760 inline void * runtime_malloc(size_t bytes  ) { return malloc(bytes); }
00761 
00766 inline void runtime_free(void * ptr  ) { free(ptr); }
00767 
00768 
00775 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
00776 
00783 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
00784 
00791 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
00792 
00793 
00800 #define free(p) PMemoryHeap::Deallocate(p, NULL)
00801 
00802 
00809 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
00810 
00811 
00826 #define PNEW  new (__FILE__, __LINE__)
00827 
00828 #if !defined(_MSC_VER) || _MSC_VER<1200
00829 #define PSPECIAL_DELETE_FUNCTION
00830 #else
00831 #define PSPECIAL_DELETE_FUNCTION \
00832     void operator delete(void * ptr, const char *, int) \
00833       { PMemoryHeap::Deallocate(ptr, Class()); } \
00834     void operator delete[](void * ptr, const char *, int) \
00835       { PMemoryHeap::Deallocate(ptr, Class()); }
00836 #endif
00837 
00838 #define PNEW_AND_DELETE_FUNCTIONS \
00839     void * operator new(size_t nSize, const char * file, int line) \
00840       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00841     void * operator new(size_t nSize) \
00842       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00843     void operator delete(void * ptr) \
00844       { PMemoryHeap::Deallocate(ptr, Class()); } \
00845     void * operator new(size_t, void * placement) \
00846       { return placement; } \
00847     void operator delete(void *, void *) \
00848       { } \
00849     void * operator new[](size_t nSize, const char * file, int line) \
00850       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00851     void * operator new[](size_t nSize) \
00852       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00853     void operator delete[](void * ptr) \
00854       { PMemoryHeap::Deallocate(ptr, Class()); } \
00855     PSPECIAL_DELETE_FUNCTION
00856 
00857 
00858 inline void * operator new(size_t nSize, const char * file, int line)
00859   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00860 
00861 inline void * operator new[](size_t nSize, const char * file, int line)
00862   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00863 
00864 #ifndef __GNUC__
00865 void * operator new(size_t nSize);
00866 void * operator new[](size_t nSize);
00867 
00868 void operator delete(void * ptr);
00869 void operator delete[](void * ptr);
00870 
00871 #if defined(_MSC_VER) && _MSC_VER>=1200
00872 inline void operator delete(void * ptr, const char *, int)
00873   { PMemoryHeap::Deallocate(ptr, NULL); }
00874 
00875 inline void operator delete[](void * ptr, const char *, int)
00876   { PMemoryHeap::Deallocate(ptr, NULL); }
00877 #endif
00878 #endif
00879 
00880 
00881 class PMemoryHeapIgnoreAllocationsForScope {
00882 public:
00883   PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(PTrue)) { }
00884   ~PMemoryHeapIgnoreAllocationsForScope() { PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations); }
00885 private:
00886   PBoolean previousIgnoreAllocations;
00887 };
00888 
00889 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
00890 
00891 class PMemoryAllocationBreakpoint {
00892 public:
00893   PMemoryAllocationBreakpoint(DWORD point)
00894   {
00895     PMemoryHeap::SetAllocationBreakpoint(point);
00896   }
00897 };
00898 
00899 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
00900 
00901 
00902 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00903 
00904 #define PMEMORY_HEAP 0
00905 
00906 #define PNEW new
00907 
00908 #define PNEW_AND_DELETE_FUNCTIONS
00909 
00910 #define runtime_malloc(s) malloc(s)
00911 #define runtime_free(p) free(p)
00912 
00913 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
00914 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
00915 
00916 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00917 
00918 
00929 #define PCLASSINFO(cls, par) \
00930   public: \
00931     static inline const char * Class() \
00932       { return #cls; } \
00933     virtual PBoolean InternalIsDescendant(const char * clsName) const \
00934       { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
00935     virtual const char * GetClass(unsigned ancestor = 0) const \
00936       { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
00937     virtual Comparison CompareObjectMemoryDirect(const PObject & _obj) const \
00938       { return (Comparison)memcmp(this, &_obj, sizeof(cls)); } \
00939     PNEW_AND_DELETE_FUNCTIONS
00940 
00941 
00942 #if P_HAS_TYPEINFO
00943 
00944 #define PIsDescendant(ptr, cls)    (dynamic_cast<const cls *>(ptr) != NULL) 
00945 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str)) 
00946 
00947 #define PRemoveConst(cls, ptr)  (const_cast<cls*>(ptr))
00948 
00949 #if P_USE_ASSERTS
00950 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line) 
00951   { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
00952 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
00953 #else
00954 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
00955 #endif
00956 
00957 #include <typeinfo>
00958 
00959 #else // P_HAS_TYPEINFO
00960 
00961 #define PIsDescendant(ptr, cls)    ((ptr)->InternalIsDescendant(cls::Class()))
00962 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
00963 
00964 #define PRemoveConst(cls, ptr)  ((cls*)(ptr))
00965 
00966 #if P_USE_ASSERTS
00967 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line) 
00968   { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
00969 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
00970 #else
00971 #define PDownCast(cls, ptr) ((cls*)(ptr))
00972 #endif
00973 
00974 #endif // P_HAS_TYPEINFO
00975 
00976 
00985 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
00986 #ifdef DOC_PLUS_PLUS
00987 } Match previous opening brace in doc++
00988 #endif
00989 
00991 // The root of all evil ... umm classes
00992 
00997 class PObject {
00998 
00999   protected:
01003     PObject() { }
01004 
01005   public:
01006     /* Destructor required to get the "virtual". A PObject really has nothing
01007        to destroy.
01008      */
01009     virtual ~PObject() { }
01010 
01023     static inline const char * Class()    { return "PObject"; }
01024 
01037     virtual const char * GetClass(unsigned /*ancestor*/ = 0) const { return Class(); }
01038 
01039     PBoolean IsClass(const char * cls) const 
01040     { return strcmp(cls, GetClass()) == 0; }
01041 
01051     virtual PBoolean InternalIsDescendant(
01052       const char * clsName    // Ancestor class name to compare against.
01053     ) const
01054     { return IsClass(clsName); }
01055 
01057 
01063     enum Comparison {
01064       LessThan = -1,
01065       EqualTo = 0,
01066       GreaterThan = 1
01067     };
01068 
01080     virtual Comparison Compare(
01081       const PObject & obj   // Object to compare against.
01082     ) const;
01083     
01095     virtual Comparison CompareObjectMemoryDirect(
01096       const PObject & obj   // Object to compare against.
01097     ) const;
01098 
01104     bool operator==(
01105       const PObject & obj   // Object to compare against.
01106     ) const { return Compare(obj) == EqualTo; }
01107 
01113     bool operator!=(
01114       const PObject & obj   // Object to compare against.
01115     ) const { return Compare(obj) != EqualTo; }
01116 
01122     bool operator<(
01123       const PObject & obj   // Object to compare against.
01124     ) const { return Compare(obj) == LessThan; }
01125 
01131     bool operator>(
01132       const PObject & obj   // Object to compare against.
01133     ) const { return Compare(obj) == GreaterThan; }
01134 
01140     bool operator<=(
01141       const PObject & obj   // Object to compare against.
01142     ) const { return Compare(obj) != GreaterThan; }
01143 
01149     bool operator>=(
01150       const PObject & obj   // Object to compare against.
01151     ) const { return Compare(obj) != LessThan; }
01153 
01162     virtual void PrintOn(
01163       ostream &strm   // Stream to print the object into.
01164     ) const;
01165 
01172     virtual void ReadFrom(
01173       istream &strm   // Stream to read the objects contents from.
01174     );
01175 
01176 
01182     inline friend ostream & operator<<(
01183       ostream &strm,       // Stream to print the object into.
01184       const PObject & obj  // Object to print to the stream.
01185     ) { obj.PrintOn(strm); return strm; }
01186 
01192     inline friend istream & operator>>(
01193       istream &strm,   // Stream to read the objects contents from.
01194       PObject & obj    // Object to read inormation into.
01195     ) { obj.ReadFrom(strm); return strm; }
01196 
01197 
01212     virtual PObject * Clone() const;
01213 
01225     virtual PINDEX HashFunction() const;
01227 };
01228 
01230 // Platform independent types
01231 
01232 // All these classes encapsulate primitive types such that they may be
01233 // transfered in a platform independent manner. In particular it is used to
01234 // do byte swapping for little endien and big endien processor architectures
01235 // as well as accommodating structure packing rules for memory structures.
01236 
01237 #define PANSI_CHAR 1
01238 #define PLITTLE_ENDIAN 2
01239 #define PBIG_ENDIAN 3
01240 
01241 
01242 #if 0
01243 class PStandardType
01244 /* Encapsulate a standard 8 bit character into a portable format. This would
01245    rarely need to do translation, only if the target platform uses EBCDIC
01246    would it do anything.
01247 
01248    The platform independent form here is always 8 bit ANSI.
01249  */
01250 {
01251   public:
01252     PStandardType(
01253       type newVal   // Value to initialise data in platform dependent form.
01254     ) { data = newVal; }
01255     /* Create a new instance of the platform independent type using platform
01256        dependent data, or platform independent streams.
01257      */
01258 
01259     operator type() { return data; }
01260     /* Get the platform dependent value for the type.
01261 
01262        @return
01263        data for instance.
01264      */
01265 
01266     friend ostream & operator<<(ostream & strm, const PStandardType & val)
01267       { return strm << (type)val; }
01268     /* Output the platform dependent value for the type to the stream.
01269 
01270        @return
01271        the stream output was made to.
01272      */
01273 
01274     friend istream & operator>>(istream & strm, PStandardType & val)
01275       { type data; strm >> data; val = PStandardType(data); return strm; }
01276     /* Input the platform dependent value for the type from the stream.
01277 
01278        @return
01279        the stream input was made from.
01280      */
01281 
01282 
01283   private:
01284     type data;
01285 };
01286 #endif
01287 
01288 
01289 #define PI_SAME(name, type) \
01290   struct name { \
01291     name() : data(0) { } \
01292     name(type value) : data(value) { } \
01293     name(const name & value) : data(value.data) { } \
01294     name & operator =(type value) { data = value; return *this; } \
01295     name & operator =(const name & value) { data = value.data; return *this; } \
01296     operator type() const { return data; } \
01297     friend ostream & operator<<(ostream & s, const name & v) { return s << v.data; } \
01298     friend istream & operator>>(istream & s, name & v) { return s >> v.data; } \
01299     private: type data; \
01300   }
01301 
01302 #define PI_LOOP(src, dst) \
01303     BYTE *s = ((BYTE *)&src)+sizeof(src); BYTE *d = (BYTE *)&dst; \
01304     while (s != (BYTE *)&src) *d++ = *--s;
01305 
01306 #define PI_DIFF(name, type) \
01307   struct name { \
01308     name() : data(0) { } \
01309     name(type value) : data(0) { operator=(value); } \
01310     name(const name & value) : data(value.data) { } \
01311     name & operator =(type value) { PI_LOOP(value, data); return *this; } \
01312     name & operator =(const name & value) { data = value.data; return *this; } \
01313     operator type() const { type value; PI_LOOP(data, value); return value; } \
01314     friend ostream & operator<<(ostream & s, const name & value) { return s << (type)value; } \
01315     friend istream & operator>>(istream & s, name & v) { type val; s >> val; v = val; return s; } \
01316     private: type data; \
01317   }
01318 
01319 #ifndef PCHAR8
01320 #define PCHAR8 PANSI_CHAR
01321 #endif
01322 
01323 #if PCHAR8==PANSI_CHAR
01324 PI_SAME(PChar8, char);
01325 #endif
01326 
01327 PI_SAME(PInt8, char);
01328 
01329 PI_SAME(PUInt8, unsigned char);
01330 
01331 #if PBYTE_ORDER==PLITTLE_ENDIAN
01332 PI_SAME(PInt16l, PInt16);
01333 #elif PBYTE_ORDER==PBIG_ENDIAN
01334 PI_DIFF(PInt16l, PInt16);
01335 #endif
01336 
01337 #if PBYTE_ORDER==PLITTLE_ENDIAN
01338 PI_DIFF(PInt16b, PInt16);
01339 #elif PBYTE_ORDER==PBIG_ENDIAN
01340 PI_SAME(PInt16b, PInt16);
01341 #endif
01342 
01343 #if PBYTE_ORDER==PLITTLE_ENDIAN
01344 PI_SAME(PUInt16l, WORD);
01345 #elif PBYTE_ORDER==PBIG_ENDIAN
01346 PI_DIFF(PUInt16l, WORD);
01347 #endif
01348 
01349 #if PBYTE_ORDER==PLITTLE_ENDIAN
01350 PI_DIFF(PUInt16b, WORD);
01351 #elif PBYTE_ORDER==PBIG_ENDIAN
01352 PI_SAME(PUInt16b, WORD);
01353 #endif
01354 
01355 #if PBYTE_ORDER==PLITTLE_ENDIAN
01356 PI_SAME(PInt32l, PInt32);
01357 #elif PBYTE_ORDER==PBIG_ENDIAN
01358 PI_DIFF(PInt32l, PInt32);
01359 #endif
01360 
01361 #if PBYTE_ORDER==PLITTLE_ENDIAN
01362 PI_DIFF(PInt32b, PInt32);
01363 #elif PBYTE_ORDER==PBIG_ENDIAN
01364 PI_SAME(PInt32b, PInt32);
01365 #endif
01366 
01367 #if PBYTE_ORDER==PLITTLE_ENDIAN
01368 PI_SAME(PUInt32l, DWORD);
01369 #elif PBYTE_ORDER==PBIG_ENDIAN
01370 PI_DIFF(PUInt32l, DWORD);
01371 #endif
01372 
01373 #if PBYTE_ORDER==PLITTLE_ENDIAN
01374 PI_DIFF(PUInt32b, DWORD);
01375 #elif PBYTE_ORDER==PBIG_ENDIAN
01376 PI_SAME(PUInt32b, DWORD);
01377 #endif
01378 
01379 #if PBYTE_ORDER==PLITTLE_ENDIAN
01380 PI_SAME(PInt64l, PInt64);
01381 #elif PBYTE_ORDER==PBIG_ENDIAN
01382 PI_DIFF(PInt64l, PInt64);
01383 #endif
01384 
01385 #if PBYTE_ORDER==PLITTLE_ENDIAN
01386 PI_DIFF(PInt64b, PInt64);
01387 #elif PBYTE_ORDER==PBIG_ENDIAN
01388 PI_SAME(PInt64b, PInt64);
01389 #endif
01390 
01391 #if PBYTE_ORDER==PLITTLE_ENDIAN
01392 PI_SAME(PUInt64l, PUInt64);
01393 #elif PBYTE_ORDER==PBIG_ENDIAN
01394 PI_DIFF(PUInt64l, PUInt64);
01395 #endif
01396 
01397 #if PBYTE_ORDER==PLITTLE_ENDIAN
01398 PI_DIFF(PUInt64b, PUInt64);
01399 #elif PBYTE_ORDER==PBIG_ENDIAN
01400 PI_SAME(PUInt64b, PUInt64);
01401 #endif
01402 
01403 #if PBYTE_ORDER==PLITTLE_ENDIAN
01404 PI_SAME(PFloat32l, float);
01405 #elif PBYTE_ORDER==PBIG_ENDIAN
01406 PI_DIFF(PFloat32l, float);
01407 #endif
01408 
01409 #if PBYTE_ORDER==PLITTLE_ENDIAN
01410 PI_DIFF(PFloat32b, float);
01411 #elif PBYTE_ORDER==PBIG_ENDIAN
01412 PI_SAME(PFloat32b, float);
01413 #endif
01414 
01415 #if PBYTE_ORDER==PLITTLE_ENDIAN
01416 PI_SAME(PFloat64l, double);
01417 #elif PBYTE_ORDER==PBIG_ENDIAN
01418 PI_DIFF(PFloat64l, double);
01419 #endif
01420 
01421 #if PBYTE_ORDER==PLITTLE_ENDIAN
01422 PI_DIFF(PFloat64b, double);
01423 #elif PBYTE_ORDER==PBIG_ENDIAN
01424 PI_SAME(PFloat64b, double);
01425 #endif
01426 
01427 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
01428 #if PBYTE_ORDER==PLITTLE_ENDIAN
01429 PI_SAME(PFloat80l, long double);
01430 #elif PBYTE_ORDER==PBIG_ENDIAN
01431 PI_DIFF(PFloat80l, long double);
01432 #endif
01433 
01434 #if PBYTE_ORDER==PLITTLE_ENDIAN
01435 PI_DIFF(PFloat80b, long double);
01436 #elif PBYTE_ORDER==PBIG_ENDIAN
01437 PI_SAME(PFloat80b, long double);
01438 #endif
01439 #endif
01440 
01441 #undef PI_LOOP
01442 #undef PI_SAME
01443 #undef PI_DIFF
01444 
01445 
01447 // Miscellaneous
01448 
01449 /*$MACRO PARRAYSIZE(array)
01450    This macro is used to calculate the number of array elements in a static
01451    array.
01452  */
01453 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01454 
01455 /*$MACRO PMIN(v1, v2)
01456    This macro is used to calculate the minimum of two values. As this is a
01457    macro the expression in #v1 or #v2 is executed
01458    twice so extreme care should be made in its use.
01459  */
01460 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01461 
01462 /*$MACRO PMAX(v1, v2)
01463    This macro is used to calculate the maximum of two values. As this is a
01464    macro the expression in #v1 or #v2 is executed
01465    twice so extreme care should be made in its use.
01466  */
01467 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01468 
01469 /*$MACRO PABS(val)
01470    This macro is used to calculate an absolute value. As this is a macro the
01471    expression in #val is executed twice so extreme care should be
01472    made in its use.
01473  */
01474 #define PABS(v) ((v) < 0 ? -(v) : (v))
01475 
01476 #endif // _POBJECT_H
01477 
01478 // End Of File ///////////////////////////////////////////////////////////////

Generated on Mon Feb 23 01:57:54 2009 for PTLib by  doxygen 1.5.1