| 78 | */ |
| 79 | |
| 80 | char *gmt_strrep(const char *s1, const char *s2, const char *s3) { |
| 81 | size_t s1_len, s2_len, s3_len, count, s1_without_s2_len, newstr_len, i, substr_len, remains; |
| 82 | const char *p, *start_substr, *end_substr; |
| 83 | char *newstr, *dst; |
| 84 | if (!s1 || !s2 || !s3) |
| 85 | return 0; |
| 86 | s1_len = strlen(s1); |
| 87 | if (!s1_len) |
| 88 | return (char *)s1; |
| 89 | s2_len = strlen(s2); |
| 90 | if (!s2_len) |
| 91 | return (char *)s1; |
| 92 | |
| 93 | /* |
| 94 | * Two-pass approach: figure out how much space to allocate for |
| 95 | * the new string, pre-allocate it, then perform replacement(s). |
| 96 | */ |
| 97 | count = 0; |
| 98 | p = s1; |
| 99 | assert(s2_len); /* otherwise, strstr(s1,s2) will return s1. */ |
| 100 | do { |
| 101 | p = strstr(p, s2); |
| 102 | if (p) { |
| 103 | p += s2_len; |
| 104 | count++; |
| 105 | } |
| 106 | } while (p); |
| 107 | |
| 108 | if (!count) |
| 109 | return (char *)s1; |
| 110 | |
| 111 | /* |
| 112 | * The following size arithmetic is extremely cautious, to guard against size_t overflows. |
| 113 | */ |
| 114 | assert(s1_len >= count * s2_len); |
| 115 | assert(count); |
| 116 | s1_without_s2_len = s1_len - count * s2_len; |
| 117 | s3_len = strlen(s3); |
| 118 | newstr_len = s1_without_s2_len + count * s3_len; |
| 119 | if (s3_len && ((newstr_len <= s1_without_s2_len) || (newstr_len + 1 == 0))) /* Overflow. */ |
| 120 | return 0; |
| 121 | |
| 122 | newstr = (char *)calloc(newstr_len + 1, sizeof(char)); /* w/ terminator */ |
| 123 | if (!newstr) /* ENOMEM, but no good way to signal it. */ |
| 124 | return 0; |
| 125 | |
| 126 | dst = newstr; |
| 127 | start_substr = s1; |
| 128 | for (i = 0; i != count; ++i) { |
| 129 | end_substr = strstr(start_substr, s2); |
| 130 | assert(end_substr); |
| 131 | substr_len = end_substr - start_substr; |
| 132 | memcpy(dst, start_substr, substr_len); |
| 133 | dst += substr_len; |
| 134 | memcpy(dst, s3, s3_len); |
| 135 | dst += s3_len; |
| 136 | start_substr = end_substr + s2_len; |
| 137 | } |
no outgoing calls
no test coverage detected