diff options
| author | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-03-26 16:43:03 -0400 | 
|---|---|---|
| committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-04-02 18:55:46 -0400 | 
| commit | 9910a30f0c26b3180d46418abad760f86a253aa2 (patch) | |
| tree | 6c5209b5decbdc4206a90dfb3120ebbe88525d65 | |
| parent | 232763cb702e5b39ec5a051ec41582e42adaef59 (diff) | |
| download | stasis-9910a30f0c26b3180d46418abad760f86a253aa2.tar.gz | |
Fix replace_text*() functions
* Now return an error code
* Completely rewrote replace_text()
| -rw-r--r-- | include/relocation.h | 4 | ||||
| -rw-r--r-- | src/relocation.c | 106 | 
2 files changed, 78 insertions, 32 deletions
| diff --git a/include/relocation.h b/include/relocation.h index ea9da9f..b734433 100644 --- a/include/relocation.h +++ b/include/relocation.h @@ -16,7 +16,7 @@  #endif  #include <unistd.h> -void replace_text(char *original, const char *target, const char *replacement); -void file_replace_text(const char* filename, const char* target, const char* replacement); +int replace_text(char *original, const char *target, const char *replacement); +int file_replace_text(const char* filename, const char* target, const char* replacement);  #endif //OMC_RELOCATION_H diff --git a/src/relocation.c b/src/relocation.c index b92af2b..8b18efd 100644 --- a/src/relocation.c +++ b/src/relocation.c @@ -10,7 +10,10 @@   * ~~~{.c}   * char *str = (char *)calloc(100, sizeof(char));   * strcpy(str, "This are a test."); - * replace_text(str, "are", "is"); + * if (replace_text(str, "are", "is")) { + *     fprintf(stderr, "string replacement failed\n"); + *     exit(1); + * }   * // str is: "This is a test."   * free(str);   * ~~~ @@ -18,64 +21,106 @@   * @param original string to modify   * @param target string value to replace   * @param replacement string value + * @return 0 on success, -1 on error   */ -void replace_text(char *original, const char *target, const char *replacement) { +int replace_text(char *original, const char *target, const char *replacement) {      char buffer[OMC_BUFSIZ]; -    char *tmp = original; +    char *pos = original; +    char *match = NULL; +    size_t original_len = strlen(original); +    size_t target_len = strlen(target); +    size_t rep_len = strlen(replacement); +    size_t buffer_len = 0; + +    if (original_len > sizeof(buffer)) { +        errno = EINVAL; +        SYSERROR("The original string is larger than buffer: %zu > %zu\n", original_len, sizeof(buffer)); +        return -1; +    }      memset(buffer, 0, sizeof(buffer)); -    while (*tmp != '\0') { -        if (!strncmp(tmp, target, strlen(target))) { -            size_t replen; -            char *stop_at = strchr(tmp, '\n'); -            if (stop_at) { -                replen = (stop_at - tmp); -            } else { -                replen = strlen(replacement); +    if ((match = strstr(pos, target))) { +        while (*pos != '\0') { +            // append to buffer the bytes leading up to the match +            strncat(buffer, pos, match - pos); +            // position in the string jump ahead to the beginning of the match +            pos = match; + +            // replacement is shorter than the target +            if (rep_len < target_len) { +                // shrink the string +                strcat(buffer, replacement); +                memmove(pos, pos + target_len, strlen(pos) - target_len); +                memset(pos + (strlen(pos) - target_len), 0, target_len); +            } else { // replacement is longer than the target +                // write the replacement value to the buffer +                strcat(buffer, replacement); +                // target consumed. jump to the end of the substring. +                pos += target_len; +            } +            // find more matches +            if (!(match = strstr(pos, target))) { +                // no more matches +                // append whatever remains to the buffer +                strcat(buffer, pos); +                // stop +                break;              } -            strcat(buffer, replacement); -            strcat(buffer, "\n"); -            tmp += replen; -        } else { -            strncat(buffer, tmp, 1);          } -        tmp++;      } + +    buffer_len = strlen(buffer); +    if (buffer_len < original_len) { +        // truncate whatever remains of the original buffer +        memset(original + buffer_len, 0, original_len - buffer_len); +    } +    // replace original with contents of buffer      strcpy(original, buffer); +    return 0;  }  /**   * Replace `target` with `replacement` in `filename`   *   * ~~~{.c} - * file_replace_text("/path/to/file.txt, "are", "is"); + * if (file_replace_text("/path/to/file.txt, "are", "is")) { + *     fprintf(stderr, "failed to replace strings in file\n"); + *     exit(1); + * }   * ~~~   *   * @param filename path to file   * @param target string value to replace   * @param replacement string + * @return 0 on success, -1 on error   */ -void file_replace_text(const char* filename, const char* target, const char* replacement) { -    FILE *fp = fopen(filename, "r"); -    if (fp == NULL) { -        fprintf(stderr, "unable to open for reading: %s\n", filename); -        return; -    } - +int file_replace_text(const char* filename, const char* target, const char* replacement) { +    int result;      char buffer[OMC_BUFSIZ];      char tempfilename[] = "tempfileXXXXXX"; -    FILE *tfp = fopen(tempfilename, "w"); +    FILE *fp; +    FILE *tfp; + +    fp = fopen(filename, "r"); +    if (!fp) { +        fprintf(stderr, "unable to open for reading: %s\n", filename); +        return -1; +    } -    if (tfp == NULL) { -        fprintf(stderr, "unable to open temporary fp for writing: %s\n", tempfilename); +    tfp = fopen(tempfilename, "w"); +    if (!tfp) { +        SYSERROR("unable to open temporary fp for writing: %s", tempfilename);          fclose(fp); -        return; +        return -1;      }      // Write modified strings to temporary file +    result = 0;      while (fgets(buffer, sizeof(buffer), fp)) {          if (strstr(buffer, target)) { -            replace_text(buffer, target, replacement); +            if (replace_text(buffer, target, replacement)) { +                result = -1; +            }          }          fputs(buffer, tfp);      } @@ -86,4 +131,5 @@ void file_replace_text(const char* filename, const char* target, const char* rep      // Replace original with modified copy      remove(filename);      rename(tempfilename, filename); +    return result;  }
\ No newline at end of file | 
