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;
295 /*============================================================================*
297 *============================================================================*/
299 /*============================================================================*
301 *============================================================================*/
304 eina_strlcpy(char *dst, const char *src, size_t siz)
307 return strlcpy(dst, src, siz);
313 /* Copy as many bytes as will fit */
317 if ((*d++ = *s++) == '\0')
321 /* Not enough room in dst, add NUL and traverse rest of src */
325 *d = '\0'; /* NUL-terminate dst */
331 return(s - src - 1); /* count does not include NUL */
336 eina_strlcat(char *dst, const char *src, size_t siz)
343 /* Find the end of dst and adjust bytes left but don't go past end */
344 while (n-- != 0 && *d != '\0')
350 return(dlen + strlen(s));
363 return(dlen + (s - src)); /* count does not include NUL */
367 eina_str_has_prefix(const char *str, const char *prefix)
372 str_len = strlen(str);
373 prefix_len = eina_strlen_bounded(prefix, str_len);
374 if (prefix_len == (size_t)-1)
377 return (strncmp(str, prefix, prefix_len) == 0);
381 eina_str_has_suffix(const char *str, const char *suffix)
383 return eina_str_has_suffix_helper(str, suffix, strcmp);
387 eina_str_has_extension(const char *str, const char *ext)
389 return eina_str_has_suffix_helper(str, ext, strcasecmp);
393 eina_str_split_full(const char *str,
396 unsigned int *elements)
398 return eina_str_split_full_helper(str, delim, max_tokens, elements);
403 eina_str_split(const char *str, const char *delim, int max_tokens)
405 return eina_str_split_full_helper(str, delim, max_tokens, NULL);
409 eina_str_join_len(char *dst,
417 size_t ret = a_len + b_len + 1;
425 memcpy(dst, a, size - 1);
426 dst[size - 1] = '\0';
430 memcpy(dst, a, a_len);
435 dst[size - 1] = '\0';
442 if (size <= off + b_len + 1)
444 memcpy(dst + off, b, size - off - 1);
445 dst[size - 1] = '\0';
449 memcpy(dst + off, b, b_len);
450 dst[off + b_len] = '\0';
456 eina_str_convert(const char *enc_from, const char *enc_to, const char *text)
459 char *new_txt, *inp, *outp;
460 size_t inb, outb, outlen, tob, outalloc;
465 ic = iconv_open(enc_to, enc_from);
466 if (ic == (iconv_t)(-1))
469 new_txt = malloc(64);
482 count = iconv(ic, &inp, &inb, &outp, &outb);
483 outlen += tob - outb;
484 if (count == (size_t)(-1))
488 new_txt = realloc(new_txt, outalloc + 64);
489 outp = new_txt + outlen;
493 else if (errno == EILSEQ)
501 else if (errno == EINVAL)
521 if (outalloc == outlen)
522 new_txt = realloc(new_txt, outalloc + 1);
533 eina_str_convert(const char *enc_from __UNUSED__,
534 const char *enc_to __UNUSED__,
535 const char *text __UNUSED__)
542 eina_str_escape(const char *str)
547 s2 = malloc((strlen(str) * 2) + 1);
551 for (s = str, d = s2; *s != 0; s++, d++)
553 if ((*s == ' ') || (*s == '\\') || (*s == '\''))
566 eina_str_tolower(char **str)
569 if ((!str) || (!(*str)))
572 for (p = *str; (*p); p++)
573 *p = tolower((unsigned char )(*p));
577 eina_str_toupper(char **str)
580 if ((!str) || (!(*str)))
583 for (p = *str; (*p); p++)
584 *p = toupper((unsigned char)(*p));