str.c 15 KB

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