447919b087bbac5be79ca8c3bb8f2ff8702795f2
[kai/samba-autobuild/.git] / lib / util / util_str.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    
5    Copyright (C) Andrew Tridgell 1992-2001
6    Copyright (C) Simo Sorce      2001-2002
7    Copyright (C) Martin Pool     2003
8    Copyright (C) James Peach     2005
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "system/locale.h"
26 #undef strncasecmp
27 #undef strcasemp
28
29 /**
30  * @file
31  * @brief String utilities.
32  **/
33
34 /**
35  * Parse a string containing a boolean value.
36  *
37  * val will be set to the read value.
38  *
39  * @retval true if a boolean value was parsed, false otherwise.
40  */
41 _PUBLIC_ bool conv_str_bool(const char * str, bool * val)
42 {
43         char *  end = NULL;
44         long    lval;
45
46         if (str == NULL || *str == '\0') {
47                 return false;
48         }
49
50         lval = strtol(str, &end, 10 /* base */);
51         if (end == NULL || *end != '\0' || end == str) {
52                 return set_boolean(str, val);
53         }
54
55         *val = (lval) ? true : false;
56         return true;
57 }
58
59 /**
60  * Convert a size specification like 16K into an integral number of bytes. 
61  **/
62 _PUBLIC_ bool conv_str_size_error(const char * str, uint64_t * val)
63 {
64         char *              end = NULL;
65         unsigned long long  lval;
66         int error = 0;
67
68         if (str == NULL || *str == '\0') {
69                 return false;
70         }
71
72         lval = strtoull_err(str, &end, 10, &error);
73         if (end == NULL || end == str || error != 0) {
74                 return false;
75         }
76
77         if (*end) {
78                 if (strwicmp(end, "K") == 0) {
79                         lval *= 1024ULL;
80                 } else if (strwicmp(end, "M") == 0) {
81                         lval *= (1024ULL * 1024ULL);
82                 } else if (strwicmp(end, "G") == 0) {
83                         lval *= (1024ULL * 1024ULL * 1024ULL);
84                 } else if (strwicmp(end, "T") == 0) {
85                         lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL);
86                 } else if (strwicmp(end, "P") == 0) {
87                         lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL);
88                 } else {
89                         return false;
90                 }
91         }
92
93         *val = (uint64_t)lval;
94         return true;
95 }
96
97 /**
98  * Parse a uint64_t value from a string
99  *
100  * val will be set to the value read.
101  *
102  * @retval true if parsing was successful, false otherwise
103  */
104 _PUBLIC_ bool conv_str_u64(const char * str, uint64_t * val)
105 {
106         char *              end = NULL;
107         unsigned long long  lval;
108         int error = 0;
109
110         if (str == NULL || *str == '\0') {
111                 return false;
112         }
113
114         lval = strtoull_err(str, &end, 10, &error);
115         if (end == NULL || *end != '\0' || end == str || error != 0) {
116                 return false;
117         }
118
119         *val = (uint64_t)lval;
120         return true;
121 }
122
123 /**
124  * Compare 2 strings.
125  *
126  * @note The comparison is case-insensitive.
127  **/
128 _PUBLIC_ bool strequal(const char *s1, const char *s2)
129 {
130         if (s1 == s2)
131                 return true;
132         if (!s1 || !s2)
133                 return false;
134   
135         return strcasecmp_m(s1,s2) == 0;
136 }
137
138 /**
139  * @file
140  * @brief String utilities.
141  **/
142
143 static bool next_token_internal_talloc(TALLOC_CTX *ctx,
144                                 const char **ptr,
145                                 char **pp_buff,
146                                 const char *sep,
147                                 bool ltrim)
148 {
149         const char *s;
150         const char *saved_s;
151         char *pbuf;
152         bool quoted;
153         size_t len=1;
154
155         *pp_buff = NULL;
156         if (!ptr) {
157                 return(false);
158         }
159
160         s = *ptr;
161
162         /* default to simple separators */
163         if (!sep) {
164                 sep = " \t\n\r";
165         }
166
167         /* find the first non sep char, if left-trimming is requested */
168         if (ltrim) {
169                 while (*s && strchr_m(sep,*s)) {
170                         s++;
171                 }
172         }
173
174         /* nothing left? */
175         if (!*s) {
176                 return false;
177         }
178
179         /* When restarting we need to go from here. */
180         saved_s = s;
181
182         /* Work out the length needed. */
183         for (quoted = false; *s &&
184                         (quoted || !strchr_m(sep,*s)); s++) {
185                 if (*s == '\"') {
186                         quoted = !quoted;
187                 } else {
188                         len++;
189                 }
190         }
191
192         /* We started with len = 1 so we have space for the nul. */
193         *pp_buff = talloc_array(ctx, char, len);
194         if (!*pp_buff) {
195                 return false;
196         }
197
198         /* copy over the token */
199         pbuf = *pp_buff;
200         s = saved_s;
201         for (quoted = false; *s &&
202                         (quoted || !strchr_m(sep,*s)); s++) {
203                 if ( *s == '\"' ) {
204                         quoted = !quoted;
205                 } else {
206                         *pbuf++ = *s;
207                 }
208         }
209
210         *ptr = (*s) ? s+1 : s;
211         *pbuf = 0;
212
213         return true;
214 }
215
216 bool next_token_talloc(TALLOC_CTX *ctx,
217                         const char **ptr,
218                         char **pp_buff,
219                         const char *sep)
220 {
221         return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
222 }
223
224 /*
225  * Get the next token from a string, return false if none found.  Handles
226  * double-quotes.  This version does not trim leading separator characters
227  * before looking for a token.
228  */
229
230 bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
231                         const char **ptr,
232                         char **pp_buff,
233                         const char *sep)
234 {
235         return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
236 }
237
238 /**
239  * Get the next token from a string, return False if none found.
240  * Handles double-quotes.
241  *
242  * Based on a routine by GJC@VILLAGE.COM.
243  * Extensively modified by Andrew.Tridgell@anu.edu.au
244  **/
245 _PUBLIC_ bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
246 {
247         const char *s;
248         bool quoted;
249         size_t len=1;
250
251         if (!ptr)
252                 return false;
253
254         s = *ptr;
255
256         /* default to simple separators */
257         if (!sep)
258                 sep = " \t\n\r";
259
260         /* find the first non sep char */
261         while (*s && strchr_m(sep,*s))
262                 s++;
263
264         /* nothing left? */
265         if (!*s)
266                 return false;
267
268         /* copy over the token */
269         for (quoted = false; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
270                 if (*s == '\"') {
271                         quoted = !quoted;
272                 } else {
273                         len++;
274                         *buff++ = *s;
275                 }
276         }
277
278         *ptr = (*s) ? s+1 : s;
279         *buff = 0;
280
281         return true;
282 }
283
284 /**
285  Set a boolean variable from the text value stored in the passed string.
286  Returns true in success, false if the passed string does not correctly
287  represent a boolean.
288 **/
289
290 _PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean)
291 {
292         if (strwicmp(boolean_string, "yes") == 0 ||
293             strwicmp(boolean_string, "true") == 0 ||
294             strwicmp(boolean_string, "on") == 0 ||
295             strwicmp(boolean_string, "1") == 0) {
296                 *boolean = true;
297                 return true;
298         } else if (strwicmp(boolean_string, "no") == 0 ||
299                    strwicmp(boolean_string, "false") == 0 ||
300                    strwicmp(boolean_string, "off") == 0 ||
301                    strwicmp(boolean_string, "0") == 0) {
302                 *boolean = false;
303                 return true;
304         }
305         return false;
306 }
307
308 /**
309 return the number of bytes occupied by a buffer in CH_UTF16 format
310 the result includes the null termination
311 **/
312 _PUBLIC_ size_t utf16_len(const void *buf)
313 {
314         size_t len;
315
316         for (len = 0; SVAL(buf,len); len += 2) ;
317
318         return len + 2;
319 }
320
321 /**
322 return the number of bytes occupied by a buffer in CH_UTF16 format
323 the result includes the null termination
324 limited by 'n' bytes
325 **/
326 _PUBLIC_ size_t utf16_len_n(const void *src, size_t n)
327 {
328         size_t len;
329
330         for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
331
332         if (len+2 <= n) {
333                 len += 2;
334         }
335
336         return len;
337 }
338
339 _PUBLIC_ int memcmp_const_time(const void *s1, const void *s2, size_t n)
340 {
341         const uint8_t *p1 = s1, *p2 = s2;
342         size_t i, sum = 0;
343
344         for (i = 0; i < n; i++) {
345                 sum |= (p1[i] ^ p2[i]);
346         }
347
348         return sum != 0;
349 }