DynString.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include <errno.h>
  2. #include <stdbool.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "DynString.h"
  6. #include "log.h"
  7. static void DynString_reserve(DynString* dstr, const size_t new_capacity) {
  8. if (dstr->capacity >= new_capacity) {
  9. return;
  10. }
  11. errno = 0;
  12. dstr->data = (char*) realloc(dstr->data, sizeof(char) * new_capacity);
  13. if (errno != 0) {
  14. LOG_FATAL("Ran out of memory");
  15. }
  16. dstr->capacity = new_capacity;
  17. }
  18. DynString DynString_alloc(const char* str, const size_t len) {
  19. DynString dstr = {
  20. .data = (char*) malloc(sizeof(char) * (len + 1)),
  21. .len = len,
  22. .capacity = len + 1
  23. };
  24. if (dstr.data == NULL) {
  25. LOG_FATAL("Ran out of memory");
  26. }
  27. dstr.data = memcpy(dstr.data, str, len);
  28. dstr.data[len] = '\0';
  29. return dstr;
  30. }
  31. void DynString_free(DynString* dstr) {
  32. if (dstr->data != NULL) {
  33. free(dstr->data);
  34. dstr->data = NULL;
  35. }
  36. dstr->len = 0;
  37. dstr->capacity = 0;
  38. }
  39. bool DynString_is_null(const DynString* dstr) {
  40. return dstr->data == NULL;
  41. }
  42. const char* DynString_c_str(const DynString* dstr) {
  43. return dstr->data;
  44. }
  45. bool DynString_equal(const DynString* s1, const DynString* s2) {
  46. if (s1->data == NULL || s2->data == NULL) {
  47. return false;
  48. }
  49. if (s1->len != s2->len) {
  50. return false;
  51. }
  52. for (size_t i = 0; i < s1->len; i++) {
  53. if (s1->data[i] != s2->data[i]) {
  54. return false;
  55. }
  56. }
  57. return true;
  58. }
  59. bool DynString_equal_c_str(const DynString* s1, const char* s2) {
  60. if (s1->data == NULL || s2 == NULL) {
  61. return false;
  62. }
  63. if (s1->len != strlen(s2)) {
  64. return false;
  65. }
  66. for (size_t i = 0; i < s1->len; i++) {
  67. if (s1->data[i] != s2[i]) {
  68. return false;
  69. }
  70. }
  71. return true;
  72. }
  73. bool DynString_equal_next_chars_c_str(
  74. const DynString* dstr,
  75. const char* str,
  76. const size_t str_len,
  77. size_t s
  78. ) {
  79. if (dstr->len < s || dstr->len < s + str_len) {
  80. return false;
  81. }
  82. const size_t e = s + str_len;
  83. for (size_t i = 0; s < e; s++, i++) {
  84. if (dstr->data[s] != str[i]) {
  85. return false;
  86. }
  87. }
  88. return true;
  89. }
  90. void DynString_concat_c_str(
  91. DynString* dstr,
  92. const char* str,
  93. const size_t str_len
  94. ) {
  95. const size_t new_len = dstr->len + str_len;
  96. if (new_len > dstr->capacity) {
  97. DynString_reserve(dstr, new_len + 1);
  98. }
  99. strncpy(dstr->data + dstr->len, str, str_len);
  100. dstr->data[new_len] = '\0';
  101. dstr->len = new_len;
  102. }
  103. DynString DynString_alloc_concat_c_strs(
  104. const char* s1,
  105. const size_t s1_len,
  106. const char* s2,
  107. const size_t s2_len
  108. ) {
  109. DynString dstr = DynString_alloc(s1, s1_len);
  110. DynString_concat_c_str(&dstr, s2, s2_len);
  111. return dstr;
  112. }
  113. DynString* DynString_split(
  114. const DynString* dstr,
  115. const char* delim,
  116. size_t* ret_len
  117. ) {
  118. DynString* arr = (DynString*) malloc(0);
  119. if (arr == NULL) {
  120. LOG_FATAL("malloc failed");
  121. }
  122. *ret_len = 0;
  123. DynString elem = DynString_alloc("", 0);
  124. size_t delim_len = strlen(delim);
  125. for (size_t i = 0; i < dstr->len; i++) {
  126. if (DynString_equal_next_chars_c_str(dstr, delim, delim_len, i)) {
  127. arr = realloc(arr, sizeof(DynString) * (*ret_len + 1));
  128. if (arr == NULL) {
  129. LOG_FATAL("realloc failed");
  130. }
  131. arr[*ret_len] = elem;
  132. *ret_len += 1;
  133. elem = DynString_alloc("", 0);
  134. i += delim_len - 1;
  135. } else {
  136. DynString_concat_c_str(&elem, dstr->data + i, 1);
  137. }
  138. }
  139. arr = realloc(arr, sizeof(DynString) * (*ret_len + 1));
  140. if (arr == NULL) {
  141. LOG_FATAL("realloc failed");
  142. }
  143. arr[*ret_len] = elem;
  144. *ret_len += 1;
  145. return arr;
  146. }