str.h 3.0 KB

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