6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
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/
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
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.164 2004/07/19 13:55:00 csoutheren
31 * Fixed typo flagged as warning by gcc 3.5-20040704
33 * Revision 1.163 2004/07/11 07:56:36 csoutheren
34 * Applied jumbo VxWorks patch, thanks to Eize Slange
36 * Revision 1.162 2004/06/08 01:31:07 csoutheren
37 * Make the test sense correct for the init(NULL)
39 * Revision 1.161 2004/06/08 01:29:00 csoutheren
40 * Removed memory leak on VS.net caused by unobvious iostream allocation
42 * Revision 1.160 2004/05/28 23:59:23 csoutheren
43 * Added guards for negative offsets and lengths in various PString functions
45 * Revision 1.159 2004/05/13 14:52:32 csoutheren
46 * Allow PString::IsEmpty to return TRUE when theArray is NULL
48 * Revision 1.158 2004/05/04 11:10:37 rjongbloed
49 * Fixed usage of MakeEmpty() with PStringStream.
51 * Revision 1.157 2004/04/24 06:27:56 rjongbloed
52 * Fixed GCC 3.4.0 warnings about PAssertNULL and improved recoverability on
53 * NULL pointer usage in various bits of code.
55 * Revision 1.156 2004/04/18 04:33:37 rjongbloed
56 * Changed all operators that return BOOL to return standard type bool. This is primarily
57 * for improved compatibility with std STL usage removing many warnings.
59 * Revision 1.155 2004/04/15 03:50:35 csoutheren
60 * Fixed problem with MakeUnique
62 * Revision 1.154 2004/04/14 23:34:52 csoutheren
63 * Added plugin for data access
65 * Revision 1.153 2004/04/12 00:36:05 csoutheren
66 * Added new class PAtomicInteger and added Windows implementation
68 * Revision 1.152 2004/04/11 06:15:36 csoutheren
69 * Modified to use Atomic_word if available
71 * Revision 1.151 2004/04/11 02:55:18 csoutheren
72 * Added PCriticalSection for Windows
73 * Added compile time option for PContainer to use critical sections to provide thread safety under some circumstances
75 * Revision 1.150 2004/04/09 06:38:11 rjongbloed
76 * Fixed compatibility with STL based streams, eg as used by VC++2003
78 * Revision 1.149 2004/04/03 23:53:09 csoutheren
79 * Added various changes to improce compatibility with the Sun Forte compiler
80 * Thanks to Brian Cameron
81 * Added detection of readdir_r version
83 * Revision 1.148 2004/04/03 08:22:21 csoutheren
84 * Remove pseudo-RTTI and replaced with real RTTI
86 * Revision 1.147 2004/04/03 06:54:25 rjongbloed
87 * Many and various changes to support new Visual C++ 2003
89 * Revision 1.146 2004/03/20 04:20:34 rjongbloed
90 * Fixed some VxWorks port issues especially underrrun memory access in
91 * the PString::FindLast function,, thanks Eize Slange
93 * Revision 1.145 2004/02/23 00:44:38 csoutheren
94 * A completely different, other regex include hack to avoid requiring
95 * the sources when using a header-file only environment
97 * Revision 1.144 2004/02/23 00:26:05 csoutheren
98 * Finally, a generic and elegant fix for the regex include hacks. Thanks to Roger Hardiman
100 * Revision 1.143 2004/02/15 03:04:52 rjongbloed
101 * Fixed problem with PSortedList nil variable and assignment between instances,
102 * pointed out by Ben Lear.
104 * Revision 1.142 2004/02/11 05:09:14 csoutheren
105 * Fixed problems with regex libraries on Solaris, and with host OS numbering
106 * being a quoted string rather than a number. Thanks to Chad Attermann
107 * Fixed problems SSL detection problems thanks to Michal Zygmuntowicz
109 * Revision 1.141 2004/02/08 11:13:20 rjongbloed
110 * Fixed crash in heavily loaded multi-threaded systems using simultaneous sorted
111 * lists, Thanks Federico Pinna, Fabrizio Ammollo and the gang at Reitek S.p.A.
113 * Revision 1.140 2004/01/17 17:28:25 csoutheren
114 * Changed PString::Empty to be inline in header file
116 * Revision 1.139 2004/01/16 13:24:38 csoutheren
117 * Changed PString::Empty to be thread-safe
118 * Fixed PContainer::SetMinSize and PAbstractArray::SetSize, thanks to 123@call2ua.com
119 * Fixed PString::FindLast, thanks to Andreas Sikkema
121 * Revision 1.138 2003/12/14 01:12:00 csoutheren
122 * Added return value to PRegularExpression::operator = again (Doh!)
124 * Revision 1.137 2003/12/13 23:08:46 csoutheren
125 * Changed PRegularExpression to allow a copy constructor and operator =
127 * Revision 1.136 2003/12/04 13:12:41 csoutheren
128 * Fixed error in PRegularExpression that caused double delete when incorrect regular expression used
130 * Revision 1.135 2003/09/17 09:02:13 csoutheren
131 * Removed memory leak detection code
133 * Revision 1.134 2003/07/28 18:44:01 dsandras
134 * Make use of the libc regex on Linux.
136 * Revision 1.133 2003/05/14 00:48:33 rjongbloed
137 * Added constructor to string lists/arrays etc that takes a single PString.
138 * Fixed bug in doing a MakeUnique on a container, it would lose the
139 * DisallowDeleteObjects flag.
141 * Revision 1.132 2003/04/28 09:14:14 robertj
142 * Fixed bad sign extension problem in PBYTEArray output
144 * Revision 1.131 2003/04/15 07:08:37 robertj
145 * Changed read and write from streams for base array classes so operates in
146 * the same way for both PIntArray and PArray<int> etc
148 * Revision 1.130 2003/03/31 01:24:23 robertj
149 * Added ReadFrom functions for standard container classes such as
150 * PIntArray and PStringList etc
152 * Revision 1.129 2003/03/05 08:48:32 robertj
153 * Added PStringArray::ToCharAray() function at suggestion of Ravelli Rossano
155 * Revision 1.128 2003/02/02 23:29:34 robertj
156 * Fixed bug in RightTrim() (lost off last non blank char), tnanks Joerg Schoemer
158 * Revision 1.127 2002/12/16 08:10:35 robertj
159 * Fixed infinite loop when converting an illegal (incomplete) UTF-8 string
160 * to UCS-2, thanks Chih-Wei Huang
162 * Revision 1.126 2002/11/26 01:08:33 robertj
163 * Fixed problem when using pre-initialised PStringStream greater than 255
164 * bytes, would truncate and lose trailing null. Reported by Thien Nguyen
166 * Revision 1.125 2002/11/12 09:18:03 robertj
167 * Added PString::NumCompare() as functional equivalent of strncmp().
168 * Added PSortedStringList::GetNextStringsIndex() to do searches of binary
169 * tree on partal strings.
171 * Revision 1.124 2002/11/01 05:10:01 robertj
172 * Fixed bug in UTF-8 to UCS-2 conversion, not compiler portable!
174 * Revision 1.123 2002/10/31 07:33:59 robertj
175 * Changed UTF-8 to UCS-2 conversion function to not include trailing null.
177 * Revision 1.122 2002/10/31 05:55:55 robertj
178 * Now comprehensively stated that a PString is ALWAYS an 8 bit string as
179 * there are far too many inheerent assumptions every to make it 16 bit.
180 * Added UTF-8/UCS-2 conversion functions to PString.
182 * Revision 1.121 2002/10/10 04:43:44 robertj
183 * VxWorks port, thanks Martijn Roest
185 * Revision 1.120 2002/08/14 00:43:40 robertj
186 * Added ability to have fixed maximum length PStringStream's so does not do
187 * unwanted malloc()'s while outputing data.
189 * Revision 1.119 2002/08/06 08:51:36 robertj
190 * Added missing va_end, thanks Klaus Kaempf
192 * Revision 1.118 2002/06/27 06:59:34 robertj
193 * Removed memory leak display of static that is not really a leak.
195 * Revision 1.117 2002/06/25 02:24:24 robertj
196 * Improved assertion system to allow C++ class name to be displayed if
197 * desired, especially relevant to container classes.
199 * Revision 1.116 2002/06/24 06:18:36 robertj
200 * Fixed bug when getting extra space at start of outputing PBaseArray.
201 * Added ability to not include ASCII in PbaseArray output using ios::fixed.
203 * Revision 1.115 2002/06/19 04:04:30 robertj
204 * Fixed bug in setting/getting bits from PBitArray, could exceed array bounds.
206 * Revision 1.114 2002/06/17 09:16:18 robertj
207 * Fixed strange deadlock woth gcc 3.0.2, thanks Artis Kugevics
209 * Revision 1.113 2002/06/14 13:22:52 robertj
210 * Added PBitArray class.
212 * Revision 1.112 2002/06/05 12:29:15 craigs
213 * Changes for gcc 3.1
215 * Revision 1.111 2002/04/09 02:30:18 robertj
216 * Removed GCC3 variable as __GNUC__ can be used instead, thanks jason Spence
218 * Revision 1.110 2002/02/15 04:30:39 robertj
219 * Added PString::Empty() to return the primordial empty string. Saves on a
220 * couple of memory allocations for every empty string ever used.
221 * Changed every place where a const char * is used with PString so that a
222 * NULL pointer is treated like an empty string instead of asserting.
224 * Revision 1.109 2002/01/26 23:57:45 craigs
225 * Changed for GCC 3.0 compatibility, thanks to manty@manty.net
227 * Revision 1.108 2002/01/22 01:03:57 craigs
228 * Added operator += and operator + functions to PStringArray and PStringList
229 * Added AppendString operator to PStringArray
231 * Revision 1.107 2001/10/30 00:20:12 robertj
232 * Fixed broken signed number conversion from previous change.
234 * Revision 1.106 2001/10/18 00:35:08 robertj
235 * Fixed problem with Tokenise() includeing empty string at beginning when
236 * not in onePerSeparator mode and a separator starts the string.
238 * Revision 1.105 2001/10/17 05:09:22 robertj
239 * Added contructors and assigmnent operators so integer types can be
240 * automatically converted to strings.
242 * Revision 1.104 2001/08/11 15:01:44 rogerh
243 * Add Mac OS Carbon changes from John Woods <jfw@jfwhome.funhouse.com>
245 * Revision 1.103 2001/05/08 23:27:12 robertj
246 * Fixed, yet again, case significance in hash function.
248 * Revision 1.102 2001/04/26 03:45:19 robertj
249 * Changed PString has function again, use a prime number for modulus.
251 * Revision 1.101 2001/04/24 02:39:18 robertj
252 * Fixed problem with new string hash function giving negative indexes.
254 * Revision 1.100 2001/04/23 03:13:16 robertj
255 * Changed PString hash function to better one, thanks Patrick Koorevaar
257 * Revision 1.99 2001/04/18 04:10:15 robertj
258 * Removed hash function for caseless strings as confuses mixed dictionaries.
260 * Revision 1.98 2001/04/18 01:20:59 robertj
261 * Fixed problem with hash function for short strings, thanks Patrick Koorevaar.
262 * Also fixed hash function for caseless strings.
264 * Revision 1.97 2001/03/14 01:51:01 craigs
265 * Changed to handle CRLF at end of PString::ReadFrom as well as LF
267 * Revision 1.96 2001/02/26 07:50:18 robertj
268 * Updated regular expression parser to latest version from Henry Spencer.
270 * Revision 1.95 2001/02/21 03:38:37 robertj
271 * Added ability to copy between various string lists/arrays etc during construction.
273 * Revision 1.94 2001/02/14 22:21:08 robertj
274 * Fixed compiler error on some versions of GCC, thanks Klaus Kaempf.
276 * Revision 1.93 2001/02/14 06:50:01 robertj
277 * Fixed bug in doing ::flush on a PStringStream, did not set pointers correctly.
279 * Revision 1.92 2001/02/13 04:39:08 robertj
280 * Fixed problem with operator= in container classes. Some containers will
281 * break unless the copy is virtual (eg PStringStream's buffer pointers) so
282 * needed to add a new AssignContents() function to all containers.
284 * Revision 1.91 2000/12/29 07:36:57 craigs
285 * Fixed problem with Tokenise function returning NULL entries in array
287 * Revision 1.90 2000/10/12 05:14:41 robertj
288 * Fixed crash caused by previous change, didn;t work if in constructor.
290 * Revision 1.89 2000/10/09 23:43:58 robertj
291 * Fixed GNU C++ compatibility on last change.
293 * Revision 1.88 2000/10/09 23:37:17 robertj
294 * Improved PString sprintf functions so no longer limited to 1000 characters, thanks Yuriy Ershov.
296 * Revision 1.87 2000/06/26 11:17:20 robertj
297 * Nucleus++ port (incomplete).
299 * Revision 1.86 2000/04/07 06:29:46 rogerh
300 * Add a short term workaround for an Internal Compiler Error on MAC OS X when
301 * returning certain types of PString. Submitted by Kevin Packard.
303 * Revision 1.85 2000/02/05 22:36:09 craigs
304 * Fixed problem caused by last modification
306 * Revision 1.84 2000/02/04 19:34:26 craigs
307 * Fixed problem with changing size of referenced objects
309 * Revision 1.83 2000/01/25 14:05:35 robertj
310 * Added optimisation to array comparisons if referencing same array.
312 * Revision 1.82 1999/08/18 01:45:13 robertj
313 * Added concatenation function to "base type" arrays.
315 * Revision 1.81 1999/08/17 03:46:40 robertj
316 * Fixed usage of inlines in optimised version.
318 * Revision 1.80 1999/08/12 12:12:47 robertj
319 * GCC 2.95 compatibility.
321 * Revision 1.79 1999/05/28 14:01:53 robertj
322 * Added initialisers to string containers (list, sorted list and set).
324 * Revision 1.78 1999/04/18 09:36:31 robertj
325 * Get date grammar build.
327 * Revision 1.77 1999/04/16 14:38:37 craigs
328 * Changes to make getdate.y compile under Linux
330 * Revision 1.76 1998/10/28 00:58:40 robertj
331 * Changed PStringStream so flush or endl does not clear the string output, this now
332 * just sets the string to minimum size.
334 * Revision 1.75 1998/10/13 14:06:18 robertj
335 * Complete rewrite of memory leak detection code.
337 * Revision 1.74 1998/09/23 06:21:54 robertj
338 * Added open source copyright license.
340 * Revision 1.73 1998/09/22 02:42:39 robertj
341 * Fixed problem treating unsigned integer as signed in PString contructor.
343 * Revision 1.72 1998/09/15 08:26:42 robertj
344 * Fixed a number of warnings at maximum optimisation.
346 * Revision 1.71 1998/09/14 12:36:29 robertj
347 * Fixed bug causing memory leak due to uninitialised member variable for dynamic allocation of arrays.
349 * Revision 1.70 1998/08/21 05:24:07 robertj
350 * Added hex dump capability to base array types.
351 * Added ability to have base arrays of static memory blocks.
353 * Revision 1.69 1998/03/17 10:13:23 robertj
354 * Fixed bug in Trim() should do all white space not just the space character.
356 * Revision 1.68 1998/01/26 00:37:48 robertj
357 * Fixed PString & operator putting space in if right hand side is empty string, it shouldn't..
358 * Added Execute() functions to PRegularExpression that take PINDEX references instead of PIntArrays.
359 * Added FindRegEx function to PString that returns position and length.
361 * Revision 1.67 1997/12/11 13:32:49 robertj
362 * Added AsUnsigned() function to convert string to DWORD.
364 * Revision 1.66 1997/07/08 13:14:41 robertj
365 * Fixed bug where freeing null pointer.
367 * Revision 1.65 1997/06/08 04:48:04 robertj
368 * Added regular expressions.
370 * Revision 1.64 1997/03/02 03:41:42 robertj
371 * Fixed bug in not being able to construct a zero length PStringArray.
373 * Revision 1.63 1996/10/08 13:13:25 robertj
374 * Added operator += and &= for char so no implicit PString construction.
376 * Revision 1.62 1996/09/14 12:45:57 robertj
377 * Fixed bug in PString::Splice() function, no end of string put in.
379 * Revision 1.61 1996/08/22 13:21:55 robertj
380 * Fixed major bug in FindLast(), could scan all of memory in negative direction.
382 * Revision 1.60 1996/08/08 10:08:45 robertj
383 * Directory structure changes for common files.
385 * Revision 1.59 1996/05/26 03:46:27 robertj
386 * Compatibility to GNU 2.7.x
388 * Revision 1.58 1996/05/15 10:17:02 robertj
389 * Fixed idiotic bug in string compare, caseless version always matched.
391 * Revision 1.57 1996/05/09 12:17:10 robertj
392 * Fixed incorrect use of memcmp/strcmp return value.
393 * Added assertion when finding empty string.
395 * Revision 1.56 1996/04/14 02:52:39 robertj
396 * Fixed bug in PString::FindLast(), never found sub-strings.
398 * Revision 1.55 1996/03/31 08:58:49 robertj
399 * Fixed hash function for strings to work for caseless strings.
401 * Revision 1.54 1996/03/16 04:56:59 robertj
402 * Fixed bug in PStringStream assignment oeprator getting pointers wrong.
404 * Revision 1.53 1996/03/02 03:20:11 robertj
405 * Fixed bug in PString::Find() not finding substring if exactly same as string.
407 * Revision 1.52 1996/02/22 10:23:54 robertj
408 * Fixed buf in *= operator only comparing up to shortest string.
409 * Fixed bug in & operator for if left string is empty.
411 * Revision 1.51 1996/02/19 13:34:53 robertj
412 * Removed PCaselessString hash function to fix dictionary match failure.
413 * Fixed *= operator yet again.
415 * Revision 1.50 1996/02/08 12:20:44 robertj
416 * Added new operators to PString for case insensitive compare and spaced concatenate.
417 * Fixed bug in Find() not finding case insensitive substrings.
419 * Revision 1.49 1996/02/03 11:08:51 robertj
420 * Changed memcpy to memove to guarentee string operations will work correctly
421 * when moving overlapping strings around eg in PString::Splice().
423 * Revision 1.48 1996/01/28 14:12:22 robertj
424 * Fixed bug in Tokenise() for first token empty and PINDEX unsigned.
426 * Revision 1.47 1996/01/28 02:53:40 robertj
427 * Added assert into all Compare functions to assure comparison between compatible objects.
428 * Fixed bug in Find() function, subset sum calculation added one to many bytes.
430 * Revision 1.46 1996/01/24 14:43:19 robertj
431 * Added initialisers to string dictionaries.
433 * Revision 1.45 1996/01/23 13:17:38 robertj
434 * Added Replace() function to strings.
435 * String searching algorithm rewrite.
437 * Revision 1.44 1996/01/02 12:51:05 robertj
438 * Mac OS compatibility changes.
439 * Removed requirement that PArray elements have parameterless constructor..
441 * Revision 1.43 1995/10/14 15:07:42 robertj
442 * Changed arrays to not break references, but strings still need to.
444 * Revision 1.42 1995/06/17 00:46:20 robertj
445 * Added flag for PStringArray constructor to create caseless strings.
446 * Fixed bug in arrays when size set to zero.
448 * Revision 1.41 1995/06/04 12:39:59 robertj
449 * Made char * array all const in PStringArray constructor.
451 * Revision 1.40 1995/04/25 11:29:38 robertj
452 * Fixed Borland compiler warnings.
454 * Revision 1.39 1995/04/02 09:27:27 robertj
455 * Added "balloon" help.
457 * Revision 1.38 1995/03/12 04:46:02 robertj
458 * Fixed use of PCaselessString as dictionary key.
460 * Revision 1.37 1995/01/15 04:56:28 robertj
461 * Fixed PStringStream for correct pointer calculations in output.
463 * Revision 1.36 1995/01/10 11:44:13 robertj
464 * Removed PString parameter in stdarg function for GNU C++ compatibility.
466 * Revision 1.35 1995/01/09 12:32:56 robertj
467 * Removed unnecesary return value from I/O functions.
468 * Changed function names due to Mac port.
470 * Revision 1.34 1995/01/04 10:57:08 robertj
471 * Changed for HPUX and GNU2.6.x
473 * Revision 1.33 1995/01/03 09:39:08 robertj
474 * Put standard malloc style memory allocation etc into memory check system.
476 * Revision 1.32 1994/12/13 11:50:56 robertj
477 * Added MakeUnique() function to all container classes.
479 * Revision 1.31 1994/12/12 13:13:17 robertj
480 * Fixed bugs in PString mods just made.
482 * Revision 1.30 1994/12/12 10:16:27 robertj
483 * Restructuring and documentation of container classes.
484 * Renaming of some macros for declaring container classes.
485 * Added some extra functionality to PString.
486 * Added start to 2 byte characters in PString.
487 * Fixed incorrect overrides in PCaselessString.
489 * Revision 1.29 1994/12/05 11:19:36 robertj
490 * Moved SetMinSize from PAbstractArray to PContainer.
492 * Revision 1.28 1994/11/28 12:37:29 robertj
493 * Added dummy parameter to container classes.
495 * Revision 1.27 1994/10/30 11:50:44 robertj
496 * Split into Object classes and Container classes.
497 * Changed mechanism for doing notification callback functions.
499 * Revision 1.26 1994/10/23 03:43:07 robertj
500 * Changed PBaseArray so can have zero elements in it.
501 * Added Printf style constructor to PString.
503 * Revision 1.25 1994/09/25 10:49:44 robertj
504 * Added empty functions for serialisation.
506 * Revision 1.24 1994/08/21 23:43:02 robertj
507 * Added object serialisation classes.
508 * Changed parameter before variable argument list to NOT be a reference.
510 * Revision 1.23 1994/08/04 12:57:10 robertj
511 * Rewrite of memory check code.
513 * Revision 1.22 1994/08/01 03:40:28 robertj
514 * Fixed PString() constructor from integer
516 * Revision 1.21 1994/07/27 05:58:07 robertj
519 * Revision 1.20 1994/07/25 03:38:38 robertj
520 * Added more memory tests.
522 * Revision 1.19 1994/07/17 10:46:06 robertj
523 * Added number conversions to PString.
525 * Revision 1.18 1994/06/25 11:55:15 robertj
526 * Unix version synchronisation.
528 * Revision 1.17 1994/04/20 12:17:44 robertj
531 * Revision 1.16 1994/04/11 12:08:37 robertj
532 * Fixed bug in memory leak hash table hash function, cant have negative numbers.
534 * Revision 1.15 1994/04/03 08:34:18 robertj
535 * Added help and focus functionality.
537 * Revision 1.14 1994/04/01 14:01:11 robertj
540 * Revision 1.13 1994/03/07 07:47:00 robertj
543 * Revision 1.12 1994/01/15 03:14:22 robertj
544 * Mac portability problems.
546 * Revision 1.11 1994/01/03 04:42:23 robertj
547 * Mass changes to common container classes and interactors etc etc etc.
549 * Revision 1.10 1993/12/31 06:53:02 robertj
550 * Made inlines optional for debugging purposes.
552 * Revision 1.9 1993/12/24 04:20:52 robertj
555 * Revision 1.8 1993/12/16 00:51:46 robertj
556 * Made some container functions const.
558 * Revision 1.7 1993/12/15 21:10:10 robertj
559 * Fixed reference system used by container classes.
560 * Plugged memory leaks in PList and PSortedList.
562 * Revision 1.6 1993/12/14 18:44:56 robertj
563 * Added RemoveAll() function to collections.
564 * Fixed bug in list processing when being destroyed (removes the item being
565 * deleted from the list before deleting it).
566 * Changed GetIndex() so does not assert if entry not in collection.
568 * Revision 1.5 1993/12/04 05:22:38 robertj
569 * Added more string functions.
571 * Revision 1.4 1993/09/27 16:35:25 robertj
572 * Fixed bugs in sorted list.
573 * Fixed compatibility problem with sprintf return value (SVR4).
574 * Change function for making string array to a constructor.
576 * Revision 1.3 1993/08/27 18:17:47 robertj
577 * Fixed bugs in PAbstractSortedList (including some formatting).
579 * Revision 1.2 1993/08/21 01:50:33 robertj
580 * Made Clone() function optional, default will assert if called.
582 * Revision 1.8 1993/08/01 14:05:27 robertj
583 * Added const to ToLower() and ToUpper() in the PString class.
585 * Revision 1.7 1993/07/16 14:40:55 robertj
586 * Added PString constructor for individual characters.
587 * Added string to C style literal format.
589 * Revision 1.6 1993/07/15 05:02:57 robertj
590 * Removed redundant word in PString enum for string types.
592 * Revision 1.5 1993/07/15 04:29:39 robertj
593 * Added new constructor to convert from other string formats.
594 * Fixed sprintf variable parameter list bug.
596 * Revision 1.4 1993/07/14 12:41:52 robertj
597 * Fixed comment leader.
599 * Revision 1.3 1993/07/14 02:06:34 robertj
600 * Fixed header comment for RCS.
607 #ifdef __NUCLEUS_PLUS__
608 extern "C" int vsprintf(char *, const char *, va_list);
614 #include "regex/regex.h"
617 #define regexpression ((regex_t *)expression)
620 #include "ptlib/contain.inl"
625 #define __CLASS__ GetClass()
628 ///////////////////////////////////////////////////////////////////////////////
630 PContainer::PContainer(PINDEX initialSize
)
632 reference
= new Reference(initialSize
);
633 PAssert(reference
!= NULL
, POutOfMemory
);
636 PContainer::PContainer(int, const PContainer
* cont
)
638 PAssert(cont
!= NULL
, PInvalidParameter
);
639 PAssert2(cont
->reference
!= NULL
, cont
->GetClass(), "Clone of deleted container");
641 #if PCONTAINER_USES_CRITSEC
642 PEnterAndLeave
m(cont
->reference
->critSec
);
645 reference
= new Reference(*cont
->reference
); // create a new reference
646 PAssert(reference
!= NULL
, POutOfMemory
);
649 PContainer::PContainer(const PContainer
& cont
)
651 PAssert2(cont
.reference
!= NULL
, cont
.GetClass(), "Copy of deleted container");
653 #if PCONTAINER_USES_CRITSEC
654 PEnterAndLeave
m(cont
.reference
->critSec
);
657 ++cont
.reference
->count
;
658 reference
= cont
.reference
; // copy the reference pointer
662 void PContainer::AssignContents(const PContainer
& cont
)
664 #if PCONTAINER_USES_CRITSEC
665 // make sure the critsecs are entered and left in the right order to avoid deadlock
666 cont
.reference
->critSec
.Enter();
667 reference
->critSec
.Enter();
670 PAssert2(cont
.reference
!= NULL
, cont
.GetClass(), "Assign of deleted container");
672 if (reference
== cont
.reference
) {
673 #if PCONTAINER_USES_CRITSEC
674 reference
->critSec
.Leave();
675 cont
.reference
->critSec
.Leave();
683 #if PCONTAINER_USES_CRITSEC
684 reference
->critSec
.Leave();
687 #if PCONTAINER_USES_CRITSEC
688 reference
->critSec
.Leave();
695 ++cont
.reference
->count
;
696 reference
= cont
.reference
;
698 #if PCONTAINER_USES_CRITSEC
699 cont
.reference
->critSec
.Leave();
704 void PContainer::Destruct()
706 if (reference
!= NULL
) {
708 #if PCONTAINER_USES_CRITSEC
709 Reference
* ref
= reference
;
710 ref
->critSec
.Enter();
715 if (reference
->count
> 0) {
717 #if PCONTAINER_USES_CRITSEC
718 ref
->critSec
.Leave();
723 #if PCONTAINER_USES_CRITSEC
724 ref
->critSec
.Leave();
734 BOOL
PContainer::SetMinSize(PINDEX minSize
)
736 PASSERTINDEX(minSize
);
739 if (minSize
< GetSize())
741 return SetSize(minSize
);
745 BOOL
PContainer::MakeUnique()
747 #if PCONTAINER_USES_CRITSEC
748 PEnterAndLeave
m(reference
->critSec
);
754 Reference
* oldReference
= reference
;
755 reference
= new Reference(*reference
);
756 --oldReference
->count
;
762 ///////////////////////////////////////////////////////////////////////////////
764 PAbstractArray::PAbstractArray(PINDEX elementSizeInBytes
, PINDEX initialSize
)
765 : PContainer(initialSize
)
767 elementSize
= elementSizeInBytes
;
768 PAssert(elementSize
!= 0, PInvalidParameter
);
773 theArray
= (char *)calloc(GetSize(), elementSize
);
774 PAssert(theArray
!= NULL
, POutOfMemory
);
777 allocatedDynamically
= TRUE
;
781 PAbstractArray::PAbstractArray(PINDEX elementSizeInBytes
,
783 PINDEX bufferSizeInElements
,
784 BOOL dynamicAllocation
)
785 : PContainer(bufferSizeInElements
)
787 elementSize
= elementSizeInBytes
;
788 PAssert(elementSize
!= 0, PInvalidParameter
);
790 allocatedDynamically
= dynamicAllocation
;
794 else if (dynamicAllocation
) {
795 PINDEX sizebytes
= elementSize
*GetSize();
796 theArray
= (char *)malloc(sizebytes
);
797 PAssert(theArray
!= NULL
, POutOfMemory
);
798 memcpy(theArray
, PAssertNULL(buffer
), sizebytes
);
801 theArray
= (char *)buffer
;
805 void PAbstractArray::DestroyContents()
807 if (theArray
!= NULL
) {
808 if (allocatedDynamically
)
815 void PAbstractArray::CopyContents(const PAbstractArray
& array
)
817 elementSize
= array
.elementSize
;
818 theArray
= array
.theArray
;
819 allocatedDynamically
= array
.allocatedDynamically
;
823 void PAbstractArray::CloneContents(const PAbstractArray
* array
)
825 elementSize
= array
->elementSize
;
826 PINDEX sizebytes
= elementSize
*GetSize();
827 char * newArray
= (char *)malloc(sizebytes
);
828 if (newArray
== NULL
)
831 memcpy(newArray
, array
->theArray
, sizebytes
);
833 allocatedDynamically
= TRUE
;
837 void PAbstractArray::PrintOn(ostream
& strm
) const
839 char separator
= strm
.fill();
840 int width
= strm
.width();
841 for (PINDEX i
= 0; i
< GetSize(); i
++) {
842 if (i
> 0 && separator
!= '\0')
845 PrintElementOn(strm
, i
);
847 if (separator
== '\n')
852 void PAbstractArray::ReadFrom(istream
& strm
)
855 while (strm
.good()) {
856 ReadElementFrom(strm
, i
);
864 PObject::Comparison
PAbstractArray::Compare(const PObject
& obj
) const
866 PAssert(PIsDescendant(&obj
, PAbstractArray
), PInvalidCast
);
867 const PAbstractArray
& other
= (const PAbstractArray
&)obj
;
869 char * otherArray
= other
.theArray
;
870 if (theArray
== otherArray
)
873 if (elementSize
< other
.elementSize
)
876 if (elementSize
> other
.elementSize
)
879 PINDEX thisSize
= GetSize();
880 PINDEX otherSize
= other
.GetSize();
882 if (thisSize
< otherSize
)
885 if (thisSize
> otherSize
)
891 int retval
= memcmp(theArray
, otherArray
, elementSize
*thisSize
);
900 BOOL
PAbstractArray::SetSize(PINDEX newSize
)
905 PINDEX newsizebytes
= elementSize
*newSize
;
906 PINDEX oldsizebytes
= elementSize
*GetSize();
910 #if PCONTAINER_USES_CRITSEC
911 PEnterAndLeave
m(reference
->critSec
);
916 if (newsizebytes
== 0)
919 if ((newArray
= (char *)malloc(newsizebytes
)) == NULL
)
922 if (theArray
!= NULL
)
923 memcpy(newArray
, theArray
, PMIN(oldsizebytes
, newsizebytes
));
927 reference
= new Reference(newSize
);
931 if (newsizebytes
== oldsizebytes
)
934 if (theArray
!= NULL
) {
935 if (newsizebytes
== 0) {
936 if (allocatedDynamically
)
940 else if (allocatedDynamically
) {
941 if ((newArray
= (char *)realloc(theArray
, newsizebytes
)) == NULL
)
945 if ((newArray
= (char *)malloc(newsizebytes
)) == NULL
)
947 memcpy(newArray
, theArray
, PMIN(newsizebytes
, oldsizebytes
));
948 allocatedDynamically
= TRUE
;
951 else if (newsizebytes
!= 0) {
952 if ((newArray
= (char *)malloc(newsizebytes
)) == NULL
)
958 reference
->size
= newSize
;
961 if (newsizebytes
> oldsizebytes
)
962 memset(newArray
+oldsizebytes
, 0, newsizebytes
-oldsizebytes
);
969 void PAbstractArray::Attach(const void *buffer
, PINDEX bufferSize
)
971 if (allocatedDynamically
&& theArray
!= NULL
)
974 #if PCONTAINER_USES_CRITSEC
975 PEnterAndLeave
m(reference
->critSec
);
978 theArray
= (char *)buffer
;
979 reference
->size
= bufferSize
;
980 allocatedDynamically
= FALSE
;
984 void * PAbstractArray::GetPointer(PINDEX minSize
)
986 PAssert(SetMinSize(minSize
), POutOfMemory
);
991 BOOL
PAbstractArray::Concatenate(const PAbstractArray
& array
)
993 if (!allocatedDynamically
|| array
.elementSize
!= elementSize
)
996 PINDEX oldLen
= GetSize();
997 PINDEX addLen
= array
.GetSize();
999 if (!SetSize(oldLen
+ addLen
))
1002 memcpy(theArray
+oldLen
*elementSize
, array
.theArray
, addLen
*elementSize
);
1007 void PAbstractArray::PrintElementOn(ostream
& /*stream*/, PINDEX
/*index*/) const
1012 void PAbstractArray::ReadElementFrom(istream
& /*stream*/, PINDEX
/*index*/)
1017 ///////////////////////////////////////////////////////////////////////////////
1019 void PCharArray::PrintOn(ostream
& strm
) const
1021 PINDEX width
= strm
.width();
1022 if (width
> GetSize())
1027 BOOL left
= (strm
.flags()&ios::adjustfield
) == ios::left
;
1029 strm
.write(theArray
, GetSize());
1032 strm
<< (char)strm
.fill();
1035 strm
.write(theArray
, GetSize());
1039 void PCharArray::ReadFrom(istream
&strm
)
1044 while (strm
.good()) {
1045 strm
>> theArray
[size
++];
1046 if (size
>= GetSize())
1054 void PBYTEArray::PrintOn(ostream
& strm
) const
1056 PINDEX line_width
= strm
.width();
1057 if (line_width
== 0)
1061 PINDEX indent
= strm
.precision();
1063 PINDEX val_width
= ((strm
.flags()&ios::basefield
) == ios::hex
) ? 2 : 3;
1066 while (i
< GetSize()) {
1070 for (j
= 0; j
< indent
; j
++)
1072 for (j
= 0; j
< line_width
; j
++) {
1073 if (j
== line_width
/2)
1075 if (i
+j
< GetSize())
1076 strm
<< setw(val_width
) << (theArray
[i
+j
]&0xff);
1079 for (k
= 0; k
< val_width
; k
++)
1084 if ((strm
.flags()&ios::floatfield
) != ios::fixed
) {
1086 for (j
= 0; j
< line_width
; j
++) {
1087 if (i
+j
< GetSize()) {
1088 unsigned val
= theArray
[i
+j
]&0xff;
1101 void PBYTEArray::ReadFrom(istream
&strm
)
1106 while (strm
.good()) {
1109 theArray
[size
] = (BYTE
)v
;
1112 if (size
>= GetSize())
1121 ///////////////////////////////////////////////////////////////////////////////
1123 PBitArray::PBitArray(PINDEX initialSize
)
1124 : PBYTEArray((initialSize
+7)>>3)
1129 PBitArray::PBitArray(const void * buffer
,
1132 : PBYTEArray((const BYTE
*)buffer
, (length
+7)>>3, dynamic
)
1137 PObject
* PBitArray::Clone() const
1139 return new PBitArray(*this);
1143 PINDEX
PBitArray::GetSize() const
1145 return PBYTEArray::GetSize()<<3;
1149 BOOL
PBitArray::SetSize(PINDEX newSize
)
1151 return PBYTEArray::SetSize((newSize
+7)>>3);
1155 BOOL
PBitArray::SetAt(PINDEX index
, BOOL val
)
1157 if (!SetMinSize(index
+1))
1161 theArray
[index
>>3] |= (1 << (index
&7));
1163 theArray
[index
>>3] &= ~(1 << (index
&7));
1168 BOOL
PBitArray::GetAt(PINDEX index
) const
1170 PASSERTINDEX(index
);
1171 if (index
>= GetSize())
1174 return (theArray
[index
>>3]&(1 << (index
&7))) != 0;
1178 void PBitArray::Attach(const void * buffer
, PINDEX bufferSize
)
1180 PBYTEArray::Attach((const BYTE
*)buffer
, (bufferSize
+7)>>3);
1184 BYTE
* PBitArray::GetPointer(PINDEX minSize
)
1186 return PBYTEArray::GetPointer((minSize
+7)>>3);
1190 BOOL
PBitArray::Concatenate(const PBitArray
& array
)
1192 return PAbstractArray::Concatenate(array
);
1196 ///////////////////////////////////////////////////////////////////////////////
1198 PString::PString(const char * cstr
)
1199 : PCharArray(cstr
!= NULL
? strlen(cstr
)+1 : 1)
1202 memcpy(theArray
, cstr
, GetSize());
1206 PString::PString(const WORD
* ustr
)
1212 while (ustr
[len
] != 0)
1214 InternalFromUCS2(ustr
, len
);
1219 PString::PString(const char * cstr
, PINDEX len
)
1223 memcpy(theArray
, PAssertNULL(cstr
), len
);
1227 PString::PString(const WORD
* ustr
, PINDEX len
)
1230 InternalFromUCS2(ustr
, len
);
1234 PString::PString(const PWORDArray
& ustr
)
1236 InternalFromUCS2(ustr
, ustr
.GetSize());
1240 static int TranslateHex(char x
)
1243 return x
- 'a' + 10;
1246 return x
- 'A' + '\x0a';
1252 static const char PStringEscapeCode
[] = { 'a', 'b', 'f', 'n', 'r', 't', 'v' };
1253 static const char PStringEscapeValue
[] = { '\a', '\b', '\f', '\n', '\r', '\t', '\v' };
1255 static void TranslateEscapes(const char * src
, char * dst
)
1260 while (*src
!= '\0') {
1262 if (c
== '"' && *src
== '\0')
1263 c
= '\0'; // Trailing '"' is ignored
1264 else if (c
== '\\') {
1266 for (PINDEX i
= 0; i
< PARRAYSIZE(PStringEscapeCode
); i
++) {
1267 if (c
== PStringEscapeCode
[i
])
1268 c
= PStringEscapeValue
[i
];
1271 if (c
== 'x' && isxdigit(*src
)) {
1272 c
= TranslateHex(*src
++);
1274 c
= (c
<< 4) + TranslateHex(*src
++);
1276 else if (c
>= '0' && c
<= '7') {
1277 int count
= c
<= '3' ? 3 : 2;
1281 c
= (c
<< 3) + *src
++ - '0';
1282 } while (--count
> 0 && *src
>= '0' && *src
<= '7');
1291 PString::PString(ConversionType type
, const char * str
, ...)
1296 PINDEX len
= *str
& 0xff;
1297 PAssert(SetSize(len
+1), POutOfMemory
);
1298 memcpy(theArray
, str
+1, len
);
1303 if (str
[0] != '\0' && str
[1] != '\0') {
1304 PINDEX len
= str
[0] | (str
[1] << 8);
1305 PAssert(SetSize(len
+1), POutOfMemory
);
1306 memcpy(theArray
, str
+2, len
);
1311 PAssert(SetSize(strlen(str
)+1), POutOfMemory
);
1312 TranslateEscapes(str
, theArray
);
1313 PAssert(MakeMinimumSize(), POutOfMemory
);
1318 va_start(args
, str
);
1319 vsprintf(str
, args
);
1325 PAssertAlways(PInvalidParameter
);
1330 template <class T
> char * p_unsigned2string(T value
, T base
, char * str
)
1333 str
= p_unsigned2string
<T
>(value
/base
, base
, str
);
1336 *str
= (char)(value
+ '0');
1338 *str
= (char)(value
+ 'A'-10);
1343 template <class T
> char * p_signed2string(T value
, T base
, char * str
)
1346 return p_unsigned2string
<T
>(value
, base
, str
);
1349 return p_unsigned2string
<T
>(-value
, base
, str
+1);
1353 PString::PString(short n
)
1354 : PCharArray(sizeof(short)*3+1)
1356 p_signed2string
<int>(n
, 10, theArray
);
1361 PString::PString(unsigned short n
)
1362 : PCharArray(sizeof(unsigned short)*3+1)
1364 p_unsigned2string
<unsigned int>(n
, 10, theArray
);
1369 PString::PString(int n
)
1370 : PCharArray(sizeof(int)*3+1)
1372 p_signed2string
<int>(n
, 10, theArray
);
1377 PString::PString(unsigned int n
)
1378 : PCharArray(sizeof(unsigned int)*3+1)
1380 p_unsigned2string
<unsigned int>(n
, 10, theArray
);
1385 PString::PString(long n
)
1386 : PCharArray(sizeof(long)*3+1)
1388 p_signed2string
<long>(n
, 10, theArray
);
1393 PString::PString(unsigned long n
)
1394 : PCharArray(sizeof(unsigned long)*3+1)
1396 p_unsigned2string
<unsigned long>(n
, 10, theArray
);
1401 PString::PString(PInt64 n
)
1402 : PCharArray(sizeof(PInt64
)*3+1)
1404 p_signed2string
<PInt64
>(n
, 10, theArray
);
1409 PString::PString(PUInt64 n
)
1410 : PCharArray(sizeof(PUInt64
)*3+1)
1412 p_unsigned2string
<PUInt64
>(n
, 10, theArray
);
1417 PString::PString(ConversionType type
, long value
, unsigned base
)
1418 : PCharArray(sizeof(long)*3+1)
1420 PAssert(base
>= 2 && base
<= 36, PInvalidParameter
);
1423 p_signed2string
<long>(value
, base
, theArray
);
1427 p_unsigned2string
<unsigned long>(value
, base
, theArray
);
1431 PAssertAlways(PInvalidParameter
);
1437 PString::PString(ConversionType type
, double value
, unsigned places
)
1441 sprintf("%0.*f", (int)places
, value
);
1445 sprintf("%0.*e", (int)places
, value
);
1449 PAssertAlways(PInvalidParameter
);
1454 PString
& PString::operator=(short n
)
1456 SetMinSize(sizeof(short)*3+1);
1457 p_signed2string
<int>(n
, 10, theArray
);
1463 PString
& PString::operator=(unsigned short n
)
1465 SetMinSize(sizeof(unsigned short)*3+1);
1466 p_unsigned2string
<unsigned int>(n
, 10, theArray
);
1472 PString
& PString::operator=(int n
)
1474 SetMinSize(sizeof(int)*3+1);
1475 p_signed2string
<int>(n
, 10, theArray
);
1481 PString
& PString::operator=(unsigned int n
)
1483 SetMinSize(sizeof(unsigned int)*3+1);
1484 p_unsigned2string
<unsigned int>(n
, 10, theArray
);
1490 PString
& PString::operator=(long n
)
1492 SetMinSize(sizeof(long)*3+1);
1493 p_signed2string
<long>(n
, 10, theArray
);
1499 PString
& PString::operator=(unsigned long n
)
1501 SetMinSize(sizeof(unsigned long)*3+1);
1502 p_unsigned2string
<unsigned long>(n
, 10, theArray
);
1508 PString
& PString::operator=(PInt64 n
)
1510 SetMinSize(sizeof(PInt64
)*3+1);
1511 p_signed2string
<PInt64
>(n
, 10, theArray
);
1517 PString
& PString::operator=(PUInt64 n
)
1519 SetMinSize(sizeof(PUInt64
)*3+1);
1520 p_unsigned2string
<PUInt64
>(n
, 10, theArray
);
1526 PString
& PString::MakeEmpty()
1534 PObject
* PString::Clone() const
1536 return new PString(*this);
1540 void PString::PrintOn(ostream
&strm
) const
1546 void PString::ReadFrom(istream
&strm
)
1549 char * ptr
= theArray
;
1552 while ((c
= strm
.get()) != EOF
&& c
!= '\n') {
1555 if (len
>= GetSize()) {
1557 ptr
= theArray
+ len
;
1561 if ((len
> 0) && (ptr
[-1] == '\r'))
1563 PAssert(MakeMinimumSize(), POutOfMemory
);
1567 PObject::Comparison
PString::Compare(const PObject
& obj
) const
1569 PAssert(PIsDescendant(&obj
, PString
), PInvalidCast
);
1570 return InternalCompare(0, P_MAX_INDEX
, ((const PString
&)obj
).theArray
);
1574 PINDEX
PString::HashFunction() const
1576 // Hash function from "Data Structures and Algorithm Analysis in C++" by
1577 // Mark Allen Weiss, with limit of only executing over first 8 characters to
1578 // increase speed when dealing with large strings.
1581 for (PINDEX i
= 0; i
< 8 && theArray
[i
] != 0; i
++)
1582 hash
= (hash
<< 5) ^ tolower(theArray
[i
]) ^ hash
;
1583 return PABSINDEX(hash
)%127;
1587 BOOL
PString::IsEmpty() const
1589 return (theArray
== NULL
) || (*theArray
== '\0');
1593 BOOL
PString::SetSize(PINDEX newSize
)
1595 return PAbstractArray::SetSize(newSize
);
1598 return PAbstractArray::SetSize(newSize
);
1600 PINDEX newsizebytes
= elementSize
*newSize
;
1601 PINDEX oldsizebytes
= elementSize
*GetSize();
1604 if (newsizebytes
== 0)
1607 if ((newArray
= (char *)malloc(newsizebytes
)) == NULL
)
1610 if (theArray
!= NULL
)
1611 memcpy(newArray
, theArray
, PMIN(oldsizebytes
, newsizebytes
));
1615 reference
= new Reference(newSize
);
1617 if (newsizebytes
> oldsizebytes
)
1618 memset(newArray
+oldsizebytes
, 0, newsizebytes
-oldsizebytes
);
1620 theArray
= newArray
;
1626 BOOL
PString::MakeUnique()
1628 #if PCONTAINER_USES_CRITSEC
1629 PEnterAndLeave
m(reference
->critSec
);
1640 PString
PString::operator+(const char * cstr
) const
1645 PINDEX olen
= GetLength();
1646 PINDEX alen
= strlen(cstr
)+1;
1648 str
.SetSize(olen
+alen
);
1649 memmove(str
.theArray
, theArray
, olen
);
1650 memcpy(str
.theArray
+olen
, cstr
, alen
);
1655 PString
PString::operator+(char c
) const
1657 PINDEX olen
= GetLength();
1659 str
.SetSize(olen
+2);
1660 memmove(str
.theArray
, theArray
, olen
);
1661 str
.theArray
[olen
] = c
;
1666 PString
& PString::operator+=(const char * cstr
)
1671 PINDEX olen
= GetLength();
1672 PINDEX alen
= strlen(cstr
)+1;
1674 memcpy(theArray
+olen
, cstr
, alen
);
1679 PString
& PString::operator+=(char ch
)
1681 PINDEX olen
= GetLength();
1683 theArray
[olen
] = ch
;
1688 PString
PString::operator&(const char * cstr
) const
1693 PINDEX alen
= strlen(cstr
)+1;
1697 PINDEX olen
= GetLength();
1699 PINDEX space
= olen
> 0 && theArray
[olen
-1]!=' ' && *cstr
!=' ' ? 1 : 0;
1700 str
.SetSize(olen
+alen
+space
);
1701 memmove(str
.theArray
, theArray
, olen
);
1703 str
.theArray
[olen
] = ' ';
1704 memcpy(str
.theArray
+olen
+space
, cstr
, alen
);
1709 PString
PString::operator&(char c
) const
1711 PINDEX olen
= GetLength();
1713 PINDEX space
= olen
> 0 && theArray
[olen
-1] != ' ' && c
!= ' ' ? 1 : 0;
1714 str
.SetSize(olen
+2+space
);
1715 memmove(str
.theArray
, theArray
, olen
);
1717 str
.theArray
[olen
] = ' ';
1718 str
.theArray
[olen
+space
] = c
;
1723 PString
& PString::operator&=(const char * cstr
)
1728 PINDEX alen
= strlen(cstr
)+1;
1731 PINDEX olen
= GetLength();
1732 PINDEX space
= olen
> 0 && theArray
[olen
-1]!=' ' && *cstr
!=' ' ? 1 : 0;
1733 SetSize(olen
+alen
+space
);
1735 theArray
[olen
] = ' ';
1736 memcpy(theArray
+olen
+space
, cstr
, alen
);
1741 PString
& PString::operator&=(char ch
)
1743 PINDEX olen
= GetLength();
1744 PINDEX space
= olen
> 0 && theArray
[olen
-1] != ' ' && ch
!= ' ' ? 1 : 0;
1745 SetSize(olen
+2+space
);
1747 theArray
[olen
] = ' ';
1748 theArray
[olen
+space
] = ch
;
1753 void PString::Delete(PINDEX start
, PINDEX len
)
1755 if (start
< 0 || len
< 0)
1760 register PINDEX slen
= GetLength();
1764 if (len
> slen
- start
)
1767 memmove(theArray
+start
, theArray
+start
+len
, slen
-start
-len
+1);
1772 PString
PString::operator()(PINDEX start
, PINDEX end
) const
1774 if (end
< 0 || start
< 0 || end
< start
)
1777 register PINDEX len
= GetLength();
1786 len
= end
- start
+ 1;
1788 return PString(theArray
+start
, len
);
1792 PString
PString::Left(PINDEX len
) const
1797 if (len
>= GetLength())
1800 return PString(theArray
, len
);
1804 PString
PString::Right(PINDEX len
) const
1809 PINDEX srclen
= GetLength();
1813 return PString(theArray
+srclen
-len
, len
);
1817 PString
PString::Mid(PINDEX start
, PINDEX len
) const
1819 if (len
<= 0 || start
< 0)
1822 if (start
+len
< start
) // Beware of wraparound
1823 return operator()(start
, P_MAX_INDEX
);
1825 return operator()(start
, start
+len
-1);
1829 bool PString::operator*=(const char * cstr
) const
1832 return IsEmpty() != FALSE
;
1834 const char * pstr
= theArray
;
1835 while (*pstr
!= '\0' && *cstr
!= '\0') {
1836 if (toupper(*pstr
) != toupper(*cstr
))
1841 return *pstr
== *cstr
;
1845 PObject::Comparison
PString::NumCompare(const PString
& str
, PINDEX count
, PINDEX offset
) const
1847 if (offset
< 0 || count
< 0)
1849 PINDEX len
= str
.GetLength();
1852 return InternalCompare(offset
, count
, str
);
1856 PObject::Comparison
PString::NumCompare(const char * cstr
, PINDEX count
, PINDEX offset
) const
1858 if (offset
< 0 || count
< 0)
1860 PINDEX len
= ::strlen(cstr
);
1863 return InternalCompare(offset
, count
, cstr
);
1867 PObject::Comparison
PString::InternalCompare(PINDEX offset
, char c
) const
1871 char ch
= theArray
[offset
];
1880 PObject::Comparison
PString::InternalCompare(
1881 PINDEX offset
, PINDEX length
, const char * cstr
) const
1883 if (offset
< 0 || length
< 0)
1886 if (offset
== 0 && theArray
== cstr
)
1889 if (offset
< 0 || cstr
== NULL
)
1890 return IsEmpty() ? EqualTo
: LessThan
;
1893 if (length
== P_MAX_INDEX
)
1894 retval
= strcmp(theArray
+offset
, cstr
);
1896 retval
= strncmp(theArray
+offset
, cstr
, length
);
1908 PINDEX
PString::Find(char ch
, PINDEX offset
) const
1913 register PINDEX len
= GetLength();
1914 while (offset
< len
) {
1915 if (InternalCompare(offset
, ch
) == EqualTo
)
1923 PINDEX
PString::Find(const char * cstr
, PINDEX offset
) const
1925 if (cstr
== NULL
|| *cstr
== '\0' || offset
< 0)
1928 PINDEX len
= GetLength();
1929 PINDEX clen
= strlen(cstr
);
1933 if (offset
> len
- clen
)
1936 if (len
- clen
< 10) {
1937 while (offset
+clen
<= len
) {
1938 if (InternalCompare(offset
, clen
, cstr
) == EqualTo
)
1947 for (PINDEX i
= 0; i
< clen
; i
++) {
1948 strSum
+= toupper(theArray
[offset
+i
]);
1949 cstrSum
+= toupper(cstr
[i
]);
1952 // search for a matching substring
1953 while (offset
+clen
<= len
) {
1954 if (strSum
== cstrSum
&& InternalCompare(offset
, clen
, cstr
) == EqualTo
)
1956 strSum
+= toupper(theArray
[offset
+clen
]);
1957 strSum
-= toupper(theArray
[offset
]);
1965 PINDEX
PString::FindLast(char ch
, PINDEX offset
) const
1967 PINDEX len
= GetLength();
1968 if (len
== 0 || offset
< 0)
1973 while (InternalCompare(offset
, ch
) != EqualTo
) {
1983 PINDEX
PString::FindLast(const char * cstr
, PINDEX offset
) const
1985 if (cstr
== NULL
|| *cstr
== '\0' || offset
< 0)
1988 PINDEX len
= GetLength();
1989 PINDEX clen
= strlen(cstr
);
1993 if (offset
> len
- clen
)
1994 offset
= len
- clen
;
1998 for (PINDEX i
= 0; i
< clen
; i
++) {
1999 strSum
+= toupper(theArray
[offset
+i
]);
2000 cstrSum
+= toupper(cstr
[i
]);
2003 // search for a matching substring
2004 while (strSum
!= cstrSum
|| InternalCompare(offset
, clen
, cstr
) != EqualTo
) {
2008 strSum
+= toupper(theArray
[offset
]);
2009 strSum
-= toupper(theArray
[offset
+clen
]);
2016 PINDEX
PString::FindOneOf(const char * cset
, PINDEX offset
) const
2018 if (cset
== NULL
|| *cset
== '\0' || offset
< 0)
2021 PINDEX len
= GetLength();
2022 while (offset
< len
) {
2023 const char * p
= cset
;
2024 while (*p
!= '\0') {
2025 if (InternalCompare(offset
, *p
) == EqualTo
)
2035 PINDEX
PString::FindRegEx(const PRegularExpression
& regex
, PINDEX offset
) const
2042 if (FindRegEx(regex
, pos
, len
, offset
))
2049 BOOL
PString::FindRegEx(const PRegularExpression
& regex
,
2053 PINDEX maxPos
) const
2055 if (offset
< 0 || maxPos
< 0 || offset
>= GetLength())
2058 if (!regex
.Execute(&theArray
[offset
], pos
, len
, 0))
2062 if (pos
+len
> maxPos
)
2069 void PString::Replace(const PString
& target
,
2070 const PString
& subs
,
2071 BOOL all
, PINDEX offset
)
2078 PINDEX tlen
= target
.GetLength();
2079 PINDEX slen
= subs
.GetLength();
2081 PINDEX pos
= Find(target
, offset
);
2082 if (pos
== P_MAX_INDEX
)
2084 Splice(subs
, pos
, tlen
);
2085 offset
= pos
+ slen
;
2090 void PString::Splice(const char * cstr
, PINDEX pos
, PINDEX len
)
2092 if (len
< 0 || pos
< 0)
2095 register PINDEX slen
= GetLength();
2100 PINDEX clen
= cstr
!= NULL
? strlen(cstr
) : 0;
2101 PINDEX newlen
= slen
-len
+clen
;
2105 memmove(theArray
+pos
+clen
, theArray
+pos
+len
, slen
-pos
-len
+1);
2107 memcpy(theArray
+pos
, cstr
, clen
);
2108 theArray
[newlen
] = '\0';
2114 PString::Tokenise(const char * separators
, BOOL onePerSeparator
) const
2116 PStringArray tokens
;
2118 if (separators
== NULL
|| IsEmpty()) // No tokens
2123 PINDEX p2
= FindOneOf(separators
);
2126 if (onePerSeparator
) { // first character is a token separator
2127 tokens
[token
] = Empty();
2128 token
++; // make first string in array empty
2130 p2
= FindOneOf(separators
, 1);
2135 } while ((p2
= FindOneOf(separators
, p1
)) == p1
);
2139 while (p2
!= P_MAX_INDEX
) {
2141 tokens
[token
] = operator()(p1
, p2
-1);
2143 tokens
[token
] = Empty();
2146 // Get next separator. If not one token per separator then continue
2147 // around loop to skip over all the consecutive separators.
2150 } while ((p2
= FindOneOf(separators
, p1
)) == p1
&& !onePerSeparator
);
2153 tokens
[token
] = operator()(p1
, P_MAX_INDEX
);
2159 PStringArray
PString::Lines() const
2169 while ((p2
= FindOneOf("\r\n", p1
)) != P_MAX_INDEX
) {
2170 lines
[line
++] = operator()(p1
, p2
-1);
2172 if (theArray
[p2
] == '\r' && theArray
[p1
] == '\n') // CR LF pair
2175 if (p1
< GetLength())
2176 lines
[line
] = operator()(p1
, P_MAX_INDEX
);
2180 PStringArray
& PStringArray::operator += (const PStringArray
& v
)
2183 for (i
= 0; i
< v
.GetSize(); i
++)
2189 PString
PString::LeftTrim() const
2191 const char * lpos
= theArray
;
2192 while (isspace(*lpos
))
2194 return PString(lpos
);
2198 PString
PString::RightTrim() const
2200 char * rpos
= theArray
+GetLength()-1;
2204 while (isspace(*rpos
)) {
2205 if (rpos
== theArray
)
2210 // make Apple & Tornado gnu compiler happy
2211 PString
retval(theArray
, rpos
- theArray
+ 1);
2216 PString
PString::Trim() const
2218 const char * lpos
= theArray
;
2219 while (isspace(*lpos
))
2224 const char * rpos
= theArray
+GetLength()-1;
2225 if (!isspace(*rpos
))
2226 return PString(lpos
);
2228 while (isspace(*rpos
))
2230 return PString(lpos
, rpos
- lpos
+ 1);
2234 PString
PString::ToLower() const
2236 PString
newStr(theArray
);
2237 for (char *cpos
= newStr
.theArray
; *cpos
!= '\0'; cpos
++) {
2239 *cpos
= (char)tolower(*cpos
);
2245 PString
PString::ToUpper() const
2247 PString
newStr(theArray
);
2248 for (char *cpos
= newStr
.theArray
; *cpos
!= '\0'; cpos
++) {
2250 *cpos
= (char)toupper(*cpos
);
2256 long PString::AsInteger(unsigned base
) const
2258 PAssert(base
>= 2 && base
<= 36, PInvalidParameter
);
2260 return strtol(theArray
, &dummy
, base
);
2264 DWORD
PString::AsUnsigned(unsigned base
) const
2266 PAssert(base
>= 2 && base
<= 36, PInvalidParameter
);
2268 return strtoul(theArray
, &dummy
, base
);
2272 double PString::AsReal() const
2274 #ifndef __HAS_NO_FLOAT
2276 return strtod(theArray
, &dummy
);
2283 PWORDArray
PString::AsUCS2() const
2285 #ifdef P_HAS_G_CONVERT
2288 gchar
* g_ucs2
= g_convert(theArray
, GetSize()-1, "UCS-2", "UTF-8", 0, &g_len
, 0);
2290 return PWORDArray();
2292 PWORDArray
ucs2((const WORD
*)g_ucs2
, (PINDEX
)g_len
);
2298 PWORDArray
ucs2(GetSize()); // Always bigger than required
2302 PINDEX length
= GetSize()-1;
2303 while (i
< length
) {
2304 int c
= theArray
[i
];
2306 ucs2
[count
++] = (BYTE
)theArray
[i
++];
2307 else if ((c
&0xe0) == 0xc0) {
2309 ucs2
[count
++] = (WORD
)(((theArray
[i
]&0x1f)<<6)|
2310 (theArray
[i
+1]&0x3f));
2313 else if ((c
&0xf0) == 0xe0) {
2315 ucs2
[count
++] = (WORD
)(((theArray
[i
]&0x0f)<<12)|
2316 ((theArray
[i
+1]&0x3f)<< 6)|
2317 (theArray
[i
+2]&0x3f));
2321 if ((c
&0xf8) == 0xf0)
2323 else if ((c
&0xfc) == 0xf8)
2328 ucs2
[count
++] = 0xffff;
2332 ucs2
.SetSize(count
);
2339 void PString::InternalFromUCS2(const WORD
* ptr
, PINDEX len
)
2341 if (ptr
== NULL
|| len
<= 0) {
2346 #ifdef P_HAS_G_CONVERT
2349 gchar
* g_utf8
= g_convert(ptr
, len
, "UTF-8", "UCS-2", 0, &g_len
, 0);
2350 if (g_utf8
== NULL
) {
2356 memcpy(theArray
, g_char
, g_len
);
2363 for (i
= 0; i
< len
; i
++) {
2366 else if (ptr
[i
] < 0x800)
2374 for (i
= 0; i
< len
; i
++) {
2375 unsigned v
= *ptr
++;
2377 theArray
[count
++] = (char)v
;
2378 else if (v
< 0x800) {
2379 theArray
[count
++] = (char)(0xc0+(v
>>6));
2380 theArray
[count
++] = (char)(0x80+(v
&0x3f));
2383 theArray
[count
++] = (char)(0xd0+(v
>>12));
2384 theArray
[count
++] = (char)(0x80+((v
>>6)&0x3f));
2385 theArray
[count
++] = (char)(0x80+(v
&0x3f));
2393 PBYTEArray
PString::ToPascal() const
2395 PINDEX len
= GetLength();
2396 PAssert(len
< 256, "Cannot convert to PASCAL string");
2399 memcpy(&buf
[1], theArray
, len
);
2400 return PBYTEArray(buf
, len
+1);
2404 PString
PString::ToLiteral() const
2407 for (char * p
= theArray
; *p
!= '\0'; p
++) {
2410 else if (isprint(*p
))
2414 for (i
= 0; i
< PARRAYSIZE(PStringEscapeValue
); i
++) {
2415 if (*p
== PStringEscapeValue
[i
]) {
2416 str
+= PString('\\') + PStringEscapeCode
[i
];
2420 if (i
>= PARRAYSIZE(PStringEscapeValue
))
2421 str
.sprintf("\\%03o", *p
& 0xff);
2428 PString
& PString::sprintf(const char * fmt
, ...)
2431 va_start(args
, fmt
);
2432 return vsprintf(fmt
, args
);
2435 #if defined(__GNUC__) || defined(__SUNPRO_CC)
2436 #define _vsnprintf vsnprintf
2439 PString
& PString::vsprintf(const char * fmt
, va_list arg
)
2441 PINDEX len
= theArray
!= NULL
? GetLength() : 0;
2443 // The library provided with tornado 2.0 does not have the implementation
2445 // as workaround, just use a array size of 2000
2446 PAssert(SetSize(2000), POutOfMemory
);
2447 ::vsprintf(theArray
+len
, fmt
, arg
);
2452 PAssert(SetSize(size
), POutOfMemory
);
2453 } while (_vsnprintf(theArray
+len
, size
-len
, fmt
, arg
) == -1);
2456 PAssert(MakeMinimumSize(), POutOfMemory
);
2461 PString
psprintf(const char * fmt
, ...)
2465 va_start(args
, fmt
);
2466 return str
.vsprintf(fmt
, args
);
2470 PString
pvsprintf(const char * fmt
, va_list arg
)
2473 return str
.vsprintf(fmt
, arg
);
2477 ///////////////////////////////////////////////////////////////////////////////
2479 PObject
* PCaselessString::Clone() const
2481 return new PCaselessString(*this);
2485 PObject::Comparison
PCaselessString::InternalCompare(PINDEX offset
, char c
) const
2490 int c1
= toupper(theArray
[offset
]);
2491 int c2
= toupper(c
);
2500 PObject::Comparison
PCaselessString::InternalCompare(
2501 PINDEX offset
, PINDEX length
, const char * cstr
) const
2503 if (offset
< 0 || length
< 0)
2507 return IsEmpty() ? EqualTo
: LessThan
;
2509 while (length
-- > 0 && (theArray
[offset
] != '\0' || *cstr
!= '\0')) {
2510 Comparison c
= PCaselessString::InternalCompare(offset
++, *cstr
++);
2519 ///////////////////////////////////////////////////////////////////////////////
2521 PStringStream::Buffer::Buffer(PStringStream
& str
, PINDEX size
)
2523 fixedBufferSize(size
!= 0)
2525 string
.SetMinSize(size
> 0 ? size
: 256);
2530 int PStringStream::Buffer::overflow(int c
)
2532 if (pptr() >= epptr()) {
2533 if (fixedBufferSize
)
2536 int gpos
= gptr() - eback();
2537 int ppos
= pptr() - pbase();
2538 char * newptr
= string
.GetPointer(string
.GetSize() + 32);
2539 setp(newptr
, newptr
+ string
.GetSize() - 1);
2541 setg(newptr
, newptr
+ gpos
, newptr
+ ppos
);
2553 int PStringStream::Buffer::underflow()
2555 return gptr() >= egptr() ? EOF
: *gptr();
2559 int PStringStream::Buffer::sync()
2561 char * base
= string
.GetPointer();
2562 PINDEX len
= string
.GetLength();
2563 setg(base
, base
, base
+ len
);
2564 setp(base
, base
+ string
.GetSize() - 1);
2570 streambuf::pos_type
PStringStream::Buffer::seekoff(off_type off
, ios_base::seekdir dir
, ios_base::openmode mode
)
2572 streampos
PStringStream::Buffer::seekoff(streamoff off
, ios::seek_dir dir
, int mode
)
2575 int len
= string
.GetLength();
2576 int gpos
= gptr() - eback();
2577 int ppos
= pptr() - pbase();
2583 newpptr
= newgptr
= eback();
2584 else if (off
>= len
)
2585 newpptr
= newgptr
= egptr();
2587 newpptr
= newgptr
= eback()+off
;
2593 else if (off
>= len
-ppos
)
2596 newpptr
= pptr()+off
;
2599 else if (off
>= len
-gpos
)
2602 newgptr
= gptr()+off
;
2607 newpptr
= newgptr
= eback();
2609 newpptr
= newgptr
= egptr();
2611 newpptr
= newgptr
= egptr()+off
;
2615 PAssertAlways2(string
.GetClass(), PInvalidParameter
);
2620 if ((mode
&ios::in
) != 0)
2621 setg(eback(), newgptr
, egptr());
2623 if ((mode
&ios::out
) != 0)
2624 setp(newpptr
, epptr());
2631 streampos
PStringStream::Buffer::seekpos(pos_type pos
, ios_base::openmode mode
)
2633 return seekoff(pos
, ios_base::beg
, mode
);
2639 #pragma warning(disable:4355)
2642 PStringStream::PStringStream()
2643 : iostream(new PStringStream::Buffer(*this, 0))
2648 PStringStream::PStringStream(PINDEX fixedBufferSize
)
2649 : iostream(new PStringStream::Buffer(*this, fixedBufferSize
))
2654 PStringStream::PStringStream(const PString
& str
)
2656 iostream(new PStringStream::Buffer(*this, 0))
2661 PStringStream::PStringStream(const char * cstr
)
2663 iostream(new PStringStream::Buffer(*this, 0))
2668 #pragma warning(default:4355)
2672 PStringStream::~PStringStream()
2674 delete (PStringStream::Buffer
*)rdbuf();
2681 PString
& PStringStream::MakeEmpty()
2689 void PStringStream::AssignContents(const PContainer
& cont
)
2691 PString::AssignContents(cont
);
2696 ///////////////////////////////////////////////////////////////////////////////
2698 PStringArray::PStringArray(PINDEX count
, char const * const * strarr
, BOOL caseless
)
2703 if (PAssertNULL(strarr
) == NULL
)
2706 if (count
== P_MAX_INDEX
) {
2708 while (strarr
[count
] != NULL
)
2713 for (PINDEX i
= 0; i
< count
; i
++) {
2714 PString
* newString
;
2716 newString
= new PCaselessString(strarr
[i
]);
2718 newString
= new PString(strarr
[i
]);
2719 SetAt(i
, newString
);
2724 PStringArray::PStringArray(const PString
& str
)
2727 (*theArray
)[0] = new PString(str
);
2731 PStringArray::PStringArray(const PStringList
& list
)
2733 SetSize(list
.GetSize());
2734 for (PINDEX i
= 0; i
< list
.GetSize(); i
++)
2735 (*theArray
)[i
] = new PString(list
[i
]);
2739 PStringArray::PStringArray(const PSortedStringList
& list
)
2741 SetSize(list
.GetSize());
2742 for (PINDEX i
= 0; i
< list
.GetSize(); i
++)
2743 (*theArray
)[i
] = new PString(list
[i
]);
2747 void PStringArray::ReadFrom(istream
& strm
)
2749 while (strm
.good()) {
2757 PString
& PStringArray::operator[](PINDEX index
)
2759 PASSERTINDEX(index
);
2760 PAssert(SetMinSize(index
+1), POutOfMemory
);
2761 if ((*theArray
)[index
] == NULL
)
2762 (*theArray
)[index
] = new PString
;
2763 return *(PString
*)(*theArray
)[index
];
2767 char ** PStringArray::ToCharArray(PCharArray
* storage
) const
2771 PINDEX mySize
= GetSize();
2772 PINDEX storageSize
= (mySize
+1)*sizeof(char *);
2773 for (i
= 0; i
< mySize
; i
++)
2774 storageSize
+= (*this)[i
].GetLength()+1;
2777 if (storage
!= NULL
)
2778 storagePtr
= (char **)storage
->GetPointer(storageSize
);
2780 storagePtr
= (char **)malloc(storageSize
);
2782 if (storagePtr
== NULL
)
2785 char * strPtr
= (char *)&storagePtr
[GetSize()+1];
2787 for (i
= 0; i
< mySize
; i
++) {
2788 storagePtr
[i
] = strPtr
;
2789 const PString
& str
= (*this)[i
];
2790 PINDEX len
= str
.GetLength()+1;
2791 memcpy(strPtr
, (const char *)str
, len
);
2795 storagePtr
[i
] = NULL
;
2801 ///////////////////////////////////////////////////////////////////////////////
2803 PStringList::PStringList(PINDEX count
, char const * const * strarr
, BOOL caseless
)
2808 if (PAssertNULL(strarr
) == NULL
)
2811 for (PINDEX i
= 0; i
< count
; i
++) {
2812 PString
* newString
;
2814 newString
= new PCaselessString(strarr
[i
]);
2816 newString
= new PString(strarr
[i
]);
2822 PStringList::PStringList(const PString
& str
)
2828 PStringList::PStringList(const PStringArray
& array
)
2830 for (PINDEX i
= 0; i
< array
.GetSize(); i
++)
2831 AppendString(array
[i
]);
2835 PStringList::PStringList(const PSortedStringList
& list
)
2837 for (PINDEX i
= 0; i
< list
.GetSize(); i
++)
2838 AppendString(list
[i
]);
2841 PStringList
& PStringList::operator += (const PStringList
& v
)
2844 for (i
= 0; i
< v
.GetSize(); i
++)
2851 void PStringList::ReadFrom(istream
& strm
)
2853 while (strm
.good()) {
2861 ///////////////////////////////////////////////////////////////////////////////
2863 PSortedStringList::PSortedStringList(PINDEX count
,
2864 char const * const * strarr
,
2870 if (PAssertNULL(strarr
) == NULL
)
2873 for (PINDEX i
= 0; i
< count
; i
++) {
2874 PString
* newString
;
2876 newString
= new PCaselessString(strarr
[i
]);
2878 newString
= new PString(strarr
[i
]);
2884 PSortedStringList::PSortedStringList(const PString
& str
)
2890 PSortedStringList::PSortedStringList(const PStringArray
& array
)
2892 for (PINDEX i
= 0; i
< array
.GetSize(); i
++)
2893 AppendString(array
[i
]);
2897 PSortedStringList::PSortedStringList(const PStringList
& list
)
2899 for (PINDEX i
= 0; i
< list
.GetSize(); i
++)
2900 AppendString(list
[i
]);
2905 void PSortedStringList::ReadFrom(istream
& strm
)
2907 while (strm
.good()) {
2915 PINDEX
PSortedStringList::GetNextStringsIndex(const PString
& str
) const
2917 PINDEX len
= str
.GetLength();
2919 info
->lastIndex
= InternalStringSelect(str
, len
, info
->root
);
2921 if (info
->lastIndex
!= 0) {
2923 while ((prev
= Predecessor(info
->lastElement
)) != &info
->nil
&&
2924 ((PString
*)prev
->data
)->NumCompare(str
, len
) >= EqualTo
) {
2925 info
->lastElement
= prev
;
2930 return info
->lastIndex
;
2934 PINDEX
PSortedStringList::InternalStringSelect(const char * str
,
2936 Element
* thisElement
) const
2938 if (thisElement
== &info
->nil
)
2941 switch (((PString
*)thisElement
->data
)->NumCompare(str
, len
)) {
2942 case PObject::LessThan
:
2944 PINDEX index
= InternalStringSelect(str
, len
, thisElement
->right
);
2945 return thisElement
->left
->subTreeSize
+ index
+ 1;
2948 case PObject::GreaterThan
:
2949 return InternalStringSelect(str
, len
, thisElement
->left
);
2952 info
->lastElement
= thisElement
;
2953 return thisElement
->left
->subTreeSize
;
2958 ///////////////////////////////////////////////////////////////////////////////
2960 PStringSet::PStringSet(PINDEX count
, char const * const * strarr
, BOOL caseless
)
2965 if (PAssertNULL(strarr
) == NULL
)
2968 for (PINDEX i
= 0; i
< count
; i
++) {
2970 Include(PCaselessString(strarr
[i
]));
2972 Include(PString(strarr
[i
]));
2977 PStringSet::PStringSet(const PString
& str
)
2983 void PStringSet::ReadFrom(istream
& strm
)
2985 while (strm
.good()) {
2993 ///////////////////////////////////////////////////////////////////////////////
2995 POrdinalToString::POrdinalToString(PINDEX count
, const Initialiser
* init
)
2997 while (count
-- > 0) {
2998 SetAt(init
->key
, init
->value
);
3004 void POrdinalToString::ReadFrom(istream
& strm
)
3006 while (strm
.good()) {
3010 strm
>> key
>> ws
>> equal
>> str
;
3012 SetAt(key
, PString::Empty());
3014 SetAt(key
, str
.Mid(equal
+1));
3019 ///////////////////////////////////////////////////////////////////////////////
3021 PStringToOrdinal::PStringToOrdinal(PINDEX count
,
3022 const Initialiser
* init
,
3025 while (count
-- > 0) {
3027 SetAt(PCaselessString(init
->key
), init
->value
);
3029 SetAt(init
->key
, init
->value
);
3035 void PStringToOrdinal::ReadFrom(istream
& strm
)
3037 while (strm
.good()) {
3040 PINDEX equal
= str
.FindLast('=');
3041 if (equal
== P_MAX_INDEX
)
3044 SetAt(str
.Left(equal
), str
.Mid(equal
+1).AsInteger());
3049 ///////////////////////////////////////////////////////////////////////////////
3051 PStringToString::PStringToString(PINDEX count
,
3052 const Initialiser
* init
,
3054 BOOL caselessValues
)
3056 while (count
-- > 0) {
3059 SetAt(PCaselessString(init
->key
), PCaselessString(init
->value
));
3061 SetAt(init
->key
, PCaselessString(init
->value
));
3064 SetAt(PCaselessString(init
->key
), init
->value
);
3066 SetAt(init
->key
, init
->value
);
3072 void PStringToString::ReadFrom(istream
& strm
)
3074 while (strm
.good()) {
3077 PINDEX equal
= str
.Find('=');
3078 if (equal
== P_MAX_INDEX
)
3079 SetAt(str
, PString::Empty());
3081 SetAt(str
.Left(equal
), str
.Mid(equal
+1));
3086 ///////////////////////////////////////////////////////////////////////////////
3088 PRegularExpression::PRegularExpression()
3090 lastError
= NotCompiled
;
3092 flagsSaved
= IgnoreCase
;
3096 PRegularExpression::PRegularExpression(const PString
& pattern
, int flags
)
3099 Compile(pattern
, flags
);
3103 PRegularExpression::PRegularExpression(const char * pattern
, int flags
)
3106 Compile(pattern
, flags
);
3109 PRegularExpression::PRegularExpression(const PRegularExpression
& from
)
3112 patternSaved
= from
.patternSaved
;
3113 flagsSaved
= from
.flagsSaved
;
3114 Compile(patternSaved
, flagsSaved
);
3117 PRegularExpression
& PRegularExpression::operator =(const PRegularExpression
& from
)
3120 patternSaved
= from
.patternSaved
;
3121 flagsSaved
= from
.flagsSaved
;
3122 Compile(patternSaved
, flagsSaved
);
3126 PRegularExpression::~PRegularExpression()
3128 if (expression
!= NULL
) {
3129 regfree(regexpression
);
3130 delete regexpression
;
3135 PRegularExpression::ErrorCodes
PRegularExpression::GetErrorCode() const
3137 return (ErrorCodes
)lastError
;
3141 PString
PRegularExpression::GetErrorText() const
3144 regerror(lastError
, regexpression
, str
.GetPointer(256), 256);
3149 BOOL
PRegularExpression::Compile(const PString
& pattern
, int flags
)
3151 return Compile((const char *)pattern
, flags
);
3155 BOOL
PRegularExpression::Compile(const char * pattern
, int flags
)
3157 patternSaved
= pattern
;
3160 if (expression
!= NULL
) {
3161 regfree(regexpression
);
3162 delete regexpression
;
3165 if (pattern
== NULL
|| *pattern
== '\0')
3166 lastError
= BadPattern
;
3168 expression
= new regex_t
;
3169 lastError
= regcomp(regexpression
, pattern
, flags
);
3171 return lastError
== NoError
;
3175 BOOL
PRegularExpression::Execute(const PString
& str
, PINDEX
& start
, int flags
) const
3178 return Execute((const char *)str
, start
, dummy
, flags
);
3182 BOOL
PRegularExpression::Execute(const PString
& str
, PINDEX
& start
, PINDEX
& len
, int flags
) const
3184 return Execute((const char *)str
, start
, len
, flags
);
3188 BOOL
PRegularExpression::Execute(const char * cstr
, PINDEX
& start
, int flags
) const
3191 return Execute(cstr
, start
, dummy
, flags
);
3195 BOOL
PRegularExpression::Execute(const char * cstr
, PINDEX
& start
, PINDEX
& len
, int flags
) const
3197 if (expression
== NULL
) {
3198 ((PRegularExpression
*)this)->lastError
= NotCompiled
;
3204 ((PRegularExpression
*)this)->lastError
= regexec(regexpression
, cstr
, 1, &match
, flags
);
3205 if (lastError
!= NoError
)
3208 start
= match
.rm_so
;
3209 len
= match
.rm_eo
- start
;
3214 BOOL
PRegularExpression::Execute(const PString
& str
, PIntArray
& starts
, int flags
) const
3217 return Execute((const char *)str
, starts
, dummy
, flags
);
3221 BOOL
PRegularExpression::Execute(const PString
& str
,
3226 return Execute((const char *)str
, starts
, ends
, flags
);
3230 BOOL
PRegularExpression::Execute(const char * cstr
, PIntArray
& starts
, int flags
) const
3233 return Execute(cstr
, starts
, dummy
, flags
);
3237 BOOL
PRegularExpression::Execute(const char * cstr
,
3242 if (expression
== NULL
) {
3243 ((PRegularExpression
*)this)->lastError
= NotCompiled
;
3247 regmatch_t single_match
;
3248 regmatch_t
* matches
= &single_match
;
3250 PINDEX count
= starts
.GetSize();
3252 matches
= new regmatch_t
[count
];
3256 ((PRegularExpression
*)this)->lastError
= regexec(regexpression
, cstr
, count
, matches
, flags
);
3258 if (lastError
== NoError
) {
3259 starts
.SetMinSize(count
);
3260 ends
.SetMinSize(count
);
3261 for (PINDEX i
= 0; i
< count
; i
++) {
3262 starts
[i
] = matches
[i
].rm_so
;
3263 ends
[i
] = matches
[i
].rm_eo
;
3267 if (matches
!= &single_match
)
3270 return lastError
== NoError
;
3274 PString
PRegularExpression::EscapeString(const PString
& str
)
3280 while ((nextPos
= str
.FindOneOf("\\^$+?*.[]()|{}", lastPos
+1)) != P_MAX_INDEX
) {
3281 translated
+= str(lastPos
, nextPos
-1) + "\\";
3288 return translated
+ str
.Mid(lastPos
);
3292 // End Of File ///////////////////////////////////////////////////////////////