xs_match.h 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */
  2. #ifndef _XS_MATCH_H
  3. #define _XS_MATCH_H
  4. /* spec is very similar to shell file globbing:
  5. an * matches anything;
  6. a ? matches any character;
  7. | select alternative strings to match;
  8. a \\ escapes a special character;
  9. any other char matches itself. */
  10. int xs_match(const char *str, const char *spec);
  11. #ifdef XS_IMPLEMENTATION
  12. int xs_match(const char *str, const char *spec)
  13. {
  14. const char *b_str;
  15. const char *b_spec = NULL;
  16. const char *o_str = str;
  17. retry:
  18. for (;;) {
  19. const char *q = spec;
  20. char c = *str++;
  21. char p = *spec++;
  22. if (c == '\0') {
  23. /* end of string; also end of spec? */
  24. if (p == '\0' || p == '|')
  25. return 1;
  26. else
  27. break;
  28. }
  29. else
  30. if (p == '?') {
  31. /* match anything except the end */
  32. if (c == '\0')
  33. return 0;
  34. }
  35. else
  36. if (p == '*') {
  37. /* end of spec? match */
  38. if (*spec == '\0')
  39. return 1;
  40. /* store spec for later */
  41. b_spec = spec;
  42. /* back one char */
  43. b_str = --str;
  44. }
  45. else {
  46. if (p == '\\')
  47. p = *spec++;
  48. if (c != p) {
  49. /* mismatch; do we have a backtrack? */
  50. if (b_spec) {
  51. /* continue where we left, one char forward */
  52. spec = b_spec;
  53. str = ++b_str;
  54. }
  55. else {
  56. if (*q == '|')
  57. spec = q;
  58. break;
  59. }
  60. }
  61. }
  62. }
  63. /* try to find an alternative mark */
  64. while (*spec) {
  65. char p = *spec++;
  66. if (p == '\\')
  67. p = *spec++;
  68. if (p == '|') {
  69. /* no backtrack spec, restart str from the beginning */
  70. b_spec = NULL;
  71. str = o_str;
  72. goto retry;
  73. }
  74. }
  75. return 0;
  76. }
  77. #endif /* XS_IMPLEMENTATION */
  78. #endif /* XS_MATCH_H */