1 /* Leave the OpenBSD version below so we can track upstream fixes */
2 /* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
5 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
36 #include "eina_private.h"
39 /*============================================================================*
41 *============================================================================*/
48 * Internal helper function used by eina_str_has_suffix() and
49 * eina_str_has_extension()
51 static inline Eina_Bool
52 eina_str_has_suffix_helper(const char *str,
54 int (*cmp)(const char *, const char *))
59 if ((!str) || (!suffix)) return EINA_FALSE;
60 str_len = strlen(str);
61 suffix_len = eina_strlen_bounded(suffix, str_len);
62 if (suffix_len == (size_t)-1)
65 return cmp(str + str_len - suffix_len, suffix) == 0;
69 eina_str_split_full_helper(const char *str,
72 unsigned int *elements)
74 char *s, *pos, **str_array;
77 unsigned int tokens = 0, x;
78 const char *idx[256] = {NULL};
80 if (max_tokens < 0) max_tokens = 0;
83 str_array = malloc(sizeof(char *) * 2);
106 dlen = strlen(delim);
116 /* count tokens and check strlen(str) */
119 const char *d = delim, *d_end = d + dlen;
120 const char *tmp = src;
121 for (; (d < d_end) && (*tmp != '\0'); d++, tmp++)
123 if (EINA_LIKELY(*d != *tmp))
126 if (EINA_UNLIKELY(d == d_end))
129 if (tokens < (sizeof(idx) / sizeof(idx[0])))
132 //printf("token %d='%s'\n", tokens + 1, idx[tokens]);
135 if (tokens && (tokens == (unsigned int)max_tokens)) break;
140 len = src - str + strlen(src);
142 str_array = malloc(sizeof(char *) * (tokens + 2));
181 if (len == tokens * dlen)
183 /* someone's having a laugh somewhere */
184 memset(s, 0, len + 1);
185 for (x = 1; x < tokens + 1; x++)
186 str_array[x] = s + x;
192 /* copy tokens and string */
193 if (idx[0] - str - dlen > len)
195 /* FIXME: don't think this can happen but putting this here just in case */
199 for (x = 0; x < MIN(tokens, (sizeof(idx) / sizeof(idx[0]))); x++)
201 if (x + 1 < (sizeof(idx) / sizeof(idx[0])))
203 /* first one is special */
206 eina_strlcpy(pos, str, idx[x] - str - dlen + 1);
208 //printf("str_array[%d] = '%s'\n", x, str_array[x]);
209 pos += idx[x] - str - dlen + 1;
210 if ((tokens == 1) && (idx[0]))
212 eina_strlcpy(pos, idx[x], len + 1 - (pos - s));
220 eina_strlcpy(pos, idx[x - 1], idx[x] - idx[x - 1] - dlen + 1);
222 //printf("str_array[%d] = '%s'\n", x, str_array[x]);
223 pos += idx[x] - idx[x - 1] - dlen + 1;
228 if (max_tokens && ((unsigned int)max_tokens < tokens + 1))
229 eina_strlcpy(pos, idx[x - 1], len + 1 - (pos - s));
232 //printf("diff: %d\n", len + 1 - (pos - s));
233 eina_strlcpy(pos, idx[x - 1], idx[x] - idx[x - 1] - dlen + 1);
235 //printf("str_array[%d] = '%s'\n", x, str_array[x]);
236 pos += idx[x] - idx[x - 1] - dlen + 1;
238 eina_strlcpy(pos, idx[x - 1], len + 1 - (pos - s));
241 //printf("str_array[%d] = '%s'\n", x, str_array[x]);
244 /* no more tokens saved after this one */
247 eina_strlcpy(pos, idx[x - 1], idx[x] - idx[x - 1] - dlen + 1);
249 //printf("str_array[%d] = '%s'\n", x, str_array[x]);
250 pos += idx[x] - idx[x - 1] - dlen + 1;
253 str_array[x] = s = pos;
257 if ((x != tokens) && ((!max_tokens) || (x < tokens)))
261 const char *d = delim, *d_end = d + dlen;
262 const char *tmp = src;
263 for (; (d < d_end) && (*tmp != '\0'); d++, tmp++)
265 if (EINA_LIKELY(*d != *tmp))
268 if (((!max_tokens) || (((tokens == (unsigned int)max_tokens) || x < tokens - 2))) && (EINA_UNLIKELY(d == d_end)))
273 //printf("str_array[%d] = '%s'\n", x, str_array[x - 1]);
284 str_array[tokens] = NULL;
288 if ((!max_tokens) || (tokens == (unsigned int)max_tokens))
299 /*============================================================================*
301 *============================================================================*/
303 /*============================================================================*
305 *============================================================================*/
308 eina_strlcpy(char *dst, const char *src, size_t siz)
311 return strlcpy(dst, src, siz);
317 /* Copy as many bytes as will fit */
321 if ((*d++ = *s++) == '\0')
325 /* Not enough room in dst, add NUL and traverse rest of src */
329 *d = '\0'; /* NUL-terminate dst */
335 return(s - src - 1); /* count does not include NUL */
340 eina_strlcat(char *dst, const char *src, size_t siz)
347 /* Find the end of dst and adjust bytes left but don't go past end */
348 while (n-- != 0 && *d != '\0')
354 return(dlen + strlen(s));
367 return(dlen + (s - src)); /* count does not include NUL */
371 eina_str_has_prefix(const char *str, const char *prefix)
376 str_len = strlen(str);
377 prefix_len = eina_strlen_bounded(prefix, str_len);
378 if (prefix_len == (size_t)-1)
381 return (strncmp(str, prefix, prefix_len) == 0);
385 eina_str_has_suffix(const char *str, const char *suffix)
387 return eina_str_has_suffix_helper(str, suffix, strcmp);
391 eina_str_has_extension(const char *str, const char *ext)
393 return eina_str_has_suffix_helper(str, ext, strcasecmp);
397 eina_str_split_full(const char *str,
400 unsigned int *elements)
402 return eina_str_split_full_helper(str, delim, max_tokens, elements);
407 eina_str_split(const char *str, const char *delim, int max_tokens)
409 return eina_str_split_full_helper(str, delim, max_tokens, NULL);
413 eina_str_join_len(char *dst,
421 size_t ret = a_len + b_len + 1;
429 memcpy(dst, a, size - 1);
430 dst[size - 1] = '\0';
434 memcpy(dst, a, a_len);
439 dst[size - 1] = '\0';
446 if (size <= off + b_len + 1)
448 memcpy(dst + off, b, size - off - 1);
449 dst[size - 1] = '\0';
453 memcpy(dst + off, b, b_len);
454 dst[off + b_len] = '\0';
460 eina_str_convert(const char *enc_from, const char *enc_to, const char *text)
463 char *new_txt, *inp, *outp;
464 size_t inb, outb, outlen, tob, outalloc;
469 ic = iconv_open(enc_to, enc_from);
470 if (ic == (iconv_t)(-1))
473 new_txt = malloc(64);
486 count = iconv(ic, &inp, &inb, &outp, &outb);
487 outlen += tob - outb;
488 if (count == (size_t)(-1))
492 new_txt = realloc(new_txt, outalloc + 64);
493 outp = new_txt + outlen;
497 else if (errno == EILSEQ)
505 else if (errno == EINVAL)
525 if (outalloc == outlen)
526 new_txt = realloc(new_txt, outalloc + 1);
537 eina_str_convert(const char *enc_from __UNUSED__,
538 const char *enc_to __UNUSED__,
539 const char *text __UNUSED__)
546 eina_str_escape(const char *str)
551 s2 = malloc((strlen(str) * 2) + 1);
555 for (s = str, d = s2; *s != 0; s++, d++)
557 if ((*s == ' ') || (*s == '\\') || (*s == '\''))
570 eina_str_tolower(char **str)
573 if ((!str) || (!(*str)))
576 for (p = *str; (*p); p++)
577 *p = tolower((unsigned char )(*p));
581 eina_str_toupper(char **str)
584 if ((!str) || (!(*str)))
587 for (p = *str; (*p); p++)
588 *p = toupper((unsigned char)(*p));