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

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

Initial checkin of helpers code which used to be in WarpIN.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 13.4 KB
Line 
1
2/*
3 *@@sourcefile xstring.c:
4 * string functions with memory management.
5 *
6 * Usage: All OS/2 programs.
7 *
8 * Function prefixes:
9 * -- xstr* extended string functions.
10 *
11 * The functions in this file used to be in stringh.c
12 * before V0.9.3 (2000-04-01).
13 *
14 * Note: Version numbering in this file relates to XWorkplace version
15 * numbering.
16 *
17 *@@added V0.9.3 (2000-04-01) [umoeller]
18 *@@header "helpers\xstring.h"
19 */
20
21/*
22 * Copyright (C) 1999-2000 Ulrich M”ller.
23 * This file is part of the XWorkplace source package.
24 * XWorkplace is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published
26 * by the Free Software Foundation, in version 2 as it comes in the
27 * "COPYING" file of the XWorkplace main distribution.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 */
33
34#define OS2EMX_PLAIN_CHAR
35 // this is needed for "os2emx.h"; if this is defined,
36 // emx will define PSZ as _signed_ char, otherwise
37 // as unsigned char
38
39#include <os2.h>
40
41#include <stdlib.h>
42#include <stdio.h>
43#include <string.h>
44
45#include "setup.h" // code generation and debugging options
46
47#include "helpers\stringh.h"
48#include "helpers\xstring.h" // extended string helpers
49
50/*
51 *@@category: Helpers\C helpers\String management
52 */
53
54/*
55 *@@ xstrcpy:
56 * copies pszString to *ppszBuf, for which memory is allocated
57 * as necessary.
58 *
59 * If *ppszBuf != NULL, the existing memory is freed.
60 *
61 * Returns the length of the new string (including the null
62 * terminator), or null upon errors.
63 *
64 * Example:
65 + PSZ psz = NULL;
66 + xstrcpy(&psz, "blah");
67 * would have "psz" point to newly allocated buffer containing
68 * "blah".
69 *
70 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxcpy
71 */
72
73ULONG xstrcpy(XSTR ppszBuf,
74 const char *pszString)
75{
76 ULONG ulrc = 0;
77 if (ppszBuf)
78 {
79 if (*ppszBuf)
80 free(*ppszBuf);
81 ulrc = strlen(pszString) + 1;
82 *ppszBuf = (PSZ)malloc(ulrc);
83 strcpy(*ppszBuf, pszString);
84 }
85 return (ulrc);
86}
87
88#ifdef __XWPMEMDEBUG__ // setup.h, helpers\memdebug.c
89
90/*
91 *@@ xstrcatDebug:
92 * debug version of xstrcat.
93 *
94 * stringh.h automatically maps xstrcat to this
95 * function if __XWPMEMDEBUG__ is defined.
96 *
97 *@@addded V0.9.1 (99-12-20) [umoeller]
98 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxcatDebug
99 */
100
101ULONG xstrcatDebug(XSTR ppszBuf,
102 const char *pszString,
103 const char *file,
104 unsigned long line,
105 const char *function)
106{
107 ULONG ulrc = 0;
108 if ((ppszBuf) && (pszString))
109 {
110 if (*ppszBuf == NULL)
111 xstrcpy(ppszBuf, pszString);
112 else
113 {
114 ULONG cbOld = strlen(*ppszBuf),
115 cbString = strlen(pszString);
116 PSZ pszOldCopy = strdup(*ppszBuf);
117
118 ulrc = cbOld + cbString + 1;
119 if (*ppszBuf)
120 free(*ppszBuf);
121 *ppszBuf = (PSZ)memdMalloc(ulrc, file, line, function);
122 // copy old string
123 memcpy(*ppszBuf,
124 pszOldCopy,
125 cbOld);
126 // append new string
127 memcpy(*ppszBuf + cbOld,
128 pszString,
129 cbString + 1); // include null terminator
130 free(pszOldCopy); // fixed V0.9.1 (99-12-20) [umoeller]
131 }
132 }
133 return (ulrc);
134}
135
136#else // __XWPMEMDEBUG__
137
138/*
139 *@@ xstrcat:
140 * appends pszString to *ppszBuf, which is re-allocated as
141 * necessary.
142 *
143 * If *ppszBuf is NULL, this behaves just as xstrcpy.
144 *
145 * Returns the length of the new string (including the null
146 * terminator), or null upon errors.
147 *
148 * Example:
149 + PSZ psz = strdup("blah");
150 + xstrcat(&psz, "blup");
151 * would do the following:
152 * a) free the old value of psz ("blah");
153 * b) reallocate psz;
154 * c) so that psz afterwards points to a new string containing
155 * "blahblup".
156 *
157 *@@changed V0.9.1 (99-12-20) [umoeller]: fixed memory leak
158 *@@changed V0.9.1 (2000-01-03) [umoeller]: crashed if pszString was null; fixed
159 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxcat
160 *@@changed V0.9.3 (2000-05-11) [umoeller]: returned 0 if pszString was initially empty; fixed
161 */
162
163ULONG xstrcat(XSTR ppszBuf,
164 const char *pszString)
165{
166 ULONG ulrc = 0;
167 if ((ppszBuf) && (pszString))
168 {
169 if (*ppszBuf == NULL)
170 ulrc = xstrcpy(ppszBuf, pszString);
171 else
172 {
173 ULONG cbOld = strlen(*ppszBuf),
174 cbString = strlen(pszString);
175 PSZ pszOldCopy = strdup(*ppszBuf);
176
177 ulrc = cbOld + cbString + 1;
178 if (*ppszBuf)
179 free(*ppszBuf);
180 *ppszBuf = (PSZ)malloc(ulrc);
181 // copy old string
182 memcpy(*ppszBuf,
183 pszOldCopy,
184 cbOld);
185 // append new string
186 memcpy(*ppszBuf + cbOld,
187 pszString,
188 cbString + 1); // include null terminator
189 free(pszOldCopy); // fixed V0.9.1 (99-12-20) [umoeller]
190 }
191 }
192 return (ulrc);
193}
194
195#endif // else __XWPMEMDEBUG__
196
197#ifdef __XWPMEMDEBUG__ // setup.h, helpers\memdebug.c
198
199/*
200 *@@ xstrrplDebug:
201 *
202 *@@added V0.9.3 (2000-04-11) [umoeller]
203 */
204
205ULONG xstrrplDebug(PSZ *ppszBuf, // in/out: text buffer
206 ULONG ulOfs, // in: where to begin search (can be 0)
207 const char *pszSearch, // in: search string
208 const char *pszReplace, // in: replacement string
209 PULONG pulAfterOfs, // out: offset where found (can be NULL)
210 const char *file,
211 unsigned long line,
212 const char *function)
213{
214 ULONG ulrc = 0;
215
216 if ((ppszBuf) && (pszSearch) && (pszReplace))
217 {
218 ULONG cbBuf = 0,
219 cbSearch = strlen(pszSearch);
220 if (*ppszBuf) // fixed V0.9.0 (99-11-08) [umoeller]
221 cbBuf = strlen(*ppszBuf);
222
223 if ((ulOfs < cbBuf) && (cbSearch))
224 {
225 PSZ pFound = strstr((*ppszBuf) + ulOfs,
226 pszSearch);
227
228 if (pFound)
229 {
230 ULONG cbReplace = strlen(pszReplace),
231 // length of new string
232 cbNew = cbBuf
233 + cbReplace
234 - cbSearch
235 + 1, // null terminator
236 // offset where pszSearch was found
237 ulFoundOfs = pFound - *ppszBuf;
238
239 // allocate new buffer
240 PSZ pszNew = (PSZ)memdMalloc(cbNew,
241 file, line, function);
242
243 if (ulFoundOfs)
244 {
245 // copy until offset
246 strncpy(pszNew,
247 *ppszBuf,
248 ulFoundOfs);
249 }
250
251 if (cbReplace)
252 {
253 // copy replacement
254 strncpy(pszNew + ulFoundOfs,
255 pszReplace,
256 cbReplace);
257 }
258 // copy rest
259 strcpy(pszNew + ulFoundOfs + cbReplace,
260 pFound + cbSearch);
261
262 // replace PSZ pointer
263 memdFree(*ppszBuf, file, line, function);
264 *ppszBuf = pszNew;
265
266 // return new length
267 ulrc = cbNew;
268 if (pulAfterOfs)
269 *pulAfterOfs = ulFoundOfs + cbReplace;
270 }
271 }
272 }
273 return (ulrc);
274}
275
276#else
277
278/*
279 *@@ xstrrpl:
280 * replaces pszSearch with pszReplace in *ppszBuf.
281 *
282 * If pszSearch was found, *ppszBuf is
283 * re-allocated so the buffer cannot overflow. As
284 * a result, *ppszBuf must be free()'able.
285 *
286 * Returns the length of the new string or 0 if
287 * pszSearch was not found (and ppszBuf was therefore
288 * not changed).
289 *
290 * If the string was found and (pulAfterOfs != NULL),
291 * *pulAfterOfs will be set to the first character
292 * after the new replacement string. This allows you
293 * to call this func again with the same strings to
294 * have several occurences replaced.
295 *
296 * Only the first occurence is replaced. To replace
297 * all occurences in a buffer, repeat calling this
298 * function until it returns 0.
299 *
300 * <B>Example usage:</B>
301 + PSZ psz = strdup("Test string");
302 + xstrrpl(&psz, "Test", "Dummy");
303 *
304 * would reallocate psz to point to a new string
305 * containing "Dummy string".
306 *
307 *@@changed V0.9.0 [umoeller]: totally rewritten.
308 *@@changed V0.9.0 (99-11-08) [umoeller]: crashed if *ppszBuf was NULL. Fixed.
309 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxrpl
310 */
311
312ULONG xstrrpl(PSZ *ppszBuf, // in/out: text buffer; cannot be NULL
313 ULONG ulOfs, // in: where to begin search (can be 0)
314 const char *pszSearch, // in: search string; cannot be NULL
315 const char *pszReplace, // in: replacement string; cannot be NULL
316 PULONG pulAfterOfs) // out: offset where found (can be NULL)
317{
318 ULONG ulrc = 0;
319
320 if ((ppszBuf) && (pszSearch) && (pszReplace))
321 {
322 ULONG cbBuf = 0,
323 cbSearch = strlen(pszSearch);
324 if (*ppszBuf) // fixed V0.9.0 (99-11-08) [umoeller]
325 cbBuf = strlen(*ppszBuf);
326
327 if ((ulOfs < cbBuf) && (cbSearch))
328 {
329 PSZ pFound = strstr((*ppszBuf) + ulOfs,
330 pszSearch);
331
332 if (pFound)
333 {
334 ULONG cbReplace = strlen(pszReplace),
335 // length of new string
336 cbNew = cbBuf
337 + cbReplace
338 - cbSearch
339 + 1, // null terminator
340 // offset where pszSearch was found
341 ulFoundOfs = pFound - *ppszBuf;
342
343 // allocate new buffer
344 PSZ pszNew = (PSZ)malloc(cbNew);
345
346 if (ulFoundOfs)
347 {
348 // copy until offset
349 strncpy(pszNew,
350 *ppszBuf,
351 ulFoundOfs);
352 }
353
354 if (cbReplace)
355 {
356 // copy replacement
357 strncpy(pszNew + ulFoundOfs,
358 pszReplace,
359 cbReplace);
360 }
361 // copy rest
362 strcpy(pszNew + ulFoundOfs + cbReplace,
363 pFound + cbSearch);
364
365 // replace PSZ pointer
366 free(*ppszBuf);
367 *ppszBuf = pszNew;
368
369 // return new length
370 ulrc = cbNew;
371 if (pulAfterOfs)
372 *pulAfterOfs = ulFoundOfs + cbReplace;
373 }
374 }
375 }
376 return (ulrc);
377}
378
379#endif // else __XWPMEMDEBUG__
380
381/*
382 *@@ xstrins:
383 * this inserts one string into another.
384 *
385 * pszInsert is inserted into pszBuffer at offset
386 * ulInsertOfs (which counts from 0).
387 *
388 * A newly allocated string is returned. pszBuffer is
389 * not changed. The new string should be free()'d after
390 * use.
391 *
392 * Upon errors, NULL is returned.
393 *
394 *@@changed V0.9.0 [umoeller]: completely rewritten.
395 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxins
396 */
397
398PSZ xstrins(PSZ pszBuffer,
399 ULONG ulInsertOfs,
400 const char *pszInsert)
401{
402 PSZ pszNew = NULL;
403
404 if ((pszBuffer) && (pszInsert))
405 {
406 do {
407 ULONG cbBuffer = strlen(pszBuffer);
408 ULONG cbInsert = strlen(pszInsert);
409
410 // check string length
411 if (ulInsertOfs > cbBuffer + 1)
412 break; // do
413
414 // OK, let's go.
415 pszNew = (PSZ)malloc(cbBuffer + cbInsert + 1); // additional null terminator
416
417 // copy stuff before pInsertPos
418 memcpy(pszNew,
419 pszBuffer,
420 ulInsertOfs);
421 // copy string to be inserted
422 memcpy(pszNew + ulInsertOfs,
423 pszInsert,
424 cbInsert);
425 // copy stuff after pInsertPos
426 strcpy(pszNew + ulInsertOfs + cbInsert,
427 pszBuffer + ulInsertOfs);
428 } while (FALSE);
429 }
430
431 return (pszNew);
432}
433
434
Note: See TracBrowser for help on using the repository browser.