forked from enlightenment/efl
enable adding just part of a string.
this allows us to add stringshare from a larger buffer that cannot be modified. SVN revision: 40516
This commit is contained in:
parent
48c7e28b20
commit
ebeabe3735
|
@ -67,6 +67,7 @@
|
||||||
|
|
||||||
EAPI int eina_stringshare_init(void);
|
EAPI int eina_stringshare_init(void);
|
||||||
EAPI int eina_stringshare_shutdown(void);
|
EAPI int eina_stringshare_shutdown(void);
|
||||||
|
EAPI const char *eina_stringshare_add_length(const char *str, unsigned int slen) EINA_WARN_UNUSED_RESULT;
|
||||||
EAPI const char *eina_stringshare_add(const char *str) EINA_WARN_UNUSED_RESULT;
|
EAPI const char *eina_stringshare_add(const char *str) EINA_WARN_UNUSED_RESULT;
|
||||||
EAPI const char *eina_stringshare_ref(const char *str);
|
EAPI const char *eina_stringshare_ref(const char *str);
|
||||||
EAPI void eina_stringshare_del(const char *str);
|
EAPI void eina_stringshare_del(const char *str);
|
||||||
|
|
|
@ -350,7 +350,7 @@ static Eina_Stringshare_Small _eina_small_share;
|
||||||
static inline int
|
static inline int
|
||||||
_eina_stringshare_small_cmp(const Eina_Stringshare_Small_Bucket *bucket, int i, const char *pstr, unsigned char plength)
|
_eina_stringshare_small_cmp(const Eina_Stringshare_Small_Bucket *bucket, int i, const char *pstr, unsigned char plength)
|
||||||
{
|
{
|
||||||
const unsigned char cur_plength = bucket->lengths[i] - 1;
|
const unsigned char cur_plength = bucket->lengths[i];
|
||||||
const char *cur_pstr;
|
const char *cur_pstr;
|
||||||
|
|
||||||
if (cur_plength > plength)
|
if (cur_plength > plength)
|
||||||
|
@ -380,7 +380,7 @@ static const char *
|
||||||
_eina_stringshare_small_bucket_find(const Eina_Stringshare_Small_Bucket *bucket, const char *str, unsigned char length, int *index)
|
_eina_stringshare_small_bucket_find(const Eina_Stringshare_Small_Bucket *bucket, const char *str, unsigned char length, int *index)
|
||||||
{
|
{
|
||||||
const char *pstr = str + 1; /* skip first letter, it's always the same */
|
const char *pstr = str + 1; /* skip first letter, it's always the same */
|
||||||
unsigned char plength = length - 1;
|
unsigned char plength = length;
|
||||||
int i, low, high;
|
int i, low, high;
|
||||||
|
|
||||||
if (bucket->count == 0)
|
if (bucket->count == 0)
|
||||||
|
@ -456,6 +456,7 @@ _eina_stringshare_small_bucket_insert_at(Eina_Stringshare_Small_Bucket **p_bucke
|
||||||
{
|
{
|
||||||
Eina_Stringshare_Small_Bucket *bucket = *p_bucket;
|
Eina_Stringshare_Small_Bucket *bucket = *p_bucket;
|
||||||
int todo, off;
|
int todo, off;
|
||||||
|
char *snew;
|
||||||
|
|
||||||
if (!bucket)
|
if (!bucket)
|
||||||
{
|
{
|
||||||
|
@ -474,12 +475,14 @@ _eina_stringshare_small_bucket_insert_at(Eina_Stringshare_Small_Bucket **p_bucke
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = strdup(str);
|
snew = malloc(length + 1);
|
||||||
if (!str)
|
if (!snew)
|
||||||
{
|
{
|
||||||
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
memcpy(snew, str, length);
|
||||||
|
snew[length] = '\0';
|
||||||
|
|
||||||
off = index + 1;
|
off = index + 1;
|
||||||
todo = bucket->count - index;
|
todo = bucket->count - index;
|
||||||
|
@ -493,12 +496,12 @@ _eina_stringshare_small_bucket_insert_at(Eina_Stringshare_Small_Bucket **p_bucke
|
||||||
todo * sizeof(bucket->references[0]));
|
todo * sizeof(bucket->references[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
bucket->strings[index] = str;
|
bucket->strings[index] = snew;
|
||||||
bucket->lengths[index] = length;
|
bucket->lengths[index] = length;
|
||||||
bucket->references[index] = 1;
|
bucket->references[index] = 1;
|
||||||
bucket->count++;
|
bucket->count++;
|
||||||
|
|
||||||
return str;
|
return snew;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -635,6 +638,7 @@ _eina_stringshare_node_init(Eina_Stringshare_Node *node, const char *str, int sl
|
||||||
node->references = 1;
|
node->references = 1;
|
||||||
node->length = slen;
|
node->length = slen;
|
||||||
memcpy(node->str, str, slen);
|
memcpy(node->str, str, slen);
|
||||||
|
node->str[slen] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Stringshare_Head *
|
static Eina_Stringshare_Head *
|
||||||
|
@ -643,7 +647,7 @@ _eina_stringshare_head_alloc(int slen)
|
||||||
Eina_Stringshare_Head *head, t;
|
Eina_Stringshare_Head *head, t;
|
||||||
const size_t head_size = (char *)&(t.builtin_node.str) - (char *)&t;
|
const size_t head_size = (char *)&(t.builtin_node.str) - (char *)&t;
|
||||||
|
|
||||||
head = malloc(head_size + slen);
|
head = malloc(head_size + slen + 1);
|
||||||
if (!head)
|
if (!head)
|
||||||
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
@ -756,7 +760,7 @@ _eina_stringshare_node_alloc(int slen)
|
||||||
Eina_Stringshare_Node *node, t;
|
Eina_Stringshare_Node *node, t;
|
||||||
const size_t node_size = (char *)&(t.str) - (char *)&t;
|
const size_t node_size = (char *)&(t.str) - (char *)&t;
|
||||||
|
|
||||||
node = malloc(node_size + slen);
|
node = malloc(node_size + slen + 1);
|
||||||
if (!node)
|
if (!node)
|
||||||
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
@ -885,6 +889,7 @@ eina_stringshare_shutdown(void)
|
||||||
* @brief Retrieve an instance of a string for use in a program.
|
* @brief Retrieve an instance of a string for use in a program.
|
||||||
*
|
*
|
||||||
* @param str The string to retrieve an instance of.
|
* @param str The string to retrieve an instance of.
|
||||||
|
* @param slen The string size (<= strlen(str)).
|
||||||
* @return A pointer to an instance of the string on success.
|
* @return A pointer to an instance of the string on success.
|
||||||
* @c NULL on failure.
|
* @c NULL on failure.
|
||||||
*
|
*
|
||||||
|
@ -894,24 +899,24 @@ eina_stringshare_shutdown(void)
|
||||||
* it is added to the strings to be searched and a duplicated string
|
* it is added to the strings to be searched and a duplicated string
|
||||||
* of @p str is returned.
|
* of @p str is returned.
|
||||||
*
|
*
|
||||||
|
* This function does not check string size, but uses the give the
|
||||||
|
* exact given size. This can be used to stringshare part of a larger
|
||||||
|
* buffer or substring.
|
||||||
|
*
|
||||||
* @note it's not possible to have more than 65k references or strings
|
* @note it's not possible to have more than 65k references or strings
|
||||||
* bigger than 65k since we use 'unsigned short' to save space.
|
* bigger than 65k since we use 'unsigned short' to save space.
|
||||||
|
*
|
||||||
|
* @see eina_stringshare_add()
|
||||||
*/
|
*/
|
||||||
EAPI const char *
|
EAPI const char *
|
||||||
eina_stringshare_add(const char *str)
|
eina_stringshare_add_length(const char *str, unsigned int slen)
|
||||||
{
|
{
|
||||||
Eina_Stringshare_Head **p_bucket, *ed;
|
Eina_Stringshare_Head **p_bucket, *ed;
|
||||||
Eina_Stringshare_Node *el;
|
Eina_Stringshare_Node *el;
|
||||||
int hash_num, slen, hash;
|
int hash_num, hash;
|
||||||
|
|
||||||
if (!str) return NULL;
|
if (!str) return NULL;
|
||||||
|
|
||||||
if (str[0] == '\0') slen = 0;
|
|
||||||
else if (str[1] == '\0') slen = 1;
|
|
||||||
else if (str[2] == '\0') slen = 2;
|
|
||||||
else if (str[3] == '\0') slen = 3;
|
|
||||||
else slen = 3 + (int)strlen(str + 3);
|
|
||||||
|
|
||||||
_eina_stringshare_population_add(slen);
|
_eina_stringshare_population_add(slen);
|
||||||
|
|
||||||
if (slen == 0)
|
if (slen == 0)
|
||||||
|
@ -921,8 +926,6 @@ eina_stringshare_add(const char *str)
|
||||||
else if (slen < 4)
|
else if (slen < 4)
|
||||||
return _eina_stringshare_small_add(str, slen);
|
return _eina_stringshare_small_add(str, slen);
|
||||||
|
|
||||||
slen++; /* everything else need to account '\0' */
|
|
||||||
|
|
||||||
hash = eina_hash_superfast(str, slen);
|
hash = eina_hash_superfast(str, slen);
|
||||||
hash_num = hash & 0xFF;
|
hash_num = hash & 0xFF;
|
||||||
hash = (hash >> 8) & EINA_STRINGSHARE_MASK;
|
hash = (hash >> 8) & EINA_STRINGSHARE_MASK;
|
||||||
|
@ -954,6 +957,44 @@ eina_stringshare_add(const char *str)
|
||||||
return el->str;
|
return el->str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve an instance of a string for use in a program.
|
||||||
|
*
|
||||||
|
* @param str The NULL terminated string to retrieve an instance of.
|
||||||
|
* @return A pointer to an instance of the string on success.
|
||||||
|
* @c NULL on failure.
|
||||||
|
*
|
||||||
|
* This function retrieves an instance of @p str. If @p str is
|
||||||
|
* @c NULL, then @c NULL is returned. If @p str is already stored, it
|
||||||
|
* is just returned and its reference counter is increased. Otherwise
|
||||||
|
* it is added to the strings to be searched and a duplicated string
|
||||||
|
* of @p str is returned.
|
||||||
|
*
|
||||||
|
* The string @a str must be NULL terminated ('\0') and its full
|
||||||
|
* length will be used. To use part of the string or non-null
|
||||||
|
* terminated, use eina_stringshare_add_length() instead.
|
||||||
|
*
|
||||||
|
* @note it's not possible to have more than 65k references or strings
|
||||||
|
* bigger than 65k since we use 'unsigned short' to save space.
|
||||||
|
*
|
||||||
|
* @see eina_stringshare_add_length()
|
||||||
|
*/
|
||||||
|
EAPI const char *
|
||||||
|
eina_stringshare_add(const char *str)
|
||||||
|
{
|
||||||
|
int slen;
|
||||||
|
|
||||||
|
if (!str) return NULL;
|
||||||
|
|
||||||
|
if (str[0] == '\0') slen = 0;
|
||||||
|
else if (str[1] == '\0') slen = 1;
|
||||||
|
else if (str[2] == '\0') slen = 2;
|
||||||
|
else if (str[3] == '\0') slen = 3;
|
||||||
|
else slen = 3 + (int)strlen(str + 3);
|
||||||
|
|
||||||
|
return eina_stringshare_add_length(str, slen);
|
||||||
|
}
|
||||||
|
|
||||||
static Eina_Stringshare_Node *
|
static Eina_Stringshare_Node *
|
||||||
_eina_stringshare_node_from_str(const char *str)
|
_eina_stringshare_node_from_str(const char *str)
|
||||||
{
|
{
|
||||||
|
@ -1058,7 +1099,7 @@ eina_stringshare_del(const char *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
node->references = 0;
|
node->references = 0;
|
||||||
slen = node->length; /* already includes '\0' */
|
slen = node->length;
|
||||||
|
|
||||||
hash = eina_hash_superfast(str, slen);
|
hash = eina_hash_superfast(str, slen);
|
||||||
hash_num = hash & 0xFF;
|
hash_num = hash & 0xFF;
|
||||||
|
@ -1116,7 +1157,7 @@ eina_stringshare_strlen(const char *str)
|
||||||
if (str[3] == '\0') return 3;
|
if (str[3] == '\0') return 3;
|
||||||
|
|
||||||
node = _eina_stringshare_node_from_str(str);
|
node = _eina_stringshare_node_from_str(str);
|
||||||
return node->length - 1;
|
return node->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dumpinfo
|
struct dumpinfo
|
||||||
|
|
Loading…
Reference in New Issue