#include "eina_private.h"
#include "eina_str.h"
-#include "eina_safety_checks.h"
+
/*============================================================================*
* Local *
*============================================================================*/
int max_tokens,
unsigned int *elements)
{
- char *s, **str_array;
+ char *s, *pos, **str_array;
const char *src;
size_t len, dlen;
- unsigned int tokens;
+ unsigned int tokens = 0, x;
+ const char *idx[256] = {NULL};
+
+ if (max_tokens < 0) max_tokens = 0;
+ if (max_tokens == 1)
+ {
+ str_array = malloc(sizeof(char *) * 2);
+ if (!str_array)
+ {
+ if (elements)
+ *elements = 0;
+
+ return NULL;
+ }
+
+ s = strdup(str);
+ if (!s)
+ {
+ free(str_array);
+ if (elements)
+ *elements = 0;
- EINA_SAFETY_ON_TRUE_RETURN_VAL(max_tokens < 0, NULL);
+ return NULL;
+ }
+ if (elements)
+ *elements = 1;
+ str_array[0] = s;
+ return str_array;
+ }
dlen = strlen(delim);
if (dlen == 0)
{
return NULL;
}
- tokens = 0;
src = str;
/* count tokens and check strlen(str) */
while (*src != '\0')
if (EINA_UNLIKELY(d == d_end))
{
src = tmp;
+ if (tokens < (sizeof(idx) / sizeof(idx[0])))
+ {
+ idx[tokens] = tmp;
+ //printf("token %d='%s'\n", tokens + 1, idx[tokens]);
+ }
tokens++;
+ if (tokens && (tokens == (unsigned int)max_tokens)) break;
}
else
src++;
}
- len = src - str;
-
- if ((max_tokens > 0) && (tokens > (unsigned int)max_tokens))
- tokens = max_tokens;
+ len = src - str + strlen(src);
str_array = malloc(sizeof(char *) * (tokens + 2));
if (!str_array)
return NULL;
}
+ if (!tokens)
+ {
+ s = strdup(str);
+ if (!s)
+ {
+ free(str_array);
+ if (elements)
+ *elements = 0;
+
+ return NULL;
+ }
+ str_array[0] = s;
+ str_array[1] = NULL;
+ if (elements)
+ *elements = 2;
+ return str_array;
+ }
+
s = malloc(len + 1);
if (!s)
{
return NULL;
}
- /* copy tokens and string */
- tokens = 0;
str_array[0] = s;
- src = str;
- while (*src != '\0')
+
+ if (len == tokens * dlen)
{
- const char *d = delim, *d_end = d + dlen;
- const char *tmp = src;
- for (; (d < d_end) && (*tmp != '\0'); d++, tmp++)
+ /* someone's having a laugh somewhere */
+ memset(s, 0, len + 1);
+ for (x = 1; x < tokens + 1; x++)
+ str_array[x] = s + x;
+ str_array[x] = NULL;
+ if (elements)
+ *elements = x + 1;
+ return str_array;
+ }
+ /* copy tokens and string */
+ if (idx[0] - str - dlen > len)
+ {
+ /* FIXME: don't think this can happen but putting this here just in case */
+ abort();
+ }
+ pos = s;
+ for (x = 0; x < MIN(tokens, (sizeof(idx) / sizeof(idx[0]))); x++)
+ {
+ if (x + 1 < (sizeof(idx) / sizeof(idx[0])))
{
- if (EINA_LIKELY(*d != *tmp))
- break;
+ /* first one is special */
+ if (!x)
+ {
+ eina_strlcpy(pos, str, idx[x] - str - dlen + 1);
+ str_array[x] = pos;
+ //printf("str_array[%d] = '%s'\n", x, str_array[x]);
+ pos += idx[x] - str - dlen + 1;
+ if ((tokens == 1) && (idx[0]))
+ {
+ eina_strlcpy(pos, idx[x], len + 1 - (pos - s));
+ x++, tokens++;
+ str_array[x] = pos;
+ }
+ }
+ /* more tokens */
+ else if (idx[x + 1])
+ {
+ eina_strlcpy(pos, idx[x - 1], idx[x] - idx[x - 1] - dlen + 1);
+ str_array[x] = pos;
+ //printf("str_array[%d] = '%s'\n", x, str_array[x]);
+ pos += idx[x] - idx[x - 1] - dlen + 1;
+ }
+ /* last token */
+ else
+ {
+ if (max_tokens && ((unsigned int)max_tokens < tokens + 1))
+ eina_strlcpy(pos, idx[x - 1], len + 1 - (pos - s));
+ else
+ {
+ //printf("diff: %d\n", len + 1 - (pos - s));
+ eina_strlcpy(pos, idx[x - 1], idx[x] - idx[x - 1] - dlen + 1);
+ str_array[x] = pos;
+ //printf("str_array[%d] = '%s'\n", x, str_array[x]);
+ pos += idx[x] - idx[x - 1] - dlen + 1;
+ x++, tokens++;
+ eina_strlcpy(pos, idx[x - 1], len + 1 - (pos - s));
+ }
+ str_array[x] = pos;
+ //printf("str_array[%d] = '%s'\n", x, str_array[x]);
+ }
}
- if (EINA_UNLIKELY(d == d_end))
+ /* no more tokens saved after this one */
+ else
{
- src = tmp;
- *s = '\0';
- s += dlen;
- tokens++;
- str_array[tokens] = s;
+ eina_strlcpy(pos, idx[x - 1], idx[x] - idx[x - 1] - dlen + 1);
+ str_array[x] = pos;
+ //printf("str_array[%d] = '%s'\n", x, str_array[x]);
+ pos += idx[x] - idx[x - 1] - dlen + 1;
+ src = idx[x];
+ x++, tokens++;
+ str_array[x] = s = pos;
+ break;
}
- else
+ }
+ if ((x != tokens) && ((!max_tokens) || (x < tokens)))
+ {
+ while (*src != '\0')
{
- *s = *src;
- s++;
- src++;
+ const char *d = delim, *d_end = d + dlen;
+ const char *tmp = src;
+ for (; (d < d_end) && (*tmp != '\0'); d++, tmp++)
+ {
+ if (EINA_LIKELY(*d != *tmp))
+ break;
+ }
+ if (((!max_tokens) || (((tokens == (unsigned int)max_tokens) || x < tokens - 2))) && (EINA_UNLIKELY(d == d_end)))
+ {
+ src = tmp;
+ *s = '\0';
+ s++, x++;
+ //printf("str_array[%d] = '%s'\n", x, str_array[x - 1]);
+ str_array[x] = s;
+ }
+ else
+ {
+ *s = *src;
+ s++, src++;
+ }
}
+ *s = 0;
}
- *s = '\0';
- str_array[tokens + 1] = NULL;
+ str_array[tokens] = NULL;
if (elements)
- *elements = (tokens + 1);
+ {
+ *elements = tokens;
+ if ((!max_tokens) || (tokens == (unsigned int)max_tokens))
+ (*elements)++;
+ }
return str_array;
}