forked from enlightenment/efl
Move ecore_str and ecore_strbuf to eina
SVN revision: 45650
This commit is contained in:
parent
4a34a3dd77
commit
436249c412
|
@ -339,6 +339,7 @@ AC_SUBST(lt_enable_auto_import)
|
|||
|
||||
### Checks for library functions
|
||||
AC_FUNC_ALLOCA
|
||||
AC_CHECK_FUNCS(strlcpy)
|
||||
|
||||
#dlopen and dladdr
|
||||
dlopen_libs=""
|
||||
|
|
|
@ -180,6 +180,8 @@ extern "C" {
|
|||
#include "eina_tiler.h"
|
||||
#include "eina_hamster.h"
|
||||
#include "eina_matrixsparse.h"
|
||||
#include "eina_str.h"
|
||||
#include "eina_strbuf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -41,7 +41,9 @@ eina_cpu.h \
|
|||
eina_tiler.h \
|
||||
eina_hamster.h \
|
||||
eina_matrixsparse.h \
|
||||
eina_inline_tiler.x
|
||||
eina_inline_tiler.x \
|
||||
eina_str.h \
|
||||
eina_strbuf.h
|
||||
|
||||
installed_mainheaderdir = $(includedir)/eina-@VMAJ@
|
||||
dist_installed_mainheader_DATA = Eina.h eina_config.h
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
#ifndef _EINA_STR_H
|
||||
#define _EINA_STR_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "eina_types.h"
|
||||
|
||||
/**
|
||||
* @file eina_str.h
|
||||
* @brief Contains useful C string functions.
|
||||
*/
|
||||
|
||||
/* strlcpy implementation for libc's lacking it */
|
||||
EAPI size_t eina_strlcpy(char *dst, const char *src, size_t siz);
|
||||
EAPI size_t eina_strlcat(char *dst, const char *src, size_t siz);
|
||||
|
||||
EAPI int eina_str_has_prefix(const char *str, const char *prefix);
|
||||
|
||||
EAPI int eina_str_has_suffix(const char *str, const char *suffix);
|
||||
EAPI int eina_str_has_extension(const char *str, const char *ext);
|
||||
|
||||
EAPI char **eina_str_split(const char *string, const char *delimiter,
|
||||
int max_tokens);
|
||||
|
||||
EAPI size_t eina_str_join_len(char *dst, size_t size, char sep, const char *a, size_t a_len, const char *b, size_t b_len);
|
||||
|
||||
|
||||
/**
|
||||
* Join two strings and store the result in @a dst buffer.
|
||||
*
|
||||
* Similar to eina_str_join_len(), but will compute the length of @a
|
||||
* and @a b using strlen().
|
||||
*
|
||||
* @param dst where to store the result.
|
||||
* @param size byte size of dst, will write at most (size - 1)
|
||||
* characters and then the '\0' (null terminator).
|
||||
* @param sep separator character to use.
|
||||
* @param a first string to use, before @a sep.
|
||||
* @param b second string to use, after @a sep.
|
||||
*
|
||||
* @return the number of characters printed (not including the
|
||||
* trailing '\0' used to end output to strings). Just like
|
||||
* snprintf(), it will not write more than @a size bytes, thus a
|
||||
* return value of @a size or more means that the output was
|
||||
* truncated.
|
||||
*
|
||||
* @see eina_str_join_len() and eina_str_join_static()
|
||||
*/
|
||||
static inline size_t eina_str_join(char *dst, size_t size, char sep, const char *a, const char *b)
|
||||
{
|
||||
return eina_str_join_len(dst, size, sep, a, strlen(a), b, strlen(b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Join two static strings and store the result in static @a dst buffer.
|
||||
*
|
||||
* Similar to eina_str_join_len(), but will assume string sizes are
|
||||
* know using sizeof(X).
|
||||
*
|
||||
* @param dst where to store the result.
|
||||
* @param sep separator character to use.
|
||||
* @param a first string to use, before @a sep.
|
||||
* @param b second string to use, after @a sep.
|
||||
*
|
||||
* @return the number of characters printed (not including the
|
||||
* trailing '\0' used to end output to strings). Just like
|
||||
* snprintf(), it will not write more than @a size bytes, thus a
|
||||
* return value of @a size or more means that the output was
|
||||
* truncated.
|
||||
*
|
||||
* @see eina_str_join() and eina_str_join_static()
|
||||
*/
|
||||
#define eina_str_join_static(dst, sep, a, b) eina_str_join_len(dst, sizeof(dst), sep, a, (sizeof(a) > 0) ? sizeof(a) - 1 : 0, b, (sizeof(b) > 0) ? sizeof(b) - 1 : 0)
|
||||
|
||||
#endif /* EINA_STR_H */
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef EINA_STRBUF_H
|
||||
#define EINA_STRBUF_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "eina_types.h"
|
||||
|
||||
typedef struct _Eina_Strbuf Eina_Strbuf;
|
||||
|
||||
EAPI Eina_Strbuf *eina_strbuf_new(void);
|
||||
EAPI void eina_strbuf_free(Eina_Strbuf *buf);
|
||||
EAPI void eina_strbuf_append(Eina_Strbuf *buf, const char *str);
|
||||
EAPI void eina_strbuf_append_char(Eina_Strbuf *buf, char c);
|
||||
EAPI void eina_strbuf_insert(Eina_Strbuf *buf, const char *str,
|
||||
size_t pos);
|
||||
#define eina_strbuf_prepend(buf, str) eina_strbuf_insert(buf, str, 0)
|
||||
EAPI const char *eina_strbuf_string_get(Eina_Strbuf *buf);
|
||||
EAPI size_t eina_strbuf_length_get(Eina_Strbuf *buf);
|
||||
EAPI int eina_strbuf_replace(Eina_Strbuf *buf, const char *str,
|
||||
const char *with, unsigned int n);
|
||||
#define eina_strbuf_replace_first(buf, str, with) \
|
||||
eina_strbuf_replace(buf, str, with, 1)
|
||||
EAPI int eina_strbuf_replace_all(Eina_Strbuf *buf, const char *str,
|
||||
const char *with);
|
||||
|
||||
#endif /* EINA_STRBUF_H */
|
|
@ -36,7 +36,9 @@ eina_stringshare.c \
|
|||
eina_cpu.c \
|
||||
eina_tiler.c \
|
||||
eina_hamster.c \
|
||||
eina_safety_checks.c
|
||||
eina_safety_checks.c \
|
||||
eina_str.c \
|
||||
eina_strbuf.c
|
||||
|
||||
if EINA_STATIC_BUILD_CHAINED_POOL
|
||||
base_sources += $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
/* Leave the OpenBSD version below so we can track upstream fixes */
|
||||
/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
static int eina_str_has_suffix_helper(const char *str, const char *suffix,
|
||||
int (*cmp)(const char *, const char *));
|
||||
/**
|
||||
* @param dst the destination
|
||||
* @param src the source
|
||||
* @param siz the size of the destination
|
||||
* @return the length of the source string
|
||||
* @brief copy a c-string
|
||||
*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
eina_strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
#ifdef HAVE_STRLCPY
|
||||
return strlcpy(dst, src, siz);
|
||||
#else
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0)
|
||||
{
|
||||
while (--n != 0)
|
||||
{
|
||||
if ((*d++ = *s++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0)
|
||||
{
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return(s - src - 1); /* count does not include NUL */
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dst the destination
|
||||
* @param src the source
|
||||
* @param siz the size of the destination
|
||||
* @return the length of the source string plus MIN(siz, strlen(initial dst))
|
||||
* @brief append a c-string
|
||||
*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
eina_strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + strlen(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src)); /* count does not include NUL */
|
||||
}
|
||||
|
||||
/**
|
||||
* @param str the string to work with
|
||||
* @param prefix the prefix to check for
|
||||
* @return true if str has the given prefix
|
||||
* @brief checks if the string has the given prefix
|
||||
*/
|
||||
int
|
||||
eina_str_has_prefix(const char *str, const char *prefix)
|
||||
{
|
||||
size_t str_len;
|
||||
size_t prefix_len;
|
||||
|
||||
str_len = strlen(str);
|
||||
prefix_len = strlen(prefix);
|
||||
if (prefix_len > str_len)
|
||||
return 0;
|
||||
|
||||
return (strncmp(str, prefix, prefix_len) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param str the string to work with
|
||||
* @param suffix the suffix to check for
|
||||
* @return true if str has the given suffix
|
||||
* @brief checks if the string has the given suffix
|
||||
*/
|
||||
int
|
||||
eina_str_has_suffix(const char *str, const char *suffix)
|
||||
{
|
||||
return eina_str_has_suffix_helper(str, suffix, strcmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function does the same like eina_str_has_suffix(), but with a
|
||||
* case insensitive compare.
|
||||
*
|
||||
* @param str the string to work with
|
||||
* @param ext the extension to check for
|
||||
* @return true if str has the given extension
|
||||
* @brief checks if the string has the given extension
|
||||
*/
|
||||
int
|
||||
eina_str_has_extension(const char *str, const char *ext)
|
||||
{
|
||||
return eina_str_has_suffix_helper(str, ext, strcasecmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal helper function used by eina_str_has_suffix() and
|
||||
* eina_str_has_extension()
|
||||
*/
|
||||
static int
|
||||
eina_str_has_suffix_helper(const char *str, const char *suffix,
|
||||
int (*cmp)(const char *, const char *))
|
||||
{
|
||||
size_t str_len;
|
||||
size_t suffix_len;
|
||||
|
||||
str_len = strlen(str);
|
||||
suffix_len = strlen(suffix);
|
||||
if (suffix_len > str_len)
|
||||
return 0;
|
||||
|
||||
return cmp(str + str_len - suffix_len, suffix) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a string into a maximum of max_tokens pieces, using the given
|
||||
* delimiter. If max_tokens is reached, the final string in the returned
|
||||
* string array contains the remainder of string.
|
||||
*
|
||||
* @param str A string to split.
|
||||
* @param delim A string which specifies the places at which to split the
|
||||
* string. The delimiter is not included in any of the
|
||||
* resulting strings, unless max_tokens is reached.
|
||||
* @param max_tokens The maximum number of strings to split string into.
|
||||
* If this is less than 1, the string is split completely.
|
||||
* @return A newly-allocated NULL-terminated array of strings.
|
||||
* To free it: free the first element of the array
|
||||
* and the array itself.
|
||||
*/
|
||||
char **
|
||||
eina_str_split(const char *str, const char *delim, int max_tokens)
|
||||
{
|
||||
char *s, *sep, **str_array;
|
||||
size_t len, dlen;
|
||||
int i;
|
||||
|
||||
if (*delim == '\0')
|
||||
return NULL;
|
||||
|
||||
max_tokens = ((max_tokens <= 0) ? (INT_MAX) : (max_tokens - 1));
|
||||
len = strlen(str);
|
||||
dlen = strlen(delim);
|
||||
s = strdup(str);
|
||||
str_array = malloc(sizeof(char *) * (len + 1));
|
||||
for (i = 0; (i < max_tokens) && (sep = strstr(s, delim)); i++)
|
||||
{
|
||||
str_array[i] = s;
|
||||
s = sep + dlen;
|
||||
*sep = 0;
|
||||
}
|
||||
|
||||
str_array[i++] = s;
|
||||
str_array = realloc(str_array, sizeof(char *) * (i + 1));
|
||||
str_array[i] = NULL;
|
||||
|
||||
return str_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join two strings of known length and store the result in @a dst buffer.
|
||||
*
|
||||
* @param dst where to store the result.
|
||||
* @param size byte size of dst, will write at most (size - 1)
|
||||
* characters and then the '\0' (null terminator).
|
||||
* @param sep separator character to use.
|
||||
* @param a first string to use, before @a sep.
|
||||
* @param a_len length of @a a, not including '\0' (strlen()-like)
|
||||
* @param b second string to use, after @a sep.
|
||||
* @param b_len length of @a b, not including '\0' (strlen()-like)
|
||||
*
|
||||
* @return the number of characters printed (not including the
|
||||
* trailing '\0' used to end output to strings). Just like
|
||||
* snprintf(), it will not write more than @a size bytes, thus a
|
||||
* return value of @a size or more means that the output was
|
||||
* truncated.
|
||||
*
|
||||
* @see eina_str_join() and eina_str_join_static()
|
||||
*/
|
||||
size_t
|
||||
eina_str_join_len(char *dst, size_t size, char sep, const char *a, size_t a_len, const char *b, size_t b_len)
|
||||
{
|
||||
size_t ret = a_len + b_len + 1;
|
||||
size_t off;
|
||||
|
||||
if (size < 1) return ret;
|
||||
|
||||
if (size <= a_len)
|
||||
{
|
||||
memcpy(dst, a, size - 1);
|
||||
dst[size - 1] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(dst, a, a_len);
|
||||
off = a_len;
|
||||
|
||||
if (size <= off + 1)
|
||||
{
|
||||
dst[size - 1] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
dst[off] = sep;
|
||||
off++;
|
||||
|
||||
if (size <= off + b_len + 1)
|
||||
{
|
||||
memcpy(dst + off, b, size - off - 1);
|
||||
dst[size - 1] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(dst + off, b, b_len);
|
||||
dst[off + b_len] = '\0';
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "eina_str.h"
|
||||
#include "eina_strbuf.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define EINA_STRBUF_INIT_SIZE 32
|
||||
#define EINA_STRBUF_INIT_STEP 32
|
||||
#define EINA_STRBUF_MAX_STEP 4096
|
||||
|
||||
struct _Eina_Strbuf
|
||||
{
|
||||
char *buf;
|
||||
size_t len;
|
||||
size_t size;
|
||||
size_t step;
|
||||
};
|
||||
|
||||
static int _eina_strbuf_resize(Eina_Strbuf *buf, size_t size);
|
||||
|
||||
/**
|
||||
* Create a new string buffer
|
||||
*/
|
||||
EAPI Eina_Strbuf *
|
||||
eina_strbuf_new(void)
|
||||
{
|
||||
Eina_Strbuf *buf;
|
||||
|
||||
buf = malloc(sizeof(Eina_Strbuf));
|
||||
if (!buf) return NULL;
|
||||
|
||||
buf->len = 0;
|
||||
buf->size = EINA_STRBUF_INIT_SIZE;
|
||||
buf->step = EINA_STRBUF_INIT_STEP;
|
||||
|
||||
buf->buf = malloc(buf->size);
|
||||
buf->buf[0] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a string buffer
|
||||
* @param buf the buffer to free
|
||||
*/
|
||||
EAPI void
|
||||
eina_strbuf_free(Eina_Strbuf *buf)
|
||||
{
|
||||
free(buf->buf);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a string to a buffer, reallocating as necessary.
|
||||
* @param buf the Eina_Strbuf to append to
|
||||
* @param str the string to append
|
||||
*/
|
||||
EAPI void
|
||||
eina_strbuf_append(Eina_Strbuf *buf, const char *str)
|
||||
{
|
||||
size_t l;
|
||||
size_t off = 0;
|
||||
|
||||
l = eina_strlcpy(buf->buf + buf->len, str, buf->size - buf->len);
|
||||
|
||||
while (l > buf->size - buf->len)
|
||||
{
|
||||
/* we successfully appended this much */
|
||||
off += buf->size - buf->len - 1;
|
||||
buf->len = buf->size - 1;
|
||||
buf->size += buf->step;
|
||||
if (buf->step < EINA_STRBUF_MAX_STEP)
|
||||
buf->step *= 2;
|
||||
buf->buf = realloc(buf->buf, buf->size);
|
||||
*(buf->buf + buf->len) = '\0';
|
||||
|
||||
l = eina_strlcpy(buf->buf + buf->len, str + off, buf->size - buf->len);
|
||||
}
|
||||
buf->len += l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a string to a buffer, reallocating as necessary.
|
||||
* @param buf the Eina_Strbuf to insert
|
||||
* @param str the string to insert
|
||||
* @param pos the position to insert the string
|
||||
*/
|
||||
EAPI void
|
||||
eina_strbuf_insert(Eina_Strbuf *buf, const char *str, size_t pos)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (pos >= buf->len)
|
||||
{
|
||||
eina_strbuf_append(buf, str);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* resize the buffer if necessary
|
||||
*/
|
||||
len = strlen(str);
|
||||
if (!_eina_strbuf_resize(buf, buf->len + len))
|
||||
return;
|
||||
/* move the existing text */
|
||||
memmove(buf->buf + len + pos, buf->buf + pos, buf->len - pos);
|
||||
/* and now insert the given string */
|
||||
memcpy(buf->buf + pos, str, len);
|
||||
buf->len += len;
|
||||
buf->buf[buf->len] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a character to a string buffer, reallocating as necessary.
|
||||
* @param buf the Eina_Strbuf to append to
|
||||
* @param c the char to append
|
||||
*/
|
||||
EAPI void
|
||||
eina_strbuf_append_char(Eina_Strbuf *buf, char c)
|
||||
{
|
||||
if (buf->len >= buf->size - 1)
|
||||
{
|
||||
buf->size += buf->step;
|
||||
if (buf->step < EINA_STRBUF_MAX_STEP)
|
||||
buf->step *= 2;
|
||||
buf->buf = realloc(buf->buf, buf->size);
|
||||
}
|
||||
|
||||
buf->buf[(buf->len)++] = c;
|
||||
buf->buf[buf->len] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a pointer to the contents of a string buffer
|
||||
* @param buf the buffer
|
||||
*
|
||||
* This pointer must not be modified, and will no longer be valid if
|
||||
* the Eina_Strbuf is modified.
|
||||
*/
|
||||
EAPI const char *
|
||||
eina_strbuf_string_get(Eina_Strbuf *buf)
|
||||
{
|
||||
return buf->buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the length of the string buffer content
|
||||
* @param buf the buffer
|
||||
*/
|
||||
EAPI size_t
|
||||
eina_strbuf_length_get(Eina_Strbuf *buf)
|
||||
{
|
||||
return buf->len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the n-th string with an other string.
|
||||
* @param buf the Eina_Strbuf to work with
|
||||
* @param str the string to replace
|
||||
* @param with the replaceing string
|
||||
* @param n the number of the fitting string
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
EAPI int
|
||||
eina_strbuf_replace(Eina_Strbuf *buf, const char *str, const char *with,
|
||||
unsigned int n)
|
||||
{
|
||||
size_t len1, len2;
|
||||
char *spos;
|
||||
size_t pos;
|
||||
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
spos = buf->buf;
|
||||
while (n--)
|
||||
{
|
||||
spos = strstr(spos, str);
|
||||
if (!spos || *spos == '\0')
|
||||
return 0;
|
||||
if (n) spos++;
|
||||
}
|
||||
|
||||
pos = spos - buf->buf;
|
||||
len1 = strlen(str);
|
||||
len2 = strlen(with);
|
||||
if (len1 != len2)
|
||||
{
|
||||
/* resize the buffer if necessary */
|
||||
if (!_eina_strbuf_resize(buf, buf->len - len1 + len2))
|
||||
return 0;
|
||||
/* move the existing text */
|
||||
memmove(buf->buf + pos + len2, buf->buf + pos + len1,
|
||||
buf->len - pos - len1);
|
||||
}
|
||||
/* and now insert the given string */
|
||||
memcpy(buf->buf + pos, with, len2);
|
||||
buf->len += len2 - len1;
|
||||
buf->buf[buf->len] = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all strings with an other string.
|
||||
* @param buf the Eina_Strbuf to work with
|
||||
* @param str the string to replace
|
||||
* @param with the replaceing string
|
||||
*
|
||||
* @return how often the string was replaced
|
||||
*/
|
||||
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;
|
||||
|
||||
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 - buf->buf;
|
||||
tmp_buf = buf->buf;
|
||||
buf->buf = malloc(buf->size);
|
||||
if (!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_strbuf_resize(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;
|
||||
buf->buf[buf->len] = 0;
|
||||
|
||||
free(tmp_buf);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* resize the buffer
|
||||
* @param buf the buffer to resize
|
||||
* @param size the minimum size of the buffer
|
||||
*/
|
||||
static int
|
||||
_eina_strbuf_resize(Eina_Strbuf *buf, size_t size)
|
||||
{
|
||||
char *buffer;
|
||||
size_t new_size;
|
||||
size_t new_step;
|
||||
|
||||
new_size = buf->size;
|
||||
new_step = buf->step;
|
||||
|
||||
/*
|
||||
* first we have to determine the new buffer size
|
||||
*/
|
||||
if (size == buf->size)
|
||||
/* nothing to do */
|
||||
return 1;
|
||||
else if (size > buf->size)
|
||||
{
|
||||
/* enlarge the buffer */
|
||||
while (size > new_size)
|
||||
{
|
||||
new_size += new_step;
|
||||
if (new_step < EINA_STRBUF_MAX_STEP)
|
||||
new_step *= 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* shrink the buffer */
|
||||
/*
|
||||
* to be done
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* reallocate the buffer to the new size */
|
||||
buffer = realloc(buf->buf, new_size);
|
||||
if (!buffer)
|
||||
return 0;
|
||||
|
||||
buf->buf = buffer;
|
||||
buf->size = new_size;
|
||||
buf->step = new_step;
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue