PTLib  Version 2.10.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
object.h
Go to the documentation of this file.
1 /*
2  * object.h
3  *
4  * Mother of all ancestor classes.
5  *
6  * Portable Tools Library
7  *
8  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25  * All Rights Reserved.
26  *
27  * Contributor(s): ______________________________________.
28  *
29  * $Revision: 26785 $
30  * $Author: rjongbloed $
31  * $Date: 2011-12-08 17:41:53 -0600 (Thu, 08 Dec 2011) $
32  */
33 
34 #ifndef PTLIB_OBJECT_H
35 #define PTLIB_OBJECT_H
36 
37 #ifdef P_USE_PRAGMA
38 #pragma interface
39 #endif
40 
41 #if defined(_WIN32) || defined(_WIN32_WCE)
42 #include "msos/ptlib/contain.h"
43 #else
44 #include "unix/ptlib/contain.h"
45 #endif
46 
47 #if defined(P_VXWORKS)
48 #include <private/stdiop.h>
49 #endif
50 
51 #include <stdio.h>
52 #include <stdarg.h>
53 #include <stdlib.h>
54 
55 #include <string.h>
56 
57 #include <string>
58 #include <iomanip>
59 #include <iostream>
60 #include <sstream>
61 
62 
63 #define P_REMOVE_VIRTUAL_INTERNAL_BASE(fn) __inline virtual struct ptlib_virtual_function_changed_or_removed ****** fn { return 0; }
64 
65 #if defined(_MSC_VER)
66  #if _MSC_VER < 1310
67  #define P_DEPRECATED
68  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
69  #elif _MSC_VER < 1400
70  #define P_DEPRECATED __declspec(deprecated)
71  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated) type fn body
72  #else
73  #define P_DEPRECATED __declspec(deprecated)
74  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated("Virtual function signature changed or function deprecated")) type fn body
75  #endif
76 #elif defined(__GNUC__)
77  #if __GNUC__ < 4
78  #define P_DEPRECATED
79  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
80  #else
81  #define P_DEPRECATED __attribute__((deprecated))
82  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __attribute__((warn_unused_result)) __attribute__((deprecated)) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
83  #endif
84 #else
85  #define P_DEPRECATED
86  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
87 #endif
88 
89 #define P_REMOVE_VIRTUAL_VOID(fn) P_REMOVE_VIRTUAL_INTERNAL(void, fn, {})
90 #define P_REMOVE_VIRTUAL(type, fn, ret) P_REMOVE_VIRTUAL_INTERNAL(type, fn, { return ret; })
91 
92 
93 // P_USE_INTEGER_BOOL is the default and gives the old behaviour (it
94 // is also used for C translation units).
95 // without P_USE_INTEGER_BOOL, the ANSI C++ bool is used.
96 
97 #if defined(P_USE_INTEGER_BOOL) || !defined(__cplusplus)
98  typedef BOOL PBoolean;
99 # define PTrue TRUE
100 # define PFalse FALSE
101 #else
102  typedef bool PBoolean;
103 # define PTrue true
104 # define PFalse false
105 #endif
106 
107 
109 // Disable inlines when debugging for faster compiles (the compiler doesn't
110 // actually inline the function with debug on any way).
111 
112 #ifndef P_USE_INLINES
113 #ifdef _DEBUG
114 #define P_USE_INLINES 0
115 #else
116 #define P_USE_INLINES 0
117 #endif
118 #endif
119 
120 #if P_USE_INLINES
121 #define PINLINE inline
122 #else
123 #define PINLINE
124 #endif
125 
126 
128 // Declare the debugging support
129 
130 #ifndef P_USE_ASSERTS
131 #define P_USE_ASSERTS 1
132 #endif
133 
134 #if !P_USE_ASSERTS
135 
136 #define PAssert(b, m) (b)
137 #define PAssert2(b, c, m) (b)
138 #define PAssertOS(b) (b)
139 #define PAssertNULL(p) (p)
140 #define PAssertAlways(m) {}
141 #define PAssertAlways2(c, m) {}
142 
143 #else // P_USE_ASSERTS
144 
161 };
162 
163 #define __CLASS__ NULL
164 
165 void PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
166 void PAssertFunc(const char * file, int line, const char * className, const char * msg);
167 void PAssertFunc(const char * full_msg);
168 
169 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, PStandardAssertMessage msg)
170 {
171  if (!b)
172  PAssertFunc(file, line, className, msg);
173  return b;
174 }
175 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, const char * msg)
176 {
177  if (!b)
178  PAssertFunc(file, line, className, msg);
179  return b;
180 }
181 
188 #define PAssert(b, msg) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,(msg))
189 
197 #define PAssert2(b, cls, msg) PAssertFuncInline((b), __FILE__,__LINE__,(cls),(msg))
198 
205 #define PAssertOS(b) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,POperatingSystemError)
206 
216 #define PAssertNULL(ptr) (((ptr)!=NULL)?(ptr): \
217  (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(ptr)))
218 
225 #define PAssertAlways(msg) PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg))
226 
233 #define PAssertAlways2(cls, msg) PAssertFunc(__FILE__,__LINE__,(cls),(msg))
234 
235 #endif // P_USE_ASSERTS
236 
237 
242 ostream & PGetErrorStream();
243 
247 void PSetErrorStream(ostream * strm );
248 
263 #define PError (PGetErrorStream())
264 
265 
266 
268 // Debug and tracing
269 
270 #ifndef PTRACING
271 #define PTRACING 1
272 #endif
273 
274 #if PTRACING
275 
288 class PTrace
289 {
290 public:
292  enum Options {
298  Blocks = 1,
304  Thread = 8,
314  GMTTime = 256,
316  RotateDaily = 512,
318  RotateHourly = 1024,
327  };
328 
329 
343  static void Initialise(
344  unsigned level,
345  const char * filename = NULL,
346  unsigned options = Timestamp | Thread | Blocks
347  );
348 
359  static void Initialise(
360  unsigned level,
361  const char * filename,
362  const char * rolloverPattern,
363  unsigned options = Timestamp | Thread | Blocks
364  );
365 
372  static void SetOptions(
373  unsigned options
374  );
375 
384  static void ClearOptions(
385  unsigned options
386  );
387 
393  static unsigned GetOptions();
394 
400  static void SetLevel(
401  unsigned level
402  );
403 
409  static unsigned GetLevel();
410 
415  static PBoolean CanTrace(
416  unsigned level
417  );
418 
423  static void SetStream(
424  ostream * out
425  );
426 
442  static ostream & Begin(
443  unsigned level,
444  const char * fileName,
445  int lineNum
446  );
447 
465  static ostream & End(
466  ostream & strm
467  );
468 
472  static void Cleanup();
473 
479  class Block {
480  public:
482  Block(
483  const char * fileName,
484  int lineNum,
485  const char * traceName
487  );
488  Block(const Block & obj)
489  : file(obj.file), line(obj.line), name(obj.name) { }
491  ~Block();
492  private:
493  Block & operator=(const Block &)
494  { return *this; }
495  const char * file;
496  int line;
497  const char * name;
498  };
499 };
500 
501 /* Macro to conditionally declare a parameter to a function to avoid compiler
502  warning due that parameter only being used in a <code>PTRACE()</code> */
503 #define PTRACE_PARAM(param) param
504 
511 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
512 
516 #define PTRACE_LINE() \
517  if (PTrace::CanTrace(1)) \
518  PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
519  else (void)0
520 
526 #define PTRACE(level, args) \
527  if (PTrace::CanTrace(level)) \
528  PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
529  else (void)0
530 
538 #define PTRACE_IF(level, cond, args) \
539  if ((PTrace::CanTrace(level) && (cond))) \
540  PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
541  else (void)0
542 
543 #else // PTRACING
544 
545 #define PTRACE_PARAM(param)
546 #define PTRACE_BLOCK(n)
547 #define PTRACE_LINE()
548 #define PTRACE(level, arg)
549 #define PTRACE_IF(level, cond, args)
550 
551 #endif // PTRACING
552 
553 
554 
555 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE))
556 
557 #define PMEMORY_HEAP 1
558 
565 class PMemoryHeap {
566  public:
568  PMemoryHeap();
569 
570  // Clear up the memory checking subsystem, dumping memory leaks.
571  ~PMemoryHeap();
572 
579  static void * Allocate(
580  size_t nSize,
581  const char * file,
582  int line,
583  const char * className
584  );
591  static void * Allocate(
592  size_t count,
593  size_t iSize,
594  const char * file,
595  int line
596  );
597 
605  static void * Reallocate(
606  void * ptr,
607  size_t nSize,
608  const char * file,
609  int line
610  );
611 
617  static void Deallocate(
618  void * ptr,
619  const char * className
620  );
621 
624  enum Validation {
626  };
634  static Validation Validate(
635  const void * ptr,
636  const char * className,
637  ostream * error
638  );
639 
644  static PBoolean ValidateHeap(
645  ostream * error = NULL
646  );
647 
654  PBoolean ignore
655  );
656 
660  static void DumpStatistics();
664  static void DumpStatistics(ostream & strm );
665 
666 #if PMEMORY_CHECK
667  struct State {
669  };
670 #else
671  typedef _CrtMemState State;
672 #endif
673 
674  /* Get memory state.
675  This returns a state that may be used to determine where to start dumping
676  objects from.
677  */
678  static void GetState(
679  State & state
680  );
681 
689  static void DumpObjectsSince(
690  const State & when
691  );
692 
698  static void DumpObjectsSince(
699  const State & when,
700  ostream & strm
701  );
702 
708  static void SetAllocationBreakpoint(
709  DWORD point
710  );
711 
712 #if PMEMORY_CHECK
713 
714  protected:
715  void * InternalAllocate(
716  size_t nSize, // Number of bytes to allocate.
717  const char * file, // Source file name for allocating function.
718  int line, // Source file line for allocating function.
719  const char * className // Class name for allocating function.
720  );
722  const void * ptr, // Pointer to memory block to check
723  const char * className, // Class name it should be.
724  ostream * error // Stream to receive error message (may be NULL)
725  );
726  void InternalDumpStatistics(ostream & strm);
727  void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
728 
729  class Wrapper {
730  public:
731  Wrapper();
732  ~Wrapper();
733  PMemoryHeap * operator->() const { return instance; }
734  private:
735  PMemoryHeap * instance;
736  };
737  friend class Wrapper;
738 
739  enum Flags {
741  };
742 
743 #pragma pack(1)
744  struct Header {
745  enum {
746  // Assure that the Header struct is aligned to 8 byte boundary
747  NumGuardBytes = 16 - (sizeof(Header *) +
748  sizeof(Header *) +
749  sizeof(const char *) +
750  sizeof(const char *) +
751  sizeof(size_t) +
752  sizeof(DWORD) +
753  sizeof(WORD) +
754  sizeof(BYTE)
755 #ifdef P_LINUX
756  + sizeof(pthread_t)
757 #endif
758  )%8
759  };
760 
763  const char * className;
764  const char * fileName;
765  size_t size;
766  DWORD request;
767  WORD line;
768  BYTE flags;
769 #ifdef P_LINUX
770  pthread_t thread;
771 #endif
773 
774  static char GuardBytes[NumGuardBytes];
775  };
776 #pragma pack()
777 
779 
782 
783  static DWORD allocationBreakpoint;
786  BYTE flags;
787 
790 
794  DWORD peakObjects;
796 
797  ostream * leakDumpStream;
798 
799 #if defined(_WIN32)
800  CRITICAL_SECTION mutex;
801 #elif defined(P_PTHREADS)
802  pthread_mutex_t mutex;
803 #elif defined(P_VXWORKS)
804  void * mutex;
805 #endif
806 
807 #else
808 
809 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
810  _CrtMemState initialState;
811 
812 #endif // PMEMORY_CHECK
813 };
814 
815 
820 inline void * runtime_malloc(size_t bytes ) { return malloc(bytes); }
821 
826 inline void runtime_free(void * ptr ) { free(ptr); }
827 
828 
835 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
836 
843 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
844 
851 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
852 
853 
860 #define free(p) PMemoryHeap::Deallocate(p, NULL)
861 
862 
869 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
870 
871 
886 #define PNEW new (__FILE__, __LINE__)
887 
888 #if !defined(_MSC_VER) || _MSC_VER<1200
889 #define PSPECIAL_DELETE_FUNCTION
890 #else
891 #define PSPECIAL_DELETE_FUNCTION \
892  void operator delete(void * ptr, const char *, int) \
893  { PMemoryHeap::Deallocate(ptr, Class()); } \
894  void operator delete[](void * ptr, const char *, int) \
895  { PMemoryHeap::Deallocate(ptr, Class()); }
896 #endif
897 
898 #define PNEW_AND_DELETE_FUNCTIONS \
899  void * operator new(size_t nSize, const char * file, int line) \
900  { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
901  void * operator new(size_t nSize) \
902  { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
903  void operator delete(void * ptr) \
904  { PMemoryHeap::Deallocate(ptr, Class()); } \
905  void * operator new(size_t, void * placement) \
906  { return placement; } \
907  void operator delete(void *, void *) \
908  { } \
909  void * operator new[](size_t nSize, const char * file, int line) \
910  { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
911  void * operator new[](size_t nSize) \
912  { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
913  void operator delete[](void * ptr) \
914  { PMemoryHeap::Deallocate(ptr, Class()); } \
915  PSPECIAL_DELETE_FUNCTION
916 
917 
918 inline void * operator new(size_t nSize, const char * file, int line)
919  { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
920 
921 inline void * operator new[](size_t nSize, const char * file, int line)
922  { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
923 
924 #ifndef __GNUC__
925 void * operator new(size_t nSize);
926 void * operator new[](size_t nSize);
927 
928 void operator delete(void * ptr);
929 void operator delete[](void * ptr);
930 
931 #if defined(_MSC_VER) && _MSC_VER>=1200
932 inline void operator delete(void * ptr, const char *, int)
933  { PMemoryHeap::Deallocate(ptr, NULL); }
934 
935 inline void operator delete[](void * ptr, const char *, int)
936  { PMemoryHeap::Deallocate(ptr, NULL); }
937 #endif
938 #endif
939 
940 
942 public:
943  PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(true)) { }
945 private:
946  PBoolean previousIgnoreAllocations;
947 };
948 
949 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
950 
952 public:
954  {
956  }
957 };
958 
959 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
960 
961 
962 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
963 
964 #define PMEMORY_HEAP 0
965 
966 #define PNEW new
967 
968 #define PNEW_AND_DELETE_FUNCTIONS
969 
970 #define runtime_malloc(s) malloc(s)
971 #define runtime_free(p) free(p)
972 
973 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
974 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
975 
976 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
977 
978 
979 
980 /*
981  * Implement "construct on first use" paradigm
982  */
983 
984 template <class GnuAllocator, class Type>
986 {
987  Type * allocate(size_t v)
988  {
989  return GetAllocator().allocate(v);
990  }
991 
992  void deallocate(Type * p, size_t v)
993  {
994  GetAllocator().deallocate(p, v);
995  }
996 
997  private:
998  static GnuAllocator & GetAllocator()
999  {
1000  static GnuAllocator instance;
1001  return instance;
1002  }
1003 };
1004 
1005 #define GCC_VERSION (__GNUC__ * 10000 \
1006  + __GNUC_MINOR__ * 100 \
1007  + __GNUC_PATCHLEVEL__)
1008 
1009 // Memory pooling allocators
1010 #if defined(__GNUC__) && (GCC_VERSION > 40000) && !defined(P_MINGW) && !defined(P_MACOSX)
1011 #include <ext/mt_allocator.h>
1012 template <class Type> struct PFixedPoolAllocator : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
1013 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
1014 
1015 #else
1016 
1017 template <class Type> struct PFixedPoolAllocator : public PAllocatorTemplate<std::allocator<Type>, Type> { };
1018 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<std::allocator<Type>, Type> { };
1019 #endif
1020 
1021 #define PDECLARE_POOL_ALLOCATOR() \
1022  void * operator new(size_t nSize); \
1023  void * operator new(size_t nSize, const char * file, int line); \
1024  void operator delete(void * ptr); \
1025  void operator delete(void * ptr, const char *, int)
1026 
1027 #define PDEFINE_POOL_ALLOCATOR(cls) \
1028  static PFixedPoolAllocator<cls> cls##_allocator; \
1029  void * cls::operator new(size_t) { return cls##_allocator.allocate(1); } \
1030  void * cls::operator new(size_t, const char *, int) { return cls##_allocator.allocate(1); } \
1031  void cls::operator delete(void * ptr) { cls##_allocator.deallocate((cls *)ptr, 1); } \
1032  void cls::operator delete(void * ptr, const char *, int) { cls##_allocator.deallocate((cls *)ptr, 1); }
1033 
1034 
1045 #define PCLASSINFO(cls, par) \
1046  public: \
1047  typedef cls P_thisClass; \
1048  static inline const char * Class() \
1049  { return #cls; } \
1050  virtual PBoolean InternalIsDescendant(const char * clsName) const \
1051  { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
1052  virtual const char * GetClass(unsigned ancestor = 0) const \
1053  { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
1054  virtual PObject::Comparison CompareObjectMemoryDirect(const PObject & obj) const \
1055  { return PObject::InternalCompareObjectMemoryDirect(this, dynamic_cast<const cls *>(&obj), sizeof(cls)); } \
1056  PNEW_AND_DELETE_FUNCTIONS
1057 
1058 
1059 #if P_HAS_TYPEINFO
1060 
1061 #define PIsDescendant(ptr, cls) (dynamic_cast<const cls *>(ptr) != NULL)
1062 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
1063 
1064 #define PRemoveConst(cls, ptr) (const_cast<cls*>(ptr))
1065 
1066 #if P_USE_ASSERTS
1067 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line)
1068  { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
1069 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
1070 #else
1071 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
1072 #endif
1073 
1074 #include <typeinfo>
1075 
1076 #else // P_HAS_TYPEINFO
1077 
1078 #define PIsDescendant(ptr, cls) ((ptr)->InternalIsDescendant(cls::Class()))
1079 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
1080 
1081 #define PRemoveConst(cls, ptr) ((cls*)(ptr))
1082 
1083 #if P_USE_ASSERTS
1084 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line)
1085  { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
1086 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
1087 #else
1088 #define PDownCast(cls, ptr) ((cls*)(ptr))
1089 #endif
1090 
1091 #endif // P_HAS_TYPEINFO
1092 
1093 
1102 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
1103 #ifdef DOC_PLUS_PLUS
1104 } Match previous opening brace in doc++
1105 #endif
1106 
1108 // The root of all evil ... umm classes
1109 
1114 class PObject {
1115 
1116  protected:
1120  PObject() { }
1121 
1122  public:
1123  /* Destructor required to get the "virtual". A PObject really has nothing
1124  to destroy.
1125  */
1126  virtual ~PObject() { }
1127 
1140  static inline const char * Class() { return "PObject"; }
1141 
1154  virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : Class(); }
1155 
1156  PBoolean IsClass(const char * cls) const
1157  { return strcmp(cls, GetClass()) == 0; }
1158 
1169  const char * clsName // Ancestor class name to compare against.
1170  ) const
1171  { return IsClass(clsName); }
1172 
1174 
1180  enum Comparison {
1181  LessThan = -1,
1182  EqualTo = 0,
1184  };
1185 
1197  virtual Comparison Compare(
1198  const PObject & obj // Object to compare against.
1199  ) const;
1200 
1213  const PObject & obj // Object to compare against.
1214  ) const;
1215 
1218  const PObject * obj1,
1219  const PObject * obj2,
1220  PINDEX size
1221  );
1222 
1229  const PObject & obj // Object to compare against.
1230  ) const { return Compare(obj) == EqualTo; }
1231 
1238  const PObject & obj // Object to compare against.
1239  ) const { return Compare(obj) != EqualTo; }
1240 
1247  const PObject & obj // Object to compare against.
1248  ) const { return Compare(obj) == LessThan; }
1249 
1256  const PObject & obj // Object to compare against.
1257  ) const { return Compare(obj) == GreaterThan; }
1258 
1265  const PObject & obj // Object to compare against.
1266  ) const { return Compare(obj) != GreaterThan; }
1267 
1274  const PObject & obj // Object to compare against.
1275  ) const { return Compare(obj) != LessThan; }
1277 
1286  virtual void PrintOn(
1287  ostream &strm // Stream to print the object into.
1288  ) const;
1289 
1296  virtual void ReadFrom(
1297  istream &strm // Stream to read the objects contents from.
1298  );
1299 
1300 
1306  inline friend ostream & operator<<(
1307  ostream &strm,
1308  const PObject & obj
1309  ) { obj.PrintOn(strm); return strm; }
1310 
1316  inline friend istream & operator>>(
1317  istream &strm,
1318  PObject & obj
1319  ) { obj.ReadFrom(strm); return strm; }
1320 
1321 
1336  virtual PObject * Clone() const;
1337 
1349  virtual PINDEX HashFunction() const;
1351 };
1352 
1354 // Platform independent types
1355 
1356 // All these classes encapsulate primitive types such that they may be
1357 // transfered in a platform independent manner. In particular it is used to
1358 // do byte swapping for little endien and big endien processor architectures
1359 // as well as accommodating structure packing rules for memory structures.
1360 
1361 #define PANSI_CHAR 1
1362 #define PLITTLE_ENDIAN 2
1363 #define PBIG_ENDIAN 3
1364 
1365 
1366 template <typename type>
1368  __inline PIntSameOrder() : data(0) { }
1369  __inline PIntSameOrder(type value) : data(value) { }
1370  __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data) { }
1371  __inline PIntSameOrder & operator=(type value) { data = value; return *this; }
1372  __inline PIntSameOrder & operator=(const PIntSameOrder & value) { data = value.data; return *this; }
1373  __inline operator type() const { return data; }
1374  __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
1375  __inline friend istream & operator>>(istream & s, PIntSameOrder & v) { return s >> v.data; }
1376 
1377  private:
1378  type data;
1379 };
1380 
1381 
1382 template <typename type>
1384  __inline PIntReversedOrder() : data(0) { }
1385  __inline PIntReversedOrder(type value) { ReverseBytes(value, data); }
1386  __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data) { }
1387  __inline PIntReversedOrder & operator=(type value) { ReverseBytes(value, data); return *this; }
1388  __inline PIntReversedOrder & operator=(const PIntReversedOrder & value) { data = value.data; return *this; }
1389  __inline operator type() const { type value; ReverseBytes(data, value); return value; }
1390  __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
1391  __inline friend istream & operator>>(istream & s, PIntReversedOrder & v) { type val; s >> val; v = val; return s; }
1392 
1393  private:
1394  type data;
1395 
1396  static __inline void ReverseBytes(const type & src, type & dst)
1397  {
1398  size_t s = sizeof(type)-1;
1399  for (size_t d = 0; d < sizeof(type); ++d,--s)
1400  ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
1401  }
1402 };
1403 
1404 #ifndef PCHAR8
1405 #define PCHAR8 PANSI_CHAR
1406 #endif
1407 
1408 #if PCHAR8==PANSI_CHAR
1410 #endif
1411 
1413 
1415 
1416 #if PBYTE_ORDER==PLITTLE_ENDIAN
1417 typedef PIntSameOrder<PInt16> PInt16l;
1418 #elif PBYTE_ORDER==PBIG_ENDIAN
1419 typedef PIntReversedOrder<PInt16> PInt16l;
1420 #endif
1421 
1422 #if PBYTE_ORDER==PLITTLE_ENDIAN
1423 typedef PIntReversedOrder<PInt16> PInt16b;
1424 #elif PBYTE_ORDER==PBIG_ENDIAN
1425 typedef PIntSameOrder<PInt16> PInt16b;
1426 #endif
1427 
1428 #if PBYTE_ORDER==PLITTLE_ENDIAN
1429 typedef PIntSameOrder<WORD> PUInt16l;
1430 #elif PBYTE_ORDER==PBIG_ENDIAN
1431 typedef PIntReversedOrder<WORD> PUInt16l;
1432 #endif
1433 
1434 #if PBYTE_ORDER==PLITTLE_ENDIAN
1435 typedef PIntReversedOrder<WORD> PUInt16b;
1436 #elif PBYTE_ORDER==PBIG_ENDIAN
1437 typedef PIntSameOrder<WORD> PUInt16b;
1438 #endif
1439 
1440 #if PBYTE_ORDER==PLITTLE_ENDIAN
1441 typedef PIntSameOrder<PInt32> PInt32l;
1442 #elif PBYTE_ORDER==PBIG_ENDIAN
1443 typedef PIntReversedOrder<PInt32> PInt32l;
1444 #endif
1445 
1446 #if PBYTE_ORDER==PLITTLE_ENDIAN
1447 typedef PIntReversedOrder<PInt32> PInt32b;
1448 #elif PBYTE_ORDER==PBIG_ENDIAN
1449 typedef PIntSameOrder<PInt32> PInt32b;
1450 #endif
1451 
1452 #if PBYTE_ORDER==PLITTLE_ENDIAN
1453 typedef PIntSameOrder<DWORD> PUInt32l;
1454 #elif PBYTE_ORDER==PBIG_ENDIAN
1455 typedef PIntReversedOrder<DWORD> PUInt32l;
1456 #endif
1457 
1458 #if PBYTE_ORDER==PLITTLE_ENDIAN
1459 typedef PIntReversedOrder<DWORD> PUInt32b;
1460 #elif PBYTE_ORDER==PBIG_ENDIAN
1461 typedef PIntSameOrder<DWORD> PUInt32b;
1462 #endif
1463 
1464 #if PBYTE_ORDER==PLITTLE_ENDIAN
1465 typedef PIntSameOrder<PInt64> PInt64l;
1466 #elif PBYTE_ORDER==PBIG_ENDIAN
1467 typedef PIntReversedOrder<PInt64> PInt64l;
1468 #endif
1469 
1470 #if PBYTE_ORDER==PLITTLE_ENDIAN
1471 typedef PIntReversedOrder<PInt64> PInt64b;
1472 #elif PBYTE_ORDER==PBIG_ENDIAN
1473 typedef PIntSameOrder<PInt64> PInt64b;
1474 #endif
1475 
1476 #if PBYTE_ORDER==PLITTLE_ENDIAN
1477 typedef PIntSameOrder<PUInt64> PUInt64l;
1478 #elif PBYTE_ORDER==PBIG_ENDIAN
1479 typedef PIntReversedOrder<PUInt64> PUInt64l;
1480 #endif
1481 
1482 #if PBYTE_ORDER==PLITTLE_ENDIAN
1483 typedef PIntReversedOrder<PUInt64> PUInt64b;
1484 #elif PBYTE_ORDER==PBIG_ENDIAN
1485 typedef PIntSameOrder<PUInt64> PUInt64b;
1486 #endif
1487 
1488 #if PBYTE_ORDER==PLITTLE_ENDIAN
1489 typedef PIntSameOrder<float> PFloat32l;
1490 #elif PBYTE_ORDER==PBIG_ENDIAN
1491 typedef PIntReversedOrder<float> PFloat32l;
1492 #endif
1493 
1494 #if PBYTE_ORDER==PLITTLE_ENDIAN
1495 typedef PIntReversedOrder<float> PFloat32b;
1496 #elif PBYTE_ORDER==PBIG_ENDIAN
1497 typedef PIntSameOrder<float> PFloat32b;
1498 #endif
1499 
1500 #if PBYTE_ORDER==PLITTLE_ENDIAN
1501 typedef PIntSameOrder<double> PFloat64l;
1502 #elif PBYTE_ORDER==PBIG_ENDIAN
1503 typedef PIntReversedOrder<double> PFloat64l;
1504 #endif
1505 
1506 #if PBYTE_ORDER==PLITTLE_ENDIAN
1507 typedef PIntReversedOrder<double> PFloat64b;
1508 #elif PBYTE_ORDER==PBIG_ENDIAN
1509 typedef PIntSameOrder<double> PFloat64b;
1510 #endif
1511 
1512 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
1513 #if PBYTE_ORDER==PLITTLE_ENDIAN
1514 typedef PIntSameOrder<long double> PFloat80l;
1515 #elif PBYTE_ORDER==PBIG_ENDIAN
1516 typedef PIntReversedOrder<long double> PFloat80l;
1517 #endif
1518 
1519 #if PBYTE_ORDER==PLITTLE_ENDIAN
1520 typedef PIntReversedOrder<long double> PFloat80b;
1521 #elif PBYTE_ORDER==PBIG_ENDIAN
1522 typedef PIntSameOrder<long double> PFloat80b;
1523 #endif
1524 #endif
1525 
1526 
1528 // Miscellaneous
1529 
1530 /*$MACRO PARRAYSIZE(array)
1531  This macro is used to calculate the number of array elements in a static
1532  array.
1533  */
1534 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
1535 
1536 /*$MACRO PMIN(v1, v2)
1537  This macro is used to calculate the minimum of two values. As this is a
1538  macro the expression in <code>v1</code> or <code>v2</code> is executed
1539  twice so extreme care should be made in its use.
1540  */
1541 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
1542 
1543 /*$MACRO PMAX(v1, v2)
1544  This macro is used to calculate the maximum of two values. As this is a
1545  macro the expression in <code>v1</code> or <code>v2</code> is executed
1546  twice so extreme care should be made in its use.
1547  */
1548 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
1549 
1550 /*$MACRO PABS(val)
1551  This macro is used to calculate an absolute value. As this is a macro the
1552  expression in <code>val</code> is executed twice so extreme care should be
1553  made in its use.
1554  */
1555 #define PABS(v) ((v) < 0 ? -(v) : (v))
1556 
1557 
1558 #endif // PTLIB_OBJECT_H
1559 
1560 
1561 // End Of File ///////////////////////////////////////////////////////////////