13 #include "eina_private.h"
15 #include "eina_magic.h"
16 #include "eina_error.h"
17 #include "eina_safety_checks.h"
18 #include "eina_strbuf.h"
19 #include "eina_strbuf_common.h"
21 /*============================================================================*
23 *============================================================================*/
29 #define EINA_STRBUF_INIT_SIZE 32
30 #define EINA_STRBUF_INIT_STEP 32
31 #define EINA_STRBUF_MAX_STEP 4096
37 /*============================================================================*
39 *============================================================================*/
43 * @brief Initialize the strbuf module.
45 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
47 * This function sets up the strbuf module of Eina. It is called by
53 eina_strbuf_common_init(void)
60 * @brief Shut down the strbuf module.
62 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
64 * This function shuts down the strbuf module set up by
65 * eina_strbuf_common_init(). It is called by eina_shutdown().
67 * @see eina_shutdown()
70 eina_strbuf_common_shutdown(void)
79 * @param csize the character size
80 * @param buf the buffer to init
82 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
85 _eina_strbuf_common_init(size_t csize, Eina_Strbuf *buf)
88 buf->size = EINA_STRBUF_INIT_SIZE;
89 buf->step = EINA_STRBUF_INIT_STEP;
92 buf->buf = calloc(csize, buf->size);
93 if (EINA_UNLIKELY(!buf->buf))
95 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
105 * init the buffer without allocating the actual string (for managed)
106 * @param csize the character size
107 * @param buf the buffer to init
109 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
112 _eina_strbuf_common_manage_init(size_t csize __UNUSED__,
119 buf->step = EINA_STRBUF_INIT_STEP;
130 * @param csize the character size
131 * @param buf the buffer to resize
132 * @param size the minimum size of the buffer
134 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
136 static inline Eina_Bool
137 _eina_strbuf_common_resize(size_t csize, Eina_Strbuf *buf, size_t size)
139 size_t new_size, new_step, delta;
142 size += 1; // Add extra space for '\0'
145 if (size == buf->size) return EINA_TRUE;
146 else if (size > buf->size) delta = size - buf->size;
147 else delta = buf->size - size;
149 /* check if should keep the same step (just used while growing) */
150 if ((delta <= buf->step) && (size > buf->size)) new_step = buf->step;
153 new_step = (((delta / EINA_STRBUF_INIT_STEP) + 1)
154 * EINA_STRBUF_INIT_STEP);
155 if (new_step > EINA_STRBUF_MAX_STEP) new_step = EINA_STRBUF_MAX_STEP;
158 new_size = (((size / new_step) + 1) * new_step);
160 /* reallocate the buffer to the new size */
161 buffer = realloc(buf->buf, new_size * csize);
162 if (EINA_UNLIKELY(!buffer))
164 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
169 buf->size = new_size;
170 buf->step = new_step;
178 * If required, enlarge the buffer to fit the new size.
180 * @param csize the character size
181 * @param buf the buffer to resize
182 * @param size the minimum size of the buffer
184 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
187 _eina_strbuf_common_grow(size_t csize, Eina_Strbuf *buf, size_t size)
189 if ((size + 1) < buf->size) return EINA_TRUE;
190 return _eina_strbuf_common_resize(csize, buf, size);
196 * insert string of known length at random within existing strbuf limits.
198 * @param csize the character size
199 * @param buf the buffer to resize, must be valid.
200 * @param str the string to copy, must be valid (!NULL and smaller than @a len)
201 * @param len the amount of bytes in @a str to copy, must be valid.
202 * @param pos the position inside buffer to insert, must be valid (smaller
203 * than eina_strbuf_common_length_get())
205 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
207 static inline Eina_Bool
208 _eina_strbuf_common_insert_length(size_t csize,
214 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len)))
217 /* move the existing text */
218 memmove(((unsigned char *)(buf->buf)) + ((len + pos) * csize),
219 ((unsigned char *)(buf->buf)) + (pos * csize),
220 (buf->len - pos) * csize);
222 /* and now insert the given string */
223 memcpy((unsigned char *)buf->buf + (pos * csize), str, len * csize);
226 memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize);
230 /*============================================================================*
232 *============================================================================*/
236 * @brief Create a new string buffer.
238 * @param csize the character size
239 * @return Newly allocated string buffer instance.
241 * This function creates a new string buffer. On error, @c NULL is
242 * returned and Eina error is set to #EINA_ERROR_OUT_OF_MEMORY. To
243 * free the resources, use eina_strbuf_common_free().
245 * @see eina_strbuf_common_free()
246 * @see eina_strbuf_common_append()
247 * @see eina_strbuf_common_string_get()
250 eina_strbuf_common_new(size_t csize)
255 buf = malloc(sizeof(Eina_Strbuf));
256 if (EINA_UNLIKELY(!buf))
258 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
261 if (EINA_UNLIKELY(!_eina_strbuf_common_init(csize, buf)))
263 eina_strbuf_common_free(buf);
271 * @brief Create a new string buffer managing str.
273 * @param csize the character size
274 * @param str the string to manage
275 * @param len the length of the string to manage
276 * @return Newly allocated string buffer instance.
278 * This function creates a new string buffer. On error, @c NULL is
279 * returned and Eina error is set to #EINA_ERROR_OUT_OF_MEMORY. To
280 * free the resources, use eina_strbuf_common_free().
282 * @see eina_strbuf_common_free()
283 * @see eina_strbuf_common_append()
284 * @see eina_strbuf_common_string_get()
288 eina_strbuf_common_manage_new(size_t csize,
295 buf = malloc(sizeof(Eina_Strbuf));
296 if (EINA_UNLIKELY(!buf))
298 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
301 if (EINA_UNLIKELY(!_eina_strbuf_common_manage_init(csize, buf, str, len)))
303 eina_strbuf_common_free(buf);
311 * @brief Free a string buffer.
313 * @param buf The string buffer to free.
315 * This function frees the memory of @p buf. @p buf must have been
316 * created by eina_strbuf_common_new().
319 eina_strbuf_common_free(Eina_Strbuf *buf)
327 * @brief Reset a string buffer.
329 * @param csize the character size
330 * @param buf The string buffer to reset.
332 * This function reset @p buf: the buffer len is set to 0, and the
333 * string is set to '\\0'. No memory is free'd.
336 eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf)
339 buf->step = EINA_STRBUF_INIT_STEP;
340 memset(buf->buf, 0, csize);
345 * @brief Append a string to a buffer, reallocating as necessary.
347 * @param csize the character size
348 * @param buf The string buffer to append to.
349 * @param str The string to append.
350 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
352 * This function appends @p str to @p buf. It computes the length of
353 * @p str, so is slightly slower than eina_strbuf_common_append_length(). If
354 * the length is known beforehand, consider using that variant. If
355 * @p buf can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
358 * @see eina_strbuf_common_append()
359 * @see eina_strbuf_common_append_length()
362 eina_strbuf_common_append(size_t csize,
367 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
369 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len)))
371 memcpy(((unsigned char *)(buf->buf)) + (buf->len * csize), str,
379 * @brief Append a string to a buffer, reallocating as necessary,
380 * limited by the given length.
382 * @param csize the character size
383 * @param buf The string buffer to append to.
384 * @param str The string to append.
385 * @param maxlen The maximum number of characters to append.
386 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
388 * This function appends at most @p maxlen characters of @p str to
389 * @p buf. It can't appends more than the length of @p str. It
390 * computes the length of @p str, so is slightly slower than
391 * eina_strbuf_common_append_length(). If the length is known beforehand,
392 * consider using that variant (@p maxlen should then be checked so
393 * that it is greater than the size of @p str). If @p str can not be
394 * appended, #EINA_FALSE is returned, otherwise, #EINA_TRUE is
397 * @see eina_strbuf_common_append()
398 * @see eina_strbuf_common_append_length()
401 eina_strbuf_common_append_n(size_t csize,
407 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
409 if (len > maxlen) len = maxlen;
410 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len)))
412 memcpy(((unsigned char *)(buf->buf)) + (buf->len * csize), str,
415 memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize);
421 * @brief Append a string of exact length to a buffer, reallocating as necessary.
423 * @param csize the character size
424 * @param buf The string buffer to append to.
425 * @param str The string to append.
426 * @param length The exact length to use.
427 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
429 * This function appends @p str to @p buf. @p str must be of size at
430 * most @p length. It is slightly faster than eina_strbuf_common_append() as
431 * it does not compute the size of @p str. It is useful when dealing
432 * with strings of known size, such as eina_strngshare. If @p buf
433 * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
436 * @see eina_stringshare_length()
437 * @see eina_strbuf_common_append()
438 * @see eina_strbuf_common_append_n()
441 eina_strbuf_common_append_length(size_t csize,
446 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
448 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + length)))
450 memcpy(((unsigned char *)(buf->buf)) + (buf->len * csize), str,
453 memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize);
459 * @brief Insert a string to a buffer, reallocating as necessary.
461 * @param csize the character size
462 * @param buf The string buffer to insert.
463 * @param str The string to insert.
464 * @param pos The position to insert the string.
465 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
467 * This function inserts @p str to @p buf at position @p pos. It
468 * computes the length of @p str, so is slightly slower than
469 * eina_strbuf_common_insert_length(). If the length is known beforehand,
470 * consider using that variant. If @p buf can't insert it, #EINA_FALSE
471 * is returned, otherwise #EINA_TRUE is returned.
474 eina_strbuf_common_insert(size_t csize,
480 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
482 if (pos >= buf->len) return eina_strbuf_common_append(csize, buf, str, len);
483 return _eina_strbuf_common_insert_length(csize, buf, str, len, pos);
488 * @brief Insert a string to a buffer, reallocating as necessary. Limited by maxlen.
490 * @param csize the character size
491 * @param buf The string buffer to insert to.
492 * @param str The string to insert.
493 * @param maxlen The maximum number of chars to insert.
494 * @param pos The position to insert the string.
495 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
497 * This function inserts @p str ot @p buf at position @p pos, with at
498 * most @p maxlen bytes. The number of inserted characters can not be
499 * greater than the length of @p str. It computes the length of
500 * @p str, so is slightly slower than eina_strbuf_common_insert_length(). If the
501 * length is known beforehand, consider using that variant (@p maxlen
502 * should then be checked so that it is greater than the size of
503 * @p str). If @p str can not be inserted, #EINA_FALSE is returned,
504 * otherwise, #EINA_TRUE is returned.
507 eina_strbuf_common_insert_n(size_t csize,
514 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
517 return eina_strbuf_common_append_n(csize, buf, str, len, maxlen);
518 if (len > maxlen) len = maxlen;
519 return _eina_strbuf_common_insert_length(csize, buf, str, len, pos);
524 * @brief Insert a string of exact length to a buffer, reallocating as necessary.
526 * @param csize the character size
527 * @param buf The string buffer to insert to.
528 * @param str The string to insert.
529 * @param length The exact length to use.
530 * @param pos The position to insert the string.
531 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
533 * This function inserts @p str to @p buf. @p str must be of size at
534 * most @p length. It is slightly faster than eina_strbuf_common_insert() as
535 * it does not compute the size of @p str. It is useful when dealing
536 * with strings of known size, such as eina_strngshare. If @p buf
537 * can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
540 * @see eina_stringshare_length()
541 * @see eina_strbuf_common_insert()
542 * @see eina_strbuf_common_insert_n()
545 eina_strbuf_common_insert_length(size_t csize,
551 EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
554 return eina_strbuf_common_append_length(csize, buf, str, length);
555 return _eina_strbuf_common_insert_length(csize, buf, str, length, pos);
560 * @brief Append a character to a string buffer, reallocating as
563 * @param csize the character size
564 * @param buf The string buffer to append to.
565 * @param c The char to append.
566 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
568 * This function inserts @p c to @p buf. If it can not insert it, #EINA_FALSE
569 * is returned, otherwise #EINA_TRUE is returned.
572 eina_strbuf_common_append_char(size_t csize, Eina_Strbuf *buf, const void *c)
574 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + 1)))
577 memcpy(((unsigned char *)(buf->buf)) + ((buf->len)++ *csize), c, csize);
578 memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize);
584 * @brief Insert a character to a string buffer, reallocating as
587 * @param csize the character size
588 * @param buf The string buffer to insert to.
589 * @param c The char to insert.
590 * @param pos The position to insert the char.
591 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
593 * This function inserts @p c to @p buf at position @p pos. If @p buf
594 * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
598 eina_strbuf_common_insert_char(size_t csize,
604 return eina_strbuf_common_append_char(csize, buf, c);
605 return _eina_strbuf_common_insert_length(csize, buf, c, 1, pos);
610 * @brief Remove a slice of the given string buffer.
612 * @param csize the character size
613 * @param buf The string buffer to remove a slice.
614 * @param start The initial (inclusive) slice position to start
615 * removing, in bytes.
616 * @param end The final (non-inclusive) slice position to finish
617 * removing, in bytes.
618 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
620 * This function removes a slice of @p buf, starting at @p start
621 * (inclusive) and ending at @p end (non-inclusive). Both values are
622 * in bytes. It returns #EINA_FALSE on failure, #EINA_TRUE otherwise.
625 eina_strbuf_common_remove(size_t csize,
630 size_t remove_len, tail_len;
632 if (end >= buf->len) end = buf->len;
633 if (end <= start) return EINA_TRUE;
635 remove_len = end - start;
636 if (remove_len == buf->len)
639 return _eina_strbuf_common_init(csize, buf);
642 tail_len = buf->len - end + 1; /* includes '\0' */
643 memmove(((unsigned char *)(buf->buf)) + (start * csize),
644 ((unsigned char *)(buf->buf)) + (end * csize),
646 buf->len -= remove_len;
647 return _eina_strbuf_common_resize(csize, buf, buf->len);
652 * @brief Retrieve a pointer to the contents of a string buffer
654 * @param buf The string buffer.
655 * @return The current string in the string buffer.
657 * This function returns the string contained in @p buf. The returned
658 * value must not be modified and will no longer be valid if @p buf is
659 * modified. In other words, any eina_strbuf_common_append() or similar will
660 * make that pointer invalid.
662 * @see eina_strbuf_common_string_steal()
665 eina_strbuf_common_string_get(const Eina_Strbuf *buf)
672 * @brief Steal the contents of a string buffer.
674 * @param csize the character size
675 * @param buf The string buffer to steal.
676 * @return The current string in the string buffer.
678 * This function returns the string contained in @p buf. @p buf is
679 * then initialized and does not own the returned string anymore. The
680 * caller must release the memory of the returned string by calling
683 * @see eina_strbuf_common_string_get()
686 eina_strbuf_common_string_steal(size_t csize, Eina_Strbuf *buf)
691 // TODO: Check return value and do something clever
692 _eina_strbuf_common_init(csize, buf);
698 * @brief Free the contents of a string buffer but not the buffer.
700 * @param csize the character size
701 * @param buf The string buffer to free the string of.
703 * This function frees the string contained in @p buf without freeing
707 eina_strbuf_common_string_free(size_t csize, Eina_Strbuf *buf)
710 _eina_strbuf_common_init(csize, buf);
715 * @brief Retrieve the length of the string buffer content.
717 * @param buf The string buffer.
718 * @return The current length of the string, in bytes.
720 * This function returns the length of @p buf.
723 eina_strbuf_common_length_get(const Eina_Strbuf *buf)
732 /*FIXME: Implementing them here is a hack! */
735 # undef _STRBUF_CSIZE
739 # undef _STRBUF_MAGIC
742 #ifdef _STRBUF_MAGIC_STR
743 # undef _STRBUF_MAGIC_STR
746 #define _STRBUF_CSIZE 1
747 #define _STRBUF_MAGIC EINA_MAGIC_STRBUF
748 #define _STRBUF_MAGIC_STR __STRBUF_STR_MAGIC_STR
749 static const char __STRBUF_STR_MAGIC_STR[] = "Eina Strbuf";
758 eina_strbuf_replace(Eina_Strbuf *buf,
767 EINA_SAFETY_ON_NULL_RETURN_VAL( str, EINA_FALSE);
768 EINA_SAFETY_ON_NULL_RETURN_VAL(with, EINA_FALSE);
769 EINA_MAGIC_CHECK_STRBUF(buf, 0);
770 if (n == 0) return EINA_FALSE;
775 spos = strstr(spos, str);
776 if (!spos || *spos == '\0') return EINA_FALSE;
780 pos = spos - (const char *)buf->buf;
785 /* resize the buffer if necessary */
786 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf,
787 buf->len - len1 + len2)))
788 return EINA_FALSE; /* move the existing text */
789 memmove(((unsigned char *)(buf->buf)) + pos + len2,
790 ((unsigned char *)(buf->buf)) + pos + len1,
791 buf->len - pos - len1);
793 /* and now insert the given string */
794 memcpy(((unsigned char *)(buf->buf)) + pos, with, len2);
795 buf->len += len2 - len1;
796 memset(((unsigned char *)(buf->buf)) + buf->len, 0, 1);
801 eina_strbuf_replace_all(Eina_Strbuf *buf, const char *str, const char *with)
803 size_t len1, len2, len;
804 char *tmp_buf = NULL;
807 size_t pos_tmp, start_tmp;
810 EINA_SAFETY_ON_NULL_RETURN_VAL( str, 0);
811 EINA_SAFETY_ON_NULL_RETURN_VAL(with, 0);
812 EINA_MAGIC_CHECK_STRBUF(buf, 0);
814 spos = strstr(buf->buf, str);
815 if (!spos || *spos == '\0') return 0;
818 /* if the size of the two string is equal, it is fairly easy to replace them
819 * we don't need to resize the buffer or doing other calculations */
824 memcpy(spos, with, len2);
825 spos = strstr(spos + len2, str);
830 pos = pos_tmp = spos - (const char *)buf->buf;
832 buf->buf = malloc(buf->size);
833 if (EINA_UNLIKELY(!buf->buf))
838 start = start_tmp = 0;
843 len = (len + len2) - len1;
844 /* resize the buffer if necessary */
845 if (EINA_UNLIKELY(!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf, len)))
847 /* we have to stop replacing here, because we haven't enough
849 len = (len + len1) - len2;
852 /* copy the untouched text */
853 memcpy(((unsigned char *)(buf->buf)) + start, tmp_buf + start_tmp,
855 /* copy the new string */
856 memcpy(((unsigned char *)(buf->buf)) + pos, with, len2);
857 /* calculate the next positions */
858 start_tmp = pos_tmp + len1;
860 spos = strstr(tmp_buf + start_tmp, str);
861 /* this calculations don't make sense if spos == NULL, but the
862 * calculated values won't be used, because the loop will stop
864 pos_tmp = spos - tmp_buf;
865 pos = start + pos_tmp - start_tmp;
867 /* and now copy the rest of the text */
868 memcpy(((unsigned char *)(buf->buf)) + start, tmp_buf + start_tmp,
871 memset(((unsigned char *)(buf->buf)) + buf->len, 0, 1);