EAPI Eina_Bool eina_strbuf_replace(Eina_Strbuf *buf, const char *str, const char *with, unsigned int n) { size_t len1, len2; char *spos; size_t pos; EINA_SAFETY_ON_NULL_RETURN_VAL( str, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(with, EINA_FALSE); EINA_MAGIC_CHECK_STRBUF(buf, 0); if (n == 0) return EINA_FALSE; spos = buf->buf; while (n--) { spos = strstr(spos, str); if (!spos || *spos == '\0') return EINA_FALSE; if (n) spos++; } /* This is a read only buffer which need change to be made */ if (buf->ro) { char *dest; dest = malloc(buf->size); if (!dest) return 0; memcpy(dest, buf->buf, buf->len); buf->buf = dest; } pos = spos - (const char *)buf->buf; len1 = strlen(str); len2 = strlen(with); if (len1 != len2) { /* resize the buffer if necessary */ if (EINA_UNLIKELY(!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf, buf->len - len1 + len2))) return EINA_FALSE; /* move the existing text */ memmove(((unsigned char *)(buf->buf)) + pos + len2, ((unsigned char *)(buf->buf)) + pos + len1, buf->len - pos - len1); } /* and now insert the given string */ memcpy(((unsigned char *)(buf->buf)) + pos, with, len2); buf->len += len2 - len1; memset(((unsigned char *)(buf->buf)) + buf->len, 0, 1); return EINA_TRUE; }
/** * @brief Replace all strings with an other string. * @param buf the string buffer to work with. * @param str The string to replace. * @param with The replaceing string. * @return How often the string was replaced. * * This function replaces all the occurrences of @p str in @ buf with * the string @p with. This function returns the number of times @p str * has been replaced. On failure, it returns 0. */ EAPI int eina_strbuf_replace_all(Eina_Strbuf * buf, const char *str, const char *with) { size_t len1, len2, len; char *tmp_buf = NULL; char *spos; size_t pos, start; size_t pos_tmp, start_tmp; int n = 0; EINA_SAFETY_ON_NULL_RETURN_VAL(str, 0); EINA_SAFETY_ON_NULL_RETURN_VAL(with, 0); EINA_MAGIC_CHECK_STRBUF(buf, 0); spos = strstr(buf->buf, str); if (!spos || *spos == '\0') return 0; len1 = strlen(str); len2 = strlen(with); /* if the size of the two string is equal, it is fairly easy to replace them * we don't need to resize the buffer or doing other calculations */ if (len1 == len2) { while (spos) { memcpy(spos, with, len2); spos = strstr(spos + len2, str); n++; } return n; } pos = pos_tmp = spos - (const char *) buf->buf; tmp_buf = buf->buf; buf->buf = malloc(buf->size); if (EINA_UNLIKELY(!buf->buf)) { buf->buf = tmp_buf; return 0; } start = start_tmp = 0; len = buf->len; while (spos) { n++; len = (len + len2) - len1; /* resize the buffer if necessary */ if (EINA_UNLIKELY (!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf, len))) { /* we have to stop replacing here, because we haven't enough * memory to go on */ len = (len + len1) - len2; break; } /* copy the untouched text */ memcpy(buf->buf + start, tmp_buf + start_tmp, pos - start); /* copy the new string */ memcpy(buf->buf + pos, with, len2); /* calculate the next positions */ start_tmp = pos_tmp + len1; start = pos + len2; spos = strstr(tmp_buf + start_tmp, str); /* this calculations don't make sense if spos == NULL, but the * calculated values won't be used, because the loop will stop * then */ pos_tmp = spos - tmp_buf; pos = start + pos_tmp - start_tmp; } /* and now copy the rest of the text */ memcpy(buf->buf + start, tmp_buf + start_tmp, len - start); buf->len = len; memset((char *) buf->buf + buf->len, 0, 1); free(tmp_buf); return n; }