123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713 |
- /*
- * Part of Very Secure FTPd
- * Licence: GPL v2
- * Author: Chris Evans
- * str.c
- *
- * Generic string handling functions. The fact that a string is implemented
- * internally using a buffer is not exposed in the API. If you can't see
- * the buffers, you can't handle them in a screwed way. Or so goes the
- * theory, anyway...
- */
- /* Anti-lamer measures deployed, sir! */
- #define PRIVATE_HANDS_OFF_p_buf p_buf
- #define PRIVATE_HANDS_OFF_len len
- #define PRIVATE_HANDS_OFF_alloc_bytes alloc_bytes
- #include "str.h"
- /* Ick. Its for die() */
- #include "utility.h"
- #include "sysutil.h"
- /* File local functions */
- static void str_split_text_common(struct mystr* p_src, struct mystr* p_rhs,
- const char* p_text, int is_reverse);
- static int str_equal_internal(const char* p_buf1, unsigned int buf1_len,
- const char* p_buf2, unsigned int buf2_len);
- /* Private functions */
- static void
- s_setbuf(struct mystr* p_str, char* p_newbuf)
- {
- if (p_str->p_buf != 0)
- {
- bug("p_buf not NULL when setting it");
- }
- p_str->p_buf = p_newbuf;
- }
- void
- private_str_alloc_memchunk(struct mystr* p_str, const char* p_src,
- unsigned int len)
- {
- /* Make sure this will fit in the buffer */
- unsigned int buf_needed;
- if (len + 1 < len)
- {
- bug("integer overflow");
- }
- buf_needed = len + 1;
- if (buf_needed > p_str->alloc_bytes)
- {
- str_free(p_str);
- s_setbuf(p_str, vsf_sysutil_malloc(buf_needed));
- p_str->alloc_bytes = buf_needed;
- }
- vsf_sysutil_memcpy(p_str->p_buf, p_src, len);
- p_str->p_buf[len] = '\0';
- p_str->len = len;
- }
- void
- private_str_append_memchunk(struct mystr* p_str, const char* p_src,
- unsigned int len)
- {
- unsigned int buf_needed;
- if (len + p_str->len < len)
- {
- bug("integer overflow");
- }
- buf_needed = len + p_str->len;
- if (buf_needed + 1 < buf_needed)
- {
- bug("integer overflow");
- }
- buf_needed++;
- if (buf_needed > p_str->alloc_bytes)
- {
- p_str->p_buf = vsf_sysutil_realloc(p_str->p_buf, buf_needed);
- p_str->alloc_bytes = buf_needed;
- }
- vsf_sysutil_memcpy(p_str->p_buf + p_str->len, p_src, len);
- p_str->p_buf[p_str->len + len] = '\0';
- p_str->len += len;
- }
- /* Public functions */
- void
- str_alloc_text(struct mystr* p_str, const char* p_src)
- {
- unsigned int len = vsf_sysutil_strlen(p_src);
- private_str_alloc_memchunk(p_str, p_src, len);
- }
- void
- str_copy(struct mystr* p_dest, const struct mystr* p_src)
- {
- private_str_alloc_memchunk(p_dest, p_src->p_buf, p_src->len);
- }
- const char*
- str_strdup(const struct mystr* p_str)
- {
- return vsf_sysutil_strdup(str_getbuf(p_str));
- }
- void
- str_alloc_alt_term(struct mystr* p_str, const char* p_src, char term)
- {
- const char* p_search = p_src;
- unsigned int len = 0;
- while (*p_search != term)
- {
- p_search++;
- len++;
- if (len == 0)
- {
- bug("integer overflow");
- }
- }
- private_str_alloc_memchunk(p_str, p_src, len);
- }
- void
- str_alloc_ulong(struct mystr* p_str, unsigned long the_long)
- {
- str_alloc_text(p_str, vsf_sysutil_ulong_to_str(the_long));
- }
- void
- str_alloc_filesize_t(struct mystr* p_str, filesize_t the_filesize)
- {
- str_alloc_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));
- }
- void
- str_free(struct mystr* p_str)
- {
- if (p_str->p_buf != 0)
- {
- vsf_sysutil_free(p_str->p_buf);
- }
- p_str->p_buf = 0;
- p_str->len = 0;
- p_str->alloc_bytes = 0;
- }
- void
- str_empty(struct mystr* p_str)
- {
- /* Ensure a buffer is allocated. */
- (void) str_getbuf(p_str);
- str_trunc(p_str, 0);
- }
- void
- str_trunc(struct mystr* p_str, unsigned int trunc_len)
- {
- if (trunc_len >= p_str->alloc_bytes)
- {
- bug("trunc_len not smaller than alloc_bytes in str_trunc");
- }
- p_str->len = trunc_len;
- p_str->p_buf[p_str->len] = '\0';
- }
- void
- str_reserve(struct mystr* p_str, unsigned int res_len)
- {
- /* Reserve space for the trailing zero as well. */
- res_len++;
- if (res_len == 0)
- {
- bug("integer overflow");
- }
- if (res_len > p_str->alloc_bytes)
- {
- p_str->p_buf = vsf_sysutil_realloc(p_str->p_buf, res_len);
- p_str->alloc_bytes = res_len;
- }
- p_str->p_buf[res_len - 1] = '\0';
- }
- int
- str_isempty(const struct mystr* p_str)
- {
- return (p_str->len == 0);
- }
- unsigned int
- str_getlen(const struct mystr* p_str)
- {
- return p_str->len;
- }
- const char*
- str_getbuf(const struct mystr* p_str)
- {
- if (p_str->p_buf == 0)
- {
- if (p_str->len != 0 || p_str->alloc_bytes != 0)
- {
- bug("p_buf NULL and len or alloc_bytes != 0 in str_getbuf");
- }
- private_str_alloc_memchunk((struct mystr*)p_str, 0, 0);
- }
- return p_str->p_buf;
- }
- int
- str_strcmp(const struct mystr* p_str1, const struct mystr* p_str2)
- {
- return str_equal_internal(p_str1->p_buf, p_str1->len,
- p_str2->p_buf, p_str2->len);
- }
- static int
- str_equal_internal(const char* p_buf1, unsigned int buf1_len,
- const char* p_buf2, unsigned int buf2_len)
- {
- int retval;
- unsigned int minlen = buf1_len;
- if (buf2_len < minlen)
- {
- minlen = buf2_len;
- }
- retval = vsf_sysutil_memcmp(p_buf1, p_buf2, minlen);
- if (retval != 0 || buf1_len == buf2_len)
- {
- return retval;
- }
- /* Strings equal but lengths differ. The greater one, then, is the longer */
- return (int) (buf1_len - buf2_len);
- }
- int
- str_equal(const struct mystr* p_str1, const struct mystr* p_str2)
- {
- return (str_strcmp(p_str1, p_str2) == 0);
- }
- int
- str_equal_text(const struct mystr* p_str, const char* p_text)
- {
- unsigned int cmplen = vsf_sysutil_strlen(p_text);
- return (str_equal_internal(p_str->p_buf, p_str->len, p_text, cmplen) == 0);
- }
- void
- str_append_str(struct mystr* p_str, const struct mystr* p_other)
- {
- private_str_append_memchunk(p_str, p_other->p_buf, p_other->len);
- }
- void
- str_append_text(struct mystr* p_str, const char* p_src)
- {
- unsigned int len = vsf_sysutil_strlen(p_src);
- private_str_append_memchunk(p_str, p_src, len);
- }
- void
- str_append_char(struct mystr* p_str, char the_char)
- {
- private_str_append_memchunk(p_str, &the_char, sizeof(the_char));
- }
- void
- str_append_ulong(struct mystr* p_str, unsigned long the_ulong)
- {
- str_append_text(p_str, vsf_sysutil_ulong_to_str(the_ulong));
- }
- void
- str_append_filesize_t(struct mystr* p_str, filesize_t the_filesize)
- {
- str_append_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));
- }
- void
- str_append_double(struct mystr* p_str, double the_double)
- {
- str_append_text(p_str, vsf_sysutil_double_to_str(the_double));
- }
- void
- str_upper(struct mystr* p_str)
- {
- unsigned int i;
- for (i=0; i < p_str->len; i++)
- {
- p_str->p_buf[i] = (char) vsf_sysutil_toupper(p_str->p_buf[i]);
- }
- }
- void
- str_rpad(struct mystr* p_str, const unsigned int min_width)
- {
- unsigned int to_pad;
- if (p_str->len >= min_width)
- {
- return;
- }
- to_pad = min_width - p_str->len;
- while (to_pad--)
- {
- str_append_char(p_str, ' ');
- }
- }
- void
- str_lpad(struct mystr* p_str, const unsigned int min_width)
- {
- static struct mystr s_tmp_str;
- unsigned int to_pad;
- if (p_str->len >= min_width)
- {
- return;
- }
- to_pad = min_width - p_str->len;
- str_empty(&s_tmp_str);
- while (to_pad--)
- {
- str_append_char(&s_tmp_str, ' ');
- }
- str_append_str(&s_tmp_str, p_str);
- str_copy(p_str, &s_tmp_str);
- }
- void
- str_replace_char(struct mystr* p_str, char from, char to)
- {
- unsigned int i;
- for (i=0; i < p_str->len; i++)
- {
- if (p_str->p_buf[i] == from)
- {
- p_str->p_buf[i] = to;
- }
- }
- }
- void
- str_replace_text(struct mystr* p_str, const char* p_from, const char* p_to)
- {
- static struct mystr s_lhs_chunk_str;
- static struct mystr s_rhs_chunk_str;
- unsigned int lhs_len;
- str_copy(&s_lhs_chunk_str, p_str);
- str_free(p_str);
- do
- {
- lhs_len = str_getlen(&s_lhs_chunk_str);
- str_split_text(&s_lhs_chunk_str, &s_rhs_chunk_str, p_from);
- /* Copy lhs to destination */
- str_append_str(p_str, &s_lhs_chunk_str);
- /* If this was a 'hit', append the 'to' text */
- if (str_getlen(&s_lhs_chunk_str) < lhs_len)
- {
- str_append_text(p_str, p_to);
- }
- /* Current rhs becomes new lhs */
- str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
- } while (!str_isempty(&s_lhs_chunk_str));
- }
- void
- str_split_char(struct mystr* p_src, struct mystr* p_rhs, char c)
- {
- /* Just use str_split_text */
- char ministr[2];
- ministr[0] = c;
- ministr[1] = '\0';
- str_split_text(p_src, p_rhs, ministr);
- }
- void
- str_split_char_reverse(struct mystr* p_src, struct mystr* p_rhs, char c)
- {
- /* Just use str_split_text_reverse */
- char ministr[2];
- ministr[0] = c;
- ministr[1] = '\0';
- str_split_text_reverse(p_src, p_rhs, ministr);
- }
- void
- str_split_text(struct mystr* p_src, struct mystr* p_rhs, const char* p_text)
- {
- str_split_text_common(p_src, p_rhs, p_text, 0);
- }
- void
- str_split_text_reverse(struct mystr* p_src, struct mystr* p_rhs,
- const char* p_text)
- {
- str_split_text_common(p_src, p_rhs, p_text, 1);
- }
- static void
- str_split_text_common(struct mystr* p_src, struct mystr* p_rhs,
- const char* p_text, int is_reverse)
- {
- struct str_locate_result locate_result;
- unsigned int indexx;
- unsigned int search_len = vsf_sysutil_strlen(p_text);
- if (is_reverse)
- {
- locate_result = str_locate_text_reverse(p_src, p_text);
- }
- else
- {
- locate_result = str_locate_text(p_src, p_text);
- }
- /* Not found? */
- if (!locate_result.found)
- {
- str_empty(p_rhs);
- return;
- }
- indexx = locate_result.index;
- if (indexx + search_len > p_src->len)
- {
- bug("indexx invalid in str_split_text");
- }
- /* Build rhs */
- private_str_alloc_memchunk(p_rhs, p_src->p_buf + indexx + search_len,
- p_src->len - indexx - search_len);
- /* Build lhs */
- str_trunc(p_src, indexx);
- }
- struct str_locate_result
- str_locate_str(const struct mystr* p_str, const struct mystr* p_look_str)
- {
- return str_locate_text(p_str, str_getbuf(p_look_str));
- }
- struct str_locate_result
- str_locate_str_reverse(const struct mystr* p_str,
- const struct mystr* p_look_str)
- {
- return str_locate_text_reverse(p_str, str_getbuf(p_look_str));
- }
- struct str_locate_result
- str_locate_char(const struct mystr* p_str, char look_char)
- {
- char look_str[2];
- look_str[0] = look_char;
- look_str[1] = '\0';
- return str_locate_text(p_str, look_str);
- }
- struct str_locate_result
- str_locate_chars(const struct mystr* p_str, const char* p_chars)
- {
- struct str_locate_result retval;
- unsigned int num_chars = vsf_sysutil_strlen(p_chars);
- unsigned int i = 0;
- retval.found = 0;
- retval.char_found = 0;
- retval.index = 0;
- for (; i < p_str->len; ++i)
- {
- unsigned int j = 0;
- char this_char = p_str->p_buf[i];
- for (; j < num_chars; ++j)
- {
- if (p_chars[j] == this_char)
- {
- retval.found = 1;
- retval.index = i;
- retval.char_found = p_chars[j];
- return retval;
- }
- }
- }
- return retval;
- }
- struct str_locate_result
- str_locate_text(const struct mystr* p_str, const char* p_text)
- {
- struct str_locate_result retval;
- unsigned int i;
- unsigned int text_len = vsf_sysutil_strlen(p_text);
- retval.found = 0;
- retval.char_found = 0;
- retval.index = 0;
- if (text_len == 0 || text_len > p_str->len)
- {
- /* Not found */
- return retval;
- }
- for (i=0; i <= (p_str->len - text_len); i++)
- {
- if (vsf_sysutil_memcmp(p_str->p_buf + i, p_text, text_len) == 0)
- {
- retval.found = 1;
- retval.index = i;
- return retval;
- }
- }
- /* Not found */
- return retval;
- }
- struct str_locate_result
- str_locate_text_reverse(const struct mystr* p_str, const char* p_text)
- {
- struct str_locate_result retval;
- unsigned int i;
- unsigned int text_len = vsf_sysutil_strlen(p_text);
- retval.found = 0;
- retval.char_found = 0;
- retval.index = 0;
- if (text_len == 0 || text_len > p_str->len)
- {
- return retval;
- }
- i = p_str->len - text_len;
- /* Want to go through loop once even if i==0 */
- while (1)
- {
- if (vsf_sysutil_memcmp(p_str->p_buf + i, p_text, text_len) == 0)
- {
- retval.found = 1;
- retval.index = i;
- return retval;
- }
- if (i == 0)
- {
- break;
- }
- i--;
- }
- /* Not found */
- return retval;
- }
- void
- str_left(const struct mystr* p_str, struct mystr* p_out, unsigned int chars)
- {
- if (chars > p_str->len)
- {
- bug("chars invalid in str_left");
- }
- private_str_alloc_memchunk(p_out, p_str->p_buf, chars);
- }
- void
- str_right(const struct mystr* p_str, struct mystr* p_out, unsigned int chars)
- {
- unsigned int indexx = p_str->len - chars;
- if (chars > p_str->len)
- {
- bug("chars invalid in str_right");
- }
- private_str_alloc_memchunk(p_out, p_str->p_buf + indexx, chars);
- }
- void
- str_mid_to_end(const struct mystr* p_str, struct mystr* p_out,
- unsigned int indexx)
- {
- if (indexx > p_str->len)
- {
- bug("invalid indexx in str_mid_to_end");
- }
- private_str_alloc_memchunk(p_out, p_str->p_buf + indexx,
- p_str->len - indexx);
- }
- char
- str_get_char_at(const struct mystr* p_str, const unsigned int indexx)
- {
- if (indexx >= p_str->len)
- {
- bug("bad indexx in str_get_char_at");
- }
- return p_str->p_buf[indexx];
- }
- int
- str_contains_space(const struct mystr* p_str)
- {
- unsigned int i;
- for (i=0; i < p_str->len; i++)
- {
- if (vsf_sysutil_isspace(p_str->p_buf[i]))
- {
- return 1;
- }
- }
- return 0;
- }
- int
- str_all_space(const struct mystr* p_str)
- {
- unsigned int i;
- for (i=0; i < p_str->len; i++)
- {
- if (!vsf_sysutil_isspace(p_str->p_buf[i]))
- {
- return 0;
- }
- }
- return 1;
- }
- int
- str_contains_unprintable(const struct mystr* p_str)
- {
- unsigned int i;
- for (i=0; i < p_str->len; i++)
- {
- if (!vsf_sysutil_isprint(p_str->p_buf[i]))
- {
- return 1;
- }
- }
- return 0;
- }
- int
- str_atoi(const struct mystr* p_str)
- {
- return vsf_sysutil_atoi(str_getbuf(p_str));
- }
- filesize_t
- str_a_to_filesize_t(const struct mystr* p_str)
- {
- return vsf_sysutil_a_to_filesize_t(str_getbuf(p_str));
- }
- unsigned int
- str_octal_to_uint(const struct mystr* p_str)
- {
- return vsf_sysutil_octal_to_uint(str_getbuf(p_str));
- }
- int
- str_getline(const struct mystr* p_str, struct mystr* p_line_str,
- unsigned int* p_pos)
- {
- unsigned int start_pos = *p_pos;
- unsigned int curr_pos = start_pos;
- unsigned int buf_len = str_getlen(p_str);
- const char* p_buf = str_getbuf(p_str);
- unsigned int out_len;
- if (start_pos > buf_len)
- {
- bug("p_pos out of range in str_getline");
- }
- str_empty(p_line_str);
- if (start_pos == buf_len)
- {
- return 0;
- }
- while (curr_pos < buf_len && p_buf[curr_pos] != '\n')
- {
- curr_pos++;
- if (curr_pos == 0)
- {
- bug("integer overflow");
- }
- }
- out_len = curr_pos - start_pos;
- /* If we ended on a \n - skip it */
- if (curr_pos < buf_len && p_buf[curr_pos] == '\n')
- {
- curr_pos++;
- if (curr_pos == 0)
- {
- bug("integer overflow");
- }
- }
- private_str_alloc_memchunk(p_line_str, p_buf + start_pos, out_len);
- *p_pos = curr_pos;
- return 1;
- }
- int
- str_contains_line(const struct mystr* p_str, const struct mystr* p_line_str)
- {
- static struct mystr s_curr_line_str;
- unsigned int pos = 0;
- while (str_getline(p_str, &s_curr_line_str, &pos))
- {
- if (str_equal(&s_curr_line_str, p_line_str))
- {
- return 1;
- }
- }
- return 0;
- }
- void
- str_replace_unprintable(struct mystr* p_str, char new_char)
- {
- unsigned int i;
- for (i=0; i < p_str->len; i++)
- {
- if (!vsf_sysutil_isprint(p_str->p_buf[i]))
- {
- p_str->p_buf[i] = new_char;
- }
- }
- }
|