str.c 3.3 KB

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