str.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:15k
源码类别:

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  * str.c
  6.  *
  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...
  11.  */
  12. /* Anti-lamer measures deployed, sir! */
  13. #define PRIVATE_HANDS_OFF_p_buf p_buf
  14. #define PRIVATE_HANDS_OFF_len len
  15. #define PRIVATE_HANDS_OFF_alloc_bytes alloc_bytes
  16. #include "str.h"
  17. /* Ick. Its for die() */
  18. #include "utility.h"
  19. #include "sysutil.h"
  20. /* File local functions */
  21. static void str_split_text_common(struct mystr* p_src, struct mystr* p_rhs,
  22.                                   const char* p_text, int is_reverse);
  23. static int str_equal_internal(const char* p_buf1, unsigned int buf1_len,
  24.                               const char* p_buf2, unsigned int buf2_len);
  25. /* Private functions */
  26. static void
  27. s_setbuf(struct mystr* p_str, char* p_newbuf)
  28. {
  29.   if (p_str->p_buf != 0)
  30.   {
  31.     bug("p_buf not NULL when setting it");
  32.   }
  33.   p_str->p_buf = p_newbuf;
  34. }
  35. void
  36. private_str_alloc_memchunk(struct mystr* p_str, const char* p_src,
  37.                            unsigned int len)
  38. {
  39.   /* Make sure this will fit in the buffer */
  40.   unsigned int buf_needed = len + 1;
  41.   if (buf_needed > p_str->alloc_bytes)
  42.   {
  43.     str_free(p_str);
  44.     s_setbuf(p_str, vsf_sysutil_malloc(buf_needed));
  45.     p_str->alloc_bytes = buf_needed;
  46.   }
  47.   vsf_sysutil_memcpy(p_str->p_buf, p_src, len);
  48.   p_str->p_buf[len] = '';
  49.   p_str->len = len;
  50. }
  51. void
  52. private_str_append_memchunk(struct mystr* p_str, const char* p_src,
  53.                             unsigned int len)
  54. {
  55.   unsigned int buf_needed = p_str->len + len + 1;
  56.   if (buf_needed > p_str->alloc_bytes)
  57.   {
  58.     p_str->p_buf = vsf_sysutil_realloc(p_str->p_buf, buf_needed);
  59.     p_str->alloc_bytes = buf_needed;
  60.   }
  61.   vsf_sysutil_memcpy(p_str->p_buf + p_str->len, p_src, len);
  62.   p_str->p_buf[p_str->len + len] = '';
  63.   p_str->len += len;
  64. }
  65. /* Public functions */
  66. void
  67. str_alloc_text(struct mystr* p_str, const char* p_src)
  68. {
  69.   unsigned int len = vsf_sysutil_strlen(p_src);
  70.   private_str_alloc_memchunk(p_str, p_src, len);
  71. }
  72. void
  73. str_copy(struct mystr* p_dest, const struct mystr* p_src)
  74. {
  75.   private_str_alloc_memchunk(p_dest, p_src->p_buf, p_src->len);
  76. }
  77. const char*
  78. str_strdup(const struct mystr* p_str)
  79. {
  80.   return vsf_sysutil_strdup(str_getbuf(p_str));
  81. }
  82. void
  83. str_alloc_alt_term(struct mystr* p_str, const char* p_src, char term)
  84. {
  85.   const char* p_search = p_src;
  86.   unsigned int len = 0;
  87.   while (*p_search != term)
  88.   {
  89.     p_search++;
  90.     len++;
  91.   }
  92.   private_str_alloc_memchunk(p_str, p_src, len);
  93. }
  94. void
  95. str_alloc_ulong(struct mystr* p_str, unsigned long the_long)
  96. {
  97.   str_alloc_text(p_str, vsf_sysutil_ulong_to_str(the_long));
  98. }
  99. void
  100. str_alloc_filesize_t(struct mystr* p_str, filesize_t the_filesize)
  101. {
  102.   str_alloc_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));
  103. }
  104. void
  105. str_free(struct mystr* p_str)
  106. {
  107.   if (p_str->p_buf != 0)
  108.   {
  109.     vsf_sysutil_free(p_str->p_buf);
  110.   }
  111.   p_str->p_buf = 0;
  112.   p_str->len = 0;
  113.   p_str->alloc_bytes = 0;
  114. }
  115. void
  116. str_empty(struct mystr* p_str)
  117. {
  118.   /* Ensure a buffer is allocated. */
  119.   (void) str_getbuf(p_str);
  120.   str_trunc(p_str, 0);
  121. }
  122. void
  123. str_trunc(struct mystr* p_str, unsigned int trunc_len)
  124. {
  125.   if (trunc_len >= p_str->alloc_bytes)
  126.   {
  127.     bug("trunc_len not smaller than alloc_bytes in str_trunc");
  128.   }
  129.   p_str->len = trunc_len;
  130.   p_str->p_buf[p_str->len] = '';
  131. }
  132. void
  133. str_reserve(struct mystr* p_str, unsigned int res_len)
  134. {
  135.   /* Reserve space for the trailing zero as well. */
  136.   res_len++;
  137.   if (res_len > p_str->alloc_bytes)
  138.   {
  139.     p_str->p_buf = vsf_sysutil_realloc(p_str->p_buf, res_len);
  140.     p_str->alloc_bytes = res_len;
  141.   }
  142.   p_str->p_buf[res_len - 1] = '';
  143. }
  144. int
  145. str_isempty(const struct mystr* p_str)
  146. {
  147.   return (p_str->len == 0);
  148. }
  149. unsigned int
  150. str_getlen(const struct mystr* p_str)
  151. {
  152.   return p_str->len;
  153. }
  154. const char*
  155. str_getbuf(const struct mystr* p_str)
  156. {
  157.   if (p_str->p_buf == 0)
  158.   {
  159.     if (p_str->len != 0 || p_str->alloc_bytes != 0)
  160.     {
  161.       bug("p_buf NULL and len or alloc_bytes != 0 in str_getbuf");
  162.     }
  163.     private_str_alloc_memchunk((struct mystr*)p_str, 0, 0);
  164.   }
  165.   return p_str->p_buf;
  166. }
  167. int
  168. str_strcmp(const struct mystr* p_str1, const struct mystr* p_str2)
  169. {
  170.   return str_equal_internal(p_str1->p_buf, p_str1->len,
  171.                             p_str2->p_buf, p_str2->len);
  172. }
  173. static int
  174. str_equal_internal(const char* p_buf1, unsigned int buf1_len,
  175.                    const char* p_buf2, unsigned int buf2_len)
  176. {
  177.   int retval;
  178.   unsigned int minlen = buf1_len;
  179.   if (buf2_len < minlen)
  180.   {
  181.     minlen = buf2_len;
  182.   }
  183.   retval = vsf_sysutil_memcmp(p_buf1, p_buf2, minlen);
  184.   if (retval != 0 || buf1_len == buf2_len)
  185.   {
  186.     return retval;
  187.   }
  188.   /* Strings equal but lengths differ. The greater one, then, is the longer */
  189.   return (int) (buf1_len - buf2_len);
  190. }
  191. int
  192. str_equal(const struct mystr* p_str1, const struct mystr* p_str2)
  193. {
  194.   return (str_strcmp(p_str1, p_str2) == 0);
  195. }
  196. int
  197. str_equal_text(const struct mystr* p_str, const char* p_text)
  198. {
  199.   unsigned int cmplen = vsf_sysutil_strlen(p_text);
  200.   return (str_equal_internal(p_str->p_buf, p_str->len, p_text, cmplen) == 0);
  201. }
  202. void
  203. str_append_str(struct mystr* p_str, const struct mystr* p_other)
  204. {
  205.   private_str_append_memchunk(p_str, p_other->p_buf, p_other->len);
  206. }
  207. void
  208. str_append_text(struct mystr* p_str, const char* p_src)
  209. {
  210.   unsigned int len = vsf_sysutil_strlen(p_src);
  211.   private_str_append_memchunk(p_str, p_src, len);
  212. }
  213. void
  214. str_append_char(struct mystr* p_str, char the_char)
  215. {
  216.   private_str_append_memchunk(p_str, &the_char, sizeof(the_char));
  217. }
  218. void
  219. str_append_ulong(struct mystr* p_str, unsigned long the_ulong)
  220. {
  221.   str_append_text(p_str, vsf_sysutil_ulong_to_str(the_ulong));
  222. }
  223. void
  224. str_append_filesize_t(struct mystr* p_str, filesize_t the_filesize)
  225. {
  226.   str_append_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));
  227. }
  228. void
  229. str_append_double(struct mystr* p_str, double the_double)
  230. {
  231.   str_append_text(p_str, vsf_sysutil_double_to_str(the_double));
  232. }
  233. void
  234. str_upper(struct mystr* p_str)
  235. {
  236.   unsigned int i;
  237.   for (i=0; i < p_str->len; i++)
  238.   {
  239.     p_str->p_buf[i] = vsf_sysutil_toupper(p_str->p_buf[i]);
  240.   }
  241. }
  242. void
  243. str_rpad(struct mystr* p_str, const unsigned int min_width)
  244. {
  245.   unsigned int to_pad;
  246.   if (p_str->len >= min_width)
  247.   {
  248.     return;
  249.   }
  250.   to_pad = min_width - p_str->len;
  251.   while (to_pad--)
  252.   {
  253.     str_append_char(p_str, ' ');
  254.   }
  255. }
  256. void
  257. str_lpad(struct mystr* p_str, const unsigned int min_width)
  258. {
  259.   static struct mystr s_tmp_str;
  260.   unsigned int to_pad;
  261.   if (p_str->len >= min_width)
  262.   {
  263.     return;
  264.   }
  265.   to_pad = min_width - p_str->len;
  266.   str_empty(&s_tmp_str);
  267.   while (to_pad--)
  268.   {
  269.     str_append_char(&s_tmp_str, ' ');
  270.   }
  271.   str_append_str(&s_tmp_str, p_str);
  272.   str_copy(p_str, &s_tmp_str);
  273. }
  274. void
  275. str_replace_char(struct mystr* p_str, char from, char to)
  276. {
  277.   unsigned int i;
  278.   for (i=0; i < p_str->len; i++)
  279.   {
  280.     if (p_str->p_buf[i] == from)
  281.     {
  282.       p_str->p_buf[i] = to;
  283.     }
  284.   }
  285. }
  286. void
  287. str_replace_text(struct mystr* p_str, const char* p_from, const char* p_to)
  288. {
  289.   static struct mystr s_lhs_chunk_str;
  290.   static struct mystr s_rhs_chunk_str;
  291.   unsigned int lhs_len;
  292.   str_copy(&s_lhs_chunk_str, p_str);
  293.   str_free(p_str);
  294.   do
  295.   {
  296.     lhs_len = str_getlen(&s_lhs_chunk_str);
  297.     str_split_text(&s_lhs_chunk_str, &s_rhs_chunk_str, p_from);
  298.     /* Copy lhs to destination */
  299.     str_append_str(p_str, &s_lhs_chunk_str);
  300.     /* If this was a 'hit', append the 'to' text */
  301.     if (str_getlen(&s_lhs_chunk_str) < lhs_len)
  302.     {
  303.       str_append_text(p_str, p_to);
  304.     }
  305.     /* Current rhs becomes new lhs */
  306.     str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
  307.   } while (!str_isempty(&s_lhs_chunk_str));
  308. }
  309. void
  310. str_split_char(struct mystr* p_src, struct mystr* p_rhs, char c)
  311. {
  312.   /* Just use str_split_text */
  313.   char ministr[2];
  314.   ministr[0] = c;
  315.   ministr[1] = '';
  316.   str_split_text(p_src, p_rhs, ministr);
  317. }
  318. void
  319. str_split_char_reverse(struct mystr* p_src, struct mystr* p_rhs, char c)
  320. {
  321.   /* Just use str_split_text_reverse */
  322.   char ministr[2];
  323.   ministr[0] = c;
  324.   ministr[1] = '';
  325.   str_split_text_reverse(p_src, p_rhs, ministr);
  326. }
  327. void
  328. str_split_text(struct mystr* p_src, struct mystr* p_rhs, const char* p_text)
  329. {
  330.   str_split_text_common(p_src, p_rhs, p_text, 0);
  331. }
  332. void
  333. str_split_text_reverse(struct mystr* p_src, struct mystr* p_rhs,
  334.                        const char* p_text)
  335. {
  336.   str_split_text_common(p_src, p_rhs, p_text, 1);
  337. }
  338. static void
  339. str_split_text_common(struct mystr* p_src, struct mystr* p_rhs,
  340.                       const char* p_text, int is_reverse)
  341. {
  342.   struct str_locate_result locate_result;
  343.   unsigned int indexx;
  344.   unsigned int search_len = vsf_sysutil_strlen(p_text);
  345.   if (is_reverse)
  346.   {
  347.     locate_result = str_locate_text_reverse(p_src, p_text);
  348.   }
  349.   else
  350.   {
  351.     locate_result = str_locate_text(p_src, p_text);
  352.   }
  353.   /* Not found? */
  354.   if (!locate_result.found)
  355.   {
  356.     str_empty(p_rhs);
  357.     return;
  358.   }
  359.   indexx = locate_result.index;
  360.   if (indexx + search_len > p_src->len)
  361.   {
  362.     bug("indexx invalid in str_split_text");
  363.   } 
  364.   /* Build rhs */
  365.   private_str_alloc_memchunk(p_rhs, p_src->p_buf + indexx + search_len,
  366.                              p_src->len - indexx - search_len);
  367.   /* Build lhs */
  368.   str_trunc(p_src, indexx);
  369. }
  370. struct str_locate_result
  371. str_locate_str(const struct mystr* p_str, const struct mystr* p_look_str)
  372. {
  373.   return str_locate_text(p_str, str_getbuf(p_look_str));
  374. }
  375. struct str_locate_result
  376. str_locate_str_reverse(const struct mystr* p_str,
  377.                        const struct mystr* p_look_str)
  378. {
  379.   return str_locate_text_reverse(p_str, str_getbuf(p_look_str));
  380. }
  381. struct str_locate_result
  382. str_locate_char(const struct mystr* p_str, char look_char)
  383. {
  384.   char look_str[2];
  385.   look_str[0] = look_char;
  386.   look_str[1] = '';
  387.   return str_locate_text(p_str, look_str);
  388. }
  389. struct str_locate_result
  390. str_locate_chars(const struct mystr* p_str, const char* p_chars)
  391. {
  392.   struct str_locate_result retval;
  393.   unsigned int num_chars = vsf_sysutil_strlen(p_chars);
  394.   unsigned int i = 0;
  395.   retval.found = 0;
  396.   retval.char_found = 0;
  397.   retval.index = 0;
  398.   for (; i < p_str->len; ++i)
  399.   {
  400.     unsigned int j = 0;
  401.     char this_char = p_str->p_buf[i];
  402.     for (; j < num_chars; ++j)
  403.     {
  404.       if (p_chars[j] == this_char)
  405.       {
  406.         retval.found = 1;
  407.         retval.index = i;
  408.         retval.char_found = p_chars[j];
  409.         return retval;
  410.       }
  411.     }
  412.   }
  413.   return retval;
  414. }
  415. struct str_locate_result
  416. str_locate_text(const struct mystr* p_str, const char* p_text)
  417. {
  418.   struct str_locate_result retval;
  419.   unsigned int i;
  420.   unsigned int text_len = vsf_sysutil_strlen(p_text);
  421.   retval.found = 0;
  422.   retval.char_found = 0;
  423.   retval.index = 0;
  424.   if (text_len == 0 || text_len > p_str->len)
  425.   {
  426.     /* Not found */
  427.     return retval;
  428.   }
  429.   for (i=0; i <= (p_str->len - text_len); i++)
  430.   {
  431.     if (vsf_sysutil_memcmp(p_str->p_buf + i, p_text, text_len) == 0)
  432.     {
  433.       retval.found = 1;
  434.       retval.index = i;
  435.       return retval;
  436.     }
  437.   }
  438.   /* Not found */
  439.   return retval;
  440. }
  441. struct str_locate_result
  442. str_locate_text_reverse(const struct mystr* p_str, const char* p_text)
  443. {
  444.   struct str_locate_result retval;
  445.   unsigned int i;
  446.   unsigned int text_len = vsf_sysutil_strlen(p_text);
  447.   retval.found = 0;
  448.   retval.char_found = 0;
  449.   retval.index = 0;
  450.   if (text_len == 0 || text_len > p_str->len)
  451.   {
  452.     return retval;
  453.   }
  454.   i = p_str->len - text_len;
  455.   /* Want to go through loop once even if i==0 */
  456.   while (1)
  457.   {
  458.     if (vsf_sysutil_memcmp(p_str->p_buf + i, p_text, text_len) == 0)
  459.     {
  460.       retval.found = 1;
  461.       retval.index = i;
  462.       return retval;
  463.     }
  464.     if (i == 0)
  465.     {
  466.       break;
  467.     }
  468.     i--;
  469.   }
  470.   /* Not found */
  471.   return retval;
  472. }
  473. void
  474. str_left(const struct mystr* p_str, struct mystr* p_out, unsigned int chars)
  475. {
  476.   if (chars > p_str->len)
  477.   {
  478.     bug("chars invalid in str_left");
  479.   }
  480.   private_str_alloc_memchunk(p_out, p_str->p_buf, chars);
  481. }
  482. void
  483. str_right(const struct mystr* p_str, struct mystr* p_out, unsigned int chars)
  484. {
  485.   unsigned int indexx = p_str->len - chars;
  486.   if (chars > p_str->len)
  487.   {
  488.     bug("chars invalid in str_right");
  489.   }
  490.   private_str_alloc_memchunk(p_out, p_str->p_buf + indexx, chars);
  491. }
  492. void
  493. str_mid_to_end(const struct mystr* p_str, struct mystr* p_out,
  494.                unsigned int indexx)
  495. {
  496.   if (indexx > p_str->len)
  497.   {
  498.     bug("invalid indexx in str_mid_to_end");
  499.   }
  500.   private_str_alloc_memchunk(p_out, p_str->p_buf + indexx,
  501.                              p_str->len - indexx);
  502. }
  503. char
  504. str_get_char_at(const struct mystr* p_str, const unsigned int indexx)
  505. {
  506.   if (indexx >= p_str->len)
  507.   {
  508.     bug("bad indexx in str_get_char_at");
  509.   }
  510.   return p_str->p_buf[indexx];
  511. }
  512. int
  513. str_contains_space(const struct mystr* p_str)
  514. {
  515.   unsigned int i;
  516.   for (i=0; i < p_str->len; i++)
  517.   {
  518.     if (vsf_sysutil_isspace(p_str->p_buf[i]))
  519.     {
  520.       return 1;
  521.     }
  522.   }
  523.   return 0;
  524. }
  525. int
  526. str_all_space(const struct mystr* p_str)
  527. {
  528.   unsigned int i;
  529.   for (i=0; i < p_str->len; i++)
  530.   {
  531.     if (!vsf_sysutil_isspace(p_str->p_buf[i]))
  532.     {
  533.       return 0;
  534.     }
  535.   }
  536.   return 1;
  537. }
  538. int
  539. str_contains_unprintable(const struct mystr* p_str)
  540. {
  541.   unsigned int i;
  542.   for (i=0; i < p_str->len; i++)
  543.   {
  544.     if (!vsf_sysutil_isprint(p_str->p_buf[i]))
  545.     {
  546.       return 1;
  547.     }
  548.   }
  549.   return 0;
  550. }
  551. int
  552. str_atoi(const struct mystr* p_str)
  553. {
  554.   return vsf_sysutil_atoi(str_getbuf(p_str));
  555. }
  556. filesize_t
  557. str_a_to_filesize_t(const struct mystr* p_str)
  558. {
  559.   return vsf_sysutil_a_to_filesize_t(str_getbuf(p_str));
  560. }
  561. unsigned int
  562. str_octal_to_uint(const struct mystr* p_str)
  563. {
  564.   return vsf_sysutil_octal_to_uint(str_getbuf(p_str));
  565. }
  566. int
  567. str_getline(const struct mystr* p_str, struct mystr* p_line_str,
  568.             unsigned int* p_pos)
  569. {
  570.   unsigned int start_pos = *p_pos;
  571.   unsigned int curr_pos = start_pos;
  572.   unsigned int buf_len = str_getlen(p_str);
  573.   const char* p_buf = str_getbuf(p_str);
  574.   unsigned int out_len;
  575.   if (start_pos > buf_len)
  576.   {
  577.     bug("p_pos out of range in str_getline");
  578.   }
  579.   str_empty(p_line_str);
  580.   if (start_pos == buf_len)
  581.   {
  582.     return 0;
  583.   }
  584.   while (curr_pos < buf_len && p_buf[curr_pos] != 'n')
  585.   {
  586.     curr_pos++;
  587.   }
  588.   out_len = curr_pos - start_pos;
  589.   /* If we ended on a n - skip it */
  590.   if (curr_pos < buf_len && p_buf[curr_pos] == 'n')
  591.   {
  592.     curr_pos++;
  593.   }
  594.   private_str_alloc_memchunk(p_line_str, p_buf + start_pos, out_len);
  595.   *p_pos = curr_pos;
  596.   return 1;
  597. }
  598. int
  599. str_contains_line(const struct mystr* p_str, const struct mystr* p_line_str)
  600. {
  601.   static struct mystr s_curr_line_str;
  602.   unsigned int pos = 0;
  603.   while (str_getline(p_str, &s_curr_line_str, &pos))
  604.   {
  605.     if (str_equal(&s_curr_line_str, p_line_str))
  606.     {
  607.       return 1;
  608.     }
  609.   }
  610.   return 0;
  611. }
  612. void
  613. str_replace_unprintable(struct mystr* p_str, char new_char)
  614. {
  615.   unsigned int i;
  616.   for (i=0; i < p_str->len; i++)
  617.   {
  618.     if (!vsf_sysutil_isprint(p_str->p_buf[i]))
  619.     {
  620.       p_str->p_buf[i] = new_char;
  621.     }
  622.   }
  623. }