xs_match.h 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /* copyright (c) 2022 - 2023 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 *o_str = str;
  15. again:
  16. if (*spec == '*') {
  17. spec++; /* wildcard */
  18. do {
  19. if (xs_match(str, spec))
  20. return 1;
  21. str++;
  22. } while (*str);
  23. return 0;
  24. }
  25. if (*spec == '?' && *str) {
  26. spec++; /* any character */
  27. str++;
  28. goto again;
  29. }
  30. if (*spec == '|')
  31. return 1; /* alternative separator? positive match */
  32. if (!*spec)
  33. return 1; /* end of spec? positive match */
  34. if (*spec == '\\')
  35. spec++; /* escaped char */
  36. if (*spec == *str) {
  37. spec++; /* matched 1 char */
  38. str++;
  39. goto again;
  40. }
  41. /* not matched; are there any alternatives? */
  42. while (*spec) {
  43. if (*spec == '|')
  44. return xs_match(o_str, spec + 1); /* try next alternative */
  45. if (*spec == '\\')
  46. spec++; /* escaped char */
  47. spec++;
  48. }
  49. return 0;
  50. }
  51. #endif /* XS_IMPLEMENTATION */
  52. #endif /* XS_MATCH_H */