str.h 2.6 KB

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