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: 20492 $
00030  * $Author: rjongbloed $
00031  * $Date: 2008-06-24 23:36:32 +0000 (Tue, 24 Jun 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,
00284     SystemLogStream = 32768
00285   };
00286 
00294   static void Initialise(
00295     unsigned level,
00296     const char * filename = NULL,
00297     unsigned options = Timestamp | Thread | Blocks
00298   );
00299 
00310   static void Initialise(
00311     unsigned level,
00312     const char * filename,
00313     const char * rolloverPattern,
00314     unsigned options = Timestamp | Thread | Blocks
00315   );
00316 
00323   static void SetOptions(unsigned options  );
00324 
00332   static void ClearOptions(unsigned options  );
00333 
00338   static unsigned GetOptions();
00339 
00345   static void SetLevel(unsigned level  );
00346 
00352   static unsigned GetLevel();
00353 
00358   static PBoolean CanTrace(unsigned level );
00359 
00364   static void SetStream(ostream * out  );
00365 
00381   static ostream & Begin(
00382     unsigned level,         
00383     const char * fileName,  
00384     int lineNum             
00385   );
00386 
00403   static ostream & End(ostream & strm );
00404 
00408   static void Cleanup();
00409 
00415   class Block {
00416     public:
00418       Block(
00419         const char * fileName, 
00420         int lineNum,           
00421         const char * traceName
00423        );
00424       Block(const Block & obj)
00425         : file(obj.file), line(obj.line), name(obj.name) { }
00427       ~Block();
00428     private:
00429       Block & operator=(const Block &)
00430       { return *this; }
00431       const char * file;
00432       int          line;
00433       const char * name;
00434   };
00435 };
00436 
00437 /* Macro to conditionally declare a parameter to a function to avoid compiler
00438    warning due that parameter only being used in a #PTRACE */
00439 #define PTRACE_PARAM(param) param
00440 
00447 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
00448 
00452 #define PTRACE_LINE() \
00453     if (PTrace::CanTrace(1)) \
00454       PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
00455     else (void)0
00456 
00462 #define PTRACE(level, args) \
00463     if (PTrace::CanTrace(level)) \
00464       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00465     else (void)0
00466 
00474 #define PTRACE_IF(level, cond, args) \
00475     if ((PTrace::CanTrace(level) && (cond))) \
00476       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
00477     else (void)0
00478 
00479 #else // PTRACING
00480 
00481 #define PTRACE_PARAM(param)
00482 #define PTRACE_BLOCK(n)
00483 #define PTRACE_LINE()
00484 #define PTRACE(level, arg)
00485 #define PTRACE_IF(level, cond, args)
00486 
00487 #endif // PTRACING
00488 
00489 
00490 
00491 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE)) 
00492 
00493 #define PMEMORY_HEAP 1
00494 
00501 class PMemoryHeap {
00502   public:
00504     PMemoryHeap();
00505 
00506     // Clear up the memory checking subsystem, dumping memory leaks.
00507     ~PMemoryHeap();
00508 
00515     static void * Allocate(
00516       size_t nSize,           
00517       const char * file,      
00518       int line,               
00519       const char * className  
00520     );
00527     static void * Allocate(
00528       size_t count,       
00529       size_t iSize,       
00530       const char * file,  
00531       int line            
00532     );
00533 
00541     static void * Reallocate(
00542       void * ptr,         
00543       size_t nSize,       
00544       const char * file,  
00545       int line            
00546     );
00547 
00553     static void Deallocate(
00554       void * ptr,             
00555       const char * className  
00556     );
00557 
00560     enum Validation {
00561       Ok, Bad, Trashed
00562     };
00570     static Validation Validate(
00571       const void * ptr,       
00572       const char * className, 
00573       ostream * error         
00574     );
00575 
00580     static PBoolean ValidateHeap(
00581       ostream * error = NULL  
00582     );
00583 
00589     static PBoolean SetIgnoreAllocations(
00590       PBoolean ignore  
00591     );
00592 
00596     static void DumpStatistics();
00600     static void DumpStatistics(ostream & strm );
00601 
00602 #if PMEMORY_CHECK
00603     struct State {
00604       DWORD allocationNumber;
00605     };
00606 #else
00607         typedef _CrtMemState State;
00608 #endif
00609 
00610     /* Get memory state.
00611       This returns a state that may be used to determine where to start dumping
00612       objects from.
00613      */
00614     static void GetState(
00615       State & state  
00616     );
00617 
00625     static void DumpObjectsSince(
00626       const State & when    
00627     );
00628 
00634     static void DumpObjectsSince(
00635       const State & when,   
00636       ostream & strm        
00637     );
00638 
00644     static void SetAllocationBreakpoint(
00645       DWORD point   
00646     );
00647 
00648 #if PMEMORY_CHECK
00649 
00650   protected:
00651     void * InternalAllocate(
00652       size_t nSize,           // Number of bytes to allocate.
00653       const char * file,      // Source file name for allocating function.
00654       int line,               // Source file line for allocating function.
00655       const char * className  // Class name for allocating function.
00656     );
00657     Validation InternalValidate(
00658       const void * ptr,       // Pointer to memory block to check
00659       const char * className, // Class name it should be.
00660       ostream * error         // Stream to receive error message (may be NULL)
00661     );
00662     void InternalDumpStatistics(ostream & strm);
00663     void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
00664 
00665     class Wrapper {
00666       public:
00667         Wrapper();
00668         ~Wrapper();
00669         PMemoryHeap * operator->() const { return instance; }
00670       private:
00671         PMemoryHeap * instance;
00672     };
00673     friend class Wrapper;
00674 
00675     enum Flags {
00676       NoLeakPrint = 1
00677     };
00678 
00679 #pragma pack(1)
00680     struct Header {
00681       enum {
00682         // Assure that the Header struct is aligned to 8 byte boundary
00683         NumGuardBytes = 16 - (sizeof(Header *) +
00684                               sizeof(Header *) +
00685                               sizeof(const char *) +
00686                               sizeof(const char *) +
00687                               sizeof(size_t) +
00688                               sizeof(DWORD) +
00689                               sizeof(WORD) +
00690                               sizeof(BYTE)
00691 #ifdef P_LINUX
00692                               + sizeof(pthread_t)
00693 #endif
00694                               )%8
00695       };
00696 
00697       Header     * prev;
00698       Header     * next;
00699       const char * className;
00700       const char * fileName;
00701       size_t       size;
00702       DWORD        request;
00703       WORD         line;
00704       BYTE         flags;
00705 #ifdef P_LINUX
00706       pthread_t    thread;
00707 #endif
00708       char         guard[NumGuardBytes];
00709 
00710       static char GuardBytes[NumGuardBytes];
00711     };
00712 #pragma pack()
00713 
00714     PBoolean isDestroyed;
00715 
00716     Header * listHead;
00717     Header * listTail;
00718 
00719     static DWORD allocationBreakpoint;
00720     DWORD allocationRequest;
00721     DWORD firstRealObject;
00722     BYTE  flags;
00723 
00724     char  allocFillChar;
00725     char  freeFillChar;
00726 
00727     DWORD currentMemoryUsage;
00728     DWORD peakMemoryUsage;
00729     DWORD currentObjects;
00730     DWORD peakObjects;
00731     DWORD totalObjects;
00732 
00733     ostream * leakDumpStream;
00734 
00735 #if defined(_WIN32)
00736     CRITICAL_SECTION mutex;
00737 #elif defined(P_PTHREADS)
00738     pthread_mutex_t mutex;
00739 #elif defined(P_VXWORKS)
00740     void * mutex;
00741 #endif
00742 
00743 #else
00744 
00745 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
00746     _CrtMemState initialState;
00747 
00748 #endif // PMEMORY_CHECK
00749 };
00750 
00751 
00756 inline void * runtime_malloc(size_t bytes  ) { return malloc(bytes); }
00757 
00762 inline void runtime_free(void * ptr  ) { free(ptr); }
00763 
00764 
00771 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
00772 
00779 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
00780 
00787 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
00788 
00789 
00796 #define free(p) PMemoryHeap::Deallocate(p, NULL)
00797 
00798 
00805 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
00806 
00807 
00822 #define PNEW  new (__FILE__, __LINE__)
00823 
00824 #if !defined(_MSC_VER) || _MSC_VER<1200
00825 #define PSPECIAL_DELETE_FUNCTION
00826 #else
00827 #define PSPECIAL_DELETE_FUNCTION \
00828     void operator delete(void * ptr, const char *, int) \
00829       { PMemoryHeap::Deallocate(ptr, Class()); } \
00830     void operator delete[](void * ptr, const char *, int) \
00831       { PMemoryHeap::Deallocate(ptr, Class()); }
00832 #endif
00833 
00834 #define PNEW_AND_DELETE_FUNCTIONS \
00835     void * operator new(size_t nSize, const char * file, int line) \
00836       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00837     void * operator new(size_t nSize) \
00838       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00839     void operator delete(void * ptr) \
00840       { PMemoryHeap::Deallocate(ptr, Class()); } \
00841     void * operator new(size_t, void * placement) \
00842       { return placement; } \
00843     void operator delete(void *, void *) \
00844       { } \
00845     void * operator new[](size_t nSize, const char * file, int line) \
00846       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
00847     void * operator new[](size_t nSize) \
00848       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
00849     void operator delete[](void * ptr) \
00850       { PMemoryHeap::Deallocate(ptr, Class()); } \
00851     PSPECIAL_DELETE_FUNCTION
00852 
00853 
00854 inline void * operator new(size_t nSize, const char * file, int line)
00855   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00856 
00857 inline void * operator new[](size_t nSize, const char * file, int line)
00858   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
00859 
00860 #ifndef __GNUC__
00861 void * operator new(size_t nSize);
00862 void * operator new[](size_t nSize);
00863 
00864 void operator delete(void * ptr);
00865 void operator delete[](void * ptr);
00866 
00867 #if defined(_MSC_VER) && _MSC_VER>=1200
00868 inline void operator delete(void * ptr, const char *, int)
00869   { PMemoryHeap::Deallocate(ptr, NULL); }
00870 
00871 inline void operator delete[](void * ptr, const char *, int)
00872   { PMemoryHeap::Deallocate(ptr, NULL); }
00873 #endif
00874 #endif
00875 
00876 
00877 class PMemoryHeapIgnoreAllocationsForScope {
00878 public:
00879   PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(PTrue)) { }
00880   ~PMemoryHeapIgnoreAllocationsForScope() { PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations); }
00881 private:
00882   PBoolean previousIgnoreAllocations;
00883 };
00884 
00885 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
00886 
00887 class PMemoryAllocationBreakpoint {
00888 public:
00889   PMemoryAllocationBreakpoint(DWORD point)
00890   {
00891     PMemoryHeap::SetAllocationBreakpoint(point);
00892   }
00893 };
00894 
00895 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
00896 
00897 
00898 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00899 
00900 #define PMEMORY_HEAP 0
00901 
00902 #define PNEW new
00903 
00904 #define PNEW_AND_DELETE_FUNCTIONS
00905 
00906 #define runtime_malloc(s) malloc(s)
00907 #define runtime_free(p) free(p)
00908 
00909 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
00910 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
00911 
00912 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
00913 
00914 
00925 #define PCLASSINFO(cls, par) \
00926   public: \
00927     static inline const char * Class() \
00928       { return #cls; } \
00929     virtual PBoolean InternalIsDescendant(const char * clsName) const \
00930       { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
00931     virtual const char * GetClass(unsigned ancestor = 0) const \
00932       { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
00933     virtual Comparison CompareObjectMemoryDirect(const PObject & _obj) const \
00934       { return (Comparison)memcmp(this, &_obj, sizeof(cls)); } \
00935     PNEW_AND_DELETE_FUNCTIONS
00936 
00937 
00938 #if P_HAS_TYPEINFO
00939 
00940 #define PIsDescendant(ptr, cls)    (dynamic_cast<const cls *>(ptr) != NULL) 
00941 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str)) 
00942 
00943 #define PRemoveConst(cls, ptr)  (const_cast<cls*>(ptr))
00944 
00945 #if P_USE_ASSERTS
00946 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line) 
00947   { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
00948 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
00949 #else
00950 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
00951 #endif
00952 
00953 #include <typeinfo>
00954 
00955 #else // P_HAS_TYPEINFO
00956 
00957 #define PIsDescendant(ptr, cls)    ((ptr)->InternalIsDescendant(cls::Class()))
00958 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
00959 
00960 #define PRemoveConst(cls, ptr)  ((cls*)(ptr))
00961 
00962 #if P_USE_ASSERTS
00963 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line) 
00964   { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
00965 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
00966 #else
00967 #define PDownCast(cls, ptr) ((cls*)(ptr))
00968 #endif
00969 
00970 #endif // P_HAS_TYPEINFO
00971 
00972 
00981 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
00982 #ifdef DOC_PLUS_PLUS
00983 } Match previous opening brace in doc++
00984 #endif
00985 
00987 // The root of all evil ... umm classes
00988 
00993 class PObject {
00994 
00995   protected:
00999     PObject() { }
01000 
01001   public:
01002     /* Destructor required to get the "virtual". A PObject really has nothing
01003        to destroy.
01004      */
01005     virtual ~PObject() { }
01006 
01019     static inline const char * Class()    { return "PObject"; }
01020 
01033     virtual const char * GetClass(unsigned /*ancestor*/ = 0) const { return Class(); }
01034 
01035     PBoolean IsClass(const char * cls) const 
01036     { return strcmp(cls, GetClass()) == 0; }
01037 
01047     virtual PBoolean InternalIsDescendant(
01048       const char * clsName    // Ancestor class name to compare against.
01049     ) const
01050     { return IsClass(clsName); }
01051 
01053 
01059     enum Comparison {
01060       LessThan = -1,
01061       EqualTo = 0,
01062       GreaterThan = 1
01063     };
01064 
01076     virtual Comparison Compare(
01077       const PObject & obj   // Object to compare against.
01078     ) const;
01079     
01091     virtual Comparison CompareObjectMemoryDirect(
01092       const PObject & obj   // Object to compare against.
01093     ) const;
01094 
01100     bool operator==(
01101       const PObject & obj   // Object to compare against.
01102     ) const { return Compare(obj) == EqualTo; }
01103 
01109     bool operator!=(
01110       const PObject & obj   // Object to compare against.
01111     ) const { return Compare(obj) != EqualTo; }
01112 
01118     bool operator<(
01119       const PObject & obj   // Object to compare against.
01120     ) const { return Compare(obj) == LessThan; }
01121 
01127     bool operator>(
01128       const PObject & obj   // Object to compare against.
01129     ) const { return Compare(obj) == GreaterThan; }
01130 
01136     bool operator<=(
01137       const PObject & obj   // Object to compare against.
01138     ) const { return Compare(obj) != GreaterThan; }
01139 
01145     bool operator>=(
01146       const PObject & obj   // Object to compare against.
01147     ) const { return Compare(obj) != LessThan; }
01149 
01158     virtual void PrintOn(
01159       ostream &strm   // Stream to print the object into.
01160     ) const;
01161 
01168     virtual void ReadFrom(
01169       istream &strm   // Stream to read the objects contents from.
01170     );
01171 
01172 
01178     inline friend ostream & operator<<(
01179       ostream &strm,       // Stream to print the object into.
01180       const PObject & obj  // Object to print to the stream.
01181     ) { obj.PrintOn(strm); return strm; }
01182 
01188     inline friend istream & operator>>(
01189       istream &strm,   // Stream to read the objects contents from.
01190       PObject & obj    // Object to read inormation into.
01191     ) { obj.ReadFrom(strm); return strm; }
01192 
01193 
01208     virtual PObject * Clone() const;
01209 
01221     virtual PINDEX HashFunction() const;
01223 };
01224 
01226 // Platform independent types
01227 
01228 // All these classes encapsulate primitive types such that they may be
01229 // transfered in a platform independent manner. In particular it is used to
01230 // do byte swapping for little endien and big endien processor architectures
01231 // as well as accommodating structure packing rules for memory structures.
01232 
01233 #define PANSI_CHAR 1
01234 #define PLITTLE_ENDIAN 2
01235 #define PBIG_ENDIAN 3
01236 
01237 
01238 #if 0
01239 class PStandardType
01240 /* Encapsulate a standard 8 bit character into a portable format. This would
01241    rarely need to do translation, only if the target platform uses EBCDIC
01242    would it do anything.
01243 
01244    The platform independent form here is always 8 bit ANSI.
01245  */
01246 {
01247   public:
01248     PStandardType(
01249       type newVal   // Value to initialise data in platform dependent form.
01250     ) { data = newVal; }
01251     /* Create a new instance of the platform independent type using platform
01252        dependent data, or platform independent streams.
01253      */
01254 
01255     operator type() { return data; }
01256     /* Get the platform dependent value for the type.
01257 
01258        @return
01259        data for instance.
01260      */
01261 
01262     friend ostream & operator<<(ostream & strm, const PStandardType & val)
01263       { return strm << (type)val; }
01264     /* Output the platform dependent value for the type to the stream.
01265 
01266        @return
01267        the stream output was made to.
01268      */
01269 
01270     friend istream & operator>>(istream & strm, PStandardType & val)
01271       { type data; strm >> data; val = PStandardType(data); return strm; }
01272     /* Input the platform dependent value for the type from the stream.
01273 
01274        @return
01275        the stream input was made from.
01276      */
01277 
01278 
01279   private:
01280     type data;
01281 };
01282 #endif
01283 
01284 
01285 #define PI_SAME(name, type) \
01286   struct name { \
01287     name() : data(0) { } \
01288     name(type value) : data(value) { } \
01289     name(const name & value) : data(value.data) { } \
01290     name & operator =(type value) { data = value; return *this; } \
01291     name & operator =(const name & value) { data = value.data; return *this; } \
01292     operator type() const { return data; } \
01293     friend ostream & operator<<(ostream & s, const name & v) { return s << v.data; } \
01294     friend istream & operator>>(istream & s, name & v) { return s >> v.data; } \
01295     private: type data; \
01296   }
01297 
01298 #define PI_LOOP(src, dst) \
01299     BYTE *s = ((BYTE *)&src)+sizeof(src); BYTE *d = (BYTE *)&dst; \
01300     while (s != (BYTE *)&src) *d++ = *--s;
01301 
01302 #define PI_DIFF(name, type) \
01303   struct name { \
01304     name() : data(0) { } \
01305     name(type value) : data(0) { operator=(value); } \
01306     name(const name & value) : data(value.data) { } \
01307     name & operator =(type value) { PI_LOOP(value, data); return *this; } \
01308     name & operator =(const name & value) { data = value.data; return *this; } \
01309     operator type() const { type value; PI_LOOP(data, value); return value; } \
01310     friend ostream & operator<<(ostream & s, const name & value) { return s << (type)value; } \
01311     friend istream & operator>>(istream & s, name & v) { type val; s >> val; v = val; return s; } \
01312     private: type data; \
01313   }
01314 
01315 #ifndef PCHAR8
01316 #define PCHAR8 PANSI_CHAR
01317 #endif
01318 
01319 #if PCHAR8==PANSI_CHAR
01320 PI_SAME(PChar8, char);
01321 #endif
01322 
01323 PI_SAME(PInt8, char);
01324 
01325 PI_SAME(PUInt8, unsigned char);
01326 
01327 #if PBYTE_ORDER==PLITTLE_ENDIAN
01328 PI_SAME(PInt16l, PInt16);
01329 #elif PBYTE_ORDER==PBIG_ENDIAN
01330 PI_DIFF(PInt16l, PInt16);
01331 #endif
01332 
01333 #if PBYTE_ORDER==PLITTLE_ENDIAN
01334 PI_DIFF(PInt16b, PInt16);
01335 #elif PBYTE_ORDER==PBIG_ENDIAN
01336 PI_SAME(PInt16b, PInt16);
01337 #endif
01338 
01339 #if PBYTE_ORDER==PLITTLE_ENDIAN
01340 PI_SAME(PUInt16l, WORD);
01341 #elif PBYTE_ORDER==PBIG_ENDIAN
01342 PI_DIFF(PUInt16l, WORD);
01343 #endif
01344 
01345 #if PBYTE_ORDER==PLITTLE_ENDIAN
01346 PI_DIFF(PUInt16b, WORD);
01347 #elif PBYTE_ORDER==PBIG_ENDIAN
01348 PI_SAME(PUInt16b, WORD);
01349 #endif
01350 
01351 #if PBYTE_ORDER==PLITTLE_ENDIAN
01352 PI_SAME(PInt32l, PInt32);
01353 #elif PBYTE_ORDER==PBIG_ENDIAN
01354 PI_DIFF(PInt32l, PInt32);
01355 #endif
01356 
01357 #if PBYTE_ORDER==PLITTLE_ENDIAN
01358 PI_DIFF(PInt32b, PInt32);
01359 #elif PBYTE_ORDER==PBIG_ENDIAN
01360 PI_SAME(PInt32b, PInt32);
01361 #endif
01362 
01363 #if PBYTE_ORDER==PLITTLE_ENDIAN
01364 PI_SAME(PUInt32l, DWORD);
01365 #elif PBYTE_ORDER==PBIG_ENDIAN
01366 PI_DIFF(PUInt32l, DWORD);
01367 #endif
01368 
01369 #if PBYTE_ORDER==PLITTLE_ENDIAN
01370 PI_DIFF(PUInt32b, DWORD);
01371 #elif PBYTE_ORDER==PBIG_ENDIAN
01372 PI_SAME(PUInt32b, DWORD);
01373 #endif
01374 
01375 #if PBYTE_ORDER==PLITTLE_ENDIAN
01376 PI_SAME(PInt64l, PInt64);
01377 #elif PBYTE_ORDER==PBIG_ENDIAN
01378 PI_DIFF(PInt64l, PInt64);
01379 #endif
01380 
01381 #if PBYTE_ORDER==PLITTLE_ENDIAN
01382 PI_DIFF(PInt64b, PInt64);
01383 #elif PBYTE_ORDER==PBIG_ENDIAN
01384 PI_SAME(PInt64b, PInt64);
01385 #endif
01386 
01387 #if PBYTE_ORDER==PLITTLE_ENDIAN
01388 PI_SAME(PUInt64l, PUInt64);
01389 #elif PBYTE_ORDER==PBIG_ENDIAN
01390 PI_DIFF(PUInt64l, PUInt64);
01391 #endif
01392 
01393 #if PBYTE_ORDER==PLITTLE_ENDIAN
01394 PI_DIFF(PUInt64b, PUInt64);
01395 #elif PBYTE_ORDER==PBIG_ENDIAN
01396 PI_SAME(PUInt64b, PUInt64);
01397 #endif
01398 
01399 #if PBYTE_ORDER==PLITTLE_ENDIAN
01400 PI_SAME(PFloat32l, float);
01401 #elif PBYTE_ORDER==PBIG_ENDIAN
01402 PI_DIFF(PFloat32l, float);
01403 #endif
01404 
01405 #if PBYTE_ORDER==PLITTLE_ENDIAN
01406 PI_DIFF(PFloat32b, float);
01407 #elif PBYTE_ORDER==PBIG_ENDIAN
01408 PI_SAME(PFloat32b, float);
01409 #endif
01410 
01411 #if PBYTE_ORDER==PLITTLE_ENDIAN
01412 PI_SAME(PFloat64l, double);
01413 #elif PBYTE_ORDER==PBIG_ENDIAN
01414 PI_DIFF(PFloat64l, double);
01415 #endif
01416 
01417 #if PBYTE_ORDER==PLITTLE_ENDIAN
01418 PI_DIFF(PFloat64b, double);
01419 #elif PBYTE_ORDER==PBIG_ENDIAN
01420 PI_SAME(PFloat64b, double);
01421 #endif
01422 
01423 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
01424 #if PBYTE_ORDER==PLITTLE_ENDIAN
01425 PI_SAME(PFloat80l, long double);
01426 #elif PBYTE_ORDER==PBIG_ENDIAN
01427 PI_DIFF(PFloat80l, long double);
01428 #endif
01429 
01430 #if PBYTE_ORDER==PLITTLE_ENDIAN
01431 PI_DIFF(PFloat80b, long double);
01432 #elif PBYTE_ORDER==PBIG_ENDIAN
01433 PI_SAME(PFloat80b, long double);
01434 #endif
01435 #endif
01436 
01437 #undef PI_LOOP
01438 #undef PI_SAME
01439 #undef PI_DIFF
01440 
01441 
01443 // Miscellaneous
01444 
01445 /*$MACRO PARRAYSIZE(array)
01446    This macro is used to calculate the number of array elements in a static
01447    array.
01448  */
01449 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
01450 
01451 /*$MACRO PMIN(v1, v2)
01452    This macro is used to calculate the minimum of two values. As this is a
01453    macro the expression in #v1 or #v2 is executed
01454    twice so extreme care should be made in its use.
01455  */
01456 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
01457 
01458 /*$MACRO PMAX(v1, v2)
01459    This macro is used to calculate the maximum of two values. As this is a
01460    macro the expression in #v1 or #v2 is executed
01461    twice so extreme care should be made in its use.
01462  */
01463 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
01464 
01465 /*$MACRO PABS(val)
01466    This macro is used to calculate an absolute value. As this is a macro the
01467    expression in #val is executed twice so extreme care should be
01468    made in its use.
01469  */
01470 #define PABS(v) ((v) < 0 ? -(v) : (v))
01471 
01472 #endif // _POBJECT_H
01473 
01474 // End Of File ///////////////////////////////////////////////////////////////

Generated on Mon Sep 15 01:21:35 2008 for PTLib by  doxygen 1.5.1