nwrap: Fix resolving hostnames with a trailing dot.
[sfrench/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
67         if (str == NULL || *str == '\0') {
68                 return false;
69         }
70
71         lval = strtoull(str, &end, 10 /* base */);
72         if (end == NULL || end == str) {
73                 return false;
74         }
75
76         if (*end) {
77                 if (strwicmp(end, "K") == 0) {
78                         lval *= 1024ULL;
79                 } else if (strwicmp(end, "M") == 0) {
80                         lval *= (1024ULL * 1024ULL);
81                 } else if (strwicmp(end, "G") == 0) {
82                         lval *= (1024ULL * 1024ULL * 1024ULL);
83                 } else if (strwicmp(end, "T") == 0) {
84                         lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL);
85                 } else if (strwicmp(end, "P") == 0) {
86                         lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL);
87                 } else {
88                         return false;
89                 }
90         }
91
92         *val = (uint64_t)lval;
93         return true;
94 }
95
96 /**
97  * Parse a uint64_t value from a string
98  *
99  * val will be set to the value read.
100  *
101  * @retval true if parsing was successful, false otherwise
102  */
103 _PUBLIC_ bool conv_str_u64(const char * str, uint64_t * val)
104 {
105         char *              end = NULL;
106         unsigned long long  lval;
107
108         if (str == NULL || *str == '\0') {
109                 return false;
110         }
111
112         lval = strtoull(str, &end, 10 /* base */);
113         if (end == NULL || *end != '\0' || end == str) {
114                 return false;
115         }
116
117         *val = (uint64_t)lval;
118         return true;
119 }
120
121 /**
122  * Compare 2 strings.
123  *
124  * @note The comparison is case-insensitive.
125  **/
126 _PUBLIC_ bool strequal(const char *s1, const char *s2)
127 {
128         if (s1 == s2)
129                 return true;
130         if (!s1 || !s2)
131                 return false;
132   
133         return strcasecmp_m(s1,s2) == 0;
134 }
135
136 /**
137  * @file
138  * @brief String utilities.
139  **/
140
141 static bool next_token_internal_talloc(TALLOC_CTX *ctx,
142                                 const char **ptr,
143                                 char **pp_buff,
144                                 const char *sep,
145                                 bool ltrim)
146 {
147         const char *s;
148         const char *saved_s;
149         char *pbuf;
150         bool quoted;
151         size_t len=1;
152
153         *pp_buff = NULL;
154         if (!ptr) {
155                 return(false);
156         }
157
158         s = *ptr;
159
160         /* default to simple separators */
161         if (!sep) {
162                 sep = " \t\n\r";
163         }
164
165         /* find the first non sep char, if left-trimming is requested */
166         if (ltrim) {
167                 while (*s && strchr_m(sep,*s)) {
168                         s++;
169                 }
170         }
171
172         /* nothing left? */
173         if (!*s) {
174                 return false;
175         }
176
177         /* When restarting we need to go from here. */
178         saved_s = s;
179
180         /* Work out the length needed. */
181         for (quoted = false; *s &&
182                         (quoted || !strchr_m(sep,*s)); s++) {
183                 if (*s == '\"') {
184                         quoted = !quoted;
185                 } else {
186                         len++;
187                 }
188         }
189
190         /* We started with len = 1 so we have space for the nul. */
191         *pp_buff = talloc_array(ctx, char, len);
192         if (!*pp_buff) {
193                 return false;
194         }
195
196         /* copy over the token */
197         pbuf = *pp_buff;
198         s = saved_s;
199         for (quoted = false; *s &&
200                         (quoted || !strchr_m(sep,*s)); s++) {
201                 if ( *s == '\"' ) {
202                         quoted = !quoted;
203                 } else {
204                         *pbuf++ = *s;
205                 }
206         }
207
208         *ptr = (*s) ? s+1 : s;
209         *pbuf = 0;
210
211         return true;
212 }
213
214 bool next_token_talloc(TALLOC_CTX *ctx,
215                         const char **ptr,
216                         char **pp_buff,
217                         const char *sep)
218 {
219         return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
220 }
221
222 /*
223  * Get the next token from a string, return false if none found.  Handles
224  * double-quotes.  This version does not trim leading separator characters
225  * before looking for a token.
226  */
227
228 bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
229                         const char **ptr,
230                         char **pp_buff,
231                         const char *sep)
232 {
233         return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
234 }
235
236 /**
237  * Get the next token from a string, return False if none found.
238  * Handles double-quotes.
239  *
240  * Based on a routine by GJC@VILLAGE.COM.
241  * Extensively modified by Andrew.Tridgell@anu.edu.au
242  **/
243 _PUBLIC_ bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
244 {
245         const char *s;
246         bool quoted;
247         size_t len=1;
248
249         if (!ptr)
250                 return false;
251
252         s = *ptr;
253
254         /* default to simple separators */
255         if (!sep)
256                 sep = " \t\n\r";
257
258         /* find the first non sep char */
259         while (*s && strchr_m(sep,*s))
260                 s++;
261
262         /* nothing left? */
263         if (!*s)
264                 return false;
265
266         /* copy over the token */
267         for (quoted = false; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
268                 if (*s == '\"') {
269                         quoted = !quoted;
270                 } else {
271                         len++;
272                         *buff++ = *s;
273                 }
274         }
275
276         *ptr = (*s) ? s+1 : s;
277         *buff = 0;
278
279         return true;
280 }
281
282 /**
283  Set a boolean variable from the text value stored in the passed string.
284  Returns true in success, false if the passed string does not correctly
285  represent a boolean.
286 **/
287
288 _PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean)
289 {
290         if (strwicmp(boolean_string, "yes") == 0 ||
291             strwicmp(boolean_string, "true") == 0 ||
292             strwicmp(boolean_string, "on") == 0 ||
293             strwicmp(boolean_string, "1") == 0) {
294                 *boolean = true;
295                 return true;
296         } else if (strwicmp(boolean_string, "no") == 0 ||
297                    strwicmp(boolean_string, "false") == 0 ||
298                    strwicmp(boolean_string, "off") == 0 ||
299                    strwicmp(boolean_string, "0") == 0) {
300                 *boolean = false;
301                 return true;
302         }
303         return false;
304 }
305
306 /**
307 return the number of bytes occupied by a buffer in CH_UTF16 format
308 the result includes the null termination
309 **/
310 _PUBLIC_ size_t utf16_len(const void *buf)
311 {
312         size_t len;
313
314         for (len = 0; SVAL(buf,len); len += 2) ;
315
316         return len + 2;
317 }
318
319 /**
320 return the number of bytes occupied by a buffer in CH_UTF16 format
321 the result includes the null termination
322 limited by 'n' bytes
323 **/
324 _PUBLIC_ size_t utf16_len_n(const void *src, size_t n)
325 {
326         size_t len;
327
328         for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
329
330         if (len+2 <= n) {
331                 len += 2;
332         }
333
334         return len;
335 }