PTLib  Version 2.12.9
 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: 30928 $
30  * $Author: rjongbloed $
31  * $Date: 2013-11-20 10:39:04 +1100 (Wed, 20 Nov 2013) $
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)
42 #include "msos/ptlib/platform.h"
43 #else
44 #include "unix/ptlib/platform.h"
45 #endif
46 
47 #include <stdio.h>
48 #include <stdarg.h>
49 #include <stdlib.h>
50 #include <limits.h>
51 #include <string.h>
52 #include <ctype.h>
53 #include <errno.h>
54 
55 #include <string>
56 #include <iomanip>
57 #include <iostream>
58 #include <sstream>
59 #include <vector>
60 #include <list>
61 #include <map>
62 #include <algorithm>
63 #include <typeinfo>
64 
65 using namespace std; // Not a good practice (name space polution), but will take too long to fix.
66 
67 // Somewhere in C headers you get this, which blows up STL version
68 #ifdef min
69 #undef min
70 #endif
71 #ifdef max
72 #undef max
73 #endif
74 
75 
77 
78 #define P_REMOVE_VIRTUAL_INTERNAL_BASE(fn) __inline virtual struct ptlib_virtual_function_changed_or_removed ****** fn { return 0; }
79 
80 #if defined(_MSC_VER)
81  #if _MSC_VER < 1310
82  #define P_DEPRECATED
83  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
84  #elif _MSC_VER < 1400
85  #define P_DEPRECATED __declspec(deprecated)
86  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated) type fn body
87  #else
88  #define P_DEPRECATED __declspec(deprecated)
89  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated("Virtual function signature changed or function deprecated")) type fn body
90  #endif
91 #elif defined(__GNUC__)
92  #if __GNUC__ < 4
93  #define P_DEPRECATED
94  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
95  #else
96  #define P_DEPRECATED __attribute__((deprecated))
97  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __attribute__((warn_unused_result)) __attribute__((deprecated)) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
98  #endif
99 #else
100  #define P_DEPRECATED
101  #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
102 #endif
103 
104 #define P_REMOVE_VIRTUAL_VOID(fn) P_REMOVE_VIRTUAL_INTERNAL(void, fn, {})
105 #define P_REMOVE_VIRTUAL(type, fn, ret) P_REMOVE_VIRTUAL_INTERNAL(type, fn, { return ret; })
106 
107 
108 #ifdef _MSC_VER
109  #define P_PUSH_MSVC_WARNINGS(warnings) __pragma(warning(push)) __pragma(warning(disable:warnings))
110  #define P_POP_MSVC_WARNINGS() __pragma(warning(pop))
111 #else
112  #define P_PUSH_MSVC_WARNINGS(warnings)
113  #define P_POP_MSVC_WARNINGS()
114 #endif // _MSC_VER
115 #define P_DISABLE_MSVC_WARNINGS(warnings, statement) P_PUSH_MSVC_WARNINGS(warnings) statement P_POP_MSVC_WARNINGS()
116 
117 
118 // P_USE_INTEGER_BOOL is the default and gives the old behaviour (it
119 // is also used for C translation units).
120 // without P_USE_INTEGER_BOOL, the ANSI C++ bool is used.
121 
122 #ifndef FALSE
123 #define FALSE 0
124 #endif
125 #ifndef TRUE
126 #define TRUE 1
127 #endif
128 
129 #if defined(P_USE_INTEGER_BOOL) || !defined(__cplusplus)
130  typedef BOOL PBoolean;
131  #define PTrue TRUE
132  #define PFalse FALSE
133 #else
134  typedef bool PBoolean;
135  #define PTrue true
136  #define PFalse false
137 #endif
138 
139 
141 // Disable inlines when debugging for faster compiles (the compiler doesn't
142 // actually inline the function with debug on any way).
143 
144 #ifndef P_USE_INLINES
145 #ifdef _DEBUG
146 #define P_USE_INLINES 0
147 #else
148 #define P_USE_INLINES 0
149 #endif
150 #endif
151 
152 #if P_USE_INLINES
153 #define PINLINE __inline
154 #else
155 #define PINLINE
156 #endif
157 
158 
160 // Handy macros
161 
163 #define PARG_COUNT(...) PARG_COUNT_PART1(PARG_COUNT_PART2(__VA_ARGS__,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
164 #define PARG_COUNT_PART1(arg) arg
165 #define PARG_COUNT_PART2(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,N,...) N
166 
168 #define P_STRINGISE(v) P_STRINGISE_PART2(v)
169 #define P_STRINGIZE(v) P_STRINGISE_PART2(v)
170 #define P_STRINGISE_PART2(v) #v
171 
183 #define P_DECLARE_ENUM_EX(name, countName, firstName, firstValue, ...) \
184  enum name { firstName = firstValue, Begin##name = firstName, __VA_ARGS__, End##name, countName = End##name-Begin##name }; \
185  friend __inline name operator++(name & e ) { PAssert(e < End##name, PInvalidParameter); return e = (name)(e+1); } \
186  friend __inline name operator++(name & e, int) { PAssert(e < End##name, PInvalidParameter); name o=e; e = (name)(e+1); return o; } \
187  friend __inline name operator--(name & e ) { PAssert(e >= Begin##name, PInvalidParameter); return e = (name)(e-1); } \
188  friend __inline name operator--(name & e, int) { PAssert(e >= Begin##name, PInvalidParameter); name o=e; e = (name)(e-1); return o; } \
189  static __inline name name##FromInt(int v) { return (name)(v < Begin##name ? Begin##name : v >= End##name ? (End##name-1) : v); }
190 
202 #define P_DECLARE_ENUM(name, first, ...) P_DECLARE_ENUM_EX(name, Num##name, first, 0, __VA_ARGS__)
203 
204 extern void PPrintEnum(std::ostream & strm, int e, int begin, int end, char const * const * names);
205 extern int PReadEnum(std::istream & strm, int begin, int end, char const * const * names);
206 
207 #define P_ENUM_NAMES_PART1(narg, args)P_ENUM_NAMES_PART2(narg, args)
208 #define P_ENUM_NAMES_PART2(narg, args) P_ENUM_NAMES_ARG_##narg args
209 #define P_ENUM_NAMES_ARG_1(_1 )#_1
210 #define P_ENUM_NAMES_ARG_2(_1,_2 )#_1,#_2
211 #define P_ENUM_NAMES_ARG_3(_1,_2,_3 )#_1,#_2,#_3
212 #define P_ENUM_NAMES_ARG_4(_1,_2,_3,_4 )#_1,#_2,#_3,#_4
213 #define P_ENUM_NAMES_ARG_5(_1,_2,_3,_4,_5 )#_1,#_2,#_3,#_4,#_5
214 #define P_ENUM_NAMES_ARG_6(_1,_2,_3,_4,_5,_6 )#_1,#_2,#_3,#_4,#_5,#_6
215 #define P_ENUM_NAMES_ARG_7(_1,_2,_3,_4,_5,_6,_7 )#_1,#_2,#_3,#_4,#_5,#_6,#_7
216 #define P_ENUM_NAMES_ARG_8(_1,_2,_3,_4,_5,_6,_7,_8 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8
217 #define P_ENUM_NAMES_ARG_9(_1,_2,_3,_4,_5,_6,_7,_8,_9 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9
218 #define P_ENUM_NAMES_ARG_10(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10
219 #define P_ENUM_NAMES_ARG_11(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11
220 #define P_ENUM_NAMES_ARG_12(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12
221 #define P_ENUM_NAMES_ARG_13(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13
222 #define P_ENUM_NAMES_ARG_14(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14
223 #define P_ENUM_NAMES_ARG_15(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15
224 #define P_ENUM_NAMES_ARG_16(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16
225 #define P_ENUM_NAMES_ARG_17(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17
226 #define P_ENUM_NAMES_ARG_18(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18
227 #define P_ENUM_NAMES_ARG_19(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19
228 #define P_ENUM_NAMES_ARG_20(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20
229 #define P_ENUM_NAMES_ARG_21(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21
230 #define P_ENUM_NAMES_ARG_22(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22
231 #define P_ENUM_NAMES_ARG_23(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23
232 #define P_ENUM_NAMES_ARG_24(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24
233 #define P_ENUM_NAMES_ARG_25(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25
234 #define P_ENUM_NAMES_ARG_26(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26
235 #define P_ENUM_NAMES_ARG_27(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27
236 #define P_ENUM_NAMES_ARG_28(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28
237 #define P_ENUM_NAMES_ARG_29(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29
238 #define P_ENUM_NAMES_ARG_30(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30
239 #define P_ENUM_NAMES_ARG_31(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31
240 #define P_ENUM_NAMES_ARG_32(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32
241 #define P_ENUM_NAMES_ARG_33(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33
242 #define P_ENUM_NAMES_ARG_34(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34
243 #define P_ENUM_NAMES_ARG_35(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35
244 #define P_ENUM_NAMES_ARG_36(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36
245 #define P_ENUM_NAMES_ARG_37(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36,#_37
246 #define P_ENUM_NAMES_ARG_38(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36,#_37,#_38
247 #define P_ENUM_NAMES_ARG_39(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36,#_37,#_38,#_39
248 #define P_ENUM_NAMES_ARG_40(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40)#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36,#_37,#_38,#_39,#_40
249 
251 #define P_DECLARE_STREAMABLE_ENUM_EX(name, countName, firstName, firstValue, ...) \
252  P_DECLARE_ENUM_EX(name, countName, firstName, firstValue, __VA_ARGS__) \
253  struct PEnumNames_##name { \
254  static char const * const * Names() { static char const * const Strings[] = \
255  { #firstName, P_ENUM_NAMES_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__)) }; return Strings; } \
256  }; \
257  friend __inline std::ostream & operator<<(std::ostream & strm, name e) \
258  { PPrintEnum(strm, e, Begin##name, End##name, PEnumNames_##name::Names()); return strm; } \
259  friend __inline std::istream & operator>>(std::istream & strm, name & e) \
260  { e = (name)PReadEnum(strm, Begin##name, End##name, PEnumNames_##name::Names()); return strm; } \
261 
262 
263 #define P_DECLARE_STREAMABLE_ENUM(name, first, ...) P_DECLARE_STREAMABLE_ENUM_EX(name, Num##name, first, 0, __VA_ARGS__)
264 
265 
267 // Declare the debugging support
268 
269 #ifndef P_USE_ASSERTS
270 #define P_USE_ASSERTS 1
271 #endif
272 
273 #if !P_USE_ASSERTS
274 
275 #define PAssert(b, m) (b)
276 #define PAssert2(b, c, m) (b)
277 #define PAssertOS(b) (b)
278 #define PAssertNULL(p) (p)
279 #define PAssertAlways(m) {}
280 #define PAssertAlways2(c, m) {}
281 
282 #else // P_USE_ASSERTS
283 
300 };
301 
302 #define __CLASS__ NULL
303 
304 bool PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
305 bool PAssertFunc(const char * file, int line, const char * className, const char * msg);
306 bool PAssertFunc(const char * full_msg);
307 
308 
315 #define PAssert(b, msg) ((b)?true:PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg)))
316 
324 #define PAssert2(b, cls, msg) ((b)?true:PAssertFunc(__FILE__,__LINE__,(cls),(msg)))
325 
332 #define PAssertOS(b) ((b)?true:PAssertFunc(__FILE__,__LINE__,__CLASS__,POperatingSystemError))
333 
343 #define PAssertNULL(ptr) (((ptr)!=NULL)?(ptr): \
344  (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(ptr)))
345 
352 #define PAssertAlways(msg) PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg))
353 
360 #define PAssertAlways2(cls, msg) PAssertFunc(__FILE__,__LINE__,(cls),(msg))
361 
362 #endif // P_USE_ASSERTS
363 
364 
369 ostream & PGetErrorStream();
370 
374 void PSetErrorStream(ostream * strm );
375 
390 #define PError (PGetErrorStream())
391 
392 
394 // Debug and tracing
395 
396 #ifndef PTRACING
397 #define PTRACING 2
398 #endif
399 
400 #if PTRACING
401 
402 class PObject;
403 class PArgList;
404 
417 class PTrace
418 {
419 public:
421  enum Options {
422  Blocks = 0x0001,
427  DateAndTime = 0x0002,
428  Timestamp = 0x0004,
429  Thread = 0x0008,
430  TraceLevel = 0x0010,
431  FileAndLine = 0x0020,
432  ThreadAddress = 0x0040,
433  AppendToFile = 0x0080,
434  GMTTime = 0x0100,
435  RotateDaily = 0x0200,
436  RotateHourly = 0x0400,
437  RotateMinutely = 0x0800,
438  RotateLogMask = RotateDaily + RotateHourly + RotateMinutely,
440  ObjectInstance = 0x1000,
441  ContextIdentifier = 0x2000,
442  SystemLogStream = 0x8000
445  };
446 
447 
448  #define PTRACE_ARGLIST_OPT_HELP \
449  "use +X or -X to add/remove option where X is one of:\r" \
450  " block PTrace::Block constructs in output\r" \
451  " time time since prgram start\r" \
452  " date date and time\r" \
453  " gmt Date/time is in UTC\r" \
454  " thread thread name and identifier\r" \
455  " level log level\r" \
456  " file source file name and line number\r" \
457  " object PObject pointer\r" \
458  " context context identifier\r" \
459  " daily rotate output file daily\r" \
460  " hour rotate output file hourly\r" \
461  " minute rotate output file every minute\r" \
462  " append append to output file, otherwise overwrites"
463 
464  #define PTRACE_ARGLIST \
465  "t-trace. Trace enable (use multiple times for more detail)\n" \
466  "o-output: Specify filename for trace output\n" \
467  "-trace-option: Specify trace option(s),\r" PTRACE_ARGLIST_OPT_HELP "\n" \
468  "-trace-rollover: Specify trace file rollover file name pattern\n"
469 
470  #define PTRACE_INITIALISE(...) PTrace::Initialise(__VA_ARGS__)
471 
475  static void Initialise(
476  const PArgList & args,
477  unsigned options =
478 #ifdef _DEBUG
479  FileAndLine |
480 #endif
481  Timestamp | Thread | Blocks,
482  const char * traceLevel = "trace",
483  const char * outputFile = "output",
484  const char * traceOpts = "trace-option",
485  const char * traceRollover = "trace-rollover"
486  );
487 
519  static void Initialise(
520  unsigned level,
521  const char * filename = NULL,
522  unsigned options = Timestamp | Thread | Blocks,
523  const char * rolloverPattern = NULL
524  );
525 
526  // Deprecated - for backward compatibility
527  static void Initialise(
528  unsigned level,
529  const char * filename,
530  const char * rolloverPattern,
531  unsigned options = Timestamp | Thread | Blocks
532  ) { Initialise(level, filename, options, rolloverPattern); }
533 
540  static void SetOptions(
541  unsigned options
542  );
543 
552  static void ClearOptions(
553  unsigned options
554  );
555 
561  static unsigned GetOptions();
562 
568  static void SetLevel(
569  unsigned level
570  );
571 
577  static unsigned GetLevel();
578 
583  static PBoolean CanTrace(
584  unsigned level
585  );
586 
591  static void SetStream(
592  ostream * out
593  );
594 
597  static ostream * GetStream();
598 
614  static ostream & Begin(
615  unsigned level,
616  const char * fileName,
617  int lineNum,
618  const PObject * instance = NULL,
619  const char * module = NULL
620  );
621 
622  static ostream & Begin(
623  unsigned level,
624  const char * fileName,
625  int lineNum,
626  const char * module,
627  const PObject * instance,
628  const char * defModule
629  ) { return Begin(level, fileName, lineNum, instance, module != NULL ? module : defModule); }
630 
631  static ostream & Begin(
632  unsigned level,
633  const char * fileName,
634  int lineNum,
635  const PObject * instance,
636  const PObject * defInstance,
637  const char * module
638  ) { return Begin(level, fileName, lineNum, instance != NULL ? instance : defInstance, module); }
639 
657  static ostream & End(
658  ostream & strm
659  );
660 
666  class Block {
667  public:
669  Block(
670  const char * fileName,
671  int lineNum,
672  const char * traceName
674  );
675  Block(const Block & obj)
676  : file(obj.file), line(obj.line), name(obj.name) { }
678  ~Block();
679  private:
680  Block & operator=(const Block &)
681  { return *this; }
682  const char * file;
683  int line;
684  const char * name;
685  };
686 
687  static unsigned GetNextContextIdentifier();
688 };
689 
690 /* Macro to conditionally declare a parameter to a function to avoid compiler
691  warning due that parameter only being used in a <code>PTRACE()</code> */
692 #define PTRACE_PARAM(...) __VA_ARGS__
693 
700 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
701 
705 #define PTRACE_LINE() \
706  if (PTrace::CanTrace(1)) \
707  PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
708  else (void)0
709 
710 
711 
712 #define PTRACE_INTERNAL(level, condition, args, ...) \
713  if (PTrace::CanTrace(level) condition) \
714  PTrace::Begin(level, __FILE__, __LINE__, __VA_ARGS__) << args << PTrace::End; \
715  else (void)0
716 
717 #define PTRACE_NO_CONDITION
718 
719 
720 #define PTRACE_PART1(narg, args) PTRACE_PART2(narg, args)
721 #define PTRACE_PART2(narg, args) PTRACE_ARG_##narg args
722 
723 #define PTRACE_ARG_4(level, object, module, args) \
724  PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, object, module)
725 
726 #define PTRACE_ARG_3(level, objectOrModule, args) \
727  PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, objectOrModule, PTraceObjectInstance(objectOrModule), PTraceModule())
728 
729 #define PTRACE_ARG_2(level, args) \
730  PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, PTraceObjectInstance(), PTraceModule())
731 
732 
733 #define PTRACE_IF_PART1(narg, args) PTRACE_IF_PART2(narg, args)
734 #define PTRACE_IF_PART2(narg, args) PTRACE_IF_ARG_##narg args
735 
736 #define PTRACE_IF_ARG_5(level, condition, object, module, args) \
737  PTRACE_INTERNAL(level, && (condition), args, object, module)
738 
739 #define PTRACE_IF_ARG_4(level, condition, objectOrModule, args) \
740  PTRACE_INTERNAL(level, && (condition), args, objectOrModule, PTraceObjectInstance(objectOrModule), PTraceModule())
741 
742 #define PTRACE_IF_ARG_3(level, condition, args) \
743  PTRACE_INTERNAL(level, && (condition), args, PTraceObjectInstance(), PTraceModule())
744 
745 
746 #define PTRACE_BEGIN_PART1(narg, args) PTRACE_BEGIN_PART2(narg, args)
747 #define PTRACE_BEGIN_PART2(narg, args) PTRACE_BEGIN_ARG_##narg args
748 
749 #define PTRACE_BEGIN_ARG_3(level, object, module) \
750  PTrace::Begin(level, __FILE__, __LINE__, object, module)
751 
752 #define PTRACE_BEGIN_ARG_2(level, objectOrModule) \
753  PTrace::Begin(level, __FILE__, __LINE__, objectOrModule, PTraceObjectInstance(objectOrModule), PTraceModule())
754 
755 #define PTRACE_BEGIN_ARG_1(level) \
756  PTrace::Begin(level, __FILE__, __LINE__, PTraceObjectInstance(), PTraceModule())
757 
758 
759 // Backward compatibility
760 #define PTRACE2(level, object, args) \
761  PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, object, PTraceModule())
762 #define PTRACE_IF2(level, condition, object, args) \
763  PTRACE_INTERNAL(level, && (condition), args, object, PTraceModule())
764 
790 #define PTRACE(...) PTRACE_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
791 
804 #define PTRACE_IF(...) PTRACE_IF_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
805 
815 #define PTRACE_BEGIN(...) PTRACE_BEGIN_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
816 
817 
818 __inline const PObject * PTraceObjectInstance() { return NULL; }
819 __inline static const PObject * PTraceObjectInstance(const void *) { return NULL; }
820 __inline const char * PTraceModule() { return NULL; }
821 
822 
823 #if PTRACING==2
824 
830 #define PTRACE_CONTEXT_ID_NEW() SetTraceContextIdentifier(PTrace::GetNextContextIdentifier())
831 #define PTRACE_CONTEXT_ID_SET(to, from) (to).SetTraceContextIdentifier(from)
832 #define PTRACE_CONTEXT_ID_FROM(obj) SetTraceContextIdentifier(obj)
833 #define PTRACE_CONTEXT_ID_TO(obj) GetTraceContextIdentifier(obj)
834 
836 {
837  private:
838  class PThread * m_currentThread;
839  unsigned m_savedContextIdentifier;
840  public:
844 };
845 
846 #define PTRACE_CONTEXT_ID_PUSH_THREAD(obj) PTraceSaveContextIdentifier praceSavedContextIdentifier(obj)
847 
848 #endif // PTRACING==2
849 
850 
851 #define P_DECLARE_TRACED_ENUM P_DECLARE_STREAMABLE_ENUM
852 #define P_DECLARE_TRACED_ENUM_EX P_DECLARE_STREAMABLE_ENUM_EX
853 
854 #endif // PTRACING
855 
856 #ifndef PTRACE_ARGLIST
857 #define PTRACE_ARGLIST
858 #endif
859 
860 #ifndef PTRACE_INITIALISE
861 #define PTRACE_INITIALISE(...)
862 #endif
863 
864 #ifndef PTRACE_PARAM
865 #define PTRACE_PARAM(...)
866 #endif
867 
868 #ifndef PTRACE_BLOCK
869 #define PTRACE_BLOCK(n)
870 #endif
871 
872 #ifndef PTRACE_LINE
873 #define PTRACE_LINE()
874 #endif
875 
876 #ifndef PTRACE
877 #define PTRACE(...)
878 #endif
879 
880 #ifndef PTRACE_IF
881 #define PTRACE_IF(...)
882 #endif
883 
884 #ifndef PTRACE_BEGIN
885 #define PTRACE_BEGIN(...)
886 #endif
887 
888 #ifndef PTRACE2
889 #define PTRACE2(level, obj, arg)
890 #endif
891 
892 #ifndef PTRACE_IF2
893 #define PTRACE_IF2(level, cond, obj, args)
894 #endif
895 
896 #ifndef PTRACE_CONTEXT_ID_NEW
897 #define PTRACE_CONTEXT_ID_NEW()
898 #endif
899 
900 #ifndef PTRACE_CONTEXT_ID_SET
901 #define PTRACE_CONTEXT_ID_SET(to, from)
902 #endif
903 
904 #ifndef PTRACE_CONTEXT_ID_FROM
905 #define PTRACE_CONTEXT_ID_FROM(obj)
906 #endif
907 
908 #ifndef PTRACE_CONTEXT_ID_TO
909 #define PTRACE_CONTEXT_ID_TO(obj)
910 #endif
911 
912 #ifndef PTRACE_CONTEXT_ID_PUSH_THREAD
913 #define PTRACE_CONTEXT_ID_PUSH_THREAD(obj)
914 #endif
915 
916 #ifndef P_DECLARE_TRACED_ENUM
917 #define P_DECLARE_TRACED_ENUM P_DECLARE_ENUM
918 #endif
919 
920 #ifndef P_DECLARE_TRACED_ENUM_EX
921 #define P_DECLARE_TRACED_ENUM_EX P_DECLARE_ENUM_EX
922 #endif
923 
924 
925 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE))
926 
927 #define PMEMORY_HEAP 1
928 
935 class PMemoryHeap {
936  protected:
938  PMemoryHeap();
939 
940  public:
941  // Clear up the memory checking subsystem, dumping memory leaks.
942  ~PMemoryHeap();
943 
950  static void * Allocate(
951  size_t nSize,
952  const char * file,
953  int line,
954  const char * className
955  );
962  static void * Allocate(
963  size_t count,
964  size_t iSize,
965  const char * file,
966  int line
967  );
968 
976  static void * Reallocate(
977  void * ptr,
978  size_t nSize,
979  const char * file,
980  int line
981  );
982 
988  static void Deallocate(
989  void * ptr,
990  const char * className
991  );
992 
995  enum Validation {
996  Ok, Bad, Trashed
997  };
1005  static Validation Validate(
1006  const void * ptr,
1007  const char * className,
1008  ostream * error
1009  );
1010 
1015  static PBoolean ValidateHeap(
1016  ostream * error = NULL
1017  );
1018 
1024  static PBoolean SetIgnoreAllocations(
1025  PBoolean ignore
1026  );
1027 
1031  static void DumpStatistics();
1035  static void DumpStatistics(ostream & strm );
1036 
1037 #if PMEMORY_CHECK
1038  struct State {
1040  };
1041 #else
1042  typedef _CrtMemState State;
1043 #endif
1044 
1045  /* Get memory state.
1046  This returns a state that may be used to determine where to start dumping
1047  objects from.
1048  */
1049  static void GetState(
1050  State & state
1051  );
1052 
1060  static void DumpObjectsSince(
1061  const State & when
1062  );
1063 
1069  static void DumpObjectsSince(
1070  const State & when,
1071  ostream & strm
1072  );
1073 
1079  static void SetAllocationBreakpoint(
1080  DWORD point
1081  );
1082 
1083 #if PMEMORY_CHECK
1084 
1085  protected:
1086  void * InternalAllocate(
1087  size_t nSize, // Number of bytes to allocate.
1088  const char * file, // Source file name for allocating function.
1089  int line, // Source file line for allocating function.
1090  const char * className // Class name for allocating function.
1091  );
1092  Validation InternalValidate(
1093  const void * ptr, // Pointer to memory block to check
1094  const char * className, // Class name it should be.
1095  ostream * error // Stream to receive error message (may be NULL)
1096  );
1097  void InternalDumpStatistics(ostream & strm);
1098  void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
1099 
1100  class Wrapper {
1101  public:
1102  Wrapper();
1103  ~Wrapper();
1104  PMemoryHeap * operator->() const { return instance; }
1105  private:
1106  PMemoryHeap * instance;
1107  };
1108  friend class Wrapper;
1109 
1110  enum Flags {
1111  NoLeakPrint = 1
1112  };
1113 
1114 #pragma pack(1)
1115  struct Header {
1116  enum {
1117  // Assure that the Header struct is aligned to 8 byte boundary
1118  NumGuardBytes = 16 - (sizeof(Header *) +
1119  sizeof(Header *) +
1120  sizeof(const char *) +
1121  sizeof(const char *) +
1122  sizeof(size_t) +
1123  sizeof(DWORD) +
1124  sizeof(WORD) +
1125  sizeof(BYTE) +
1126  sizeof(PThreadIdentifier)
1127  )%8
1128  };
1129 
1132  const char * className;
1133  const char * fileName;
1134  size_t size;
1135  DWORD request;
1136  WORD line;
1137  BYTE flags;
1138  PThreadIdentifier threadId;
1139  char guard[NumGuardBytes];
1140 
1141  static char GuardBytes[NumGuardBytes];
1142  };
1143 #pragma pack()
1144 
1146 
1149 
1150  static DWORD allocationBreakpoint;
1153  BYTE flags;
1154 
1157 
1163 
1164  ostream * leakDumpStream;
1165 
1166 #if defined(_WIN32)
1167  CRITICAL_SECTION mutex;
1168 #elif defined(P_PTHREADS)
1169  pthread_mutex_t mutex;
1170 #elif defined(P_VXWORKS)
1171  void * mutex;
1172 #endif
1173 
1174 #else
1175 
1176  static void CreateInstance();
1177 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
1178  _CrtMemState initialState;
1179 
1180 #endif // PMEMORY_CHECK
1181 };
1182 
1183 
1188 inline void * runtime_malloc(size_t bytes ) { return malloc(bytes); }
1189 
1194 inline void runtime_free(void * ptr ) { free(ptr); }
1195 
1196 
1203 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
1204 
1211 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
1212 
1219 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
1220 
1221 
1228 #define free(p) PMemoryHeap::Deallocate(p, NULL)
1229 
1230 
1237 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
1238 
1239 
1254 #define PNEW new (__FILE__, __LINE__)
1255 
1256 #if !defined(_MSC_VER) || _MSC_VER<1200
1257 #define PSPECIAL_DELETE_FUNCTION
1258 #else
1259 #define PSPECIAL_DELETE_FUNCTION \
1260  void operator delete(void * ptr, const char *, int) \
1261  { PMemoryHeap::Deallocate(ptr, Class()); } \
1262  void operator delete[](void * ptr, const char *, int) \
1263  { PMemoryHeap::Deallocate(ptr, Class()); }
1264 #endif
1265 
1266 #define PNEW_AND_DELETE_FUNCTIONS \
1267  void * operator new(size_t nSize, const char * file, int line) \
1268  { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
1269  void * operator new(size_t nSize) \
1270  { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
1271  void operator delete(void * ptr) \
1272  { PMemoryHeap::Deallocate(ptr, Class()); } \
1273  void * operator new(size_t, void * placement) \
1274  { return placement; } \
1275  void operator delete(void *, void *) \
1276  { } \
1277  void * operator new[](size_t nSize, const char * file, int line) \
1278  { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
1279  void * operator new[](size_t nSize) \
1280  { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
1281  void operator delete[](void * ptr) \
1282  { PMemoryHeap::Deallocate(ptr, Class()); } \
1283  PSPECIAL_DELETE_FUNCTION
1284 
1285 
1286 inline void * operator new(size_t nSize, const char * file, int line)
1287  { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
1288 
1289 inline void * operator new[](size_t nSize, const char * file, int line)
1290  { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
1291 
1292 #ifndef __GNUC__
1293 void * operator new(size_t nSize);
1294 void * operator new[](size_t nSize);
1295 
1296 void operator delete(void * ptr);
1297 void operator delete[](void * ptr);
1298 
1299 #if defined(_MSC_VER) && _MSC_VER>=1200
1300 inline void operator delete(void * ptr, const char *, int)
1301  { PMemoryHeap::Deallocate(ptr, NULL); }
1302 
1303 inline void operator delete[](void * ptr, const char *, int)
1304  { PMemoryHeap::Deallocate(ptr, NULL); }
1305 #endif
1306 #endif
1307 
1308 
1310 public:
1311  PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(true)) { }
1313 private:
1314  PBoolean previousIgnoreAllocations;
1315 };
1316 
1317 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
1318 
1320 public:
1322  {
1324  }
1325 };
1326 
1327 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
1328 
1329 
1330 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
1331 
1332 #define PMEMORY_HEAP 0
1333 
1334 #define PNEW new
1335 
1336 #define PNEW_AND_DELETE_FUNCTIONS
1337 
1338 #define runtime_malloc(s) malloc(s)
1339 #define runtime_free(p) free(p)
1340 
1341 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
1342 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
1343 
1344 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
1345 
1346 
1348 
1360 template <class Type, typename GuardType = unsigned>
1362 {
1363  protected:
1364  Type * m_instance;
1365  public:
1367  {
1368  static Type * s_pointer;
1369  static GuardType s_guard;
1370  if (s_guard++ != 0)
1371  s_guard = 1;
1372  else {
1373 #if PMEMORY_HEAP
1374  // Do this to make sure debugging is initialised as early as possible
1375  PMemoryHeap::Validate(NULL, NULL, NULL);
1376 #endif
1377  static Type s_instance;
1378  s_pointer = &s_instance;
1379  }
1380  m_instance = s_pointer;
1381  }
1382 
1383  Type * operator->() const { return m_instance; }
1384  Type & operator* () const { return *m_instance; }
1385 };
1386 
1387 
1389 // Memory pool allocators
1390 
1391 #if P_GNU_ALLOCATOR
1392 
1393  #include <ext/mt_allocator.h>
1394 
1395  /* Need this tempalte class specialisation of standard class to do the
1396  de-allocation of the pool memory. As per:
1397  http://gcc.gnu.org/viewcvs/trunk/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-6.cc?view=markup
1398  */
1399  template <bool _Thread>
1400  struct PMemoryPool : public __gnu_cxx::__pool<_Thread>
1401  {
1402  PMemoryPool()
1403  : __gnu_cxx::__pool<_Thread>()
1404  {
1405  }
1406 
1407  PMemoryPool(const __gnu_cxx::__pool_base::_Tune& t)
1408  : __gnu_cxx::__pool<_Thread>(t)
1409  {
1410  }
1411  };
1412 
1413  /*Do this template class specialisation so each type has it's own separate
1414  memory block for the pool. */
1415  template <class Type>
1416  struct PCommonPool : public __gnu_cxx::__common_pool_policy<PMemoryPool, true>
1417  {
1418  };
1419 
1420  /*This template class specialisation adds the singleton instance.
1421  */
1422  template <class Type, class Pool = PCommonPool<Type> >
1423  struct PVariablePoolAllocator : public PSingleton<__gnu_cxx::__mt_alloc<Type, Pool> >
1424  {
1425  };
1426 
1427  #if P_GNU_ALLOCATOR==1
1428  template <class Type>
1429  struct PFixedPoolAllocator : public PSingleton<__gnu_cxx::__mt_alloc<Type, PCommonPool<Type> > >
1430  {
1431  };
1432  #else
1433  #include <ext/bitmap_allocator.h>
1434  template <class Type>
1435  struct PFixedPoolAllocator : public PSingleton<__gnu_cxx::bitmap_allocator<Type> >
1436  {
1437  };
1438  #endif
1439 
1440 #else
1441 
1442  template <class Type, class Pool = void>
1443  struct PVariablePoolAllocator : public PSingleton<std::allocator<Type> >
1444  {
1445  };
1446 
1447  template <class Type>
1448  struct PFixedPoolAllocator : public PSingleton<std::allocator<Type> >
1449  {
1450  };
1451 
1452 #endif
1453 
1454 #define PDECLARE_POOL_ALLOCATOR() \
1455  void * operator new(size_t nSize); \
1456  void * operator new(size_t nSize, const char * file, int line); \
1457  void operator delete(void * ptr); \
1458  void operator delete(void * ptr, const char *, int)
1459 
1460 #define PDEFINE_POOL_ALLOCATOR(cls) \
1461  void * cls::operator new(size_t) { return PFixedPoolAllocator<cls>()->allocate(1); } \
1462  void * cls::operator new(size_t, const char *, int) { return PFixedPoolAllocator<cls>()->allocate(1); } \
1463  void cls::operator delete(void * ptr) { PFixedPoolAllocator<cls>()->deallocate((cls *)ptr, 1); } \
1464  void cls::operator delete(void * ptr, const char *, int) { PFixedPoolAllocator<cls>()->deallocate((cls *)ptr, 1); }
1465 
1466 
1467 
1478 #define PCLASSINFO(cls, par) \
1479  public: \
1480  typedef cls P_thisClass; \
1481  static inline const char * Class() \
1482  { return #cls; } \
1483  virtual PBoolean InternalIsDescendant(const char * clsName) const \
1484  { return strcmp(clsName, this->Class()) == 0 || par::InternalIsDescendant(clsName); } \
1485  virtual const char * GetClass(unsigned ancestor = 0) const \
1486  { return ancestor > 0 ? par::GetClass(ancestor-1) : this->Class(); } \
1487  virtual PObject::Comparison CompareObjectMemoryDirect(const PObject & obj) const \
1488  { return PObject::InternalCompareObjectMemoryDirect(this, dynamic_cast<const cls *>(&obj), sizeof(cls)); } \
1489  PNEW_AND_DELETE_FUNCTIONS
1490 
1492 #define PCLASSINFO_WITH_CLONE(cls, par) \
1493  PCLASSINFO(cls, par) \
1494  virtual PObject * Clone() const { return new cls(*this); }
1495 
1496 
1497 #define PIsDescendant(ptr, cls) (dynamic_cast<const cls *>(ptr) != NULL)
1498 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
1499 
1500 #define PRemoveConst(cls, ptr) (const_cast<cls*>(ptr))
1501 
1502 #if P_USE_ASSERTS
1503 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line)
1504  { if (obj == NULL) PAssertFunc(file, line, obj->Class(), PInvalidCast); return obj; }
1505 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
1506 #else
1507 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
1508 #endif
1509 
1510 
1519 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
1520 #ifdef DOC_PLUS_PLUS
1521 } Match previous opening brace in doc++
1522 #endif
1523 
1525 // The root of all evil ... umm classes
1526 
1531 class PObject {
1532  protected:
1534 #if PTRACING==2
1535  public:
1544 #endif // PTRACING==2
1545 
1546  protected:
1552  { }
1553 
1554  public:
1555  /* Destructor required to get the "virtual". A PObject really has nothing
1556  to destroy.
1557  */
1558  virtual ~PObject() { }
1559 
1572  static inline const char * Class() { return "PObject"; }
1573 
1586  virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : this->Class(); }
1587 
1588  PBoolean IsClass(const char * cls) const
1589  { return strcmp(cls, GetClass()) == 0; }
1590 
1601  const char * clsName // Ancestor class name to compare against.
1602  ) const
1603  { return IsClass(clsName); }
1604 
1605  __inline const PObject * PTraceObjectInstance() const { return this; }
1606  __inline static const PObject * PTraceObjectInstance(const char *) { return NULL; }
1607  __inline static const PObject * PTraceObjectInstance(const PObject * obj) { return obj; }
1609 
1615  enum Comparison {
1616  LessThan = -1,
1617  EqualTo = 0,
1619  };
1620 
1632  virtual Comparison Compare(
1633  const PObject & obj // Object to compare against.
1634  ) const;
1635 
1648  const PObject & obj // Object to compare against.
1649  ) const;
1650 
1653  const PObject * obj1,
1654  const PObject * obj2,
1655  PINDEX size
1656  );
1657 
1664  const PObject & obj // Object to compare against.
1665  ) const { return Compare(obj) == EqualTo; }
1666 
1673  const PObject & obj // Object to compare against.
1674  ) const { return Compare(obj) != EqualTo; }
1675 
1682  const PObject & obj // Object to compare against.
1683  ) const { return Compare(obj) == LessThan; }
1684 
1691  const PObject & obj // Object to compare against.
1692  ) const { return Compare(obj) == GreaterThan; }
1693 
1700  const PObject & obj // Object to compare against.
1701  ) const { return Compare(obj) != GreaterThan; }
1702 
1709  const PObject & obj // Object to compare against.
1710  ) const { return Compare(obj) != LessThan; }
1712 
1721  virtual void PrintOn(
1722  ostream &strm // Stream to print the object into.
1723  ) const;
1724 
1731  virtual void ReadFrom(
1732  istream &strm // Stream to read the objects contents from.
1733  );
1734 
1735 
1741  inline friend ostream & operator<<(
1742  ostream &strm,
1743  const PObject & obj
1744  ) { obj.PrintOn(strm); return strm; }
1745 
1751  inline friend istream & operator>>(
1752  istream &strm,
1753  PObject & obj
1754  ) { obj.ReadFrom(strm); return strm; }
1755 
1756 
1771  virtual PObject * Clone() const;
1772 
1775  template <class CLS>
1776  CLS * CloneAs() const
1777  {
1778  PObject * clone = Clone();
1779  CLS * obj = dynamic_cast<CLS *>(clone);
1780  if (obj != NULL)
1781  return obj;
1782  delete clone;
1783  return NULL;
1784  }
1785 
1797  virtual PINDEX HashFunction() const;
1799 };
1800 
1802 // Platform independent types
1803 
1804 // All these classes encapsulate primitive types such that they may be
1805 // transfered in a platform independent manner. In particular it is used to
1806 // do byte swapping for little endien and big endien processor architectures
1807 // as well as accommodating structure packing rules for memory structures.
1808 
1809 #define PANSI_CHAR 1
1810 #define PLITTLE_ENDIAN 2
1811 #define PBIG_ENDIAN 3
1812 
1813 
1814 template <typename type>
1816  __inline PIntSameOrder() : data(0) { }
1817  __inline PIntSameOrder(type value) : data(value) { }
1818  __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data) { }
1819  __inline PIntSameOrder & operator=(type value) { data = value; return *this; }
1820  __inline PIntSameOrder & operator=(const PIntSameOrder & value) { data = value.data; return *this; }
1821  __inline operator type() const { return data; }
1822  __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
1823  __inline friend istream & operator>>(istream & s, PIntSameOrder & v) { return s >> v.data; }
1824 
1825  private:
1826  type data;
1827 };
1828 
1829 
1830 template <typename type>
1832  __inline PIntReversedOrder() : data(0) { }
1833  __inline PIntReversedOrder(type value) { ReverseBytes(value, data); }
1834  __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data) { }
1835  __inline PIntReversedOrder & operator=(type value) { ReverseBytes(value, data); return *this; }
1836  __inline PIntReversedOrder & operator=(const PIntReversedOrder & value) { data = value.data; return *this; }
1837  __inline operator type() const { type value; ReverseBytes(data, value); return value; }
1838  __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
1839  __inline friend istream & operator>>(istream & s, PIntReversedOrder & v) { type val; s >> val; v = val; return s; }
1840 
1841  private:
1842  type data;
1843 
1844  static __inline void ReverseBytes(const type & src, type & dst)
1845  {
1846  size_t s = sizeof(type)-1;
1847  for (size_t d = 0; d < sizeof(type); ++d,--s)
1848  ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
1849  }
1850 };
1851 
1852 #ifndef PCHAR8
1853 #define PCHAR8 PANSI_CHAR
1854 #endif
1855 
1856 #if PCHAR8==PANSI_CHAR
1858 #endif
1859 
1861 
1863 
1864 #if PBYTE_ORDER==PLITTLE_ENDIAN
1865 typedef PIntSameOrder<PInt16> PInt16l;
1866 #elif PBYTE_ORDER==PBIG_ENDIAN
1867 typedef PIntReversedOrder<PInt16> PInt16l;
1868 #endif
1869 
1870 #if PBYTE_ORDER==PLITTLE_ENDIAN
1871 typedef PIntReversedOrder<PInt16> PInt16b;
1872 #elif PBYTE_ORDER==PBIG_ENDIAN
1873 typedef PIntSameOrder<PInt16> PInt16b;
1874 #endif
1875 
1876 #if PBYTE_ORDER==PLITTLE_ENDIAN
1877 typedef PIntSameOrder<WORD> PUInt16l;
1878 #elif PBYTE_ORDER==PBIG_ENDIAN
1879 typedef PIntReversedOrder<WORD> PUInt16l;
1880 #endif
1881 
1882 #if PBYTE_ORDER==PLITTLE_ENDIAN
1883 typedef PIntReversedOrder<WORD> PUInt16b;
1884 #elif PBYTE_ORDER==PBIG_ENDIAN
1885 typedef PIntSameOrder<WORD> PUInt16b;
1886 #endif
1887 
1888 #if PBYTE_ORDER==PLITTLE_ENDIAN
1889 typedef PIntSameOrder<PInt32> PInt32l;
1890 #elif PBYTE_ORDER==PBIG_ENDIAN
1891 typedef PIntReversedOrder<PInt32> PInt32l;
1892 #endif
1893 
1894 #if PBYTE_ORDER==PLITTLE_ENDIAN
1895 typedef PIntReversedOrder<PInt32> PInt32b;
1896 #elif PBYTE_ORDER==PBIG_ENDIAN
1897 typedef PIntSameOrder<PInt32> PInt32b;
1898 #endif
1899 
1900 #if PBYTE_ORDER==PLITTLE_ENDIAN
1901 typedef PIntSameOrder<DWORD> PUInt32l;
1902 #elif PBYTE_ORDER==PBIG_ENDIAN
1903 typedef PIntReversedOrder<DWORD> PUInt32l;
1904 #endif
1905 
1906 #if PBYTE_ORDER==PLITTLE_ENDIAN
1907 typedef PIntReversedOrder<DWORD> PUInt32b;
1908 #elif PBYTE_ORDER==PBIG_ENDIAN
1909 typedef PIntSameOrder<DWORD> PUInt32b;
1910 #endif
1911 
1912 #if PBYTE_ORDER==PLITTLE_ENDIAN
1913 typedef PIntSameOrder<PInt64> PInt64l;
1914 #elif PBYTE_ORDER==PBIG_ENDIAN
1915 typedef PIntReversedOrder<PInt64> PInt64l;
1916 #endif
1917 
1918 #if PBYTE_ORDER==PLITTLE_ENDIAN
1919 typedef PIntReversedOrder<PInt64> PInt64b;
1920 #elif PBYTE_ORDER==PBIG_ENDIAN
1921 typedef PIntSameOrder<PInt64> PInt64b;
1922 #endif
1923 
1924 #if PBYTE_ORDER==PLITTLE_ENDIAN
1925 typedef PIntSameOrder<PUInt64> PUInt64l;
1926 #elif PBYTE_ORDER==PBIG_ENDIAN
1927 typedef PIntReversedOrder<PUInt64> PUInt64l;
1928 #endif
1929 
1930 #if PBYTE_ORDER==PLITTLE_ENDIAN
1931 typedef PIntReversedOrder<PUInt64> PUInt64b;
1932 #elif PBYTE_ORDER==PBIG_ENDIAN
1933 typedef PIntSameOrder<PUInt64> PUInt64b;
1934 #endif
1935 
1936 #if PBYTE_ORDER==PLITTLE_ENDIAN
1937 typedef PIntSameOrder<float> PFloat32l;
1938 #elif PBYTE_ORDER==PBIG_ENDIAN
1939 typedef PIntReversedOrder<float> PFloat32l;
1940 #endif
1941 
1942 #if PBYTE_ORDER==PLITTLE_ENDIAN
1943 typedef PIntReversedOrder<float> PFloat32b;
1944 #elif PBYTE_ORDER==PBIG_ENDIAN
1945 typedef PIntSameOrder<float> PFloat32b;
1946 #endif
1947 
1948 #if PBYTE_ORDER==PLITTLE_ENDIAN
1949 typedef PIntSameOrder<double> PFloat64l;
1950 #elif PBYTE_ORDER==PBIG_ENDIAN
1951 typedef PIntReversedOrder<double> PFloat64l;
1952 #endif
1953 
1954 #if PBYTE_ORDER==PLITTLE_ENDIAN
1955 typedef PIntReversedOrder<double> PFloat64b;
1956 #elif PBYTE_ORDER==PBIG_ENDIAN
1957 typedef PIntSameOrder<double> PFloat64b;
1958 #endif
1959 
1960 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
1961 #if PBYTE_ORDER==PLITTLE_ENDIAN
1962 typedef PIntSameOrder<long double> PFloat80l;
1963 #elif PBYTE_ORDER==PBIG_ENDIAN
1964 typedef PIntReversedOrder<long double> PFloat80l;
1965 #endif
1966 
1967 #if PBYTE_ORDER==PLITTLE_ENDIAN
1968 typedef PIntReversedOrder<long double> PFloat80b;
1969 #elif PBYTE_ORDER==PBIG_ENDIAN
1970 typedef PIntSameOrder<long double> PFloat80b;
1971 #endif
1972 #endif
1973 
1974 typedef intptr_t P_INT_PTR;
1975 
1976 #if defined(_MSC_VER)
1977 #define P_ALIGN_FIELD(f,a) __declspec(align(a)) f
1978 #define P_PACK_FIELD(f) __declspec(align(1)) f
1979 #elif defined(__GNUC__)
1980 #define P_ALIGN_FIELD(f,a) f __attribute__ ((aligned(a)))
1981 #define P_PACK_FIELD(f) f __attribute__ ((packed))
1982 #endif
1983 
1984 typedef intptr_t P_INT_PTR;
1985 
1987 // Miscellaneous
1988 
1989 /*$MACRO PARRAYSIZE(array)
1990  This macro is used to calculate the number of array elements in a static
1991  array.
1992  */
1993 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
1994 
1995 /*$MACRO PMIN(v1, v2)
1996  This macro is used to calculate the minimum of two values.
1997  Maps to std::min and is for backward compatibility only.
1998  */
1999 #define PMIN(v1, v2) std::min(v1, v2)
2000 
2001 /*$MACRO PMAX(v1, v2)
2002  This macro is used to calculate the maximum of two values.
2003  Maps to std::max and is for backward compatibility only.
2004  */
2005 #define PMAX(v1, v2) std::max(v1, v2)
2006 
2007 /*$MACRO PABS(val)
2008  This macro is used to calculate an absolute value.
2009  Maps to std::abs and is for backward compatibility only.
2010  */
2011 #define PABS(v) std::abs(v)
2012 
2013 
2014 #if _MSC_VER >= 1700
2015  class p_iostream : public std::iostream {
2016  public:
2017  p_iostream(std::streambuf * sbuf) : std::iostream(sbuf) { }
2018  private:
2019  virtual void __CLR_OR_THIS_CALL _Add_vtordisp1() { } // compiler bug workaround
2020  virtual void __CLR_OR_THIS_CALL _Add_vtordisp2() { } // compiler bug workaround
2021  };
2022  #define P_IOSTREAM p_iostream
2023 #else
2024  #define P_IOSTREAM std::iostream
2025 #endif
2026 
2027 
2028 #endif // PTLIB_OBJECT_H
2029 
2030 
2031 // End Of File ///////////////////////////////////////////////////////////////