source: trunk/src/helpers/xstring.c@ 14

Last change on this file since 14 was 14, checked in by umoeller, 25 years ago

Major updates; timers, LVM, miscellaneous.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 28.1 KB
Line 
1
2/*
3 *@@sourcefile xstring.c:
4 * string functions with memory management.
5 *
6 * Usage: All OS/2 programs.
7 *
8 * The functions in this file are intended as a replacement
9 * to the C library string functions (such as strcpy, strcat)
10 * in cases where the length of the string is unknown and
11 * dynamic memory management is desirable.
12 *
13 * Instead of char* pointers, the functions in this file
14 * operate on an XSTRING structure, which contains a char*
15 * pointer instead.
16 *
17 * Using these functions has the following advantages:
18 *
19 * -- Automatic memory management. For example, xstrcat will
20 * automatically allocate new memory if the new string
21 * does not fit into the present buffer.
22 *
23 * -- The length of the string is always known. Instead
24 * of running strlen (which consumes time), XSTRING.ulLength
25 * always contains the current length of the string.
26 *
27 * -- The functions also differentiate between allocated
28 * memory and the length of the string. That is, for
29 * iterative appends, you can pre-allocate memory to
30 * avoid excessive reallocations.
31 *
32 * Usage:
33 *
34 * 1) Allocate an XSTRING structure on the stack. Always
35 * call xstrInit on the structure, like this:
36 *
37 + XSTRING str;
38 + xstrInit(&str, 0); // no pre-allocation
39 *
40 * Alternatively, use xstrCreate to have an XSTRING
41 * allocated from the heap.
42 *
43 * Always call xstrClear(&str) to free allocated
44 * memory. Otherwise you'll get memory leaks.
45 * (For heap XSTRING's from xstrCreate, use xstrFree.)
46 *
47 * 2) To copy something into the string, use xstrcpy.
48 * To append something to the string, use xstrcat.
49 * See those functions for samples.
50 *
51 * 3) If you need the char* pointer (e.g. for a call
52 * to another function), use XSTRING.psz. However,
53 * you should ONLY modify the psz pointer yourself
54 * if the other XSTRING members are updated accordingly.
55 * You may, for example, change single characters
56 * in the psz buffer. By contrast, if you change the
57 * length of the string, you must update XSTRING.ulLength.
58 * Otherwise these functions will get into trouble.
59 *
60 * Also, you should never assume that the "psz"
61 * pointer has not changed after you have called
62 * one of the xstr* functions because these can
63 * always reallocate the buffer if more memory
64 * was needed.
65 *
66 * 4) If (and only if) you have a char* buffer which
67 * is free()'able (e.g. from strdup()), you can
68 * use xstrset to avoid duplicate copying.
69 *
70 * Function prefixes:
71 * -- xstr* extended string functions.
72 *
73 * The functions in this file used to be in stringh.c
74 * before V0.9.3 (2000-04-01). These have been largely
75 * rewritten with V0.9.6 (2000-11-01) and are now much
76 * more efficient.
77 *
78 * Note: Version numbering in this file relates to XWorkplace
79 * version numbering.
80 *
81 *@@added V0.9.3 (2000-04-01) [umoeller]
82 *@@header "helpers\xstring.h"
83 */
84
85/*
86 * Copyright (C) 1999-2000 Ulrich M”ller.
87 * This file is part of the "XWorkplace helpers" source package.
88 * This is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published
90 * by the Free Software Foundation, in version 2 as it comes in the
91 * "COPYING" file of the XWorkplace main distribution.
92 * This program is distributed in the hope that it will be useful,
93 * but WITHOUT ANY WARRANTY; without even the implied warranty of
94 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95 * GNU General Public License for more details.
96 */
97
98#define OS2EMX_PLAIN_CHAR
99 // this is needed for "os2emx.h"; if this is defined,
100 // emx will define PSZ as _signed_ char, otherwise
101 // as unsigned char
102
103#include <os2.h>
104
105#include <stdlib.h>
106#include <stdio.h>
107#include <string.h>
108
109#include "setup.h" // code generation and debugging options
110
111#include "helpers\stringh.h"
112#include "helpers\xstring.h" // extended string helpers
113
114/*
115 *@@category: Helpers\C helpers\String management
116 */
117
118/*
119 *@@ xstrInit:
120 * initializes an empty XSTRING.
121 *
122 * If (ulPreAllocate != 0), memory is pre-allocated
123 * for the string, but the string will be empty.
124 * This is useful if you plan to add more stuff to
125 * the string later so we don't have to reallocate
126 * all the time in xstrcat.
127 *
128 * Do not use this on an XSTRING which is already
129 * initialized. Use xstrset instead.
130 *
131 *@@added V0.9.6 (2000-11-01) [umoeller]
132 */
133
134void xstrInit(PXSTRING pxstr, // in/out: string
135 ULONG ulPreAllocate) // in: if > 0, memory to allocate
136{
137 memset(pxstr, 0, sizeof(XSTRING));
138 if (ulPreAllocate)
139 {
140 pxstr->psz = (PSZ)malloc(ulPreAllocate);
141 pxstr->cbAllocated = ulPreAllocate;
142 // ulLength is still zero
143 *(pxstr->psz) = 0;
144 }
145}
146
147/*
148 *@@ xstrInitSet:
149 * this can be used instead of xstrInit if you
150 * have a free()'able string you want to initialize
151 * the XSTRING with.
152 *
153 * This does not create a copy of pszNew. Instead,
154 * pszNew is used as the member string in pxstr
155 * directly.
156 *
157 * Do not use this on an XSTRING which is already
158 * initialized. Use xstrset instead.
159 *
160 * Example:
161 *
162 + XSTRING str;
163 + xstrInitSet(&str, strdup("blah"));
164 *
165 *@@added V0.9.6 (2000-11-01) [umoeller]
166 */
167
168void xstrInitSet(PXSTRING pxstr,
169 PSZ pszNew)
170{
171 pxstr->psz = pszNew;
172 if (!pszNew)
173 {
174 pxstr->cbAllocated = 0;
175 pxstr->ulLength = 0;
176 }
177 else
178 {
179 pxstr->ulLength = strlen(pszNew);
180 pxstr->cbAllocated = pxstr->ulLength + 1;
181 }
182}
183
184/*
185 *@@ xstrInitCopy:
186 * this can be used instead of xstrInit if you
187 * want to initialize an XSTRING with a copy
188 * of an existing string.
189 *
190 * As opposed to xstrInitSet, this does create
191 * a copy of pcszSource.
192 *
193 * Do not use this on an XSTRING which is already
194 * initialized. Use xstrcpy instead.
195 *
196 * Example:
197 *
198 + XSTRING str;
199 + xstrInitCopy(&str, "blah");
200 *
201 *@@added V0.9.6 (2000-11-01) [umoeller]
202 */
203
204void xstrInitCopy(PXSTRING pxstr,
205 const char *pcszSource)
206{
207 if (pxstr)
208 {
209 memset(pxstr, 0, sizeof(XSTRING));
210
211 if (pcszSource)
212 pxstr->ulLength = strlen(pcszSource);
213
214 if (pxstr->ulLength)
215 {
216 // we do have a source string:
217 pxstr->cbAllocated = pxstr->ulLength + 1;
218 pxstr->psz = (PSZ)malloc(pxstr->cbAllocated);
219 strcpy(pxstr->psz, pcszSource);
220 }
221 }
222}
223
224/*
225 *@@ xstrClear:
226 * clears the specified stack XSTRING and
227 * frees allocated memory.
228 *
229 * This is the reverse to xstrInit.
230 *
231 *@@added V0.9.6 (2000-11-01) [umoeller]
232 */
233
234void xstrClear(PXSTRING pxstr) // in/out: string
235{
236 if (pxstr->psz)
237 free(pxstr->psz);
238 memset(pxstr, 0, sizeof(XSTRING));
239}
240
241/*
242 *@@ xstrCreate:
243 * allocates a new XSTRING from the heap
244 * and calls xstrInit on it.
245 *
246 * Always use xstrFree to free associated
247 * resources.
248 *
249 *@@added V0.9.6 (2000-11-01) [umoeller]
250 */
251
252PXSTRING xstrCreate(ULONG ulPreAllocate)
253{
254 PXSTRING pxstr = (PXSTRING)malloc(sizeof(XSTRING));
255 if (pxstr)
256 xstrInit(pxstr, ulPreAllocate);
257
258 return (pxstr);
259}
260
261/*
262 *@@ xstrFree:
263 * frees the specified heap XSTRING, which must
264 * have been created using xstrCreate.
265 *
266 *@@added V0.9.6 (2000-11-01) [umoeller]
267 */
268
269VOID xstrFree(PXSTRING pxstr) // in/out: string
270{
271 if (pxstr)
272 {
273 xstrClear(pxstr);
274 free(pxstr);
275 }
276}
277
278/*
279 *@@ xstrset:
280 * sets the specified XSTRING to a new string
281 * without copying it.
282 *
283 * pxstr is cleared before the new string is set.
284 *
285 * This ONLY works if pszNew has been allocated from
286 * the heap using malloc() or strdup() and is thus
287 * free()'able.
288 *
289 * This assumes that exactly strlen(pszNew) + 1
290 * bytes have been allocated for pszNew, which
291 * is true if pszNew comes from strdup().
292 *
293 *@@added V0.9.6 (2000-11-01) [umoeller]
294 */
295
296ULONG xstrset(PXSTRING pxstr, // in/out: string
297 PSZ pszNew) // in: heap PSZ to use
298{
299 xstrClear(pxstr);
300 pxstr->psz = pszNew;
301 if (pszNew)
302 {
303 pxstr->ulLength = strlen(pszNew);
304 pxstr->cbAllocated = pxstr->ulLength + 1;
305 }
306 // else null string: cbAllocated and ulLength are 0 already
307
308 return (pxstr->ulLength);
309}
310
311/*
312 *@@ xstrcpy:
313 * copies pcszSource to pxstr, for which memory is allocated
314 * as necessary.
315 *
316 * If pxstr contains something, its contents are destroyed.
317 *
318 * Returns the length of the new string (excluding the null
319 * terminator), or null upon errors.
320 *
321 * Example:
322 *
323 + XSTRING str;
324 + xstrInit(&str, 0);
325 + xstrcpy(&str, "blah");
326 *
327 * This sequence can be abbreviated using xstrInitCopy.
328 *
329 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxcpy
330 *@@changed V0.9.6 (2000-11-01) [umoeller]: rewritten
331 */
332
333ULONG xstrcpy(PXSTRING pxstr, // in/out: string
334 const char *pcszSource) // in: source, can be NULL
335{
336 xstrClear(pxstr);
337
338 if (pxstr)
339 {
340 ULONG ulSourceLength = 0;
341 if (pcszSource)
342 ulSourceLength = strlen(pcszSource);
343
344 if (ulSourceLength)
345 {
346 // we do have a source string:
347 ULONG cbNeeded = ulSourceLength + 1;
348 if (cbNeeded > pxstr->cbAllocated)
349 {
350 // we need more memory than we have previously
351 // allocated:
352 pxstr->cbAllocated = cbNeeded;
353 pxstr->psz = (PSZ)malloc(cbNeeded);
354 }
355 // else: we have enough memory
356
357 strcpy(pxstr->psz, pcszSource);
358 }
359 else
360 {
361 // no source specified or source is empty:
362 if (pxstr->cbAllocated)
363 // we did have a string: set to empty,
364 // but leave allocated memory intact
365 *(pxstr->psz) = 0;
366 // else: pxstr->psz is still NULL
367 }
368
369 // in all cases, set new length
370 pxstr->ulLength = ulSourceLength;
371 }
372
373 return (pxstr->ulLength);
374}
375
376/*
377 *@@ xstrcat:
378 * appends pcszSource to pxstr, for which memory is
379 * reallocated if necessary.
380 *
381 * If pxstr is empty, this behaves just like xstrcpy.
382 *
383 * Returns the length of the new string (excluding the null
384 * terminator), or null upon errors.
385 *
386 * Example:
387 *
388 + XSTRING str;
389 + xstrInit(&str, 0);
390 + xstrcpy(&str, "blah");
391 + xstrcat(&str, "blup");
392 *
393 * After this, psz points to a new string containing
394 * "blahblup".
395 *
396 *@@changed V0.9.1 (99-12-20) [umoeller]: fixed memory leak
397 *@@changed V0.9.1 (2000-01-03) [umoeller]: crashed if pszString was null; fixed
398 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxcat
399 *@@changed V0.9.3 (2000-05-11) [umoeller]: returned 0 if pszString was initially empty; fixed
400 *@@changed V0.9.6 (2000-11-01) [umoeller]: rewritten
401 */
402
403ULONG xstrcat(PXSTRING pxstr, // in/out: string
404 const char *pcszSource) // in: source, can be NULL
405{
406 ULONG ulrc = 0;
407
408 if (pxstr)
409 {
410 ULONG ulSourceLength = 0;
411 if (pcszSource)
412 ulSourceLength = strlen(pcszSource);
413
414 if (ulSourceLength)
415 {
416 // we do have a source string:
417
418 // 1) memory management
419 ULONG cbNeeded = pxstr->ulLength + ulSourceLength + 1;
420 if (cbNeeded > pxstr->cbAllocated)
421 {
422 // we need more memory than we have previously
423 // allocated:
424 if (pxstr->cbAllocated)
425 // appendee already had memory:
426 // reallocate
427 pxstr->psz = (PSZ)realloc(pxstr->psz,
428 cbNeeded);
429 else
430 // appendee has no memory:
431 pxstr->psz = (PSZ)malloc(cbNeeded);
432
433 pxstr->cbAllocated = cbNeeded;
434 // ulLength is unchanged yet
435 }
436 // else: we have enough memory, both if appendee
437 // is empty or not empty
438
439 // now we have:
440 // -- if appendee (pxstr) had enough memory, no problem
441 // -- if appendee (pxstr) needed more memory
442 // -- and was not empty: pxstr->psz now points to a
443 // reallocated copy of the old string
444 // -- and was empty: pxstr->psz now points to a
445 // new (unitialized) buffer
446
447 // 2) append source string:
448 memcpy(pxstr->psz + pxstr->ulLength,
449 pcszSource,
450 ulSourceLength + 1); // null terminator
451
452 // in all cases, set new length
453 pxstr->ulLength += ulSourceLength;
454 ulrc = ulSourceLength;
455
456 } // end if (ulSourceLength)
457 // else no source specified or source is empty:
458 // do nothing
459 }
460
461 return (ulrc);
462}
463
464/*
465 *@@ xstrFindWord:
466 * searches for pstrFind in pxstr, starting at ulOfs.
467 * However, this only finds pstrFind if it's a "word",
468 * i.e. surrounded by one of the characters in the
469 * pcszBeginChars and pcszEndChars array.
470 *
471 * This is similar to strhFindWord, but this uses
472 * strhmemfind for fast searching, and it doesn't
473 * have to calculate the string lengths because these
474 * already in XSTRING.
475 *
476 * Returns 0 if no "word" was found, or the offset
477 * of the "word" in pxstr if found.
478 *
479 *@@added V0.9.6 (2000-11-12) [umoeller]
480 */
481
482PSZ xstrFindWord(const XSTRING *pxstr, // in: buffer to search ("haystack")
483 ULONG ulOfs, // in: where to begin search (0 = start)
484 const XSTRING *pstrFind, // in: word to find ("needle")
485 size_t *pShiftTable, // in: shift table (see strhmemfind)
486 PBOOL pfRepeatFind, // in: repeat find? (see strhmemfind)
487 const char *pcszBeginChars, // suggestion: "\x0d\x0a ()/\\-,."
488 const char *pcszEndChars) // suggestion: "\x0d\x0a ()/\\-,.:;"
489{
490 PSZ pReturn = 0;
491 ULONG ulFoundLen = pstrFind->ulLength;
492
493 if ((pxstr->ulLength) && (ulFoundLen))
494 {
495 const char *p = pxstr->psz + ulOfs;
496
497 do // while p
498 {
499 // p = strstr(p, pstrFind->psz);
500 p = (PSZ)strhmemfind(p, // in: haystack
501 pxstr->ulLength - (p - pxstr->psz),
502 // remaining length of haystack
503 pstrFind->psz,
504 ulFoundLen,
505 pShiftTable,
506 pfRepeatFind);
507 if (p)
508 {
509 // string found:
510 // check if that's a word
511
512 if (strhIsWord(pxstr->psz,
513 p,
514 ulFoundLen,
515 pcszBeginChars,
516 pcszEndChars))
517 {
518 // valid end char:
519 pReturn = (PSZ)p;
520 break;
521 }
522
523 p += ulFoundLen;
524 }
525 } while (p);
526
527 }
528 return (pReturn);
529}
530
531/*
532 *@@ xstrrpl:
533 * replaces the first occurence of pstrSearch with
534 * pstrReplace in pxstr.
535 *
536 * Starting with V0.9.6, this operates entirely on
537 * XSTRING's for speed because we then know the string
538 * lengths already and can use memcpy instead of strcpy.
539 * This new version should be magnitudes faster,
540 * especially with large string bufffers.
541 *
542 * None of the pointers can be NULL, but if pstrReplace
543 * is empty, this effectively erases pstrSearch in pxstr.
544 *
545 * Returns the length of the new string (exclusing the
546 * null terminator) or 0 if pszSearch was not found
547 * (and pxstr was therefore not changed).
548 *
549 * This starts the search at *pulOffset. If
550 * (*pulOffset == 0), this starts from the beginning
551 * of pxstr.
552 * If the string was found, *pulOffset will be set to the
553 * first character after the new replacement string. This
554 * allows you to call this func again with the same strings
555 * to have several occurences replaced (see the example below).
556 *
557 * There are two wrappers around this function which
558 * work on C strings instead (however, thus losing the
559 * speed advantage):
560 *
561 * -- strhrpl operates on C strings only;
562 *
563 * -- xstrcrpl uses C strings for the search and replace
564 * parameters.
565 *
566 * <B>Example usage:</B>
567 *
568 + XSTRING str;
569 + ULONG ulOffset = 0;
570 + xstrInit(&str, 0);
571 + xstrcpy(&str, "Test phrase 1. Test phrase 2.");
572 + while (xstrrpl(&str,
573 + &ulPos, // in/out: offset
574 + "Test", // search
575 + "Dummy") // replace
576 + ;
577 *
578 * would replace all occurences of "Test" in str with
579 * "Dummy".
580 *
581 *@@changed V0.9.0 [umoeller]: totally rewritten.
582 *@@changed V0.9.0 (99-11-08) [umoeller]: crashed if *ppszBuf was NULL. Fixed.
583 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxrpl
584 *@@changed V0.9.6 (2000-11-01) [umoeller]: rewritten
585 *@@changed V0.9.6 (2000-11-12) [umoeller]: now using strhmemfind
586 */
587
588ULONG xstrrpl(PXSTRING pxstr, // in/out: string
589 PULONG pulOfs, // in: where to begin search (0 = start);
590 // out: ofs of first char after replacement string
591 const XSTRING *pstrSearch, // in: search string; cannot be NULL
592 const XSTRING *pstrReplace, // in: replacement string; cannot be NULL
593 size_t *pShiftTable, // in: shift table (see strhmemfind)
594 PBOOL pfRepeatFind) // in: repeat find? (see strhmemfind)
595{
596 ULONG ulrc = 0; // default: not found
597
598 if ((pxstr) && (pstrSearch) && (pstrReplace))
599 {
600 ULONG cSearchLen = pstrSearch->ulLength;
601
602 // can we search this?
603 if ( (*pulOfs < pxstr->ulLength)
604 && (cSearchLen)
605 )
606 {
607 // yes:
608 /* PSZ pFound = strstr(pxstr->psz + *pulOfs,
609 pstrSearch->psz); */
610 PSZ pFound = (PSZ)strhmemfind(pxstr->psz + *pulOfs, // in: haystack
611 pxstr->ulLength - *pulOfs,
612 pstrSearch->psz,
613 cSearchLen,
614 pShiftTable,
615 pfRepeatFind);
616 if (pFound)
617 {
618 // found in buffer from ofs:
619 ULONG cReplaceLen = pstrReplace->ulLength;
620 // can be 0!
621
622 // length of new string
623 ULONG cbNeeded = pxstr->ulLength
624 + cReplaceLen
625 - cSearchLen
626 + 1, // null terminator
627 // offset where pszSearch was found
628 ulFoundOfs = pFound - pxstr->psz;
629
630 // now check if we have enough memory...
631 if (pxstr->cbAllocated < cbNeeded)
632 {
633 // no, we need more memory:
634 // allocate new buffer
635 PSZ pszNew = (PSZ)malloc(cbNeeded);
636
637 if (ulFoundOfs)
638 // "found" was not at the beginning:
639 // copy from beginning up to found-offset
640 memcpy(pszNew,
641 pxstr->psz,
642 ulFoundOfs); // up to "found"
643
644 if (cReplaceLen)
645 {
646 // we have a replacement:
647 // insert it next
648 memcpy(pszNew + ulFoundOfs,
649 pstrReplace->psz,
650 cReplaceLen + 1); // include null terminator
651 }
652
653 // copy rest:
654 // pxstr frontFOUNDtail
655 // 0 1
656 // 01234567890123
657 // ³ ³ ³ ³
658 // ³ ³ ÀÄ ulFoundOfs + cSearchLen = 10
659 // ³ ³ ³
660 // ³ ÀÄ ulFoundOfs = 5
661 // ³ ³
662 // pxstr->ulLength = 14
663 memcpy(pszNew + ulFoundOfs + cReplaceLen,
664 pFound + cSearchLen,
665 // remaining bytes:
666 pxstr->ulLength - ulFoundOfs - cSearchLen // 9
667 + 1); // null terminator
668
669 // replace old buffer with new one
670 free(pxstr->psz);
671 pxstr->psz = pszNew;
672 pxstr->ulLength = cbNeeded - 1;
673 pxstr->cbAllocated = cbNeeded;
674 } // end if (pxstr->cbAllocated < cbNeeded)
675 else
676 {
677 // we have enough memory left,
678 // we can just overwrite in the middle...
679
680 PSZ pszAfterFoundBackup = 0;
681 // calc length of string after "found"
682 ULONG cTailLength = pxstr->ulLength - ulFoundOfs - cSearchLen;
683
684 // if "replace" is longer than "found",
685 // make a backup of the stuff after "found",
686 // or this would get overwritten
687 if (cReplaceLen > cSearchLen)
688 {
689 pszAfterFoundBackup = (PSZ)malloc(cTailLength + 1);
690 memcpy(pszAfterFoundBackup,
691 pFound + cSearchLen,
692 cTailLength + 1);
693 }
694
695 // now overwrite "found" in the middle
696 if (cReplaceLen)
697 {
698 memcpy(pxstr->psz + ulFoundOfs,
699 pstrReplace->psz,
700 cReplaceLen); // no null terminator
701 }
702
703 // now append tail (stuff after "found") again...
704 if (pszAfterFoundBackup)
705 {
706 // we made a backup above:
707 memcpy(pxstr->psz + ulFoundOfs + cReplaceLen,
708 pszAfterFoundBackup,
709 cTailLength + 1);
710 free(pszAfterFoundBackup);
711 // done!
712 }
713 else
714 // no backup:
715 if (cReplaceLen < cSearchLen)
716 // "replace" is shorter than "found:
717 memcpy(pxstr->psz + ulFoundOfs + cReplaceLen,
718 pFound + cSearchLen,
719 cTailLength + 1);
720 // else (cReplaceLen == cSearchLen):
721 // we can leave the tail as it is
722
723 pxstr->ulLength = cbNeeded - 1;
724 }
725
726 // return new length
727 ulrc = cbNeeded - 1;
728 *pulOfs = ulFoundOfs + cReplaceLen;
729 } // end if (pFound)
730 } // end if ( (*pulOfs < pxstr->ulLength) ...
731 } // end if ((pxstr) && (pstrSearch) && (pstrReplace))
732
733 return (ulrc);
734}
735
736/*
737 *@@ xstrcrpl:
738 * wrapper around xstrrpl() which allows using C strings
739 * for the find and replace parameters.
740 *
741 * This creates two temporary XSTRING's for pcszSearch
742 * pcszReplace. As a result, this is slower than xstrrpl.
743 * If you search with the same strings several times,
744 * you'll be better off using xstrrpl() directly.
745 *
746 *@@added V0.9.6 (2000-11-01) [umoeller]
747 */
748
749ULONG xstrcrpl(PXSTRING pxstr, // in/out: string
750 PULONG pulOfs, // in: where to begin search (0 = start);
751 // out: ofs of first char after replacement string
752 const char *pcszSearch, // in: search string; cannot be NULL
753 const char *pcszReplace) // in: replacement string; cannot be NULL
754{
755 // ULONG ulrc = 0;
756 XSTRING xstrFind,
757 xstrReplace;
758 size_t ShiftTable[256];
759 BOOL fRepeat = FALSE;
760 // initialize find/replace strings... note that the
761 // C strings are not free()'able, so we MUST NOT use xstrClear
762 // before leaving
763 xstrInitSet(&xstrFind, (PSZ)pcszSearch);
764 xstrInitSet(&xstrReplace, (PSZ)pcszReplace);
765
766 return (xstrrpl(pxstr, pulOfs, &xstrFind, &xstrReplace, ShiftTable, &fRepeat));
767}
768
769// test case
770
771/* int main(void)
772{
773 XSTRING str,
774 strFind,
775 strReplace;
776 ULONG ulOfs = 0;
777
778 xstrInit(&str, 100);
779 xstrInit(&strFind, 0);
780 xstrInit(&strReplace, 0);
781
782 xstrcpy(&str, "Test string 1. Test string 2. Test string 3. !");
783 xstrcpy(&strFind, "Test");
784 xstrcpy(&strReplace, "Dummy");
785
786 printf("Old string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated);
787
788 while (xstrrpl(&str,
789 ulOfs,
790 &strFind,
791 &strReplace,
792 &ulOfs))
793 ;
794
795 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated);
796
797 xstrcpy(&strFind, strReplace.psz);
798 xstrClear(&strReplace);
799 ulOfs = 0;
800 while (xstrrpl(&str,
801 ulOfs,
802 &strFind,
803 &strReplace,
804 &ulOfs))
805 ;
806
807 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated);
808
809 xstrcpy(&strFind, " ");
810 xstrcpy(&strReplace, ".");
811 ulOfs = 0;
812 while (xstrrpl(&str,
813 ulOfs,
814 &strFind,
815 &strReplace,
816 &ulOfs))
817 ;
818
819 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated);
820
821 xstrcpy(&strFind, ".");
822 xstrcpy(&strReplace, "***************************");
823 ulOfs = 0;
824 while (xstrrpl(&str,
825 ulOfs,
826 &strFind,
827 &strReplace,
828 &ulOfs))
829 ;
830
831 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated);
832
833 xstrcpy(&strFind, "*");
834 xstrClear(&strReplace);
835 ulOfs = 0;
836 while (xstrrpl(&str,
837 ulOfs,
838 &strFind,
839 &strReplace,
840 &ulOfs))
841 ;
842
843 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated);
844} */
845
Note: See TracBrowser for help on using the repository browser.