Changeset 12 for trunk/src/helpers/xstring.c
- Timestamp:
- Nov 4, 2000, 8:55:45 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/xstring.c
r8 r12 6 6 * Usage: All OS/2 programs. 7 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 NEVER modify the psz pointer yourself 54 * because then these functions will get into trouble. 55 * 56 * Also, you should never assume that the "psz" 57 * pointer has not changed after you have called 58 * one of the xstr* functions because these can 59 * always reallocate the buffer if needed. 60 * 61 * 4) If (and only if) you have a char* buffer which 62 * is free()'able (e.g. from strdup()), you can 63 * use xstrset to avoid duplicate copying. 64 * 8 65 * Function prefixes: 9 66 * -- xstr* extended string functions. 10 67 * 11 68 * 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. 69 * before V0.9.3 (2000-04-01). These have been largely 70 * rewritten with V0.9.6 (2000-11-01). 71 * 72 * Note: Version numbering in this file relates to XWorkplace 73 * version numbering. 16 74 * 17 75 *@@added V0.9.3 (2000-04-01) [umoeller] … … 53 111 54 112 /* 113 *@@ xstrInit: 114 * initializes an empty XSTRING. 115 * 116 * If (ulPreAllocate != 0), memory is pre-allocated 117 * for the string, but the string will be empty. 118 * This is useful if you plan to add more stuff to 119 * the string later so we don't have to reallocate 120 * all the time in xstrcat. 121 * 122 * Do not use this on an XSTRING which is already 123 * initialized. Use xstrset instead. 124 * 125 *@@added V0.9.6 (2000-11-01) [umoeller] 126 */ 127 128 void xstrInit(PXSTRING pxstr, // in/out: string 129 ULONG ulPreAllocate) // in: if > 0, memory to allocate 130 { 131 memset(pxstr, 0, sizeof(XSTRING)); 132 if (ulPreAllocate) 133 { 134 pxstr->psz = (PSZ)malloc(ulPreAllocate); 135 pxstr->cbAllocated = ulPreAllocate; 136 // ulLength is still zero 137 *(pxstr->psz) = 0; 138 } 139 } 140 141 /* 142 *@@ xstrInitSet: 143 * this can be used instead of xstrInit if you 144 * have a free()'able string you want to initialize 145 * the XSTRING with. 146 * 147 * Do not use this on an XSTRING which is already 148 * initialized. Use xstrset instead. 149 * 150 *@@added V0.9.6 (2000-11-01) [umoeller] 151 */ 152 153 void xstrInitSet(PXSTRING pxstr, 154 PSZ pszNew) 155 { 156 pxstr->psz = pszNew; 157 if (!pszNew) 158 { 159 pxstr->cbAllocated = 0; 160 pxstr->ulLength = 0; 161 } 162 else 163 { 164 pxstr->ulLength = strlen(pszNew); 165 pxstr->cbAllocated = pxstr->ulLength + 1; 166 } 167 } 168 169 /* 170 *@@ xstrInitCopy: 171 * this can be used instead of xstrInit if you 172 * want to initialize an XSTRING with a copy 173 * of an existing string. 174 * 175 * Do not use this on an XSTRING which is already 176 * initialized. Use xstrcpy instead. 177 * 178 *@@added V0.9.6 (2000-11-01) [umoeller] 179 */ 180 181 void xstrInitCopy(PXSTRING pxstr, 182 const char *pcszSource) 183 { 184 if (pxstr) 185 { 186 memset(pxstr, 0, sizeof(XSTRING)); 187 188 if (pcszSource) 189 pxstr->ulLength = strlen(pcszSource); 190 191 if (pxstr->ulLength) 192 { 193 // we do have a source string: 194 pxstr->cbAllocated = pxstr->ulLength + 1; 195 pxstr->psz = (PSZ)malloc(pxstr->cbAllocated); 196 strcpy(pxstr->psz, pcszSource); 197 } 198 } 199 } 200 201 /* 202 *@@ xstrClear: 203 * clears the specified stack XSTRING and 204 * frees allocated memory. 205 * 206 * This is the reverse to xstrInit. 207 * 208 *@@added V0.9.6 (2000-11-01) [umoeller] 209 */ 210 211 void xstrClear(PXSTRING pxstr) // in/out: string 212 { 213 if (pxstr->psz) 214 free(pxstr->psz); 215 memset(pxstr, 0, sizeof(XSTRING)); 216 } 217 218 /* 219 *@@ xstrCreate: 220 * allocates a new XSTRING from the heap 221 * and calls xstrInit on it. 222 * 223 * Always use xstrFree to free associated 224 * resources. 225 * 226 *@@added V0.9.6 (2000-11-01) [umoeller] 227 */ 228 229 PXSTRING xstrCreate(ULONG ulPreAllocate) 230 { 231 PXSTRING pxstr = (PXSTRING)malloc(sizeof(XSTRING)); 232 if (pxstr) 233 xstrInit(pxstr, ulPreAllocate); 234 235 return (pxstr); 236 } 237 238 /* 239 *@@ xstrFree: 240 * frees the specified heap XSTRING, which must 241 * have been created using xstrCreate. 242 * 243 *@@added V0.9.6 (2000-11-01) [umoeller] 244 */ 245 246 VOID xstrFree(PXSTRING pxstr) // in/out: string 247 { 248 if (pxstr) 249 { 250 xstrClear(pxstr); 251 free(pxstr); 252 } 253 } 254 255 /* 256 *@@ xstrset: 257 * sets the specified XSTRING to a new string 258 * without copying it. 259 * 260 * pxstr is cleared before the new string is set. 261 * 262 * This ONLY works if pszNew has been allocated from 263 * the heap using malloc() or strdup() and is thus 264 * free()'able. 265 * 266 * This assumes that exactly strlen(pszNew) + 1 267 * bytes have been allocated for pszNew, which 268 * is true if pszNew comes from strdup(). 269 * 270 *@@added V0.9.6 (2000-11-01) [umoeller] 271 */ 272 273 ULONG xstrset(PXSTRING pxstr, // in/out: string 274 PSZ pszNew) // in: heap PSZ to use 275 { 276 xstrClear(pxstr); 277 pxstr->psz = pszNew; 278 if (pszNew) 279 { 280 pxstr->ulLength = strlen(pszNew); 281 pxstr->cbAllocated = pxstr->ulLength + 1; 282 } 283 // else null string: cbAllocated and ulLength are 0 already 284 285 return (pxstr->ulLength); 286 } 287 288 /* 55 289 *@@ xstrcpy: 56 * copies p szString to *ppszBuf, for which memory is allocated290 * copies pcszSource to pxstr, for which memory is allocated 57 291 * as necessary. 58 292 * 59 * If *ppszBuf != NULL, the existing memory is freed.60 * 61 * Returns the length of the new string ( including the null293 * If pxstr contains something, its contents are destroyed. 294 * 295 * Returns the length of the new string (excluding the null 62 296 * terminator), or null upon errors. 63 297 * 64 298 * Example: 65 + PSZ psz = NULL;66 + xstrcpy(&psz, "blah");67 * would have "psz" point to newly allocated buffer containing68 * "blah".299 * 300 + XSTRING str; 301 + xstrInit(&str, 0); 302 + xstrcpy(&str, "blah"); 69 303 * 70 304 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxcpy 71 */ 72 73 ULONG 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 101 ULONG 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); 305 *@@changed V0.9.6 (2000-11-01) [umoeller]: rewritten 306 */ 307 308 ULONG xstrcpy(PXSTRING pxstr, // in/out: string 309 const char *pcszSource) // in: source, can be NULL 310 { 311 xstrClear(pxstr); 312 313 if (pxstr) 314 { 315 ULONG ulSourceLength = 0; 316 if (pcszSource) 317 ulSourceLength = strlen(pcszSource); 318 319 if (ulSourceLength) 320 { 321 // we do have a source string: 322 ULONG cbNeeded = ulSourceLength + 1; 323 if (cbNeeded > pxstr->cbAllocated) 324 { 325 // we need more memory than we have previously 326 // allocated: 327 pxstr->cbAllocated = cbNeeded; 328 pxstr->psz = (PSZ)malloc(cbNeeded); 329 } 330 // else: we have enough memory 331 332 strcpy(pxstr->psz, pcszSource); 333 } 112 334 else 113 335 { 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] 336 // no source specified or source is empty: 337 if (pxstr->cbAllocated) 338 // we did have a string: set to empty, 339 // but leave allocated memory intact 340 *(pxstr->psz) = 0; 341 // else: pxstr->psz is still NULL 131 342 } 132 } 133 return (ulrc); 134 } 135 136 #else // __XWPMEMDEBUG__ 343 344 // in all cases, set new length 345 pxstr->ulLength = ulSourceLength; 346 } 347 348 return (pxstr->ulLength); 349 } 137 350 138 351 /* 139 352 *@@ xstrcat: 140 * appends p szString to *ppszBuf, which is re-allocated as141 * necessary.142 * 143 * If *ppszBuf is NULL, this behaves just asxstrcpy.144 * 145 * Returns the length of the new string ( including the null353 * appends pcszSource to pxstr, for which memory is allocated 354 * as necessary. 355 * 356 * If pxstr is empty, this behaves just like xstrcpy. 357 * 358 * Returns the length of the new string (excluding the null 146 359 * terminator), or null upon errors. 147 360 * 148 361 * Example: 149 + PSZ psz = strdup("blah"); 150 + xstrcat(&psz, "blup"); 362 * 363 + XSTRING str; 364 + xstrInit(&str, 0); 365 + xstrcpy(&str, "blah"); 366 + xstrcat(&str, "blup"); 367 * 151 368 * would do the following: 152 * a) free the old value of psz("blah");153 * b) reallocate psz;369 * a) free the old value of str ("blah"); 370 * b) reallocate str; 154 371 * c) so that psz afterwards points to a new string containing 155 372 * "blahblup". … … 159 376 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxcat 160 377 *@@changed V0.9.3 (2000-05-11) [umoeller]: returned 0 if pszString was initially empty; fixed 161 */ 162 163 ULONG xstrcat(XSTR ppszBuf, 164 const char *pszString) 378 *@@changed V0.9.6 (2000-11-01) [umoeller]: rewritten 379 */ 380 381 ULONG xstrcat(PXSTRING pxstr, // in/out: string 382 const char *pcszSource) // in: source, can be NULL 165 383 { 166 384 ULONG ulrc = 0; 167 if ((ppszBuf) && (pszString)) 168 { 169 if (*ppszBuf == NULL) 170 ulrc = xstrcpy(ppszBuf, pszString); 171 else 385 386 if (pxstr) 387 { 388 ULONG ulSourceLength = 0; 389 if (pcszSource) 390 ulSourceLength = strlen(pcszSource); 391 392 if (ulSourceLength) 172 393 { 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] 394 // we do have a source string: 395 396 // 1) memory management 397 ULONG cbNeeded = pxstr->ulLength + ulSourceLength + 1; 398 if (cbNeeded > pxstr->cbAllocated) 399 { 400 // we need more memory than we have previously 401 // allocated: 402 if (pxstr->cbAllocated) 403 // appendee already had memory: 404 // reallocate 405 pxstr->psz = (PSZ)realloc(pxstr->psz, 406 cbNeeded); 407 else 408 // appendee has no memory: 409 pxstr->psz = (PSZ)malloc(cbNeeded); 410 411 pxstr->cbAllocated = cbNeeded; 412 // ulLength is unchanged yet 413 } 414 // else: we have enough memory, both if appendee 415 // is empty or not empty 416 417 // now we have: 418 // -- if appendee (pxstr) had enough memory, no problem 419 // -- if appendee (pxstr) needed more memory 420 // -- and was not empty: pxstr->psz now points to a 421 // reallocated copy of the old string 422 // -- and was empty: pxstr->psz now points to a 423 // new (unitialized) buffer 424 425 // 2) append source string: 426 strcpy(pxstr->psz + pxstr->ulLength, 427 pcszSource); 428 429 // in all cases, set new length 430 pxstr->ulLength += ulSourceLength; 431 ulrc = ulSourceLength; 190 432 } 191 } 433 // else no source specified or source is empty: 434 // do nothing 435 } 436 192 437 return (ulrc); 193 438 } 194 439 195 #endif // else __XWPMEMDEBUG__196 197 #ifdef __XWPMEMDEBUG__ // setup.h, helpers\memdebug.c198 199 /*200 *@@ xstrrplDebug:201 *202 *@@added V0.9.3 (2000-04-11) [umoeller]203 */204 205 ULONG xstrrplDebug(PSZ *ppszBuf, // in/out: text buffer206 ULONG ulOfs, // in: where to begin search (can be 0)207 const char *pszSearch, // in: search string208 const char *pszReplace, // in: replacement string209 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 string232 cbNew = cbBuf233 + cbReplace234 - cbSearch235 + 1, // null terminator236 // offset where pszSearch was found237 ulFoundOfs = pFound - *ppszBuf;238 239 // allocate new buffer240 PSZ pszNew = (PSZ)memdMalloc(cbNew,241 file, line, function);242 243 if (ulFoundOfs)244 {245 // copy until offset246 strncpy(pszNew,247 *ppszBuf,248 ulFoundOfs);249 }250 251 if (cbReplace)252 {253 // copy replacement254 strncpy(pszNew + ulFoundOfs,255 pszReplace,256 cbReplace);257 }258 // copy rest259 strcpy(pszNew + ulFoundOfs + cbReplace,260 pFound + cbSearch);261 262 // replace PSZ pointer263 memdFree(*ppszBuf, file, line, function);264 *ppszBuf = pszNew;265 266 // return new length267 ulrc = cbNew;268 if (pulAfterOfs)269 *pulAfterOfs = ulFoundOfs + cbReplace;270 }271 }272 }273 return (ulrc);274 }275 276 #else277 278 440 /* 279 441 *@@ 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). 442 * replaces pstrSearch with pstrReplace in pxstr. 443 * 444 * Starting with V0.9.6, this operates entirely on 445 * XSTRING's for speed because we then know the string 446 * lengths already and can use memcpy instead of strcpy. 447 * This new version should be magnitudes faster. 448 * 449 * None of the pointers can be NULL, but if pstrReplace 450 * is empty, this effectively erases pstrSearch in pxstr. 451 * 452 * Returns the length of the new string (exclusing the 453 * null terminator) or 0 if pszSearch was not found 454 * (and pxstr was therefore not changed). 289 455 * 290 456 * If the string was found and (pulAfterOfs != NULL), … … 298 464 * function until it returns 0. 299 465 * 466 * There are two wrappers around this function which 467 * work on C strings instead (however, thus losing the 468 * speed advantage): 469 * 470 * -- strhrpl operates on C strings only; 471 * 472 * -- xstrcrpl uses C strings for the search and replace 473 * parameters. 474 * 300 475 * <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". 476 * 477 + XSTRING str; 478 + ULONG ulPos = 0; 479 + xstrInit(&str, 0); 480 + xstrcpy(&str, "Test phrase 1. Test phrase 2."); 481 + while (xstrrpl(&str, 482 + ulPos, 483 + "Test", // search 484 + "Dummy", // replace 485 + &ulPos)) 486 + ; 487 * 488 * would replace all occurences of "Test" in str with 489 * "Dummy". 306 490 * 307 491 *@@changed V0.9.0 [umoeller]: totally rewritten. 308 492 *@@changed V0.9.0 (99-11-08) [umoeller]: crashed if *ppszBuf was NULL. Fixed. 309 493 *@@changed V0.9.2 (2000-04-01) [umoeller]: renamed from strhxrpl 310 */ 311 312 ULONG 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) 494 *@@changed V0.9.6 (2000-11-01) [umoeller]: rewritten 495 */ 496 497 ULONG xstrrpl(PXSTRING pxstr, // in/out: string 498 ULONG ulOfs, // in: where to begin search (0 = start) 499 const XSTRING *pstrSearch, // in: search string; cannot be NULL 500 const XSTRING *pstrReplace, // in: replacement string; cannot be NULL 501 PULONG pulAfterOfs) // out: offset where found (ptr can be NULL) 317 502 { 318 503 ULONG ulrc = 0; 319 504 320 if ((p pszBuf) && (pszSearch) && (pszReplace))321 { 322 ULONG c bBuf = 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))505 if ((pxstr) && (pstrSearch) && (pstrReplace)) 506 { 507 ULONG cSearchLen = pstrSearch->ulLength; 508 509 // can we search this? 510 if ( (ulOfs < pxstr->ulLength) 511 && (cSearchLen) 512 ) 328 513 { 329 PSZ pFound = strstr((*ppszBuf) + ulOfs, 330 pszSearch); 514 // yes: 515 PSZ pFound = strstr(pxstr->psz + ulOfs, 516 pstrSearch->psz); 331 517 332 518 if (pFound) 333 519 { 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) 520 // found in buffer from ofs: 521 ULONG cReplaceLen = pstrReplace->ulLength; 522 // can be 0! 523 524 // length of new string 525 ULONG cbNeeded = pxstr->ulLength 526 + cReplaceLen 527 - cSearchLen 528 + 1, // null terminator 529 // offset where pszSearch was found 530 ulFoundOfs = pFound - pxstr->psz; 531 532 // now check if we have enough memory... 533 if (pxstr->cbAllocated < cbNeeded) 347 534 { 348 // copy until offset 349 strncpy(pszNew, 350 *ppszBuf, 351 ulFoundOfs); 535 // no, we need more memory: 536 // allocate new buffer 537 PSZ pszNew = (PSZ)malloc(cbNeeded); 538 539 if (ulFoundOfs) 540 // "found" was not at the beginning: 541 // copy from beginning up to found-offset 542 memcpy(pszNew, 543 pxstr->psz, 544 ulFoundOfs); // up to "found" 545 546 if (cReplaceLen) 547 { 548 // we have a replacement: 549 // insert it next 550 memcpy(pszNew + ulFoundOfs, 551 pstrReplace->psz, 552 cReplaceLen + 1); // include null terminator 553 } 554 555 // copy rest: 556 // pxstr frontFOUNDtail 557 // 0 1 558 // 01234567890123 559 // ³ ³ ³ ³ 560 // ³ ³ ÀÄ ulFoundOfs + cSearchLen = 10 561 // ³ ³ ³ 562 // ³ ÀÄ ulFoundOfs = 5 563 // ³ ³ 564 // pxstr->ulLength = 14 565 memcpy(pszNew + ulFoundOfs + cReplaceLen, 566 pFound + cSearchLen, 567 // remaining bytes: 568 pxstr->ulLength - ulFoundOfs - cSearchLen // 9 569 + 1); // null terminator 570 571 free(pxstr->psz); 572 pxstr->psz = pszNew; 573 pxstr->ulLength = cbNeeded - 1; 574 pxstr->cbAllocated = cbNeeded; 575 } // end if (pxstr->cbAllocated < cbNeeded) 576 else 577 { 578 // we have enough memory left, 579 // we can just overwrite in the middle... 580 581 PSZ pszAfterFoundBackup = 0; 582 // calc length of string after "found" 583 ULONG cTailLength = pxstr->ulLength - ulFoundOfs - cSearchLen; 584 585 // if "replace" is longer than "found", 586 // make a backup of the stuff after "found", 587 // or this would get overwritten 588 if (cReplaceLen > cSearchLen) 589 { 590 pszAfterFoundBackup = (PSZ)malloc(cTailLength + 1); 591 memcpy(pszAfterFoundBackup, 592 pFound + cSearchLen, 593 cTailLength + 1); 594 } 595 596 // now overwrite "found" in the middle 597 if (cReplaceLen) 598 { 599 memcpy(pxstr->psz + ulFoundOfs, 600 pstrReplace->psz, 601 cReplaceLen); // no null terminator 602 } 603 604 // now append tail (stuff after "found") again... 605 if (pszAfterFoundBackup) 606 { 607 // we made a backup above: 608 memcpy(pxstr->psz + ulFoundOfs + cReplaceLen, 609 pszAfterFoundBackup, 610 cTailLength + 1); 611 free(pszAfterFoundBackup); 612 // done! 613 } 614 else 615 // no backup: 616 if (cReplaceLen < cSearchLen) 617 // "replace" is shorter than "found: 618 memcpy(pxstr->psz + ulFoundOfs + cReplaceLen, 619 pFound + cSearchLen, 620 cTailLength + 1); 621 // else (cReplaceLen == cSearchLen): 622 // we can leave the tail as it is 623 624 pxstr->ulLength = cbNeeded - 1; 352 625 } 353 626 354 if (cbReplace)355 {356 // copy replacement357 strncpy(pszNew + ulFoundOfs,358 pszReplace,359 cbReplace);360 }361 // copy rest362 strcpy(pszNew + ulFoundOfs + cbReplace,363 pFound + cbSearch);364 365 // replace PSZ pointer366 free(*ppszBuf);367 *ppszBuf = pszNew;368 369 627 // return new length 370 ulrc = cbNe w;628 ulrc = cbNeeded - 1; 371 629 if (pulAfterOfs) 372 *pulAfterOfs = ulFoundOfs + c bReplace;630 *pulAfterOfs = ulFoundOfs + cReplaceLen; 373 631 } 374 632 } 375 633 } 634 376 635 return (ulrc); 377 636 } 378 637 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 398 PSZ 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 638 /* 639 *@@ xstrcrpl: 640 * wrapper around xstrrpl which allows using C strings 641 * for the find and replace parameters. 642 * 643 *@@added V0.9.6 (2000-11-01) [umoeller] 644 */ 645 646 ULONG xstrcrpl(PXSTRING pxstr, // in/out: string 647 ULONG ulOfs, // in: where to begin search (0 = start) 648 const char *pcszSearch, // in: search string; cannot be NULL 649 const char *pcszReplace, // in: replacement string; cannot be NULL 650 PULONG pulAfterOfs) // out: offset where found (ptr can be NULL) 651 { 652 ULONG ulrc = 0; 653 XSTRING xstrFind, 654 xstrReplace; 655 xstrInit(&xstrFind, 0); 656 xstrset(&xstrFind, (PSZ)pcszSearch); 657 xstrInit(&xstrReplace, 0); 658 xstrset(&xstrReplace, (PSZ)pcszReplace); 659 660 return (xstrrpl(pxstr, ulOfs, &xstrFind, &xstrReplace, pulAfterOfs)); 661 } 662 663 // test case 664 665 /* int main(void) 666 { 667 XSTRING str, 668 strFind, 669 strReplace; 670 ULONG ulOfs = 0; 671 672 xstrInit(&str, 100); 673 xstrInit(&strFind, 0); 674 xstrInit(&strReplace, 0); 675 676 xstrcpy(&str, "Test string 1. Test string 2. Test string 3. !"); 677 xstrcpy(&strFind, "Test"); 678 xstrcpy(&strReplace, "Dummy"); 679 680 printf("Old string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated); 681 682 while (xstrrpl(&str, 683 ulOfs, 684 &strFind, 685 &strReplace, 686 &ulOfs)) 687 ; 688 689 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated); 690 691 xstrcpy(&strFind, strReplace.psz); 692 xstrClear(&strReplace); 693 ulOfs = 0; 694 while (xstrrpl(&str, 695 ulOfs, 696 &strFind, 697 &strReplace, 698 &ulOfs)) 699 ; 700 701 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated); 702 703 xstrcpy(&strFind, " "); 704 xstrcpy(&strReplace, "."); 705 ulOfs = 0; 706 while (xstrrpl(&str, 707 ulOfs, 708 &strFind, 709 &strReplace, 710 &ulOfs)) 711 ; 712 713 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated); 714 715 xstrcpy(&strFind, "."); 716 xstrcpy(&strReplace, "***************************"); 717 ulOfs = 0; 718 while (xstrrpl(&str, 719 ulOfs, 720 &strFind, 721 &strReplace, 722 &ulOfs)) 723 ; 724 725 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated); 726 727 xstrcpy(&strFind, "*"); 728 xstrClear(&strReplace); 729 ulOfs = 0; 730 while (xstrrpl(&str, 731 ulOfs, 732 &strFind, 733 &strReplace, 734 &ulOfs)) 735 ; 736 737 printf("New string is: \"%s\" (%d/%d)\n", str.psz, str.ulLength, str.cbAllocated); 738 } */ 739
Note:
See TracChangeset
for help on using the changeset viewer.