str.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #include "str.h"
  2. #include <ctype.h>
  3. #include <stdarg.h>
  4. #include <stdbool.h>
  5. #include <stddef.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. char **str_split(char *str, char delim) {
  10. char **ret;
  11. if (str == NULL) return NULL;
  12. if (*str == '\n') {
  13. ret = malloc(sizeof(char *));
  14. *ret = NULL;
  15. return ret;
  16. }
  17. int count = 0;
  18. char *begin = str;
  19. for (char *p = str; *p != '\0'; p++) {
  20. if (*p != delim && !(delim == '\0' && isspace(*p))) {
  21. continue;
  22. }
  23. int size = p - begin;
  24. if (size > 0) count++;
  25. }
  26. count++;
  27. ret = malloc((count + 1) * sizeof(char *));
  28. memset(ret, 0, (count + 1) * sizeof(char *));
  29. begin = str;
  30. int i = 0;
  31. bool finished = false;
  32. for (char *p = str; !finished; p++) {
  33. if (*p == '\0') finished = true;
  34. if (*p != delim && *p != '\0' && !(delim == '\0' && isspace(*p))) {
  35. continue;
  36. }
  37. int size = p - begin;
  38. if (size == 0) {
  39. begin = p + 1;
  40. continue;
  41. }
  42. char *buf = malloc(sizeof(char) * (size + 1));
  43. buf[size] = '\0';
  44. memcpy(buf, begin, size * sizeof(char));
  45. begin = p + 1;
  46. ret[i] = buf;
  47. i++;
  48. }
  49. return ret;
  50. }
  51. void destroy_str_list(char **list) {
  52. char **p = list;
  53. while (*p != NULL) {
  54. free(*p);
  55. p++;
  56. }
  57. free(list);
  58. }
  59. char *str_strip(char *str) {
  60. if (str == NULL) return NULL;
  61. int len = strlen(str);
  62. char *begin = str;
  63. char *end = str + len - 1;
  64. while (isspace(*begin) && begin < end) {
  65. begin++;
  66. }
  67. while (isspace(*end) && end >= begin) {
  68. end--;
  69. }
  70. len = end - begin + 1;
  71. char *buf = malloc(sizeof(char) * (len) + 1);
  72. buf[len] = '\0';
  73. memcpy(buf, begin, len);
  74. return buf;
  75. }
  76. void init_str_builder(str_builder_t *sb) {
  77. *sb = (str_builder_t){.size = 0, .cap = 16};
  78. sb->buf = malloc(sizeof(char) * 17);
  79. }
  80. static void sb_reserve(str_builder_t *sb, int extra) {
  81. if (sb->size + extra <= sb->cap) {
  82. return;
  83. }
  84. int new_cap = (sb->size + extra) * 2;
  85. sb->buf = realloc(sb->buf, new_cap + 1);
  86. memset(sb->buf + sb->cap, 0, new_cap - sb->cap + 1);
  87. sb->cap = new_cap;
  88. }
  89. void str_builder_append(str_builder_t *sb, char *format, ...) {
  90. va_list va1;
  91. va_list va2;
  92. va_start(va1, format);
  93. va_copy(va2, va1);
  94. int size = vsnprintf(NULL, 0, format, va1);
  95. sb_reserve(sb, size);
  96. vsnprintf(sb->buf + sb->size, sb->cap - sb->size + 1, format, va2);
  97. }
  98. void str_builder_append_char(str_builder_t *sb, char c) {
  99. sb_reserve(sb, 1);
  100. sb->buf[sb->size] = c;
  101. sb->size++;
  102. }
  103. char *fgetline(FILE *fp) {
  104. str_builder_t sb;
  105. init_str_builder(&sb);
  106. while (true) {
  107. int c = fgetc(fp);
  108. if (c == EOF && sb.size == 0) return NULL;
  109. if (c != EOF) str_builder_append_char(&sb, c);
  110. if (c == EOF || c == '\n') return sb.buf;
  111. }
  112. return NULL;
  113. }
  114. int fpeek(FILE *fp) {
  115. int c = fgetc(fp);
  116. if (c == EOF) return c;
  117. ungetc(c, fp);
  118. return c;
  119. }