str.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #ifndef STR_H
  2. #define STR_H
  3. #include <stdint.h>
  4. #include <stddef.h>
  5. #include <stdbool.h>
  6. struct str {
  7. const char *data;
  8. size_t size;
  9. };
  10. const struct str STR_EMPTY = {"", 0};
  11. struct str_tokenizer {
  12. struct str str;
  13. size_t cur;
  14. char c;
  15. };
  16. struct str str_from_cstr(const char *cstr, size_t cstr_size);
  17. struct str str_rstrip(struct str str);
  18. struct str str_lstrip(struct str str);
  19. struct str str_strip(struct str str);
  20. size_t str_count_char(struct str str, char c);
  21. struct str_tokenizer str_tokenize(struct str str, char c);
  22. struct str str_tokenizer_next(struct str_tokenizer *st);
  23. struct str str_slice(struct str str, size_t from, size_t to);
  24. bool str_eq_cstr(struct str str, const char *cstr, size_t cstr_size);
  25. #if defined(IMP) || defined(IMP_STR)
  26. #include <ctype.h>
  27. struct str
  28. str_from_cstr(const char *cstr, size_t cstr_size)
  29. {
  30. struct str str;
  31. str.data = cstr;
  32. str.size = cstr_size;
  33. return str;
  34. }
  35. struct str
  36. str_rstrip(struct str str)
  37. {
  38. while ( isspace(str.data[str.size-1]) ) {
  39. --str.size;
  40. }
  41. return str;
  42. }
  43. struct str
  44. str_lstrip(struct str str)
  45. {
  46. while ( isspace(*str.data) ) {
  47. ++str.data;
  48. --str.size;
  49. }
  50. return str;
  51. }
  52. struct str
  53. str_strip(struct str str)
  54. {
  55. return str_lstrip(str_rstrip(str));
  56. }
  57. size_t
  58. str_count_char(struct str str, char c)
  59. {
  60. size_t i = 0;
  61. size_t res = 0;
  62. for ( i = 0; i < str.size; ++i ) {
  63. res += ( str.data[i] == c );
  64. }
  65. return res;
  66. }
  67. struct str_tokenizer
  68. str_tokenize(struct str str, char c)
  69. {
  70. struct str_tokenizer st = {0};
  71. st.str = str;
  72. st.c = c;
  73. return st;
  74. }
  75. struct str
  76. str_tokenizer_next(struct str_tokenizer *st)
  77. {
  78. struct str str;
  79. if ( st == NULL ) {
  80. goto ret_err;
  81. }
  82. if ( st->cur >= st->str.size ) {
  83. goto ret_done;
  84. }
  85. if ( st->str.data[st->cur] == '\0' ) {
  86. goto ret_done;
  87. }
  88. str = st->str;
  89. str.data += st->cur;
  90. str.size = 0;
  91. while ( str.data[str.size] != st->c
  92. && st->cur < st->str.size ) {
  93. ++str.size;
  94. ++st->cur;
  95. }
  96. ++st->cur;
  97. if ( str.size == 0 ) {
  98. goto ret_empty;
  99. }
  100. return str;
  101. ret_empty:
  102. str.data = "";
  103. str.size = 0;
  104. return str;
  105. ret_done:
  106. str.data = "";
  107. str.size = (size_t) -1;
  108. return str;
  109. ret_err:
  110. str.data = "";
  111. str.size = (size_t) -2;
  112. return str;
  113. }
  114. struct str
  115. str_slice(struct str str, size_t from, size_t to)
  116. {
  117. if ( from > str.size ) {
  118. goto ret_err;
  119. }
  120. if ( from > to ) {
  121. goto ret_err;
  122. }
  123. to = ( to > str.size ) * str.size \
  124. + ( to <= str.size ) * to;
  125. str.data += from;
  126. str.size = to - from;
  127. return str;
  128. ret_err:
  129. str.data = "";
  130. str.size = (size_t) -2;
  131. return str;
  132. }
  133. bool
  134. str_eq_cstr(struct str str, const char *cstr, size_t cstr_size)
  135. {
  136. size_t i = 0;
  137. if ( str.size != cstr_size ) {
  138. return false;
  139. }
  140. for ( i = 0; i < str.size; ++i ) {
  141. if ( str.data[i] != cstr[i] ) {
  142. return false;
  143. }
  144. }
  145. return true;
  146. }
  147. #endif /* defined(IMP) || defined(IMP_STR) */
  148. #endif /* STR_H */