#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include <stddef.h>#include <stdarg.h>#include "logger.h"#include "pldstr.h"#include "MALLOC.h"Include dependency graph for pldstr.c:

Go to the source code of this file.
Functions | |
| char * | PLD_strstr (char *haystack, char *needle, int insensitive) |
| char * | PLD_strncpy (char *dst, const char *src, size_t len) |
| char * | PLD_strncat (char *dst, const char *src, size_t len) |
| char * | PLD_strncate (char *dst, const char *src, size_t len, char *endpoint) |
| int | PLD_strncasecmp (char *s1, char *s2, int n) |
| char * | PLD_strtok (struct PLD_strtok *st, char *line, char *delimeters) |
| int | PLD_strlower (unsigned char *convertme) |
| char * | PLD_strreplace_general (struct PLD_strreplace *replace_details) |
| char * | PLD_strreplace (char **source, char *searchfor, char *replacewith, int replacenumber) |
| char * | PLD_dprintf (const char *format,...) |
| char* PLD_dprintf | ( | const char * | format, | |
| ... | ||||
| ) |
Definition at line 725 of file pldstr.c.
References FREE, MALLOC, n, NULL, p, REALLOC, size, and vsnprintf().
Referenced by OLE_decode_stream(), OLE_store_stream(), OLEUNWRAP_decode_attachment(), and OLEUNWRAP_save_stream().
00726 { 00727 int n, size = 1024; /* Assume we don't need more than 1K to start with*/ 00728 char *p; 00729 va_list ap; 00730 00731 /* Attempt to allocate and then check */ 00732 p = MALLOC(size *sizeof(char)); 00733 if (p == NULL) return NULL; 00734 00735 while (1) 00736 { 00737 /* Attempt to print out string out into the allocated space*/ 00738 va_start(ap, format); 00739 00740 n = vsnprintf (p, size, format, ap); 00741 va_end(ap); 00742 00743 /* If things went well, then return the new string*/ 00744 if ((n > -1) && (n < size)) return p; 00745 00746 /* If things didn't go well, then we have to allocate more space*/ 00747 /* based on which glibc we're using ( fortunately, the return codes*/ 00748 /* tell us which glibc is being used! *phew**/ 00749 00750 /* If n > -1, then we're being told precisely how much space we need*/ 00751 /* else (older glibc) we have to just guess again ...*/ 00752 00753 if (n > -1) size = n+1; /* Allocate precisely what is needed*/ 00754 else size *= 2; /* Double the amount allocated, note, we could just increase by 1K, but if we have a long string, we'd end up using a lot of realloc's*/ 00755 00756 /* We could just realloc 'blind', but that'd be wrong and potentially cause a DoS, so*/ 00757 /* instead, we'll be good and first attempt to realloc to a temp variable then, if all*/ 00758 /* is well, we go ahead and update*/ 00759 if (1) 00760 { 00761 char *tmp_p; 00762 00763 tmp_p = REALLOC(p, size); 00764 if (tmp_p == NULL){ if (p != NULL) FREE(p); return NULL; } 00765 else p = tmp_p; 00766 } 00767 } 00768 00769 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int PLD_strlower | ( | unsigned char * | convertme | ) |
Definition at line 366 of file pldstr.c.
Referenced by PLD_strstr().
00367 { 00368 00369 /* Updates:*/ 00370 /* 09-11-2002 - changed from 'char *' to 'unsigned char *' to deal with*/ 00371 /* non-ASCII characters ( ie, french ). Pointed out by Emmanuel Collignon*/ 00372 00373 char *c = convertme; 00374 00375 while ( *c != '\0') {*c = tolower((int)*c); c++;} 00376 00377 return 0; 00378 }
Here is the caller graph for this function:

Definition at line 234 of file pldstr.c.
00235 { 00236 char *ds1 = s1, *ds2 = s2; 00237 char c1, c2; 00238 int result = 0; 00239 00240 while(n > 0) 00241 { 00242 c1 = tolower(*ds1); 00243 c2 = tolower(*ds2); 00244 00245 if (c1 == c2) 00246 { 00247 n--; 00248 ds1++; 00249 ds2++; 00250 } 00251 else 00252 { 00253 result = c2 - c1; 00254 n = 0; 00255 } 00256 00257 } 00258 00259 return result; 00260 00261 }
| char* PLD_strncat | ( | char * | dst, | |
| const char * | src, | |||
| size_t | len | |||
| ) |
Definition at line 127 of file pldstr.c.
References sp().
00128 { 00129 char *dp = dst; 00130 const char *sp = src; 00131 size_t cc; 00132 00133 if (len == 0) return dst; 00134 00135 len--; 00136 00137 /* Locate the end of the current string.*/ 00138 cc = 0; 00139 while ((*dp)&&(cc < len)) { dp++; cc++; } 00140 00141 /* If we have no more buffer space, then return the destination*/ 00142 00143 if (cc >= len) return dst; 00144 00145 /* While we have more source, and there's more char space left in the buffer*/ 00146 00147 while ((*sp)&&(cc < len)) 00148 { 00149 cc++; 00150 *dp = *sp; 00151 dp++; 00152 sp++; 00153 } 00154 00155 /* Terminate dst, as a gaurantee of string ending.*/ 00156 00157 *dp = '\0'; 00158 00159 return dst; 00160 }
Here is the call graph for this function:

| char* PLD_strncate | ( | char * | dst, | |
| const char * | src, | |||
| size_t | len, | |||
| char * | endpoint | |||
| ) |
Definition at line 176 of file pldstr.c.
References sp().
00177 { 00178 char *dp = dst; 00179 const char *sp = src; 00180 size_t cc = 0; 00181 00182 if (len == 0) return dst; 00183 00184 len--; 00185 00186 /* If endpoint does not relate correctly, then force manual detection*/ 00187 /* of the endpoint.*/ 00188 00189 if ((!endpoint)||(endpoint == dst)||((endpoint -dst +1)>(int)len)) 00190 { 00191 /* Locate the end of the current string.*/ 00192 cc = 0; 00193 while ((*dp != '\0')&&(cc < len)) { dp++; cc++; } 00194 } 00195 else { 00196 cc = endpoint -dst +1; 00197 dp = endpoint; 00198 } 00199 00200 /* If we have no more buffer space, then return the destination*/ 00201 00202 if (cc >= len) return dst; 00203 00204 /* While we have more source, and there's more char space left in the buffer*/ 00205 00206 while ((*sp)&&(cc < len)) 00207 { 00208 cc++; 00209 *dp = *sp; 00210 dp++; 00211 sp++; 00212 } 00213 00214 /* Terminate dst, as a gaurantee of string ending.*/ 00215 00216 *dp = '\0'; 00217 00218 return dst; 00219 }
Here is the call graph for this function:

| char* PLD_strncpy | ( | char * | dst, | |
| const char * | src, | |||
| size_t | len | |||
| ) |
Definition at line 82 of file pldstr.c.
00083 { 00084 00085 /* Thanks go to 'defrost' of #c for providing the replacement*/ 00086 /* code which you now see here. It covers the errors better*/ 00087 /* than my own previous code.*/ 00088 00089 /* If we have no buffer space, then it's futile attempting*/ 00090 /* to copy anything, just return NULL*/ 00091 if (len==0) return NULL; 00092 00093 /* Providing our destination pointer isn't NULL, we can*/ 00094 /* commence copying data across*/ 00095 00096 if (dst) 00097 { 00098 char *dp = dst; 00099 00100 /* If our source string exists, start moving it to the*/ 00101 /* destination string character at a time.*/ 00102 if (src) 00103 { 00104 char *sp = (char *)src; 00105 while ((--len)&&(*sp)) { *dp=*sp; dp++; sp++; } 00106 } 00107 00108 *dp='\0'; 00109 } 00110 00111 return dst; 00112 }
Here is the call graph for this function:

| char* PLD_strreplace | ( | char ** | source, | |
| char * | searchfor, | |||
| char * | replacewith, | |||
| int | replacenumber | |||
| ) |
Definition at line 685 of file pldstr.c.
References PLD_strreplace::insensitive, NULL, PLD_strreplace_general(), PLD_strreplace::postexist, PLD_strreplace::preexist, PLD_strreplace::replacenumber, PLD_strreplace::replacewith, PLD_strreplace::searchfor, and PLD_strreplace::source.
00686 { 00687 struct PLD_strreplace replace_details; 00688 char *tmp_source; 00689 00690 replace_details.source = *source; 00691 replace_details.searchfor = searchfor; 00692 replace_details.replacewith = replacewith; 00693 replace_details.replacenumber = replacenumber; 00694 replace_details.preexist = NULL; 00695 replace_details.postexist = NULL; 00696 replace_details.insensitive = 0; 00697 00698 tmp_source = PLD_strreplace_general( &replace_details ); 00699 00700 if (tmp_source != *source) *source = tmp_source; 00701 00702 return *source; 00703 }
Here is the call graph for this function:

| char* PLD_strreplace_general | ( | struct PLD_strreplace * | replace_details | ) |
Definition at line 403 of file pldstr.c.
References FL, FREE, PLD_strreplace::insensitive, LOGGER_log(), MALLOC, NULL, p, PLD_strstr(), PLD_strreplace::postexist, PLD_strreplace::preexist, PLD_strreplace::replacenumber, PLD_strreplace::replacewith, PLD_strreplace::searchfor, and PLD_strreplace::source.
Referenced by PLD_strreplace().
00404 { 00405 char *new_buffer=NULL; 00406 char *source_end; 00407 char *segment_start, *segment_end, *segment_p; 00408 char *new_p; 00409 char *preexist_location=NULL; 00410 char *postexist_location=NULL; 00411 int replace_count=0; 00412 int size_required; 00413 int size_difference; 00414 int source_length; 00415 int searchfor_length; 00416 int replacewith_length; 00417 int segment_ok; 00418 00419 if (replace_details->source == NULL) return NULL; 00420 00421 source_length = strlen( replace_details->source ); 00422 source_end = replace_details->source +source_length; 00423 searchfor_length = strlen(replace_details->searchfor); 00424 replacewith_length = strlen(replace_details->replacewith); 00425 size_difference = replacewith_length -searchfor_length; 00426 size_required = source_length; 00427 replace_count = replace_details->replacenumber; 00428 00429 if ((replace_details->preexist != NULL)&&(strlen(replace_details->preexist) < 1)) replace_details->preexist = NULL; 00430 if ((replace_details->postexist != NULL)&&(strlen(replace_details->postexist) < 1)) replace_details->postexist = NULL; 00431 00432 /* If we have a 'pre-exist' request, then we need to check this out first*/ 00433 /* because if the pre-exist string cannot be found, then there's very*/ 00434 /* little point us continuing on in our search ( because without the*/ 00435 /* preexist string existing, we are thus not qualified to replace anything )*/ 00436 if (replace_details->preexist != NULL) 00437 { 00438 preexist_location = PLD_strstr(replace_details->source, replace_details->preexist, replace_details->insensitive); 00439 if (preexist_location == NULL) 00440 { 00441 return replace_details->source; 00442 } 00443 } 00444 00445 /* Determine if initial POSTexist tests will pass, if we don't pick up*/ 00446 /* anything here, then there's no point in continuing either*/ 00447 if (replace_details->postexist != NULL) 00448 { 00449 char *p = replace_details->source; 00450 postexist_location = NULL; 00451 do { 00452 p = PLD_strstr(p, replace_details->postexist, replace_details->insensitive); 00453 if (p != NULL) 00454 { 00455 postexist_location = p; 00456 p = p +strlen(replace_details->postexist); 00457 } 00458 } while (p != NULL); 00459 00460 if (postexist_location == NULL) 00461 { 00462 return replace_details->source; 00463 } 00464 } 00465 00466 00467 /* Step 1 - determine the MAXIMUM number of times we might have to replace this string ( or the limit*/ 00468 /* set by replacenumber*/ 00469 00470 /* Note - we only need this number if the string we're going to be inserting into the */ 00471 /* source is larger than the one we're replacing - this is so that we can ensure that*/ 00472 /* we have sufficient memory available in the buffer.*/ 00473 if (size_difference > 0) 00474 { 00475 if (replace_count == 0) 00476 { 00477 char *p, *q; 00478 00479 p = replace_details->source; 00480 q = PLD_strstr(p, replace_details->searchfor, replace_details->insensitive); 00481 while (q != NULL) 00482 { 00483 replace_count++; 00484 /*size_required += size_difference;*/ 00485 p = q +searchfor_length; 00486 q = PLD_strstr(p, replace_details->searchfor, replace_details->insensitive); 00487 } 00488 00489 } 00490 size_required = source_length +(size_difference *replace_count) +1; 00491 } else size_required = source_length +1; 00492 00493 00494 /* Allocate the memory required to hold the new string [at least], check to see that*/ 00495 /* all went well, if not, then return an error*/ 00496 new_buffer = MALLOC( sizeof(char) *size_required); 00497 if (new_buffer == NULL) 00498 { 00499 LOGGER_log("%s:%d:PLD_strreplace:ERROR: Cannot allocate %d bytes of memory to perform replacement operation", FL, size_required); 00500 return replace_details->source; 00501 } 00502 00503 /* Our segment must always start at the beginning of the source, */ 00504 /* on the other hand, the segment_end can be anything from the*/ 00505 /* next byte to NULL ( which is specially treated to mean to */ 00506 /* the end of the source )*/ 00507 segment_start = replace_details->source; 00508 00509 00510 /* Locate the first segment */ 00511 segment_ok = 0; 00512 segment_end = PLD_strstr(replace_details->source, replace_details->searchfor, replace_details->insensitive); 00513 00514 /* Determine if the first segment is valid in the presence of the */ 00515 /* pre-exist and post-exist requirements*/ 00516 while ((segment_end != NULL)&&(segment_ok == 0)\ 00517 &&((replace_details->preexist != NULL)||(replace_details->postexist != NULL))) 00518 { 00519 int pre_ok = 0; 00520 int post_ok = 0; 00521 00522 /* The PREexist test assumes a couple of factors - please ensure these are*/ 00523 /* relevant if you change any code prior to this point.*/ 00524 /* */ 00525 /* 1. preexist_location has already been computed and is not NULL*/ 00526 00527 /* 2. By relative position, the first preexist_location will be a valid location*/ 00528 /* on which to validate for ALL replacements beyond that point, thus, we*/ 00529 /* never actually have to recompute preexist_location again.*/ 00530 00531 /* 3. Conversely, the last computed postexist_location is valid for all */ 00532 /* matches before it*/ 00533 00534 if (preexist_location == NULL) pre_ok = 1; 00535 else if (preexist_location < segment_end){ pre_ok = 1;} 00536 00537 if (postexist_location == NULL) post_ok = 1; 00538 else if (postexist_location > segment_end){ post_ok = 1;} 00539 00540 if ((pre_ok == 0)||(post_ok == 0)) { segment_end = PLD_strstr(segment_end +searchfor_length, replace_details->searchfor, replace_details->insensitive); } 00541 else segment_ok = 1; 00542 } 00543 00544 segment_p = segment_start; 00545 new_p = new_buffer; 00546 while (segment_start != NULL) 00547 { 00548 int replacewith_count; 00549 char *replacewith_p; 00550 00551 if (segment_end == NULL) segment_end = source_end; 00552 00553 replace_count--; 00554 00555 /* Perform the segment copy*/ 00556 segment_p = segment_start; 00557 while ((segment_p < segment_end)&&(size_required > 0)) 00558 { 00559 *new_p = *segment_p; 00560 new_p++; 00561 segment_p++; 00562 size_required--; 00563 } 00564 00565 /* Perform the string replacement*/ 00566 if (segment_end < source_end) 00567 { 00568 replacewith_count = replacewith_length; 00569 replacewith_p = replace_details->replacewith; 00570 while ((replacewith_count--)&&(size_required > 0)) 00571 { 00572 *new_p = *replacewith_p; 00573 new_p++; 00574 replacewith_p++; 00575 size_required--; 00576 } 00577 } 00578 00579 if (size_required < 1 ) 00580 { 00581 LOGGER_log("%s:%d:PLD_strreplace_general: Allocated memory ran out while replacing '%s' with '%s'",FL, replace_details->searchfor, replace_details->replacewith); 00582 *new_p='\0'; 00583 break; 00584 } 00585 00586 /* Find the next segment*/ 00587 segment_start = segment_end +searchfor_length; 00588 00589 /* If we've reached the end of the number of replacements we're supposed*/ 00590 /* to do, then we prepare the termination of the while loop by setting*/ 00591 /* our segment end to the end of the source.*/ 00592 00593 /* NOTE: Remember that the replace_count is pre-decremented at the start*/ 00594 /* of the while loop, so, if the caller requested '0' replacements*/ 00595 /* this will now be -1, thus, it won't get terminated from this == 0*/ 00596 /* match. Just thought you'd like to be reminded of that incase you*/ 00597 /* were wondering "Huh? this would terminate an unlimited replacement"*/ 00598 if (replace_count == 0) 00599 { 00600 segment_end = NULL; 00601 } else { 00602 /* If our new segment to copy starts after the*/ 00603 /* end of the source, then we actually have */ 00604 /* nothing else to copy, thus, we prepare the*/ 00605 /* segment_start varible to cause the while loop */ 00606 /* to terminate.*/ 00607 00608 /* Otherwise, we try and locate the next segment*/ 00609 /* ending point, and set the starting point to*/ 00610 /* be on the 'other side' of the 'searchfor' string*/ 00611 /* which we found in the last search.*/ 00612 00613 if (segment_start > source_end) 00614 { 00615 segment_start = NULL; 00616 } else { 00617 00618 /* Try find the next segment*/ 00619 segment_ok = 0; 00620 segment_end = PLD_strstr(segment_end +searchfor_length, replace_details->searchfor, replace_details->insensitive); 00621 00622 /* If we have a pre/post-exist requirement, then enter into this*/ 00623 /* series of tests. NOTE - at least one of the pre or post tests*/ 00624 /* must fire to give an meaningful result - else we'll end up with */ 00625 /* a loop which simply goes to the end of the searchspace buffer*/ 00626 while ((segment_end != NULL)&&(segment_ok == 0)\ 00627 &&((replace_details->preexist != NULL)||(replace_details->postexist != NULL))) 00628 { 00629 int pre_ok = 0; 00630 int post_ok = 0; 00631 00632 /* The PREexist test assumes a couple of factors - please ensure these are*/ 00633 /* relevant if you change any code prior to this point.*/ 00634 /* */ 00635 /* 1. preexist_location has already been computed and is not NULL*/ 00636 00637 /* 2. By relative position, the first preexist_location will be a valid location*/ 00638 /* on which to validate for ALL replacements beyond that point, thus, we*/ 00639 /* never actually have to recompute preexist_location again.*/ 00640 00641 /* 3. Conversely, the last computed postexist_location is valid for all */ 00642 /* matches before it*/ 00643 00644 if (preexist_location == NULL) pre_ok = 1; 00645 else if (preexist_location < segment_end){ pre_ok = 1;} 00646 00647 if (postexist_location == NULL) post_ok = 1; 00648 else if (postexist_location > segment_end){ post_ok = 1;} 00649 00650 if ((pre_ok == 0)||(post_ok == 0)) { segment_end = PLD_strstr(segment_end +searchfor_length, replace_details->searchfor, replace_details->insensitive); } 00651 else segment_ok = 1; 00652 } 00653 00654 } /* If-else segment_start > source_end*/ 00655 00656 } 00657 00658 } 00659 00660 *new_p = '\0'; 00661 00662 if (replace_details->source != NULL) FREE (replace_details->source); 00663 replace_details->source = new_buffer; 00664 return new_buffer; 00665 }
Here is the call graph for this function:

Here is the caller graph for this function:

| char* PLD_strstr | ( | char * | haystack, | |
| char * | needle, | |||
| int | insensitive | |||
| ) |
Definition at line 37 of file pldstr.c.
References FREE, ne, NULL, PLD_strlower(), and result.
Referenced by PLD_strreplace_general().
00038 { 00039 char *hs, *ne; 00040 char *result; 00041 00042 /* LOGGER_log("%s:%d:\nHS=%s\nNE=%s\nIS=%d\n",FL, haystack, needle, insensitive );*/ 00043 00044 if (insensitive > 0) 00045 { 00046 hs = strdup(haystack); 00047 PLD_strlower(hs); 00048 ne = strdup(needle); 00049 PLD_strlower(ne); 00050 } else { 00051 hs = haystack; 00052 ne = needle; 00053 } 00054 00055 result = strstr(hs, ne); 00056 /* if (result) LOGGER_log("%s:%d:HIT: %s",FL, result);*/ 00057 /* else LOGGER_log("%s:%d:MISS (looking for %s|%s)",FL, needle,ne);*/ 00058 00059 if ((result != NULL)&&(insensitive > 0)) 00060 { 00061 result = result -hs +haystack; 00062 FREE(hs); 00063 FREE(ne); 00064 00065 /* LOGGER_log("%s:%d:HIT - %s",FL, result );*/ 00066 } 00067 00068 return result; 00069 }
Here is the call graph for this function:

Here is the caller graph for this function:

| char* PLD_strtok | ( | struct PLD_strtok * | st, | |
| char * | line, | |||
| char * | delimeters | |||
| ) |
Definition at line 274 of file pldstr.c.
References PLD_strtok::delimeter, NULL, result, and PLD_strtok::start.
00275 { 00276 char *stop; 00277 char *dc; 00278 char *result = NULL; 00279 00280 if ( line ) 00281 { 00282 st->start = line; 00283 } 00284 00285 /*Strip off any leading delimeters*/ 00286 00287 dc = delimeters; 00288 while ((st->start)&&(*dc != '\0')) 00289 { 00290 if (*dc == *(st->start)) 00291 { 00292 st->start++; 00293 dc = delimeters; 00294 } 00295 else dc++; 00296 } 00297 00298 /* Where we are left, is the start of our token.*/ 00299 00300 result = st->start; 00301 00302 if ((st->start)&&(st->start != '\0')) 00303 { 00304 stop = strpbrk( st->start, delimeters ); /* locate our next delimeter */ 00305 00306 /* If we found a delimeter, then that is good. We must now break the string here*/ 00307 /* and don't forget to store the character which we stopped on. Very useful bit*/ 00308 /* of information for programs which process expressions.*/ 00309 00310 if (stop) 00311 { 00312 00313 /* Store our delimeter.*/ 00314 00315 st->delimeter = *stop; 00316 00317 /* Terminate our token.*/ 00318 00319 *stop = '\0'; 00320 00321 00322 /* Because we're emulating strtok() behaviour here, we have to*/ 00323 /* absorb all the concurrent delimeters, that is, unless we*/ 00324 /* reach the end of the string, we cannot return a string with*/ 00325 /* no chars.*/ 00326 00327 stop++; 00328 dc = delimeters; 00329 while (*dc != '\0') 00330 { 00331 if (*dc == *stop) 00332 { 00333 stop++; 00334 dc = delimeters; 00335 } 00336 else dc++; 00337 } /* While*/ 00338 00339 if (*stop == '\0') st->start = NULL; 00340 else st->start = stop; 00341 00342 } 00343 else { 00344 st->start = NULL; 00345 st->delimeter = '\0'; 00346 } 00347 } 00348 else { 00349 st->start = NULL; 00350 result = NULL; 00351 } 00352 00353 00354 return result; 00355 }
1.5.1