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: 28201 $
30 * $Author: rjongbloed $
31 * $Date: 2012-08-14 21:30:31 -0500 (Tue, 14 Aug 2012) $
32 */
33
34 #ifndef PTLIB_OBJECT_H
35 #define PTLIB_OBJECT_H
36
37 #ifdef P_USE_PRAGMA
38 #pragma interface
39 #endif
40
41 #if defined(_WIN32) || defined(_WIN32_WCE)
42 #include "msos/ptlib/contain.h"
43 #else
44 #include "unix/ptlib/contain.h"
45 #endif
46
47 #if defined(P_VXWORKS)
48 #include <private/stdiop.h>
49 #endif
50
51 #include <stdio.h>
52 #include <stdarg.h>
53 #include <stdlib.h>
54
55 #include <string.h>
56
57 #include <string>
58 #include <iomanip>
59 #include <iostream>
60 #include <sstream>
61 #include <vector>
62 #include <list>
63 #include <map>
64 #include <algorithm>
65
66
67 #define P_REMOVE_VIRTUAL_INTERNAL_BASE(fn) __inline virtual struct ptlib_virtual_function_changed_or_removed ****** fn { return 0; }
68
69 #if defined(_MSC_VER)
70 #if _MSC_VER < 1310
71 #define P_DEPRECATED
72 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
73 #elif _MSC_VER < 1400
74 #define P_DEPRECATED __declspec(deprecated)
75 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated) type fn body
76 #else
77 #define P_DEPRECATED __declspec(deprecated)
78 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated("Virtual function signature changed or function deprecated")) type fn body
79 #endif
80 #elif defined(__GNUC__)
81 #if __GNUC__ < 4
82 #define P_DEPRECATED
83 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
84 #else
85 #define P_DEPRECATED __attribute__((deprecated))
86 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __attribute__((warn_unused_result)) __attribute__((deprecated)) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
87 #endif
88 #else
89 #define P_DEPRECATED
90 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
91 #endif
92
93 #define P_REMOVE_VIRTUAL_VOID(fn) P_REMOVE_VIRTUAL_INTERNAL(void, fn, {})
94 #define P_REMOVE_VIRTUAL(type, fn, ret) P_REMOVE_VIRTUAL_INTERNAL(type, fn, { return ret; })
95
96
97 // P_USE_INTEGER_BOOL is the default and gives the old behaviour (it
98 // is also used for C translation units).
99 // without P_USE_INTEGER_BOOL, the ANSI C++ bool is used.
100
101 #if defined(P_USE_INTEGER_BOOL) || !defined(__cplusplus)
102 typedef BOOL PBoolean;
103 # define PTrue TRUE
104 # define PFalse FALSE
105 #else
106 typedef bool PBoolean;
107 # define PTrue true
108 # define PFalse false
109 #endif
110
111
112 ///////////////////////////////////////////////////////////////////////////////
113 // Disable inlines when debugging for faster compiles (the compiler doesn't
114 // actually inline the function with debug on any way).
115
116 #ifndef P_USE_INLINES
117 #ifdef _DEBUG
118 #define P_USE_INLINES 0
119 #else
120 #define P_USE_INLINES 0
121 #endif
122 #endif
123
124 #if P_USE_INLINES
125 #define PINLINE inline
126 #else
127 #define PINLINE
128 #endif
129
130
131 ///////////////////////////////////////////////////////////////////////////////
132 // Declare the debugging support
133
134 #ifndef P_USE_ASSERTS
135 #define P_USE_ASSERTS 1
136 #endif
137
138 #if !P_USE_ASSERTS
139
140 #define PAssert(b, m) (b)
141 #define PAssert2(b, c, m) (b)
142 #define PAssertOS(b) (b)
143 #define PAssertNULL(p) (p)
144 #define PAssertAlways(m) {}
145 #define PAssertAlways2(c, m) {}
146
147 #else // P_USE_ASSERTS
148
149 /// Standard assert messages for the PAssert macro.
150 enum PStandardAssertMessage {
151 PLogicError, ///< A logic error occurred.
152 POutOfMemory, ///< A new or malloc failed.
153 PNullPointerReference, ///< A reference was made through a NULL pointer.
154 PInvalidCast, ///< An invalid cast to descendant is required.
155 PInvalidArrayIndex, ///< An index into an array was negative.
156 PInvalidArrayElement, ///< A NULL array element object was accessed.
157 PStackEmpty, ///< A Pop() was made of a stack with no elements.
158 PUnimplementedFunction, ///< Funtion is not implemented.
159 PInvalidParameter, ///< Invalid parameter was passed to a function.
160 POperatingSystemError, ///< Error was returned by Operating System.
161 PChannelNotOpen, ///< Operation attempted when channel not open.
162 PUnsupportedFeature, ///< Feature is not supported.
163 PInvalidWindow, ///< Access through invalid window.
164 PMaxStandardAssertMessage ///< Number of standard assert message.
165 };
166
167 #define __CLASS__ NULL
168
169 void PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
170 void PAssertFunc(const char * file, int line, const char * className, const char * msg);
171 void PAssertFunc(const char * full_msg);
172
PAssertFuncInline(bool b,const char * file,int line,const char * className,PStandardAssertMessage msg)173 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, PStandardAssertMessage msg)
174 {
175 if (!b)
176 PAssertFunc(file, line, className, msg);
177 return b;
178 }
PAssertFuncInline(bool b,const char * file,int line,const char * className,const char * msg)179 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, const char * msg)
180 {
181 if (!b)
182 PAssertFunc(file, line, className, msg);
183 return b;
184 }
185
186 /** This macro is used to assert that a condition must be true.
187 If the condition is false then an assert function is called with the source
188 file and line number the macro was instantiated on, plus the message described
189 by the <code>msg</code> parameter. This parameter may be either a standard value
190 from the <code>PStandardAssertMessage</code> enum or a literal string.
191 */
192 #define PAssert(b, msg) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,(msg))
193
194 /** This macro is used to assert that a condition must be true.
195 If the condition is false then an assert function is called with the source
196 file and line number the macro was instantiated on, plus the message described
197 by the <code>msg</code> parameter. This parameter may be either a standard value
198 from the <code>PStandardAssertMessage</code> enum or a literal string.
199 The <code>cls</code> parameter specifies the class name that the error occurred in
200 */
201 #define PAssert2(b, cls, msg) PAssertFuncInline((b), __FILE__,__LINE__,(cls),(msg))
202
203 /** This macro is used to assert that an operating system call succeeds.
204 If the condition is false then an assert function is called with the source
205 file and line number the macro was instantiated on, plus the message
206 described by the <code>POperatingSystemError</code> value in the <code>PStandardAssertMessage</code>
207 enum.
208 */
209 #define PAssertOS(b) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,POperatingSystemError)
210
211 /** This macro is used to assert that a pointer must be non-null.
212 If the pointer is NULL then an assert function is called with the source file
213 and line number the macro was instantiated on, plus the message described by
214 the PNullPointerReference value in the <code>PStandardAssertMessage</code> enum.
215
216 Note that this evaluates the expression defined by <code>ptr</code> twice. To
217 prevent incorrect behaviour with this, the macro will assume that the
218 <code>ptr</code> parameter is an L-Value.
219 */
220 #define PAssertNULL(ptr) (((ptr)!=NULL)?(ptr): \
221 (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(ptr)))
222
223 /** This macro is used to assert immediately.
224 The assert function is called with the source file and line number the macro
225 was instantiated on, plus the message described by the <code>msg</code> parameter. This
226 parameter may be either a standard value from the <code>PStandardAssertMessage</code>
227 enum or a literal string.
228 */
229 #define PAssertAlways(msg) PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg))
230
231 /** This macro is used to assert immediately.
232 The assert function is called with the source file and line number the macro
233 was instantiated on, plus the message described by the <code>msg</code> parameter. This
234 parameter may be either a standard value from the <code>PStandardAssertMessage</code>
235 enum or a literal string.
236 */
237 #define PAssertAlways2(cls, msg) PAssertFunc(__FILE__,__LINE__,(cls),(msg))
238
239 #endif // P_USE_ASSERTS
240
241
242 /** Get the stream being used for error output.
243 This stream is used for all trace output using the various trace functions
244 and macros.
245 */
246 ostream & PGetErrorStream();
247
248 /** Set the stream to be used for error output.
249 This stream is used for all error output using the <code>PError</code> macro.
250 */
251 void PSetErrorStream(ostream * strm /** New stream for error output */ );
252
253 /** This macro is used to access the platform specific error output stream.
254 This is to be used in preference to assuming <code>cerr</code> is always available. On
255 Unix platforms this {\b is} <code>cerr</code> but for MS-Windows this is another stream
256 that uses the OutputDebugString() Windows API function. Note that a MS-DOS or
257 Windows NT console application would still use <code>cerr</code>.
258
259 The <code>PError</code> stream would normally only be used for debugging information as
260 a suitable display is not always available in windowed environments.
261
262 The macro is a wrapper for a global variable error stream. The internal variable
263 is initialised to <i>std::cerr</i> for all but MS-Windows and NT GUI applications.
264 An application could change this pointer to a <i>std::ofstream</i> variable of
265 #PError output is wished to be redirected to a file.
266 */
267 #define PError (PGetErrorStream())
268
269
270
271 ///////////////////////////////////////////////////////////////////////////////
272 // Debug and tracing
273
274 #ifndef PTRACING
275 #define PTRACING 1
276 #endif
277
278 #if PTRACING
279
280 /**Class to encapsulate tracing functions.
281 This class does not require any instances and is only being used as a
282 method of grouping functions together in a name space.
283
284 There are a number of macros for supporting tracing. These will all
285 evaluate as empty in a "No Trace" build of the system:
286 - PTRACE()
287 - PTRACE_IF()
288 - PTRACE_PARAM()
289 - PTRACE_BLOCK()
290 - PTRACE_LINE()
291 */
292 class PTrace
293 {
294 public:
295 /// Options for trace output.
296 enum Options {
297 /**Include PTrace::Block constructs in output
298 If this is bit is clear, all PTrace::Block output is inhibited
299 regardless of the trace level. If set, the PTrace::Block may occur
300 provided the trace level is greater than zero.
301 */
302 Blocks = 1,
303 /// Include date and time in all output
304 DateAndTime = 2,
305 /// Include (millisecond) timestamp in all output
306 Timestamp = 4,
307 /// Include identifier for thread trace is made from in all output
308 Thread = 8,
309 /// Include trace level in all output
310 TraceLevel = 16,
311 /// Include the file and line for the trace call in all output
312 FileAndLine = 32,
313 /// Include thread object pointer address in all trace output
314 ThreadAddress = 64,
315 /// Append to log file rather than resetting every time
316 AppendToFile = 128,
317 /// Output timestamps in GMT time rather than local time
318 GMTTime = 256,
319 /// If set, log file will be rotated daily
320 RotateDaily = 512,
321 /// If set, log file will be rotated hourly
322 RotateHourly = 1024,
323 /// If set, log file will be rotated every minute
324 RotateMinutely = 2048,
325 /// Mask for all the rotate bits
326 RotateLogMask = RotateDaily + RotateHourly + RotateMinutely,
327 /** SystemLog flag for tracing within a PServiceProcess application. Must
328 be set in conjection with <code>#SetStream(new PSystemLog)</code>.
329 */
330 SystemLogStream = 32768
331 };
332
333
334 /**Set the most common trace options.
335 If \p filename is not NULL then a PTextFile is created and attached the
336 trace output stream. This object is never closed or deleted until the
337 termination of the program.
338
339 There are several special values for \p filename:
340 <dl>
341 <dt>"stderr" <dd>Output to standard error
342 <dt>"stdout" <dd>Output to standard output
343 <dt>"DEBUGSTREAM" <dd>Output to debugger (Windows only)
344 </dl>
345 A trace output of the program name version and OS is written as well.
346 */
347 static void Initialise(
348 unsigned level, ///< Level for tracing
349 const char * filename = NULL, ///< Filename for log output
350 unsigned options = Timestamp | Thread | Blocks ///< #Options for tracing
351 );
352
353 /**Set the most common trace options.
354 If \p filename is not NULL then a PTextFile is created and attached the
355 trace output stream. This object is never closed or deleted until the
356 termination of the program.
357
358 If \p rolloverPatterm is not NULL it is used as the time format patterm
359 appended to filename if the #RotateDaily is set. Default is "yyyy_MM_dd".
360
361 A trace output of the program name version and OS is written as well.
362 */
363 static void Initialise(
364 unsigned level, ///< Level for tracing
365 const char * filename, ///< Filename for log output
366 const char * rolloverPattern, ///< Pattern for rolling over trace files
367 unsigned options = Timestamp | Thread | Blocks ///< #Options for tracing
368 );
369
370 /** Set the trace options.
371 The PTRACE(), PTRACE_BLOCK() and PTRACE_LINE() macros output trace text that
372 may contain assorted values. These are defined by the #Options enum.
373
374 Note this function OR's the bits included in the options parameter.
375 */
376 static void SetOptions(
377 unsigned options ///< New option bits for tracing
378 );
379
380 /** Clear the trace options.
381 The <code>PTRACE()</code>, <code>PTRACE_BLOCK()</code> and
382 <code>PTRACE_LINE()</code> macros output trace text that
383 may contain assorted values. These are defined by the #Options enum.
384
385 Note this function AND's the complement of the bits included in the options
386 parameter.
387 */
388 static void ClearOptions(
389 unsigned options ///< Option bits to turn off
390 );
391
392 /** Get the current trace options.
393 The <code>PTRACE()</code>, <code>PTRACE_BLOCK()</code> and
394 <code>PTRACE_LINE()</code> macros output trace text that
395 may contain assorted values. These are defined by the #Options enum.
396 */
397 static unsigned GetOptions();
398
399 /** Set the trace level.
400 The <code>PTRACE()</code> macro checks to see if its level is equal to or lower then the
401 level set by this function. If so then the trace text is output to the trace
402 stream.
403 */
404 static void SetLevel(
405 unsigned level ///< New level for tracing
406 );
407
408 /** Get the trace level.
409 The <code>PTRACE()</code> macro checks to see if its level is equal to or lower then the
410 level set by this function. If so then the trace text is output to the trace
411 stream.
412 */
413 static unsigned GetLevel();
414
415 /** Determine if the level may cause trace output.
416 This checks against the current global trace level set by SetLevel()
417 for if the trace output may be emitted. This is used by the PTRACE() macro.
418 */
419 static PBoolean CanTrace(
420 unsigned level ///< Trace level to check
421 );
422
423 /** Set the stream to be used for trace output.
424 This stream is used for all trace output using the various trace functions
425 and macros.
426 */
427 static void SetStream(
428 ostream * out ///< New output stream from trace.
429 );
430
431 /** Begin a trace output.
432 If the trace stream output is used outside of the provided macros, it
433 should be noted that a mutex is obtained on the call to Begin() which
434 will prevent any other threads from using the trace stream until the
435 End() function is called.
436
437 So a typical usage would be:
438 <pre><code>
439 ostream & s = PTrace::Begin(3, __FILE__, __LINE__);
440 s << "hello";
441 if (want_there)
442 s << " there";
443 s << '!' << PTrace::End;
444 </code></pre>
445 */
446 static ostream & Begin(
447 unsigned level, ///< Log level for output
448 const char * fileName, ///< Filename of source file being traced
449 int lineNum ///< Line number of source file being traced.
450 );
451
452 /** End a trace output.
453 If the trace stream output is used outside of the provided macros, the
454 End() function must be used at the end of the section of trace
455 output. A mutex is obtained on the call to Begin() which will prevent
456 any other threads from using the trace stream until the End(). The
457 End() is used in a similar manner to <code>std::endl</code> or
458 <code>std::flush</code>.
459
460 So a typical usage would be:
461 <pre><code>
462 ostream & s = PTrace::Begin();
463 s << "hello";
464 if (want_there)
465 s << " there";
466 s << '!' << PTrace::End;
467 </code></pre>
468 */
469 static ostream & End(
470 ostream & strm ///< Trace output stream being completed
471 );
472
473 /** Cleanup the trace system for a specific thread
474 When using thread local storage, this will delete the per-thread trace context
475 */
476 static void Cleanup();
477
478 /** Class to trace Execution blocks.
479 This class is used for tracing the entry and exit of program blocks. Upon
480 construction it outputs an entry trace message and on destruction outputs an
481 exit trace message. This is normally only used from in the <code>PTRACE_BLOCK()</code> macro.
482 */
483 class Block {
484 public:
485 /** Output entry trace message. */
486 Block(
487 const char * fileName, ///< Filename of source file being traced
488 int lineNum, ///< Line number of source file being traced.
489 const char * traceName
490 ///< String to be output with trace, typically it is the function name.
491 );
Block(const Block & obj)492 Block(const Block & obj)
493 : file(obj.file), line(obj.line), name(obj.name) { }
494 /// Output exit trace message.
495 ~Block();
496 private:
497 Block & operator=(const Block &)
498 { return *this; }
499 const char * file;
500 int line;
501 const char * name;
502 };
503 };
504
505 /* Macro to conditionally declare a parameter to a function to avoid compiler
506 warning due that parameter only being used in a <code>PTRACE()</code> */
507 #define PTRACE_PARAM(param) param
508
509 /** Trace an execution block.
510 This macro creates a trace variable for tracking the entry and exit of program
511 blocks. It creates an instance of the PTraceBlock class that will output a
512 trace message at the line <code>PTRACE_BLOCK()</code> is called and then on exit from the
513 scope it is defined in.
514 */
515 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
516
517 /** Trace the execution of a line.
518 This macro outputs a trace of a source file line execution.
519 */
520 #define PTRACE_LINE() \
521 if (PTrace::CanTrace(1)) \
522 PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
523 else (void)0
524
525 /** Output trace.
526 This macro outputs a trace of any information needed, using standard stream
527 output operators. The output is only made if the trace level set by the
528 SetLevel() function is greater than or equal to the \p level argument.
529 */
530 #define PTRACE(level, args) \
531 if (PTrace::CanTrace(level)) \
532 PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
533 else (void)0
534
535 /** Output trace on condition.
536 This macro outputs a trace of any information needed, using standard stream
537 output operators. The output is only made if the trace level set by the
538 SetLevel() function is greater than or equal to the <code>level</code> argument
539 and the conditional is true. Note the conditional is only evaluated if the
540 trace level is sufficient.
541 */
542 #define PTRACE_IF(level, cond, args) \
543 if ((PTrace::CanTrace(level) && (cond))) \
544 PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
545 else (void)0
546
547 #else // PTRACING
548
549 #define PTRACE_PARAM(param)
550 #define PTRACE_BLOCK(n)
551 #define PTRACE_LINE()
552 #define PTRACE(level, arg)
553 #define PTRACE_IF(level, cond, args)
554
555 #endif // PTRACING
556
557
558
559 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE))
560
561 #define PMEMORY_HEAP 1
562
563 /** Memory heap checking class.
564 This class implements the memory heap checking and validation functions. It
565 maintains lists of allocated block so that memory leaks can be detected. It
566 also initialises memory on allocation and deallocation to help catch errors
567 involving the use of dangling pointers.
568 */
569 class PMemoryHeap {
570 public:
571 /// Initialise the memory checking subsystem.
572 PMemoryHeap();
573
574 // Clear up the memory checking subsystem, dumping memory leaks.
575 ~PMemoryHeap();
576
577 /** Allocate a memory block.
578 This allocates a new memory block and keeps track of it. The memory
579 block is filled with the value in the <code>allocFillChar</code> member variable
580 to help detect uninitialised structures.
581 @return pointer to newly allocated memory block.
582 */
583 static void * Allocate(
584 size_t nSize, ///< Number of bytes to allocate.
585 const char * file, ///< Source file name for allocating function.
586 int line, ///< Source file line for allocating function.
587 const char * className ///< Class name for allocating function.
588 );
589 /** Allocate a memory block.
590 This allocates a new memory block and keeps track of it. The memory
591 block is filled with the value in the <code>allocFillChar</code> member variable
592 to help detect uninitialised structures.
593 @return pointer to newly allocated memory block.
594 */
595 static void * Allocate(
596 size_t count, ///< Number of items to allocate.
597 size_t iSize, ///< Size in bytes of each item.
598 const char * file, ///< Source file name for allocating function.
599 int line ///< Source file line for allocating function.
600 );
601
602 /** Change the size of an allocated memory block.
603 This allocates a new memory block and keeps track of it. The memory
604 block is filled with the value in the <code>allocFillChar</code> member variable
605 to help detect uninitialised structures.
606 @return pointer to reallocated memory block. Note this may
607 {\em not} be the same as the pointer passed into the function.
608 */
609 static void * Reallocate(
610 void * ptr, ///< Pointer to memory block to reallocate.
611 size_t nSize, ///< New number of bytes to allocate.
612 const char * file, ///< Source file name for allocating function.
613 int line ///< Source file line for allocating function.
614 );
615
616 /** Free a memory block.
617 The memory is deallocated, a warning is displayed if it was never
618 allocated. The block of memory is filled with the value in the
619 <code>freeFillChar</code> member variable.
620 */
621 static void Deallocate(
622 void * ptr, ///< Pointer to memory block to deallocate.
623 const char * className ///< Class name for deallocating function.
624 );
625
626 /** Validation result.
627 */
628 enum Validation {
629 Ok, Bad, Trashed
630 };
631 /** Validate the memory pointer.
632 The <code>ptr</code> parameter is validated as a currently allocated heap
633 variable.
634 @return Ok for pointer is in heap, Bad for pointer is not in the heap
635 or Trashed if the pointer is in the heap but has overwritten the guard
636 bytes before or after the actual data part of the memory block.
637 */
638 static Validation Validate(
639 const void * ptr, ///< Pointer to memory block to check
640 const char * className, ///< Class name it should be.
641 ostream * error ///< Stream to receive error message (may be NULL)
642 );
643
644 /** Validate all objects in memory.
645 This effectively calls Validate() on every object in the heap.
646 @return true if every object in heap is Ok.
647 */
648 static PBoolean ValidateHeap(
649 ostream * error = NULL ///< Stream to output, use default if NULL
650 );
651
652 /** Ignore/Monitor allocations.
653 Set internal flag so that allocations are not included in the memory
654 leak check on program termination.
655 Returns the previous state.
656 */
657 static PBoolean SetIgnoreAllocations(
658 PBoolean ignore ///< New flag for allocation ignoring.
659 );
660
661 /** Get memory check system statistics.
662 Dump statistics output to the default stream.
663 */
664 static void DumpStatistics();
665 /** Get memory check system statistics.
666 Dump statistics output to the specified stream.
667 */
668 static void DumpStatistics(ostream & strm /** Stream to output to */);
669
670 #if PMEMORY_CHECK
671 struct State {
672 DWORD allocationNumber;
673 };
674 #else
675 typedef _CrtMemState State;
676 #endif
677
678 /* Get memory state.
679 This returns a state that may be used to determine where to start dumping
680 objects from.
681 */
682 static void GetState(
683 State & state ///< Memory state
684 );
685
686 /** Dump allocated objects.
687 Dump ojects allocated and not deallocated since the specified object
688 number. This would be a value returned by the <code>GetAllocationRequest()</code>
689 function.
690
691 Output is to the default stream.
692 */
693 static void DumpObjectsSince(
694 const State & when ///< Memory state to begin dump from.
695 );
696
697 /** Dump allocated objects.
698 Dump ojects allocated and not deallocated since the specified object
699 number. This would be a value returned by the <code>GetAllocationRequest()</code>
700 function.
701 */
702 static void DumpObjectsSince(
703 const State & when, ///< Memory state to begin dump from.
704 ostream & strm ///< Stream to output dump
705 );
706
707 /** Set break point allocation number.
708 Set the allocation request number to cause an assert. This allows a
709 developer to cause a halt in a debugger on a certain allocation allowing
710 them to determine memory leaks allocation point.
711 */
712 static void SetAllocationBreakpoint(
713 DWORD point ///< Allocation number to stop at.
714 );
715
716 #if PMEMORY_CHECK
717
718 protected:
719 void * InternalAllocate(
720 size_t nSize, // Number of bytes to allocate.
721 const char * file, // Source file name for allocating function.
722 int line, // Source file line for allocating function.
723 const char * className // Class name for allocating function.
724 );
725 Validation InternalValidate(
726 const void * ptr, // Pointer to memory block to check
727 const char * className, // Class name it should be.
728 ostream * error // Stream to receive error message (may be NULL)
729 );
730 void InternalDumpStatistics(ostream & strm);
731 void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
732
733 class Wrapper {
734 public:
735 Wrapper();
736 ~Wrapper();
737 PMemoryHeap * operator->() const { return instance; }
738 private:
739 PMemoryHeap * instance;
740 };
741 friend class Wrapper;
742
743 enum Flags {
744 NoLeakPrint = 1
745 };
746
747 #pragma pack(1)
748 struct Header {
749 enum {
750 // Assure that the Header struct is aligned to 8 byte boundary
751 NumGuardBytes = 16 - (sizeof(Header *) +
752 sizeof(Header *) +
753 sizeof(const char *) +
754 sizeof(const char *) +
755 sizeof(size_t) +
756 sizeof(DWORD) +
757 sizeof(WORD) +
758 sizeof(BYTE)
759 #if P_PTHREADS
760 + sizeof(pthread_t)
761 #endif
762 )%8
763 };
764
765 Header * prev;
766 Header * next;
767 const char * className;
768 const char * fileName;
769 size_t size;
770 DWORD request;
771 WORD line;
772 BYTE flags;
773 #if P_PTHREADS
774 pthread_t thread;
775 #endif
776 char guard[NumGuardBytes];
777
778 static char GuardBytes[NumGuardBytes];
779 };
780 #pragma pack()
781
782 PBoolean isDestroyed;
783
784 Header * listHead;
785 Header * listTail;
786
787 static DWORD allocationBreakpoint;
788 DWORD allocationRequest;
789 DWORD firstRealObject;
790 BYTE flags;
791
792 char allocFillChar;
793 char freeFillChar;
794
795 DWORD currentMemoryUsage;
796 DWORD peakMemoryUsage;
797 DWORD currentObjects;
798 DWORD peakObjects;
799 DWORD totalObjects;
800
801 ostream * leakDumpStream;
802
803 #if defined(_WIN32)
804 CRITICAL_SECTION mutex;
805 #elif defined(P_PTHREADS)
806 pthread_mutex_t mutex;
807 #elif defined(P_VXWORKS)
808 void * mutex;
809 #endif
810
811 #else
812
813 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
814 _CrtMemState initialState;
815
816 #endif // PMEMORY_CHECK
817 };
818
819
820 /** Allocate memory for the run time library.
821 This version of free is used for data that is not to be allocated using the
822 memory check system, ie will be free'ed inside the C run time library.
823 */
runtime_malloc(size_t bytes)824 inline void * runtime_malloc(size_t bytes /** Size of block to allocate */ ) { return malloc(bytes); }
825
826 /** Free memory allocated by run time library.
827 This version of free is used for data that is not allocated using the
828 memory check system, ie was malloc'ed inside the C run time library.
829 */
runtime_free(void * ptr)830 inline void runtime_free(void * ptr /** Memory block to free */ ) { free(ptr); }
831
832
833 /** Override of system call for memory check system.
834 This macro is used to allocate memory via the memory check system selected
835 with the <code>PMEMORY_CHECK</code> compile time option. It will include the source file
836 and line into the memory allocation to allow the PMemoryHeap class to keep
837 track of the memory block.
838 */
839 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
840
841 /** Override of system call for memory check system.
842 This macro is used to allocate memory via the memory check system selected
843 with the <code>PMEMORY_CHECK</code> compile time option. It will include the source file
844 and line into the memory allocation to allow the PMemoryHeap class to keep
845 track of the memory block.
846 */
847 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
848
849 /** Override of system call for memory check system.
850 This macro is used to allocate memory via the memory check system selected
851 with the <code>PMEMORY_CHECK</code> compile time option. It will include the source file
852 and line into the memory allocation to allow the PMemoryHeap class to keep
853 track of the memory block.
854 */
855 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
856
857
858 /** Override of system call for memory check system.
859 This macro is used to deallocate memory via the memory check system selected
860 with the <code>PMEMORY_CHECK</code> compile time option. It will include the source file
861 and line into the memory allocation to allow the PMemoryHeap class to keep
862 track of the memory block.
863 */
864 #define free(p) PMemoryHeap::Deallocate(p, NULL)
865
866
867 /** Override of system call for memory check system.
868 This macro is used to deallocate memory via the memory check system selected
869 with the <code>PMEMORY_CHECK</code> compile time option. It will include the source file
870 and line into the memory allocation to allow the PMemoryHeap class to keep
871 track of the memory block.
872 */
873 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
874
875
876 /** Macro for overriding system default <code>new</code> operator.
877 This macro is used to allocate memory via the memory check system selected
878 with the PMEMORY_CHECK compile time option. It will include the source file
879 and line into the memory allocation to allow the PMemoryHeap class to keep
880 track of the memory block.
881
882 This macro could be used instead of the system <code>new</code> operator. Or you can place
883 the line
884 <pre><code>
885 #define new PNEW
886 </code></pre>
887 at the begining of the source file, after all declarations that use the
888 <code>#PCLASSINFO</code> macro.
889 */
890 #define PNEW new (__FILE__, __LINE__)
891
892 #if !defined(_MSC_VER) || _MSC_VER<1200
893 #define PSPECIAL_DELETE_FUNCTION
894 #else
895 #define PSPECIAL_DELETE_FUNCTION \
896 void operator delete(void * ptr, const char *, int) \
897 { PMemoryHeap::Deallocate(ptr, Class()); } \
898 void operator delete[](void * ptr, const char *, int) \
899 { PMemoryHeap::Deallocate(ptr, Class()); }
900 #endif
901
902 #define PNEW_AND_DELETE_FUNCTIONS \
903 void * operator new(size_t nSize, const char * file, int line) \
904 { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
905 void * operator new(size_t nSize) \
906 { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
907 void operator delete(void * ptr) \
908 { PMemoryHeap::Deallocate(ptr, Class()); } \
909 void * operator new(size_t, void * placement) \
910 { return placement; } \
911 void operator delete(void *, void *) \
912 { } \
913 void * operator new[](size_t nSize, const char * file, int line) \
914 { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
915 void * operator new[](size_t nSize) \
916 { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
917 void operator delete[](void * ptr) \
918 { PMemoryHeap::Deallocate(ptr, Class()); } \
919 PSPECIAL_DELETE_FUNCTION
920
921
new(size_t nSize,const char * file,int line)922 inline void * operator new(size_t nSize, const char * file, int line)
923 { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
924
925 inline void * operator new[](size_t nSize, const char * file, int line)
926 { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
927
928 #ifndef __GNUC__
929 void * operator new(size_t nSize);
930 void * operator new[](size_t nSize);
931
932 void operator delete(void * ptr);
933 void operator delete[](void * ptr);
934
935 #if defined(_MSC_VER) && _MSC_VER>=1200
delete(void * ptr,const char *,int)936 inline void operator delete(void * ptr, const char *, int)
937 { PMemoryHeap::Deallocate(ptr, NULL); }
938
939 inline void operator delete[](void * ptr, const char *, int)
940 { PMemoryHeap::Deallocate(ptr, NULL); }
941 #endif
942 #endif
943
944
945 class PMemoryHeapIgnoreAllocationsForScope {
946 public:
PMemoryHeapIgnoreAllocationsForScope()947 PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(true)) { }
~PMemoryHeapIgnoreAllocationsForScope()948 ~PMemoryHeapIgnoreAllocationsForScope() { PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations); }
949 private:
950 PBoolean previousIgnoreAllocations;
951 };
952
953 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
954
955 class PMemoryAllocationBreakpoint {
956 public:
PMemoryAllocationBreakpoint(DWORD point)957 PMemoryAllocationBreakpoint(DWORD point)
958 {
959 PMemoryHeap::SetAllocationBreakpoint(point);
960 }
961 };
962
963 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
964
965
966 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
967
968 #define PMEMORY_HEAP 0
969
970 #define PNEW new
971
972 #define PNEW_AND_DELETE_FUNCTIONS
973
974 #define runtime_malloc(s) malloc(s)
975 #define runtime_free(p) free(p)
976
977 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
978 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
979
980 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
981
982
983
984 /*
985 * Implement "construct on first use" paradigm
986 */
987
988 template <class GnuAllocator, class Type>
989 struct PAllocatorTemplate
990 {
allocatePAllocatorTemplate991 Type * allocate(size_t v)
992 {
993 return GetAllocator().allocate(v);
994 }
995
deallocatePAllocatorTemplate996 void deallocate(Type * p, size_t v)
997 {
998 GetAllocator().deallocate(p, v);
999 }
1000
1001 private:
GetAllocatorPAllocatorTemplate1002 static GnuAllocator & GetAllocator()
1003 {
1004 static GnuAllocator instance;
1005 return instance;
1006 }
1007 };
1008
1009 #define GCC_VERSION (__GNUC__ * 10000 \
1010 + __GNUC_MINOR__ * 100 \
1011 + __GNUC_PATCHLEVEL__)
1012
1013 // Memory pooling allocators
1014 #if defined(__GNUC__) && (GCC_VERSION > 40000) && !defined(P_MINGW) && !defined(P_MACOSX) && !defined(_LIBCPP_VERSION)
1015 #include <ext/mt_allocator.h>
1016 template <class Type> struct PFixedPoolAllocator : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
1017 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
1018
1019 #else
1020
1021 template <class Type> struct PFixedPoolAllocator : public PAllocatorTemplate<std::allocator<Type>, Type> { };
1022 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<std::allocator<Type>, Type> { };
1023 #endif
1024
1025 #define PDECLARE_POOL_ALLOCATOR() \
1026 void * operator new(size_t nSize); \
1027 void * operator new(size_t nSize, const char * file, int line); \
1028 void operator delete(void * ptr); \
1029 void operator delete(void * ptr, const char *, int)
1030
1031 #define PDEFINE_POOL_ALLOCATOR(cls) \
1032 static PFixedPoolAllocator<cls> cls##_allocator; \
1033 void * cls::operator new(size_t) { return cls##_allocator.allocate(1); } \
1034 void * cls::operator new(size_t, const char *, int) { return cls##_allocator.allocate(1); } \
1035 void cls::operator delete(void * ptr) { cls##_allocator.deallocate((cls *)ptr, 1); } \
1036 void cls::operator delete(void * ptr, const char *, int) { cls##_allocator.deallocate((cls *)ptr, 1); }
1037
1038
1039 /** Declare all the standard PTLib class information.
1040 This macro is used to provide the basic run-time typing capability needed
1041 by the library. All descendent classes from the <code>PObject</code> class require
1042 these functions for correct operation. Either use this macro or the
1043 <code>#PDECLARE_CLASS</code> macro.
1044
1045 The use of the <code>#PDECLARE_CLASS</code> macro is no longer recommended for reasons
1046 of compatibility with documentation systems.
1047 */
1048
1049 #define PCLASSINFO(cls, par) \
1050 public: \
1051 typedef cls P_thisClass; \
1052 static inline const char * Class() \
1053 { return #cls; } \
1054 virtual PBoolean InternalIsDescendant(const char * clsName) const \
1055 { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
1056 virtual const char * GetClass(unsigned ancestor = 0) const \
1057 { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
1058 virtual PObject::Comparison CompareObjectMemoryDirect(const PObject & obj) const \
1059 { return PObject::InternalCompareObjectMemoryDirect(this, dynamic_cast<const cls *>(&obj), sizeof(cls)); } \
1060 PNEW_AND_DELETE_FUNCTIONS
1061
1062
1063 #if P_HAS_TYPEINFO
1064
1065 #define PIsDescendant(ptr, cls) (dynamic_cast<const cls *>(ptr) != NULL)
1066 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
1067
1068 #define PRemoveConst(cls, ptr) (const_cast<cls*>(ptr))
1069
1070 #if P_USE_ASSERTS
PAssertCast(BaseClass * obj,const char * file,int line)1071 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line)
1072 { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
1073 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
1074 #else
1075 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
1076 #endif
1077
1078 #include <typeinfo>
1079
1080 #else // P_HAS_TYPEINFO
1081
1082 #define PIsDescendant(ptr, cls) ((ptr)->InternalIsDescendant(cls::Class()))
1083 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
1084
1085 #define PRemoveConst(cls, ptr) ((cls*)(ptr))
1086
1087 #if P_USE_ASSERTS
PAssertCast(PObject * obj,const char * file,int line)1088 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line)
1089 { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
1090 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
1091 #else
1092 #define PDownCast(cls, ptr) ((cls*)(ptr))
1093 #endif
1094
1095 #endif // P_HAS_TYPEINFO
1096
1097
1098 /** Declare a class with PWLib class information.
1099 This macro is used to declare a new class with a single public ancestor. It
1100 starts the class declaration and then uses the <code>#PCLASSINFO</code> macro to
1101 get all the run-time type functions.
1102
1103 The use of this macro is no longer recommended for reasons of compatibility
1104 with documentation systems.
1105 */
1106 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
1107 #ifdef DOC_PLUS_PLUS
1108 } Match previous opening brace in doc++
1109 #endif
1110
1111 ///////////////////////////////////////////////////////////////////////////////
1112 // The root of all evil ... umm classes
1113
1114 /** Ultimate parent class for all objects in the class library.
1115 This provides functionality provided to all classes, eg run-time types,
1116 default comparison operations, simple stream I/O and serialisation support.
1117 */
1118 class PObject {
1119
1120 protected:
1121 /** Constructor for PObject, made protected so cannot ever create one on
1122 its own.
1123 */
1124 PObject() { }
1125
1126 public:
1127 /* Destructor required to get the "virtual". A PObject really has nothing
1128 to destroy.
1129 */
1130 virtual ~PObject() { }
1131
1132 /**@name Run Time Type functions */
1133 //@{
1134 /** Get the name of the class as a C string. This is a static function which
1135 returns the type of a specific class.
1136
1137 When comparing class names, always use the <code>strcmp()</code>
1138 function rather than comparing pointers. The pointers are not
1139 necessarily the same over compilation units depending on the compiler,
1140 platform etc.
1141
1142 @return pointer to C string literal.
1143 */
1144 static inline const char * Class() { return "PObject"; }
1145
1146 /** Get the current dynamic type of the object instance.
1147
1148 When comparing class names, always use the <code>strcmp()</code>
1149 function rather than comparing pointers. The pointers are not
1150 necessarily the same over compilation units depending on the compiler,
1151 platform etc.
1152
1153 The <code>#PCLASSINFO</code> macro declares an override of this function for
1154 the particular class. The user need not implement it.
1155
1156 @return pointer to C string literal.
1157 */
1158 virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : Class(); }
1159
1160 PBoolean IsClass(const char * cls) const
1161 { return strcmp(cls, GetClass()) == 0; }
1162
1163 /** Determine if the dynamic type of the current instance is a descendent of
1164 the specified class. The class name is usually provided by the
1165 <code>Class()</code> static function of the desired class.
1166
1167 The <code>#PCLASSINFO</code> macro declares an override of this function for
1168 the particular class. The user need not implement it.
1169
1170 @return true if object is descended from the class.
1171 */
1172 virtual PBoolean InternalIsDescendant(
1173 const char * clsName // Ancestor class name to compare against.
1174 ) const
1175 { return IsClass(clsName); }
1176
1177 //@}
1178
1179 /**@name Comparison functions */
1180 //@{
1181 /** Result of the comparison operation performed by the <code>Compare()</code>
1182 function.
1183 */
1184 enum Comparison {
1185 LessThan = -1,
1186 EqualTo = 0,
1187 GreaterThan = 1
1188 };
1189
1190 /** Compare the two objects and return their relative rank. This function is
1191 usually overridden by descendent classes to yield the ranking according
1192 to the semantics of the object.
1193
1194 The default function is to use the <code>CompareObjectMemoryDirect()</code>
1195 function to do a byte wise memory comparison of the two objects.
1196
1197 @return
1198 <code>LessThan</code>, <code>EqualTo</code> or <code>GreaterThan</code>
1199 according to the relative rank of the objects.
1200 */
1201 virtual Comparison Compare(
1202 const PObject & obj // Object to compare against.
1203 ) const;
1204
1205 /** Determine the byte wise comparison of two objects. This is the default
1206 comparison operation for objects that do not explicitly override the
1207 <code>Compare()</code> function.
1208
1209 The <code>#PCLASSINFO</code> macro declares an override of this function for
1210 the particular class. The user need not implement it.
1211
1212 @return
1213 <code>LessThan</code>, <code>EqualTo</code> or <code>GreaterThan</code>
1214 according to the result <code>memcpy()</code> function.
1215 */
1216 virtual Comparison CompareObjectMemoryDirect(
1217 const PObject & obj // Object to compare against.
1218 ) const;
1219
1220 /// Internal function caled from CompareObjectMemoryDirect()
1221 static Comparison InternalCompareObjectMemoryDirect(
1222 const PObject * obj1,
1223 const PObject * obj2,
1224 PINDEX size
1225 );
1226
1227 /** Compare the two objects.
1228
1229 @return
1230 true if objects are equal.
1231 */
1232 bool operator==(
1233 const PObject & obj // Object to compare against.
1234 ) const { return Compare(obj) == EqualTo; }
1235
1236 /** Compare the two objects.
1237
1238 @return
1239 true if objects are not equal.
1240 */
1241 bool operator!=(
1242 const PObject & obj // Object to compare against.
1243 ) const { return Compare(obj) != EqualTo; }
1244
1245 /** Compare the two objects.
1246
1247 @return
1248 true if objects are less than.
1249 */
1250 bool operator<(
1251 const PObject & obj // Object to compare against.
1252 ) const { return Compare(obj) == LessThan; }
1253
1254 /** Compare the two objects.
1255
1256 @return
1257 true if objects are greater than.
1258 */
1259 bool operator>(
1260 const PObject & obj // Object to compare against.
1261 ) const { return Compare(obj) == GreaterThan; }
1262
1263 /** Compare the two objects.
1264
1265 @return
1266 true if objects are less than or equal.
1267 */
1268 bool operator<=(
1269 const PObject & obj // Object to compare against.
1270 ) const { return Compare(obj) != GreaterThan; }
1271
1272 /** Compare the two objects.
1273
1274 @return
1275 true if objects are greater than or equal.
1276 */
1277 bool operator>=(
1278 const PObject & obj // Object to compare against.
1279 ) const { return Compare(obj) != LessThan; }
1280 //@}
1281
1282 /**@name I/O functions */
1283 //@{
1284 /** Output the contents of the object to the stream. The exact output is
1285 dependent on the exact semantics of the descendent class. This is
1286 primarily used by the standard <code>#operator<<</code> function.
1287
1288 The default behaviour is to print the class name.
1289 */
1290 virtual void PrintOn(
1291 ostream &strm // Stream to print the object into.
1292 ) const;
1293
1294 /** Input the contents of the object from the stream. The exact input is
1295 dependent on the exact semantics of the descendent class. This is
1296 primarily used by the standard <code>#operator>></code> function.
1297
1298 The default behaviour is to do nothing.
1299 */
1300 virtual void ReadFrom(
1301 istream &strm // Stream to read the objects contents from.
1302 );
1303
1304
1305 /** Global function for using the standard << operator on objects descended
1306 from PObject. This simply calls the objects <code>PrintOn()</code> function.
1307
1308 @return the \p strm parameter.
1309 */
1310 inline friend ostream & operator<<(
1311 ostream &strm, ///< Stream to print the object into.
1312 const PObject & obj ///< Object to print to the stream.
1313 ) { obj.PrintOn(strm); return strm; }
1314
1315 /** Global function for using the standard >> operator on objects descended
1316 from PObject. This simply calls the objects <code>ReadFrom()</code> function.
1317
1318 @return the \p strm parameter.
1319 */
1320 inline friend istream & operator>>(
1321 istream &strm, ///< Stream to read the objects contents from.
1322 PObject & obj ///< Object to read inormation into.
1323 ) { obj.ReadFrom(strm); return strm; }
1324
1325
1326 /**@name Miscellaneous functions */
1327 //@{
1328 /** Create a copy of the class on the heap. The exact semantics of the
1329 descendent class determine what is required to make a duplicate of the
1330 instance. Not all classes can even \b do a clone operation.
1331
1332 The main user of the clone function is the <code>PDictionary</code> class as
1333 it requires copies of the dictionary keys.
1334
1335 The default behaviour is for this function to assert.
1336
1337 @return
1338 pointer to new copy of the class instance.
1339 */
1340 virtual PObject * Clone() const;
1341
1342 /** This function yields a hash value required by the <code>PDictionary</code>
1343 class. A descendent class that is required to be the key of a dictionary
1344 should override this function. The precise values returned is dependent
1345 on the semantics of the class. For example, the <code>PString</code> class
1346 overrides it to provide a hash function for distinguishing text strings.
1347
1348 The default behaviour is to return the value zero.
1349
1350 @return
1351 hash function value for class instance.
1352 */
1353 virtual PINDEX HashFunction() const;
1354 //@}
1355 };
1356
1357 ///////////////////////////////////////////////////////////////////////////////
1358 // Platform independent types
1359
1360 // All these classes encapsulate primitive types such that they may be
1361 // transfered in a platform independent manner. In particular it is used to
1362 // do byte swapping for little endien and big endien processor architectures
1363 // as well as accommodating structure packing rules for memory structures.
1364
1365 #define PANSI_CHAR 1
1366 #define PLITTLE_ENDIAN 2
1367 #define PBIG_ENDIAN 3
1368
1369
1370 template <typename type>
1371 struct PIntSameOrder {
1372 __inline PIntSameOrder() : data(0) { }
1373 __inline PIntSameOrder(type value) : data(value) { }
1374 __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data) { }
1375 __inline PIntSameOrder & operator=(type value) { data = value; return *this; }
1376 __inline PIntSameOrder & operator=(const PIntSameOrder & value) { data = value.data; return *this; }
1377 __inline operator type() const { return data; }
1378 __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
1379 __inline friend istream & operator>>(istream & s, PIntSameOrder & v) { return s >> v.data; }
1380
1381 private:
1382 type data;
1383 };
1384
1385
1386 template <typename type>
1387 struct PIntReversedOrder {
1388 __inline PIntReversedOrder() : data(0) { }
1389 __inline PIntReversedOrder(type value) { ReverseBytes(value, data); }
1390 __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data) { }
1391 __inline PIntReversedOrder & operator=(type value) { ReverseBytes(value, data); return *this; }
1392 __inline PIntReversedOrder & operator=(const PIntReversedOrder & value) { data = value.data; return *this; }
1393 __inline operator type() const { type value; ReverseBytes(data, value); return value; }
1394 __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
1395 __inline friend istream & operator>>(istream & s, PIntReversedOrder & v) { type val; s >> val; v = val; return s; }
1396
1397 private:
1398 type data;
1399
1400 static __inline void ReverseBytes(const type & src, type & dst)
1401 {
1402 size_t s = sizeof(type)-1;
1403 for (size_t d = 0; d < sizeof(type); ++d,--s)
1404 ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
1405 }
1406 };
1407
1408 #ifndef PCHAR8
1409 #define PCHAR8 PANSI_CHAR
1410 #endif
1411
1412 #if PCHAR8==PANSI_CHAR
1413 typedef PIntSameOrder<char> PChar8;
1414 #endif
1415
1416 typedef PIntSameOrder<char> PInt8;
1417
1418 typedef PIntSameOrder<unsigned char> PUInt8;
1419
1420 #if PBYTE_ORDER==PLITTLE_ENDIAN
1421 typedef PIntSameOrder<PInt16> PInt16l;
1422 #elif PBYTE_ORDER==PBIG_ENDIAN
1423 typedef PIntReversedOrder<PInt16> PInt16l;
1424 #endif
1425
1426 #if PBYTE_ORDER==PLITTLE_ENDIAN
1427 typedef PIntReversedOrder<PInt16> PInt16b;
1428 #elif PBYTE_ORDER==PBIG_ENDIAN
1429 typedef PIntSameOrder<PInt16> PInt16b;
1430 #endif
1431
1432 #if PBYTE_ORDER==PLITTLE_ENDIAN
1433 typedef PIntSameOrder<WORD> PUInt16l;
1434 #elif PBYTE_ORDER==PBIG_ENDIAN
1435 typedef PIntReversedOrder<WORD> PUInt16l;
1436 #endif
1437
1438 #if PBYTE_ORDER==PLITTLE_ENDIAN
1439 typedef PIntReversedOrder<WORD> PUInt16b;
1440 #elif PBYTE_ORDER==PBIG_ENDIAN
1441 typedef PIntSameOrder<WORD> PUInt16b;
1442 #endif
1443
1444 #if PBYTE_ORDER==PLITTLE_ENDIAN
1445 typedef PIntSameOrder<PInt32> PInt32l;
1446 #elif PBYTE_ORDER==PBIG_ENDIAN
1447 typedef PIntReversedOrder<PInt32> PInt32l;
1448 #endif
1449
1450 #if PBYTE_ORDER==PLITTLE_ENDIAN
1451 typedef PIntReversedOrder<PInt32> PInt32b;
1452 #elif PBYTE_ORDER==PBIG_ENDIAN
1453 typedef PIntSameOrder<PInt32> PInt32b;
1454 #endif
1455
1456 #if PBYTE_ORDER==PLITTLE_ENDIAN
1457 typedef PIntSameOrder<DWORD> PUInt32l;
1458 #elif PBYTE_ORDER==PBIG_ENDIAN
1459 typedef PIntReversedOrder<DWORD> PUInt32l;
1460 #endif
1461
1462 #if PBYTE_ORDER==PLITTLE_ENDIAN
1463 typedef PIntReversedOrder<DWORD> PUInt32b;
1464 #elif PBYTE_ORDER==PBIG_ENDIAN
1465 typedef PIntSameOrder<DWORD> PUInt32b;
1466 #endif
1467
1468 #if PBYTE_ORDER==PLITTLE_ENDIAN
1469 typedef PIntSameOrder<PInt64> PInt64l;
1470 #elif PBYTE_ORDER==PBIG_ENDIAN
1471 typedef PIntReversedOrder<PInt64> PInt64l;
1472 #endif
1473
1474 #if PBYTE_ORDER==PLITTLE_ENDIAN
1475 typedef PIntReversedOrder<PInt64> PInt64b;
1476 #elif PBYTE_ORDER==PBIG_ENDIAN
1477 typedef PIntSameOrder<PInt64> PInt64b;
1478 #endif
1479
1480 #if PBYTE_ORDER==PLITTLE_ENDIAN
1481 typedef PIntSameOrder<PUInt64> PUInt64l;
1482 #elif PBYTE_ORDER==PBIG_ENDIAN
1483 typedef PIntReversedOrder<PUInt64> PUInt64l;
1484 #endif
1485
1486 #if PBYTE_ORDER==PLITTLE_ENDIAN
1487 typedef PIntReversedOrder<PUInt64> PUInt64b;
1488 #elif PBYTE_ORDER==PBIG_ENDIAN
1489 typedef PIntSameOrder<PUInt64> PUInt64b;
1490 #endif
1491
1492 #if PBYTE_ORDER==PLITTLE_ENDIAN
1493 typedef PIntSameOrder<float> PFloat32l;
1494 #elif PBYTE_ORDER==PBIG_ENDIAN
1495 typedef PIntReversedOrder<float> PFloat32l;
1496 #endif
1497
1498 #if PBYTE_ORDER==PLITTLE_ENDIAN
1499 typedef PIntReversedOrder<float> PFloat32b;
1500 #elif PBYTE_ORDER==PBIG_ENDIAN
1501 typedef PIntSameOrder<float> PFloat32b;
1502 #endif
1503
1504 #if PBYTE_ORDER==PLITTLE_ENDIAN
1505 typedef PIntSameOrder<double> PFloat64l;
1506 #elif PBYTE_ORDER==PBIG_ENDIAN
1507 typedef PIntReversedOrder<double> PFloat64l;
1508 #endif
1509
1510 #if PBYTE_ORDER==PLITTLE_ENDIAN
1511 typedef PIntReversedOrder<double> PFloat64b;
1512 #elif PBYTE_ORDER==PBIG_ENDIAN
1513 typedef PIntSameOrder<double> PFloat64b;
1514 #endif
1515
1516 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
1517 #if PBYTE_ORDER==PLITTLE_ENDIAN
1518 typedef PIntSameOrder<long double> PFloat80l;
1519 #elif PBYTE_ORDER==PBIG_ENDIAN
1520 typedef PIntReversedOrder<long double> PFloat80l;
1521 #endif
1522
1523 #if PBYTE_ORDER==PLITTLE_ENDIAN
1524 typedef PIntReversedOrder<long double> PFloat80b;
1525 #elif PBYTE_ORDER==PBIG_ENDIAN
1526 typedef PIntSameOrder<long double> PFloat80b;
1527 #endif
1528 #endif
1529
1530
1531 ///////////////////////////////////////////////////////////////////////////////
1532 // Miscellaneous
1533
1534 /*$MACRO PARRAYSIZE(array)
1535 This macro is used to calculate the number of array elements in a static
1536 array.
1537 */
1538 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
1539
1540 /*$MACRO PMIN(v1, v2)
1541 This macro is used to calculate the minimum of two values. As this is a
1542 macro the expression in <code>v1</code> or <code>v2</code> is executed
1543 twice so extreme care should be made in its use.
1544 */
1545 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
1546
1547 /*$MACRO PMAX(v1, v2)
1548 This macro is used to calculate the maximum of two values. As this is a
1549 macro the expression in <code>v1</code> or <code>v2</code> is executed
1550 twice so extreme care should be made in its use.
1551 */
1552 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
1553
1554 /*$MACRO PABS(val)
1555 This macro is used to calculate an absolute value. As this is a macro the
1556 expression in <code>val</code> is executed twice so extreme care should be
1557 made in its use.
1558 */
1559 #define PABS(v) ((v) < 0 ? -(v) : (v))
1560
1561
1562 #endif // PTLIB_OBJECT_H
1563
1564
1565 // End Of File ///////////////////////////////////////////////////////////////
1566