PTLib  Version 2.14.3
 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: 32643 $
30  * $Author: rjongbloed $
31  * $Date: 2014-09-01 14:31:04 +1000 (Mon, 01 Sep 2014) $
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 // We are gradually converting over to standard C++ names, these
119 // are for backward compatibility only
120 
121 #ifndef FALSE
122 #define FALSE 0
123 #endif
124 #ifndef TRUE
125 #define TRUE 1
126 #endif
127 
128 typedef bool PBoolean;
129 #define PTrue true
130 #define PFalse false
131 
132 
134 // Disable inlines when debugging for faster compiles (the compiler doesn't
135 // actually inline the function with debug on any way).
136 
137 #ifndef P_USE_INLINES
138 #ifdef _DEBUG
139 #define P_USE_INLINES 0
140 #else
141 #define P_USE_INLINES 0
142 #endif
143 #endif
144 
145 #if P_USE_INLINES
146 #define PINLINE __inline
147 #else
148 #define PINLINE
149 #endif
150 
151 
153 // Handy macros
154 
156 #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))
157 #define PARG_COUNT_PART1(arg) arg
158 #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
159 
161 #define P_STRINGISE(v) P_STRINGISE_PART2(v)
162 #define P_STRINGIZE(v) P_STRINGISE_PART2(v)
163 #define P_STRINGISE_PART2(v) #v
164 
176 #define P_DECLARE_ENUM_EX(name, countName, firstName, firstValue, ...) \
177  enum name { firstName = firstValue, Begin##name = firstName, __VA_ARGS__, End##name, countName = End##name-Begin##name }; \
178  friend __inline name operator++(name & e ) { PAssert(e < End##name, PInvalidParameter); return e = (name)(e+1); } \
179  friend __inline name operator++(name & e, int) { PAssert(e < End##name, PInvalidParameter); name o=e; e = (name)(e+1); return o; } \
180  friend __inline name operator--(name & e ) { PAssert(e >= Begin##name, PInvalidParameter); return e = (name)(e-1); } \
181  friend __inline name operator--(name & e, int) { PAssert(e >= Begin##name, PInvalidParameter); name o=e; e = (name)(e-1); return o; } \
182  static __inline name name##FromInt(int v) { return (name)(v < Begin##name ? Begin##name : v >= End##name ? (End##name-1) : v); }
183 
195 #define P_DECLARE_ENUM(name, first, ...) P_DECLARE_ENUM_EX(name, Num##name, first, 0, __VA_ARGS__)
196 
197 extern void PPrintEnum(std::ostream & strm, int e, int begin, int end, char const * const * names);
198 extern int PReadEnum(std::istream & strm, int begin, int end, char const * const * names, bool matchCase = true);
199 extern int PParseEnum(const char * str, int begin, int end, char const * const * names, bool matchCase = true);
200 
201 #define P_ENUM_NAMES_PART1(narg, args)P_ENUM_NAMES_PART2(narg, args)
202 #define P_ENUM_NAMES_PART2(narg, args) P_ENUM_NAMES_ARG_##narg args
203 #define P_ENUM_NAMES_ARG_1(_1 )#_1
204 #define P_ENUM_NAMES_ARG_2(_1,_2 )#_1,#_2
205 #define P_ENUM_NAMES_ARG_3(_1,_2,_3 )#_1,#_2,#_3
206 #define P_ENUM_NAMES_ARG_4(_1,_2,_3,_4 )#_1,#_2,#_3,#_4
207 #define P_ENUM_NAMES_ARG_5(_1,_2,_3,_4,_5 )#_1,#_2,#_3,#_4,#_5
208 #define P_ENUM_NAMES_ARG_6(_1,_2,_3,_4,_5,_6 )#_1,#_2,#_3,#_4,#_5,#_6
209 #define P_ENUM_NAMES_ARG_7(_1,_2,_3,_4,_5,_6,_7 )#_1,#_2,#_3,#_4,#_5,#_6,#_7
210 #define P_ENUM_NAMES_ARG_8(_1,_2,_3,_4,_5,_6,_7,_8 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8
211 #define P_ENUM_NAMES_ARG_9(_1,_2,_3,_4,_5,_6,_7,_8,_9 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9
212 #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
213 #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
214 #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
215 #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
216 #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
217 #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
218 #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
219 #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
220 #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
221 #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
222 #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
223 #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
224 #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
225 #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
226 #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
227 #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
228 #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
229 #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
230 #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
231 #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
232 #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
233 #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
234 #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
235 #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
236 #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
237 #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
238 #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
239 #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
240 #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
241 #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
242 #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
243 
250 #define P_DECLARE_ENUM_NAMES(name, ...) \
251  struct PEnumNames_##name { \
252  static char const * const * Names() { static char const * const Strings[] = { __VA_ARGS__ }; return Strings; } \
253  }; \
254  friend __inline std::ostream & operator<<(std::ostream & strm, name e) \
255  { PPrintEnum(strm, e, Begin##name, End##name, PEnumNames_##name::Names()); return strm; } \
256  friend __inline std::istream & operator>>(std::istream & strm, name & e) \
257  { e = (name)PReadEnum(strm, Begin##name, End##name, PEnumNames_##name::Names()); return strm; } \
258  static __inline const char * name##ToString(name e) { return e >= Begin##name && e < End##name ? PAssertNULL(PEnumNames_##name::Names()[e-Begin##name]) : ""; } \
259  static __inline name name##FromString(const char * str, bool matchCase = true) { return (name)PParseEnum(str, Begin##name, End##name, PEnumNames_##name::Names(), matchCase); }
260 
265 #define P_DECLARE_STREAMABLE_ENUM_EX(name, countName, firstName, firstValue, ...) \
266  P_DECLARE_ENUM_EX(name, countName, firstName, firstValue, __VA_ARGS__) \
267  P_DECLARE_ENUM_NAMES(name, #firstName, P_ENUM_NAMES_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__)))
268 
273 #define P_DECLARE_STREAMABLE_ENUM(name, first, ...) P_DECLARE_STREAMABLE_ENUM_EX(name, Num##name, first, 0, __VA_ARGS__)
274 
275 
277 // Declare the debugging support
278 
279 #ifndef P_USE_ASSERTS
280 #define P_USE_ASSERTS 1
281 #endif
282 
283 #if !P_USE_ASSERTS
284 
285 #define PAssert(b, m) (b)
286 #define PAssert2(b, c, m) (b)
287 #define PAssertOS(b) (b)
288 #define PAssertNULL(p) (p)
289 #define PAssertAlways(m) {}
290 #define PAssertAlways2(c, m) {}
291 
292 #else // P_USE_ASSERTS
293 
310 };
311 
312 #define __CLASS__ NULL
313 
314 bool PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
315 bool PAssertFunc(const char * file, int line, const char * className, const char * msg);
316 bool PAssertFunc(const char * full_msg);
317 
318 
325 #define PAssert(b, msg) ((b)?true:PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg)))
326 
334 #define PAssert2(b, cls, msg) ((b)?true:PAssertFunc(__FILE__,__LINE__,(cls),(msg)))
335 
342 #define PAssertOS(b) ((b)?true:PAssertFunc(__FILE__,__LINE__,__CLASS__,POperatingSystemError))
343 
353 #define PAssertNULL(ptr) (((ptr)!=NULL)?(ptr): \
354  (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(ptr)))
355 
362 #define PAssertAlways(msg) PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg))
363 
370 #define PAssertAlways2(cls, msg) PAssertFunc(__FILE__,__LINE__,(cls),(msg))
371 
372 #endif // P_USE_ASSERTS
373 
374 
379 ostream & PGetErrorStream();
380 
384 void PSetErrorStream(ostream * strm );
385 
400 #define PError (PGetErrorStream())
401 
402 
404 // Debug and tracing
405 
406 #ifndef PTRACING
407 #define PTRACING 2
408 #endif
409 
410 #if PTRACING
411 
412 class PObject;
413 class PArgList;
414 
427 class PTrace
428 {
429 public:
431  enum Options {
432  Blocks = 0x0001,
437  DateAndTime = 0x0002,
438  Timestamp = 0x0004,
439  Thread = 0x0008,
440  TraceLevel = 0x0010,
441  FileAndLine = 0x0020,
442  ThreadAddress = 0x0040,
443  AppendToFile = 0x0080,
444  GMTTime = 0x0100,
445  RotateDaily = 0x0200,
446  RotateHourly = 0x0400,
447  RotateMinutely = 0x0800,
448  RotateLogMask = RotateDaily + RotateHourly + RotateMinutely,
450  ObjectInstance = 0x1000,
451  ContextIdentifier = 0x2000,
452  SystemLogStream = 0x8000,
455  HasFilePermissions = 0x8000000,
456  FilePermissionMask = 0x7ff0000,
458  FilePermissionShift = 16
459  };
460 
461 
462  #define PTRACE_ARGLIST_OPT_HELP \
463  "use +X or -X to add/remove option where X is one of:\r" \
464  " block PTrace::Block constructs in output\r" \
465  " time time since prgram start\r" \
466  " date date and time\r" \
467  " gmt Date/time is in UTC\r" \
468  " thread thread name and identifier\r" \
469  " level log level\r" \
470  " file source file name and line number\r" \
471  " object PObject pointer\r" \
472  " context context identifier\r" \
473  " daily rotate output file daily\r" \
474  " hour rotate output file hourly\r" \
475  " minute rotate output file every minute\r" \
476  " append append to output file, otherwise overwrites\r" \
477  " <perm> file permission similar to unix chmod, but starts\r" \
478  " with +/- and only has one combination at a time,\r" \
479  " e.g. +uw is user write, +or is other read, etc"
480 
481  #define PTRACE_ARG_TRACE "trace"
482  #define PTRACE_ARG_LEVEL "trace-level"
483  #define PTRACE_ARG_OUTPUT "output"
484  #define PTRACE_ARG_ROLLOVER "trace-rollover"
485  #define PTRACE_ARG_OPTION "trace-option"
486 
487  #define PTRACE_ARGLIST_EXT(t,l,o,r,O) \
488  t"-"PTRACE_ARG_TRACE". Trace enable (use multiple times for more detail).\n" \
489  l"-"PTRACE_ARG_LEVEL": Specify trace detail level.\n" \
490  o"-"PTRACE_ARG_OUTPUT": Specify filename for trace output\rMay be special value such as \"stderr\" dependent on platform.\n" \
491  r"-"PTRACE_ARG_ROLLOVER": Specify trace file rollover file name pattern.\n" \
492  O"-"PTRACE_ARG_OPTION": Specify trace option(s),\r" PTRACE_ARGLIST_OPT_HELP "\n"
493 
494  #define PTRACE_ARGLIST PTRACE_ARGLIST_EXT("t","","o","","")
495 
496  #define PTRACE_INITIALISE(...) PTrace::Initialise(__VA_ARGS__)
497 
501  static void Initialise(
502  const PArgList & args,
503  unsigned options =
504 #ifdef _DEBUG
505  FileAndLine |
506 #endif
507  Timestamp | Thread | Blocks,
508  const char * traceCount = PTRACE_ARG_TRACE,
509  const char * outputFile = PTRACE_ARG_OUTPUT,
510  const char * traceOpts = PTRACE_ARG_OPTION,
511  const char * traceRollover = PTRACE_ARG_ROLLOVER,
512  const char * traceLevel = PTRACE_ARG_LEVEL
513  );
514 
546  static void Initialise(
547  unsigned level,
548  const char * filename = NULL,
549  unsigned options = Timestamp | Thread | Blocks,
550  const char * rolloverPattern = NULL
551  );
552 
553  // Deprecated - for backward compatibility
554  static void Initialise(
555  unsigned level,
556  const char * filename,
557  const char * rolloverPattern,
558  unsigned options = Timestamp | Thread | Blocks
559  ) { Initialise(level, filename, options, rolloverPattern); }
560 
567  static void SetOptions(
568  unsigned options
569  );
570 
579  static void ClearOptions(
580  unsigned options
581  );
582 
588  static unsigned GetOptions();
589 
595  static void SetLevel(
596  unsigned level
597  );
598 
604  static unsigned GetLevel();
605 
610  static PBoolean CanTrace(
611  unsigned level
612  );
613 
618  static void SetStream(
619  ostream * out
620  );
621 
624  static ostream * GetStream();
625 
628  static ostream & PrintInfo(
629  ostream & strm,
630  bool crlf = true
631  );
632 
648  static ostream & Begin(
649  unsigned level,
650  const char * fileName,
651  int lineNum,
652  const PObject * instance = NULL,
653  const char * module = NULL
654  );
655 
656  static ostream & Begin(
657  unsigned level,
658  const char * fileName,
659  int lineNum,
660  const char * module,
661  const PObject * instance,
662  const char * defModule
663  ) { return Begin(level, fileName, lineNum, instance, module != NULL ? module : defModule); }
664 
665  static ostream & Begin(
666  unsigned level,
667  const char * fileName,
668  int lineNum,
669  const PObject * instance,
670  const PObject * defInstance,
671  const char * module
672  ) { return Begin(level, fileName, lineNum, instance != NULL ? instance : defInstance, module); }
673 
691  static ostream & End(
692  ostream & strm
693  );
694 
700  class Block {
701  public:
703  Block(
704  const char * fileName,
705  int lineNum,
706  const char * traceName
708  );
709  Block(const Block & obj)
710  : file(obj.file), line(obj.line), name(obj.name) { }
712  ~Block();
713  private:
714  Block & operator=(const Block &)
715  { return *this; }
716  const char * file;
717  int line;
718  const char * name;
719  };
720 
721  static void WalkStack(
722  ostream & strm,
723  PThreadIdentifier id = PNullThreadIdentifier
724  );
725 
726  static unsigned MaxStackWalk; // Default 20
727 
728 #if PTRACING==2
729  static unsigned GetNextContextIdentifier();
730 #endif
731 };
732 
733 /* Macro to conditionally declare a parameter to a function to avoid compiler
734  warning due that parameter only being used in a <code>PTRACE()</code> */
735 #define PTRACE_PARAM(...) __VA_ARGS__
736 
743 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
744 
748 #define PTRACE_LINE() \
749  if (PTrace::CanTrace(1)) \
750  PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
751  else (void)0
752 
753 
754 
755 #define PTRACE_INTERNAL(level, condition, args, ...) \
756  if (PTrace::CanTrace(level) condition) \
757  PTrace::Begin(level, __FILE__, __LINE__, __VA_ARGS__) << args << PTrace::End; \
758  else (void)0
759 
760 #define PTRACE_NO_CONDITION
761 
762 
763 #define PTRACE_PART1(narg, args) PTRACE_PART2(narg, args)
764 #define PTRACE_PART2(narg, args) PTRACE_ARG_##narg args
765 
766 #define PTRACE_ARG_4(level, object, module, args) \
767  PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, object, module)
768 
769 #define PTRACE_ARG_3(level, objectOrModule, args) \
770  PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, objectOrModule, PTraceObjectInstance(objectOrModule), PTraceModule())
771 
772 #define PTRACE_ARG_2(level, args) \
773  PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, PTraceObjectInstance(), PTraceModule())
774 
775 
776 #define PTRACE_IF_PART1(narg, args) PTRACE_IF_PART2(narg, args)
777 #define PTRACE_IF_PART2(narg, args) PTRACE_IF_ARG_##narg args
778 
779 #define PTRACE_IF_ARG_5(level, condition, object, module, args) \
780  PTRACE_INTERNAL(level, && (condition), args, object, module)
781 
782 #define PTRACE_IF_ARG_4(level, condition, objectOrModule, args) \
783  PTRACE_INTERNAL(level, && (condition), args, objectOrModule, PTraceObjectInstance(objectOrModule), PTraceModule())
784 
785 #define PTRACE_IF_ARG_3(level, condition, args) \
786  PTRACE_INTERNAL(level, && (condition), args, PTraceObjectInstance(), PTraceModule())
787 
788 
789 #define PTRACE_BEGIN_PART1(narg, args) PTRACE_BEGIN_PART2(narg, args)
790 #define PTRACE_BEGIN_PART2(narg, args) PTRACE_BEGIN_ARG_##narg args
791 
792 #define PTRACE_BEGIN_ARG_3(level, object, module) \
793  PTrace::Begin(level, __FILE__, __LINE__, object, module)
794 
795 #define PTRACE_BEGIN_ARG_2(level, objectOrModule) \
796  PTrace::Begin(level, __FILE__, __LINE__, objectOrModule, PTraceObjectInstance(objectOrModule), PTraceModule())
797 
798 #define PTRACE_BEGIN_ARG_1(level) \
799  PTrace::Begin(level, __FILE__, __LINE__, PTraceObjectInstance(), PTraceModule())
800 
801 
802 // Backward compatibility
803 #define PTRACE2(level, object, args) \
804  PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, object, PTraceModule())
805 #define PTRACE_IF2(level, condition, object, args) \
806  PTRACE_INTERNAL(level, && (condition), args, object, PTraceModule())
807 
833 #define PTRACE(...) PTRACE_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
834 
847 #define PTRACE_IF(...) PTRACE_IF_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
848 
858 #define PTRACE_BEGIN(...) PTRACE_BEGIN_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
859 
860 
861 __inline const PObject * PTraceObjectInstance() { return NULL; }
862 __inline static const PObject * PTraceObjectInstance(const void *) { return NULL; }
863 __inline const char * PTraceModule() { return NULL; }
864 
865 
866 #if PTRACING==2
867 
873 #define PTRACE_CONTEXT_ID_NEW() SetTraceContextIdentifier(PTrace::GetNextContextIdentifier())
874 #define PTRACE_CONTEXT_ID_SET(to, from) (to).SetTraceContextIdentifier(from)
875 #define PTRACE_CONTEXT_ID_FROM(obj) SetTraceContextIdentifier(obj)
876 #define PTRACE_CONTEXT_ID_TO(obj) GetTraceContextIdentifier(obj)
877 
879 {
880  private:
881  class PThread * m_currentThread;
882  unsigned m_savedContextIdentifier;
883  public:
887 };
888 
889 #define PTRACE_CONTEXT_ID_PUSH_THREAD(obj) PTraceSaveContextIdentifier praceSavedContextIdentifier(obj)
890 
891 #endif // PTRACING==2
892 
893 
894 #define P_DECLARE_TRACED_ENUM P_DECLARE_STREAMABLE_ENUM
895 #define P_DECLARE_TRACED_ENUM_EX P_DECLARE_STREAMABLE_ENUM_EX
896 
897 #endif // PTRACING
898 
899 #ifndef PTRACE_ARGLIST_EXT
900 #define PTRACE_ARGLIST_EXT(...) ""
901 #endif
902 
903 #ifndef PTRACE_ARGLIST
904 #define PTRACE_ARGLIST ""
905 #endif
906 
907 #ifndef PTRACE_INITIALISE
908 #define PTRACE_INITIALISE(...)
909 #endif
910 
911 #ifndef PTRACE_PARAM
912 #define PTRACE_PARAM(...)
913 #endif
914 
915 #ifndef PTRACE_BLOCK
916 #define PTRACE_BLOCK(n)
917 #endif
918 
919 #ifndef PTRACE_LINE
920 #define PTRACE_LINE()
921 #endif
922 
923 #ifndef PTRACE
924 #define PTRACE(...)
925 #endif
926 
927 #ifndef PTRACE_IF
928 #define PTRACE_IF(...)
929 #endif
930 
931 #ifndef PTRACE_BEGIN
932 #define PTRACE_BEGIN(...)
933 #endif
934 
935 #ifndef PTRACE2
936 #define PTRACE2(level, obj, arg)
937 #endif
938 
939 #ifndef PTRACE_IF2
940 #define PTRACE_IF2(level, cond, obj, args)
941 #endif
942 
943 #ifndef PTRACE_CONTEXT_ID_NEW
944 #define PTRACE_CONTEXT_ID_NEW()
945 #endif
946 
947 #ifndef PTRACE_CONTEXT_ID_SET
948 #define PTRACE_CONTEXT_ID_SET(to, from)
949 #endif
950 
951 #ifndef PTRACE_CONTEXT_ID_FROM
952 #define PTRACE_CONTEXT_ID_FROM(obj)
953 #endif
954 
955 #ifndef PTRACE_CONTEXT_ID_TO
956 #define PTRACE_CONTEXT_ID_TO(obj)
957 #endif
958 
959 #ifndef PTRACE_CONTEXT_ID_PUSH_THREAD
960 #define PTRACE_CONTEXT_ID_PUSH_THREAD(obj)
961 #endif
962 
963 #ifndef P_DECLARE_TRACED_ENUM
964 #define P_DECLARE_TRACED_ENUM P_DECLARE_ENUM
965 #endif
966 
967 #ifndef P_DECLARE_TRACED_ENUM_EX
968 #define P_DECLARE_TRACED_ENUM_EX P_DECLARE_ENUM_EX
969 #endif
970 
971 
972 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE))
973 
974 #define PMEMORY_HEAP 1
975 
982 class PMemoryHeap {
983  protected:
985  PMemoryHeap();
986 
987  public:
988  // Clear up the memory checking subsystem, dumping memory leaks.
989  ~PMemoryHeap();
990 
997  static void * Allocate(
998  size_t nSize,
999  const char * file,
1000  int line,
1001  const char * className
1002  );
1009  static void * Allocate(
1010  size_t count,
1011  size_t iSize,
1012  const char * file,
1013  int line
1014  );
1015 
1023  static void * Reallocate(
1024  void * ptr,
1025  size_t nSize,
1026  const char * file,
1027  int line
1028  );
1029 
1035  static void Deallocate(
1036  void * ptr,
1037  const char * className
1038  );
1039 
1042  enum Validation {
1043  Ok, Bad, Trashed
1044  };
1052  static Validation Validate(
1053  const void * ptr,
1054  const char * className,
1055  ostream * error
1056  );
1057 
1062  static PBoolean ValidateHeap(
1063  ostream * error = NULL
1064  );
1065 
1071  static PBoolean SetIgnoreAllocations(
1072  PBoolean ignore
1073  );
1074 
1078  static void DumpStatistics();
1082  static void DumpStatistics(ostream & strm );
1083 
1084 #if PMEMORY_CHECK
1085  struct State {
1087  };
1088 #else
1089  typedef _CrtMemState State;
1090 #endif
1091 
1092  /* Get memory state.
1093  This returns a state that may be used to determine where to start dumping
1094  objects from.
1095  */
1096  static void GetState(
1097  State & state
1098  );
1099 
1107  static void DumpObjectsSince(
1108  const State & when
1109  );
1110 
1116  static void DumpObjectsSince(
1117  const State & when,
1118  ostream & strm
1119  );
1120 
1126  static void SetAllocationBreakpoint(
1127  DWORD point
1128  );
1129 
1130 #if PMEMORY_CHECK
1131 
1132  protected:
1133  void * InternalAllocate(
1134  size_t nSize, // Number of bytes to allocate.
1135  const char * file, // Source file name for allocating function.
1136  int line, // Source file line for allocating function.
1137  const char * className // Class name for allocating function.
1138  );
1139  Validation InternalValidate(
1140  const void * ptr, // Pointer to memory block to check
1141  const char * className, // Class name it should be.
1142  ostream * error // Stream to receive error message (may be NULL)
1143  );
1144  void InternalDumpStatistics(ostream & strm);
1145  void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
1146 
1147  class Wrapper {
1148  public:
1149  Wrapper();
1150  ~Wrapper();
1151  PMemoryHeap * operator->() const { return instance; }
1152  private:
1153  PMemoryHeap * instance;
1154  };
1155  friend class Wrapper;
1156 
1157  enum Flags {
1158  NoLeakPrint = 1
1159  };
1160 
1161 #pragma pack(1)
1162  struct Header {
1163  enum {
1164  // Assure that the Header struct is aligned to 8 byte boundary
1165  NumGuardBytes = 16 - (sizeof(Header *) +
1166  sizeof(Header *) +
1167  sizeof(const char *) +
1168  sizeof(const char *) +
1169  sizeof(size_t) +
1170  sizeof(DWORD) +
1171  sizeof(WORD) +
1172  sizeof(BYTE) +
1173  sizeof(PThreadIdentifier)
1174  )%8
1175  };
1176 
1179  const char * className;
1180  const char * fileName;
1181  size_t size;
1182  DWORD request;
1183  WORD line;
1184  BYTE flags;
1185  PThreadIdentifier threadId;
1186  char guard[NumGuardBytes];
1187 
1188  static char GuardBytes[NumGuardBytes];
1189  };
1190 #pragma pack()
1191 
1193 
1196 
1197  static DWORD allocationBreakpoint;
1200  BYTE flags;
1201 
1204 
1210 
1211  ostream * leakDumpStream;
1212 
1213 #if defined(_WIN32)
1214  CRITICAL_SECTION mutex;
1215 #elif defined(P_PTHREADS)
1216  pthread_mutex_t mutex;
1217 #elif defined(P_VXWORKS)
1218  void * mutex;
1219 #endif
1220 
1221 #else
1222 
1223  static void CreateInstance();
1224 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
1225  _CrtMemState initialState;
1226 
1227 #endif // PMEMORY_CHECK
1228 };
1229 
1230 
1235 inline void * runtime_malloc(size_t bytes ) { return malloc(bytes); }
1236 
1241 inline void runtime_free(void * ptr ) { free(ptr); }
1242 
1243 
1250 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
1251 
1258 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
1259 
1266 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
1267 
1268 
1275 #define free(p) PMemoryHeap::Deallocate(p, NULL)
1276 
1277 
1284 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
1285 
1286 
1301 #define PNEW new (__FILE__, __LINE__)
1302 
1303 #if !defined(_MSC_VER) || _MSC_VER<1200
1304 #define PSPECIAL_DELETE_FUNCTION
1305 #else
1306 #define PSPECIAL_DELETE_FUNCTION \
1307  void operator delete(void * ptr, const char *, int) \
1308  { PMemoryHeap::Deallocate(ptr, Class()); } \
1309  void operator delete[](void * ptr, const char *, int) \
1310  { PMemoryHeap::Deallocate(ptr, Class()); }
1311 #endif
1312 
1313 #define PNEW_AND_DELETE_FUNCTIONS \
1314  void * operator new(size_t nSize, const char * file, int line) \
1315  { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
1316  void * operator new(size_t nSize) \
1317  { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
1318  void operator delete(void * ptr) \
1319  { PMemoryHeap::Deallocate(ptr, Class()); } \
1320  void * operator new(size_t, void * placement) \
1321  { return placement; } \
1322  void operator delete(void *, void *) \
1323  { } \
1324  void * operator new[](size_t nSize, const char * file, int line) \
1325  { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
1326  void * operator new[](size_t nSize) \
1327  { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
1328  void operator delete[](void * ptr) \
1329  { PMemoryHeap::Deallocate(ptr, Class()); } \
1330  PSPECIAL_DELETE_FUNCTION
1331 
1332 
1333 inline void * operator new(size_t nSize, const char * file, int line)
1334  { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
1335 
1336 inline void * operator new[](size_t nSize, const char * file, int line)
1337  { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
1338 
1339 #ifndef __GNUC__
1340 void * operator new(size_t nSize);
1341 void * operator new[](size_t nSize);
1342 
1343 void operator delete(void * ptr);
1344 void operator delete[](void * ptr);
1345 
1346 #if defined(_MSC_VER) && _MSC_VER>=1200
1347 inline void operator delete(void * ptr, const char *, int)
1348  { PMemoryHeap::Deallocate(ptr, NULL); }
1349 
1350 inline void operator delete[](void * ptr, const char *, int)
1351  { PMemoryHeap::Deallocate(ptr, NULL); }
1352 #endif
1353 #endif
1354 
1355 
1357 public:
1358  PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(true)) { }
1360 private:
1361  PBoolean previousIgnoreAllocations;
1362 };
1363 
1364 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
1365 
1367 public:
1369  {
1371  }
1372 };
1373 
1374 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
1375 
1376 
1377 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
1378 
1379 #define PMEMORY_HEAP 0
1380 
1381 #define PNEW new
1382 
1383 #define PNEW_AND_DELETE_FUNCTIONS
1384 
1385 #define runtime_malloc(s) malloc(s)
1386 #define runtime_free(p) free(p)
1387 
1388 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
1389 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
1390 
1391 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
1392 
1393 
1395 
1407 template <class Type, typename GuardType = unsigned>
1409 {
1410  protected:
1411  Type * m_instance;
1412  public:
1414  {
1415  static Type * s_pointer;
1416  static GuardType s_guard;
1417  if (s_guard++ != 0)
1418  s_guard = 1;
1419  else {
1420 #if PMEMORY_HEAP
1421  // Do this to make sure debugging is initialised as early as possible
1422  PMemoryHeap::Validate(NULL, NULL, NULL);
1423 #endif
1424  static Type s_instance;
1425  s_pointer = &s_instance;
1426  }
1427  m_instance = s_pointer;
1428  }
1429 
1430  Type * operator->() const { return m_instance; }
1431  Type & operator* () const { return *m_instance; }
1432 };
1433 
1434 
1436 // Memory pool allocators
1437 
1438 #if P_GNU_ALLOCATOR
1439 
1440  #include <ext/mt_allocator.h>
1441 
1442  /* Need this tempalte class specialisation of standard class to do the
1443  de-allocation of the pool memory. As per:
1444  http://gcc.gnu.org/viewcvs/trunk/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-6.cc?view=markup
1445  */
1446  template <bool _Thread>
1447  struct PMemoryPool : public __gnu_cxx::__pool<_Thread>
1448  {
1449  PMemoryPool()
1450  : __gnu_cxx::__pool<_Thread>()
1451  {
1452  }
1453 
1454  PMemoryPool(const __gnu_cxx::__pool_base::_Tune& t)
1455  : __gnu_cxx::__pool<_Thread>(t)
1456  {
1457  }
1458  };
1459 
1460  /*Do this template class specialisation so each type has it's own separate
1461  memory block for the pool. */
1462  template <class Type>
1463  struct PCommonPool : public __gnu_cxx::__common_pool_policy<PMemoryPool, true>
1464  {
1465  };
1466 
1467  /*This template class specialisation adds the singleton instance.
1468  */
1469  template <class Type, class Pool = PCommonPool<Type> >
1470  struct PVariablePoolAllocator : public PSingleton<__gnu_cxx::__mt_alloc<Type, Pool> >
1471  {
1472  };
1473 
1474  #if P_GNU_ALLOCATOR==1
1475  template <class Type>
1476  struct PFixedPoolAllocator : public PSingleton<__gnu_cxx::__mt_alloc<Type, PCommonPool<Type> > >
1477  {
1478  };
1479  #else
1480  #include <ext/bitmap_allocator.h>
1481  template <class Type>
1482  struct PFixedPoolAllocator : public PSingleton<__gnu_cxx::bitmap_allocator<Type> >
1483  {
1484  };
1485  #endif
1486 
1487 #else
1488 
1489  template <class Type, class Pool = void>
1490  struct PVariablePoolAllocator : public PSingleton<std::allocator<Type> >
1491  {
1492  };
1493 
1494  template <class Type>
1495  struct PFixedPoolAllocator : public PSingleton<std::allocator<Type> >
1496  {
1497  };
1498 
1499 #endif
1500 
1501 #define PDECLARE_POOL_ALLOCATOR() \
1502  void * operator new(size_t nSize); \
1503  void * operator new(size_t nSize, const char * file, int line); \
1504  void operator delete(void * ptr); \
1505  void operator delete(void * ptr, const char *, int)
1506 
1507 #define PDEFINE_POOL_ALLOCATOR(cls) \
1508  void * cls::operator new(size_t) { return PFixedPoolAllocator<cls>()->allocate(1); } \
1509  void * cls::operator new(size_t, const char *, int) { return PFixedPoolAllocator<cls>()->allocate(1); } \
1510  void cls::operator delete(void * ptr) { PFixedPoolAllocator<cls>()->deallocate((cls *)ptr, 1); } \
1511  void cls::operator delete(void * ptr, const char *, int) { PFixedPoolAllocator<cls>()->deallocate((cls *)ptr, 1); }
1512 
1513 
1514 
1525 #define PCLASSINFO(cls, par) \
1526  public: \
1527  typedef cls P_thisClass; \
1528  static inline const char * Class() \
1529  { return #cls; } \
1530  virtual PBoolean InternalIsDescendant(const char * clsName) const \
1531  { return strcmp(clsName, this->Class()) == 0 || par::InternalIsDescendant(clsName); } \
1532  virtual const char * GetClass(unsigned ancestor = 0) const \
1533  { return ancestor > 0 ? par::GetClass(ancestor-1) : this->Class(); } \
1534  virtual PObject::Comparison CompareObjectMemoryDirect(const PObject & obj) const \
1535  { return PObject::InternalCompareObjectMemoryDirect(this, dynamic_cast<const cls *>(&obj), sizeof(cls)); } \
1536  PNEW_AND_DELETE_FUNCTIONS
1537 
1539 #define PCLASSINFO_WITH_CLONE(cls, par) \
1540  PCLASSINFO(cls, par) \
1541  virtual PObject * Clone() const { return new cls(*this); }
1542 
1543 
1544 #define PIsDescendant(ptr, cls) (dynamic_cast<const cls *>(ptr) != NULL)
1545 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
1546 
1547 #define PRemoveConst(cls, ptr) (const_cast<cls*>(ptr))
1548 
1549 #if P_USE_ASSERTS
1550 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line)
1551  { if (obj == NULL) PAssertFunc(file, line, obj->Class(), PInvalidCast); return obj; }
1552 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
1553 #else
1554 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
1555 #endif
1556 
1557 
1566 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
1567 #ifdef DOC_PLUS_PLUS
1568 } Match previous opening brace in doc++
1569 #endif
1570 
1572 // The root of all evil ... umm classes
1573 
1578 class PObject {
1579  protected:
1581 #if PTRACING==2
1582  public:
1591 #endif // PTRACING==2
1592 
1593  protected:
1599  { }
1600 
1601  public:
1602  /* Destructor required to get the "virtual". A PObject really has nothing
1603  to destroy.
1604  */
1605  virtual ~PObject() { }
1606 
1619  static inline const char * Class() { return "PObject"; }
1620 
1633  virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : this->Class(); }
1634 
1635  PBoolean IsClass(const char * cls) const
1636  { return strcmp(cls, GetClass()) == 0; }
1637 
1648  const char * clsName // Ancestor class name to compare against.
1649  ) const
1650  { return IsClass(clsName); }
1651 
1652  __inline const PObject * PTraceObjectInstance() const { return this; }
1653  __inline static const PObject * PTraceObjectInstance(const char *) { return NULL; }
1654  __inline static const PObject * PTraceObjectInstance(const PObject * obj) { return obj; }
1656 
1662  enum Comparison {
1663  LessThan = -1,
1664  EqualTo = 0,
1666  };
1667 
1679  virtual Comparison Compare(
1680  const PObject & obj // Object to compare against.
1681  ) const;
1682 
1695  const PObject & obj // Object to compare against.
1696  ) const;
1697 
1700  const PObject * obj1,
1701  const PObject * obj2,
1702  PINDEX size
1703  );
1704 
1711  const PObject & obj // Object to compare against.
1712  ) const { return Compare(obj) == EqualTo; }
1713 
1720  const PObject & obj // Object to compare against.
1721  ) const { return Compare(obj) != EqualTo; }
1722 
1729  const PObject & obj // Object to compare against.
1730  ) const { return Compare(obj) == LessThan; }
1731 
1738  const PObject & obj // Object to compare against.
1739  ) const { return Compare(obj) == GreaterThan; }
1740 
1747  const PObject & obj // Object to compare against.
1748  ) const { return Compare(obj) != GreaterThan; }
1749 
1756  const PObject & obj // Object to compare against.
1757  ) const { return Compare(obj) != LessThan; }
1759 
1768  virtual void PrintOn(
1769  ostream &strm // Stream to print the object into.
1770  ) const;
1771 
1778  virtual void ReadFrom(
1779  istream &strm // Stream to read the objects contents from.
1780  );
1781 
1782 
1788  inline friend ostream & operator<<(
1789  ostream &strm,
1790  const PObject & obj
1791  ) { obj.PrintOn(strm); return strm; }
1792 
1798  inline friend istream & operator>>(
1799  istream &strm,
1800  PObject & obj
1801  ) { obj.ReadFrom(strm); return strm; }
1802 
1803 
1818  virtual PObject * Clone() const;
1819 
1822  template <class CLS>
1823  CLS * CloneAs() const
1824  {
1825  PObject * clone = Clone();
1826  CLS * obj = dynamic_cast<CLS *>(clone);
1827  if (obj != NULL)
1828  return obj;
1829  delete clone;
1830  return NULL;
1831  }
1832 
1844  virtual PINDEX HashFunction() const;
1846 };
1847 
1849 // Platform independent types
1850 
1851 // All these classes encapsulate primitive types such that they may be
1852 // transfered in a platform independent manner. In particular it is used to
1853 // do byte swapping for little endien and big endien processor architectures
1854 // as well as accommodating structure packing rules for memory structures.
1855 
1856 #define PANSI_CHAR 1
1857 #define PLITTLE_ENDIAN 2
1858 #define PBIG_ENDIAN 3
1859 
1860 
1861 template <typename type>
1863  __inline PIntSameOrder() : data(0) { }
1864  __inline PIntSameOrder(type value) : data(value) { }
1865  __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data) { }
1866  __inline PIntSameOrder & operator=(type value) { data = value; return *this; }
1867  __inline PIntSameOrder & operator=(const PIntSameOrder & value) { data = value.data; return *this; }
1868  __inline operator type() const { return data; }
1869  __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
1870  __inline friend istream & operator>>(istream & s, PIntSameOrder & v) { return s >> v.data; }
1871 
1872  private:
1873  type data;
1874 };
1875 
1876 
1877 template <typename type>
1879  __inline PIntReversedOrder() : data(0) { }
1880  __inline PIntReversedOrder(type value) { ReverseBytes(value, data); }
1881  __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data) { }
1882  __inline PIntReversedOrder & operator=(type value) { ReverseBytes(value, data); return *this; }
1883  __inline PIntReversedOrder & operator=(const PIntReversedOrder & value) { data = value.data; return *this; }
1884  __inline operator type() const { type value; ReverseBytes(data, value); return value; }
1885  __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
1886  __inline friend istream & operator>>(istream & s, PIntReversedOrder & v) { type val; s >> val; v = val; return s; }
1887 
1888  private:
1889  type data;
1890 
1891  static __inline void ReverseBytes(const type & src, type & dst)
1892  {
1893  size_t s = sizeof(type)-1;
1894  for (size_t d = 0; d < sizeof(type); ++d,--s)
1895  ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
1896  }
1897 };
1898 
1899 #ifndef PCHAR8
1900 #define PCHAR8 PANSI_CHAR
1901 #endif
1902 
1903 #if PCHAR8==PANSI_CHAR
1905 #endif
1906 
1908 
1910 
1911 #if PBYTE_ORDER==PLITTLE_ENDIAN
1912 typedef PIntSameOrder<PInt16> PInt16l;
1913 #elif PBYTE_ORDER==PBIG_ENDIAN
1914 typedef PIntReversedOrder<PInt16> PInt16l;
1915 #endif
1916 
1917 #if PBYTE_ORDER==PLITTLE_ENDIAN
1918 typedef PIntReversedOrder<PInt16> PInt16b;
1919 #elif PBYTE_ORDER==PBIG_ENDIAN
1920 typedef PIntSameOrder<PInt16> PInt16b;
1921 #endif
1922 
1923 #if PBYTE_ORDER==PLITTLE_ENDIAN
1924 typedef PIntSameOrder<WORD> PUInt16l;
1925 #elif PBYTE_ORDER==PBIG_ENDIAN
1926 typedef PIntReversedOrder<WORD> PUInt16l;
1927 #endif
1928 
1929 #if PBYTE_ORDER==PLITTLE_ENDIAN
1930 typedef PIntReversedOrder<WORD> PUInt16b;
1931 #elif PBYTE_ORDER==PBIG_ENDIAN
1932 typedef PIntSameOrder<WORD> PUInt16b;
1933 #endif
1934 
1935 #if PBYTE_ORDER==PLITTLE_ENDIAN
1936 typedef PIntSameOrder<PInt32> PInt32l;
1937 #elif PBYTE_ORDER==PBIG_ENDIAN
1938 typedef PIntReversedOrder<PInt32> PInt32l;
1939 #endif
1940 
1941 #if PBYTE_ORDER==PLITTLE_ENDIAN
1942 typedef PIntReversedOrder<PInt32> PInt32b;
1943 #elif PBYTE_ORDER==PBIG_ENDIAN
1944 typedef PIntSameOrder<PInt32> PInt32b;
1945 #endif
1946 
1947 #if PBYTE_ORDER==PLITTLE_ENDIAN
1948 typedef PIntSameOrder<DWORD> PUInt32l;
1949 #elif PBYTE_ORDER==PBIG_ENDIAN
1950 typedef PIntReversedOrder<DWORD> PUInt32l;
1951 #endif
1952 
1953 #if PBYTE_ORDER==PLITTLE_ENDIAN
1954 typedef PIntReversedOrder<DWORD> PUInt32b;
1955 #elif PBYTE_ORDER==PBIG_ENDIAN
1956 typedef PIntSameOrder<DWORD> PUInt32b;
1957 #endif
1958 
1959 #if PBYTE_ORDER==PLITTLE_ENDIAN
1960 typedef PIntSameOrder<PInt64> PInt64l;
1961 #elif PBYTE_ORDER==PBIG_ENDIAN
1962 typedef PIntReversedOrder<PInt64> PInt64l;
1963 #endif
1964 
1965 #if PBYTE_ORDER==PLITTLE_ENDIAN
1966 typedef PIntReversedOrder<PInt64> PInt64b;
1967 #elif PBYTE_ORDER==PBIG_ENDIAN
1968 typedef PIntSameOrder<PInt64> PInt64b;
1969 #endif
1970 
1971 #if PBYTE_ORDER==PLITTLE_ENDIAN
1972 typedef PIntSameOrder<PUInt64> PUInt64l;
1973 #elif PBYTE_ORDER==PBIG_ENDIAN
1974 typedef PIntReversedOrder<PUInt64> PUInt64l;
1975 #endif
1976 
1977 #if PBYTE_ORDER==PLITTLE_ENDIAN
1978 typedef PIntReversedOrder<PUInt64> PUInt64b;
1979 #elif PBYTE_ORDER==PBIG_ENDIAN
1980 typedef PIntSameOrder<PUInt64> PUInt64b;
1981 #endif
1982 
1983 #if PBYTE_ORDER==PLITTLE_ENDIAN
1984 typedef PIntSameOrder<float> PFloat32l;
1985 #elif PBYTE_ORDER==PBIG_ENDIAN
1986 typedef PIntReversedOrder<float> PFloat32l;
1987 #endif
1988 
1989 #if PBYTE_ORDER==PLITTLE_ENDIAN
1990 typedef PIntReversedOrder<float> PFloat32b;
1991 #elif PBYTE_ORDER==PBIG_ENDIAN
1992 typedef PIntSameOrder<float> PFloat32b;
1993 #endif
1994 
1995 #if PBYTE_ORDER==PLITTLE_ENDIAN
1996 typedef PIntSameOrder<double> PFloat64l;
1997 #elif PBYTE_ORDER==PBIG_ENDIAN
1998 typedef PIntReversedOrder<double> PFloat64l;
1999 #endif
2000 
2001 #if PBYTE_ORDER==PLITTLE_ENDIAN
2002 typedef PIntReversedOrder<double> PFloat64b;
2003 #elif PBYTE_ORDER==PBIG_ENDIAN
2004 typedef PIntSameOrder<double> PFloat64b;
2005 #endif
2006 
2007 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
2008 #if PBYTE_ORDER==PLITTLE_ENDIAN
2009 typedef PIntSameOrder<long double> PFloat80l;
2010 #elif PBYTE_ORDER==PBIG_ENDIAN
2011 typedef PIntReversedOrder<long double> PFloat80l;
2012 #endif
2013 
2014 #if PBYTE_ORDER==PLITTLE_ENDIAN
2015 typedef PIntReversedOrder<long double> PFloat80b;
2016 #elif PBYTE_ORDER==PBIG_ENDIAN
2017 typedef PIntSameOrder<long double> PFloat80b;
2018 #endif
2019 #endif
2020 
2021 typedef intptr_t P_INT_PTR;
2022 
2023 #if defined(_MSC_VER)
2024 #define P_ALIGN_FIELD(fieldType,fieldName,alignment) fieldType __declspec(align(alignment)) fieldName
2025 #elif defined(__GNUC__)
2026 #define P_ALIGN_FIELD(fieldType,fieldName,alignment) fieldType fieldName __attribute__ ((aligned(alignment)))
2027 #endif
2028 
2029 typedef intptr_t P_INT_PTR;
2030 
2032 // Miscellaneous
2033 
2034 /*$MACRO PARRAYSIZE(array)
2035  This macro is used to calculate the number of array elements in a static
2036  array.
2037  */
2038 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
2039 
2040 /*$MACRO PMIN(v1, v2)
2041  This macro is used to calculate the minimum of two values.
2042  Maps to std::min and is for backward compatibility only.
2043  */
2044 #define PMIN(v1, v2) std::min(v1, v2)
2045 
2046 /*$MACRO PMAX(v1, v2)
2047  This macro is used to calculate the maximum of two values.
2048  Maps to std::max and is for backward compatibility only.
2049  */
2050 #define PMAX(v1, v2) std::max(v1, v2)
2051 
2052 /*$MACRO PABS(val)
2053  This macro is used to calculate an absolute value.
2054  Maps to std::abs and is for backward compatibility only.
2055  */
2056 #define PABS(v) std::abs(v)
2057 
2058 
2059 #endif // PTLIB_OBJECT_H
2060 
2061 
2062 // End Of File ///////////////////////////////////////////////////////////////