str.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:15k
- /*
- * 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 = 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] = ' ';
- p_str->len = len;
- }
- void
- private_str_append_memchunk(struct mystr* p_str, const char* p_src,
- unsigned int len)
- {
- unsigned int buf_needed = p_str->len + len + 1;
- 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] = ' ';
- 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++;
- }
- 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] = ' ';
- }
- void
- str_reserve(struct mystr* p_str, unsigned int res_len)
- {
- /* Reserve space for the trailing zero as well. */
- res_len++;
- 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] = ' ';
- }
- 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] = 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] = ' ';
- 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] = ' ';
- 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] = ' ';
- 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++;
- }
- 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++;
- }
- 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;
- }
- }
- }