dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / vsftpd / str.c
blobd810a783c8fc13e258bc9992f290c2efd95de2d4
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * str.c
7 * Generic string handling functions. The fact that a string is implemented
8 * internally using a buffer is not exposed in the API. If you can't see
9 * the buffers, you can't handle them in a screwed way. Or so goes the
10 * theory, anyway...
13 /* Anti-lamer measures deployed, sir! */
14 #define PRIVATE_HANDS_OFF_p_buf p_buf
15 #define PRIVATE_HANDS_OFF_len len
16 #define PRIVATE_HANDS_OFF_alloc_bytes alloc_bytes
17 #include "str.h"
19 /* Ick. Its for die() */
20 #include "utility.h"
21 #include "sysutil.h"
23 /* File local functions */
24 static void str_split_text_common(struct mystr* p_src, struct mystr* p_rhs,
25 const char* p_text, int is_reverse);
26 static int str_equal_internal(const char* p_buf1, unsigned int buf1_len,
27 const char* p_buf2, unsigned int buf2_len);
29 /* Private functions */
30 static void
31 s_setbuf(struct mystr* p_str, char* p_newbuf)
33 if (p_str->p_buf != 0)
35 bug("p_buf not NULL when setting it");
37 p_str->p_buf = p_newbuf;
40 void
41 private_str_alloc_memchunk(struct mystr* p_str, const char* p_src,
42 unsigned int len)
44 /* Make sure this will fit in the buffer */
45 unsigned int buf_needed = len + 1;
46 if (buf_needed > p_str->alloc_bytes)
48 str_free(p_str);
49 s_setbuf(p_str, vsf_sysutil_malloc(buf_needed));
50 p_str->alloc_bytes = buf_needed;
52 vsf_sysutil_memcpy(p_str->p_buf, p_src, len);
53 p_str->p_buf[len] = '\0';
54 p_str->len = len;
57 void
58 private_str_append_memchunk(struct mystr* p_str, const char* p_src,
59 unsigned int len)
61 unsigned int buf_needed = p_str->len + len + 1;
62 if (buf_needed > p_str->alloc_bytes)
64 p_str->p_buf = vsf_sysutil_realloc(p_str->p_buf, buf_needed);
65 p_str->alloc_bytes = buf_needed;
67 vsf_sysutil_memcpy(p_str->p_buf + p_str->len, p_src, len);
68 p_str->p_buf[p_str->len + len] = '\0';
69 p_str->len += len;
72 /* Public functions */
73 void
74 str_alloc_text(struct mystr* p_str, const char* p_src)
76 unsigned int len = vsf_sysutil_strlen(p_src);
77 private_str_alloc_memchunk(p_str, p_src, len);
80 void
81 str_copy(struct mystr* p_dest, const struct mystr* p_src)
83 private_str_alloc_memchunk(p_dest, p_src->p_buf, p_src->len);
86 const char*
87 str_strdup(const struct mystr* p_str)
89 return vsf_sysutil_strdup(str_getbuf(p_str));
92 void
93 str_alloc_alt_term(struct mystr* p_str, const char* p_src, char term)
95 const char* p_search = p_src;
96 unsigned int len = 0;
97 while (*p_search != term)
99 p_search++;
100 len++;
102 private_str_alloc_memchunk(p_str, p_src, len);
105 void
106 str_alloc_ulong(struct mystr* p_str, unsigned long the_long)
108 str_alloc_text(p_str, vsf_sysutil_ulong_to_str(the_long));
111 void
112 str_alloc_filesize_t(struct mystr* p_str, filesize_t the_filesize)
114 str_alloc_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));
117 void
118 str_free(struct mystr* p_str)
120 if (p_str->p_buf != 0)
122 vsf_sysutil_free(p_str->p_buf);
124 p_str->p_buf = 0;
125 p_str->len = 0;
126 p_str->alloc_bytes = 0;
129 void
130 str_empty(struct mystr* p_str)
132 /* Ensure a buffer is allocated. */
133 (void) str_getbuf(p_str);
134 str_trunc(p_str, 0);
137 void
138 str_trunc(struct mystr* p_str, unsigned int trunc_len)
140 if (trunc_len >= p_str->alloc_bytes)
142 bug("trunc_len not smaller than alloc_bytes in str_trunc");
144 p_str->len = trunc_len;
145 p_str->p_buf[p_str->len] = '\0';
148 void
149 str_reserve(struct mystr* p_str, unsigned int res_len)
151 /* Reserve space for the trailing zero as well. */
152 res_len++;
153 if (res_len > p_str->alloc_bytes)
155 p_str->p_buf = vsf_sysutil_realloc(p_str->p_buf, res_len);
156 p_str->alloc_bytes = res_len;
158 p_str->p_buf[res_len - 1] = '\0';
162 str_isempty(const struct mystr* p_str)
164 return (p_str->len == 0);
167 unsigned int
168 str_getlen(const struct mystr* p_str)
170 return p_str->len;
173 const char*
174 str_getbuf(const struct mystr* p_str)
176 if (p_str->p_buf == 0)
178 if (p_str->len != 0 || p_str->alloc_bytes != 0)
180 bug("p_buf NULL and len or alloc_bytes != 0 in str_getbuf");
182 private_str_alloc_memchunk((struct mystr*)p_str, 0, 0);
184 return p_str->p_buf;
188 str_strcmp(const struct mystr* p_str1, const struct mystr* p_str2)
190 return str_equal_internal(p_str1->p_buf, p_str1->len,
191 p_str2->p_buf, p_str2->len);
194 static int
195 str_equal_internal(const char* p_buf1, unsigned int buf1_len,
196 const char* p_buf2, unsigned int buf2_len)
198 int retval;
199 unsigned int minlen = buf1_len;
200 if (buf2_len < minlen)
202 minlen = buf2_len;
204 retval = vsf_sysutil_memcmp(p_buf1, p_buf2, minlen);
205 if (retval != 0 || buf1_len == buf2_len)
207 return retval;
209 /* Strings equal but lengths differ. The greater one, then, is the longer */
210 return (int) (buf1_len - buf2_len);
214 str_equal(const struct mystr* p_str1, const struct mystr* p_str2)
216 return (str_strcmp(p_str1, p_str2) == 0);
220 str_equal_text(const struct mystr* p_str, const char* p_text)
222 unsigned int cmplen = vsf_sysutil_strlen(p_text);
223 return (str_equal_internal(p_str->p_buf, p_str->len, p_text, cmplen) == 0);
226 void
227 str_append_str(struct mystr* p_str, const struct mystr* p_other)
229 private_str_append_memchunk(p_str, p_other->p_buf, p_other->len);
232 void
233 str_append_text(struct mystr* p_str, const char* p_src)
235 unsigned int len = vsf_sysutil_strlen(p_src);
236 private_str_append_memchunk(p_str, p_src, len);
239 void
240 str_append_char(struct mystr* p_str, char the_char)
242 private_str_append_memchunk(p_str, &the_char, sizeof(the_char));
245 void
246 str_append_ulong(struct mystr* p_str, unsigned long the_ulong)
248 str_append_text(p_str, vsf_sysutil_ulong_to_str(the_ulong));
251 void
252 str_append_filesize_t(struct mystr* p_str, filesize_t the_filesize)
254 str_append_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));
257 void
258 str_append_double(struct mystr* p_str, double the_double)
260 str_append_text(p_str, vsf_sysutil_double_to_str(the_double));
263 void
264 str_upper(struct mystr* p_str)
266 unsigned int i;
267 for (i=0; i < p_str->len; i++)
269 p_str->p_buf[i] = vsf_sysutil_toupper(p_str->p_buf[i]);
273 void
274 str_rpad(struct mystr* p_str, const unsigned int min_width)
276 unsigned int to_pad;
277 if (p_str->len >= min_width)
279 return;
281 to_pad = min_width - p_str->len;
282 while (to_pad--)
284 str_append_char(p_str, ' ');
288 void
289 str_lpad(struct mystr* p_str, const unsigned int min_width)
291 static struct mystr s_tmp_str;
292 unsigned int to_pad;
293 if (p_str->len >= min_width)
295 return;
297 to_pad = min_width - p_str->len;
298 str_empty(&s_tmp_str);
299 while (to_pad--)
301 str_append_char(&s_tmp_str, ' ');
303 str_append_str(&s_tmp_str, p_str);
304 str_copy(p_str, &s_tmp_str);
307 void
308 str_replace_char(struct mystr* p_str, char from, char to)
310 unsigned int i;
311 for (i=0; i < p_str->len; i++)
313 if (p_str->p_buf[i] == from)
315 p_str->p_buf[i] = to;
320 void
321 str_replace_text(struct mystr* p_str, const char* p_from, const char* p_to)
323 static struct mystr s_lhs_chunk_str;
324 static struct mystr s_rhs_chunk_str;
325 unsigned int lhs_len;
326 str_copy(&s_lhs_chunk_str, p_str);
327 str_free(p_str);
330 lhs_len = str_getlen(&s_lhs_chunk_str);
331 str_split_text(&s_lhs_chunk_str, &s_rhs_chunk_str, p_from);
332 /* Copy lhs to destination */
333 str_append_str(p_str, &s_lhs_chunk_str);
334 /* If this was a 'hit', append the 'to' text */
335 if (str_getlen(&s_lhs_chunk_str) < lhs_len)
337 str_append_text(p_str, p_to);
339 /* Current rhs becomes new lhs */
340 str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
341 } while (!str_isempty(&s_lhs_chunk_str));
344 void
345 str_split_char(struct mystr* p_src, struct mystr* p_rhs, char c)
347 /* Just use str_split_text */
348 char ministr[2];
349 ministr[0] = c;
350 ministr[1] = '\0';
351 str_split_text(p_src, p_rhs, ministr);
354 void
355 str_split_char_reverse(struct mystr* p_src, struct mystr* p_rhs, char c)
357 /* Just use str_split_text_reverse */
358 char ministr[2];
359 ministr[0] = c;
360 ministr[1] = '\0';
361 str_split_text_reverse(p_src, p_rhs, ministr);
364 void
365 str_split_text(struct mystr* p_src, struct mystr* p_rhs, const char* p_text)
367 str_split_text_common(p_src, p_rhs, p_text, 0);
370 void
371 str_split_text_reverse(struct mystr* p_src, struct mystr* p_rhs,
372 const char* p_text)
374 str_split_text_common(p_src, p_rhs, p_text, 1);
377 static void
378 str_split_text_common(struct mystr* p_src, struct mystr* p_rhs,
379 const char* p_text, int is_reverse)
381 struct str_locate_result locate_result;
382 unsigned int indexx;
383 unsigned int search_len = vsf_sysutil_strlen(p_text);
384 if (is_reverse)
386 locate_result = str_locate_text_reverse(p_src, p_text);
388 else
390 locate_result = str_locate_text(p_src, p_text);
392 /* Not found? */
393 if (!locate_result.found)
395 str_empty(p_rhs);
396 return;
398 indexx = locate_result.index;
399 if (indexx + search_len > p_src->len)
401 bug("indexx invalid in str_split_text");
403 /* Build rhs */
404 private_str_alloc_memchunk(p_rhs, p_src->p_buf + indexx + search_len,
405 p_src->len - indexx - search_len);
406 /* Build lhs */
407 str_trunc(p_src, indexx);
410 struct str_locate_result
411 str_locate_str(const struct mystr* p_str, const struct mystr* p_look_str)
413 return str_locate_text(p_str, str_getbuf(p_look_str));
416 struct str_locate_result
417 str_locate_str_reverse(const struct mystr* p_str,
418 const struct mystr* p_look_str)
420 return str_locate_text_reverse(p_str, str_getbuf(p_look_str));
423 struct str_locate_result
424 str_locate_char(const struct mystr* p_str, char look_char)
426 char look_str[2];
427 look_str[0] = look_char;
428 look_str[1] = '\0';
429 return str_locate_text(p_str, look_str);
432 struct str_locate_result
433 str_locate_chars(const struct mystr* p_str, const char* p_chars)
435 struct str_locate_result retval;
436 unsigned int num_chars = vsf_sysutil_strlen(p_chars);
437 unsigned int i = 0;
438 retval.found = 0;
439 retval.char_found = 0;
440 retval.index = 0;
441 for (; i < p_str->len; ++i)
443 unsigned int j = 0;
444 char this_char = p_str->p_buf[i];
445 for (; j < num_chars; ++j)
447 if (p_chars[j] == this_char)
449 retval.found = 1;
450 retval.index = i;
451 retval.char_found = p_chars[j];
452 return retval;
456 return retval;
459 struct str_locate_result
460 str_locate_text(const struct mystr* p_str, const char* p_text)
462 struct str_locate_result retval;
463 unsigned int i;
464 unsigned int text_len = vsf_sysutil_strlen(p_text);
465 retval.found = 0;
466 retval.char_found = 0;
467 retval.index = 0;
468 if (text_len == 0 || text_len > p_str->len)
470 /* Not found */
471 return retval;
473 for (i=0; i <= (p_str->len - text_len); i++)
475 if (vsf_sysutil_memcmp(p_str->p_buf + i, p_text, text_len) == 0)
477 retval.found = 1;
478 retval.index = i;
479 return retval;
482 /* Not found */
483 return retval;
486 struct str_locate_result
487 str_locate_text_reverse(const struct mystr* p_str, const char* p_text)
489 struct str_locate_result retval;
490 unsigned int i;
491 unsigned int text_len = vsf_sysutil_strlen(p_text);
492 retval.found = 0;
493 retval.char_found = 0;
494 retval.index = 0;
495 if (text_len == 0 || text_len > p_str->len)
497 return retval;
499 i = p_str->len - text_len;
500 /* Want to go through loop once even if i==0 */
501 while (1)
503 if (vsf_sysutil_memcmp(p_str->p_buf + i, p_text, text_len) == 0)
505 retval.found = 1;
506 retval.index = i;
507 return retval;
509 if (i == 0)
511 break;
513 i--;
515 /* Not found */
516 return retval;
519 void
520 str_left(const struct mystr* p_str, struct mystr* p_out, unsigned int chars)
522 if (chars > p_str->len)
524 bug("chars invalid in str_left");
526 private_str_alloc_memchunk(p_out, p_str->p_buf, chars);
529 void
530 str_right(const struct mystr* p_str, struct mystr* p_out, unsigned int chars)
532 unsigned int indexx = p_str->len - chars;
533 if (chars > p_str->len)
535 bug("chars invalid in str_right");
537 private_str_alloc_memchunk(p_out, p_str->p_buf + indexx, chars);
540 void
541 str_mid_to_end(const struct mystr* p_str, struct mystr* p_out,
542 unsigned int indexx)
544 if (indexx > p_str->len)
546 bug("invalid indexx in str_mid_to_end");
548 private_str_alloc_memchunk(p_out, p_str->p_buf + indexx,
549 p_str->len - indexx);
552 char
553 str_get_char_at(const struct mystr* p_str, const unsigned int indexx)
555 if (indexx >= p_str->len)
557 bug("bad indexx in str_get_char_at");
559 return p_str->p_buf[indexx];
563 str_contains_space(const struct mystr* p_str)
565 unsigned int i;
566 for (i=0; i < p_str->len; i++)
568 if (vsf_sysutil_isspace(p_str->p_buf[i]))
570 return 1;
573 return 0;
577 str_all_space(const struct mystr* p_str)
579 unsigned int i;
580 for (i=0; i < p_str->len; i++)
582 if (!vsf_sysutil_isspace(p_str->p_buf[i]))
584 return 0;
587 return 1;
591 str_contains_unprintable(const struct mystr* p_str)
593 unsigned int i;
594 for (i=0; i < p_str->len; i++)
596 if (!vsf_sysutil_isprint(p_str->p_buf[i]))
598 return 1;
601 return 0;
605 str_atoi(const struct mystr* p_str)
607 return vsf_sysutil_atoi(str_getbuf(p_str));
610 filesize_t
611 str_a_to_filesize_t(const struct mystr* p_str)
613 return vsf_sysutil_a_to_filesize_t(str_getbuf(p_str));
616 unsigned int
617 str_octal_to_uint(const struct mystr* p_str)
619 return vsf_sysutil_octal_to_uint(str_getbuf(p_str));
623 str_getline(const struct mystr* p_str, struct mystr* p_line_str,
624 unsigned int* p_pos)
626 unsigned int start_pos = *p_pos;
627 unsigned int curr_pos = start_pos;
628 unsigned int buf_len = str_getlen(p_str);
629 const char* p_buf = str_getbuf(p_str);
630 unsigned int out_len;
631 if (start_pos > buf_len)
633 bug("p_pos out of range in str_getline");
635 str_empty(p_line_str);
636 if (start_pos == buf_len)
638 return 0;
640 while (curr_pos < buf_len && p_buf[curr_pos] != '\n')
642 curr_pos++;
644 out_len = curr_pos - start_pos;
645 /* If we ended on a \n - skip it */
646 if (curr_pos < buf_len && p_buf[curr_pos] == '\n')
648 curr_pos++;
650 private_str_alloc_memchunk(p_line_str, p_buf + start_pos, out_len);
651 *p_pos = curr_pos;
652 return 1;
656 str_contains_line(const struct mystr* p_str, const struct mystr* p_line_str)
658 static struct mystr s_curr_line_str;
659 unsigned int pos = 0;
660 while (str_getline(p_str, &s_curr_line_str, &pos))
662 if (str_equal(&s_curr_line_str, p_line_str))
664 return 1;
667 return 0;
670 void
671 str_replace_unprintable(struct mystr* p_str, char new_char)
673 unsigned int i;
674 for (i=0; i < p_str->len; i++)
676 if (!vsf_sysutil_isprint(p_str->p_buf[i]))
678 p_str->p_buf[i] = new_char;