📄 str.c
字号:
/* * 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 voids_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;}voidprivate_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] = '\0'; p_str->len = len;}voidprivate_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] = '\0'; p_str->len += len;}/* Public functions */voidstr_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);}voidstr_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));}voidstr_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);}voidstr_alloc_ulong(struct mystr* p_str, unsigned long the_long){ str_alloc_text(p_str, vsf_sysutil_ulong_to_str(the_long));}voidstr_alloc_filesize_t(struct mystr* p_str, filesize_t the_filesize){ str_alloc_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));}voidstr_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;}voidstr_empty(struct mystr* p_str){ /* Ensure a buffer is allocated. */ (void) str_getbuf(p_str); str_trunc(p_str, 0);}voidstr_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';}voidstr_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] = '\0';}intstr_isempty(const struct mystr* p_str){ return (p_str->len == 0);}unsigned intstr_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;}intstr_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 intstr_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);}intstr_equal(const struct mystr* p_str1, const struct mystr* p_str2){ return (str_strcmp(p_str1, p_str2) == 0);}intstr_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);}voidstr_append_str(struct mystr* p_str, const struct mystr* p_other){ private_str_append_memchunk(p_str, p_other->p_buf, p_other->len);}voidstr_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);}voidstr_append_char(struct mystr* p_str, char the_char){ private_str_append_memchunk(p_str, &the_char, sizeof(the_char));}voidstr_append_ulong(struct mystr* p_str, unsigned long the_ulong){ str_append_text(p_str, vsf_sysutil_ulong_to_str(the_ulong));}voidstr_append_filesize_t(struct mystr* p_str, filesize_t the_filesize){ str_append_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));}voidstr_append_double(struct mystr* p_str, double the_double){ str_append_text(p_str, vsf_sysutil_double_to_str(the_double));}voidstr_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]); }}voidstr_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, ' '); }}voidstr_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);}voidstr_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; } }}voidstr_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));}voidstr_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);}voidstr_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);}voidstr_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);}voidstr_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 voidstr_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_resultstr_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_resultstr_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_resultstr_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_resultstr_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_resultstr_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_resultstr_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;}voidstr_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);}voidstr_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);}voidstr_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);}charstr_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];}intstr_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;}intstr_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;}intstr_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;}intstr_atoi(const struct mystr* p_str){ return vsf_sysutil_atoi(str_getbuf(p_str));}filesize_tstr_a_to_filesize_t(const struct mystr* p_str){ return vsf_sysutil_a_to_filesize_t(str_getbuf(p_str));}unsigned intstr_octal_to_uint(const struct mystr* p_str){ return vsf_sysutil_octal_to_uint(str_getbuf(p_str));}intstr_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;}intstr_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;}voidstr_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; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -