1 /*
2 * Copyright (C) 2004-2011 Christos Tsantilas
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA.
18 */
19
20 #include "common.h"
21 #include "c-icap.h"
22 #include "array.h"
23 #include "util.h"
24 #include <ctype.h>
25 #include <errno.h>
26 #include <limits.h>
27
ci_strnstr(const char * s,const char * find,size_t slen)28 const char *ci_strnstr(const char *s, const char *find, size_t slen)
29 {
30 size_t len = strlen(find);
31
32 if (len == 0)
33 return NULL;
34
35 while (len <= slen) {
36 if (*s == *find && strncmp(s, find, len) == 0 )
37 return s;
38 s++,slen--;
39 }
40 return NULL;
41 }
42
ci_strcasestr(const char * str,const char * find)43 const char *ci_strcasestr(const char *str, const char *find)
44 {
45 const char *s, *c, *f;
46 for (s = str; *s != '\0'; ++s) {
47 for (f = find, c = s; ; ++f, ++c) {
48 if (*f == '\0') /*find matched s*/
49 return s;
50 if (*c == '\0') /*find is longer than the remaining string */
51 return NULL;
52 if (tolower(*c) != tolower(*f))
53 break;
54 }
55 }
56 return NULL;
57 }
58
ci_strncasestr(const char * s,const char * find,size_t slen)59 const char *ci_strncasestr(const char *s, const char *find, size_t slen)
60 {
61 size_t len = strlen(find);
62
63 if (len == 0)
64 return NULL;
65
66 while (len <= slen) {
67 if (tolower(*s) == tolower(*find) && strncasecmp(s, find, len) == 0 )
68 return s;
69 s++,slen--;
70 }
71 return NULL;
72 }
73
74 static const char *atol_err_erange = "ERANGE";
75 static const char *atol_err_conversion = "CONVERSION_ERROR";
76 static const char *atol_err_nonumber = "NO_DIGITS_ERROR";
77
ci_atol_ext(const char * str,const char ** error)78 long int ci_atol_ext(const char *str, const char **error)
79 {
80 char *e;
81
82 long int val;
83 errno = 0;
84 val = strtol(str, &e, 10);
85
86 if (error) {
87 *error = NULL;
88
89 if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
90 *error = atol_err_erange;
91 else if (errno != 0 && val == 0)
92 *error = atol_err_conversion;
93 else if (e == str)
94 *error = atol_err_nonumber;
95
96 if (*error)
97 return 0;
98 }
99
100 if (val) {
101 if (*e == 'k' || * e == 'K')
102 val = val * 1024;
103 else if (*e == 'm' || * e == 'M')
104 val = val * 1024 * 1024;
105 }
106 return val;
107 }
108
ci_str_trim(char * str)109 void ci_str_trim(char *str)
110 {
111 char *s, *e;
112
113 if (!str)
114 return;
115
116 s = str;
117 e = NULL;
118 while (isspace(*s)) {
119 e = s;
120 while (*e != '\0') {
121 *e = *(e+1);
122 e++;
123 }
124 }
125
126 /*if (e) e--; else */
127 e = str+strlen(str);
128 e--;
129 while (isspace(*e) && e >= str) {*e = '\0'; --e;};
130 }
131
ci_str_trim2(char * s)132 char *ci_str_trim2(char *s)
133 {
134 char *e;
135
136 if (!s)
137 return NULL;
138
139 while (isspace(*s)) ++s;
140 e = s + strlen(s);
141 e--;
142 while (isspace(*e) && e >= s) {*e = '\0'; --e;};
143 return s;
144 }
145
ci_strerror(int error,char * buf,size_t buflen)146 char * ci_strerror(int error, char *buf, size_t buflen)
147 {
148 #if defined(STRERROR_R_CHAR_P)
149 return strerror_r(error, buf, buflen);
150 #elif defined(HAVE_STRERROR_R)
151 if (strerror_r(error, buf, buflen) == 0)
152 return buf;
153 #else
154 snprintf(buf, buflen, "%d", error);
155 return buf;
156
157 #endif
158 }
159
160 /*
161 TODO: support escaped chars,
162 */
ci_parse_key_value_list(const char * str,char sep)163 ci_dyn_array_t *ci_parse_key_value_list(const char *str, char sep)
164 {
165 char *s, *e, *k, *v;
166 ci_dyn_array_t *args_array;
167 s = strdup(str);
168 if (!s)
169 return NULL;
170
171 args_array = ci_dyn_array_new(1024);
172 k = s;
173 while (k) {
174 if ((e = strchr(k, sep))) {
175 *e = '\0';
176 e++;
177 }
178 if ((v = strchr(k, '='))) {
179 *v = '\0';
180 ++v;
181 }
182 k = ci_str_trim2(k);
183 if (v)
184 v = ci_str_trim2(v);
185 if (*k) {
186 ci_dyn_array_add(args_array, k, v ? v : "", v ? strlen(v) + 1 : 1);
187 }
188 k = (e && *e) ? e : NULL;
189 }
190 free(s);
191 return args_array;
192 }
193