Move ecore_str and ecore_strbuf to eina

SVN revision: 45650
This commit is contained in:
Sebastian Dransfeld 2010-01-27 20:47:47 +00:00
parent 4a34a3dd77
commit 436249c412
8 changed files with 751 additions and 2 deletions

View File

@ -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=""

View File

@ -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
}

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}