wildmatch.tpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. template<typename C, C NORMALIZE_FN(C)>
  15. inline bool mismatches(C left, C right, bool doNormalize)
  16. {
  17. return doNormalize ? (NORMALIZE_FN(left)!=NORMALIZE_FN(right)) : (left!=right);
  18. }
  19. template<typename C, C NORMALIZE_FN(C), C QUERY, C ASTERISK>
  20. bool doWildMatch(const C * src, unsigned srcLen, unsigned srcIdx, const C * pat, unsigned patLen, unsigned patIdx, bool doNormalize)
  21. {
  22. while (patIdx < patLen)
  23. {
  24. C next_char = pat[patIdx++];
  25. switch(next_char)
  26. {
  27. case QUERY:
  28. if (srcIdx == srcLen)
  29. return false;
  30. srcIdx++;
  31. break;
  32. case ASTERISK:
  33. //ensure adjacent *s don't cause exponential search times.
  34. for (;;)
  35. {
  36. if (patIdx == patLen)
  37. return true;
  38. if (pat[patIdx] != ASTERISK)
  39. break;
  40. patIdx++;
  41. }
  42. //check for non wildcarded trailing text
  43. for (;;)
  44. {
  45. //No need to guard patLen since guaranteed to contain an ASTERISK
  46. const C tail_char = pat[patLen-1];
  47. if (tail_char == ASTERISK)
  48. break;
  49. if (srcIdx == srcLen)
  50. return false;
  51. if ((tail_char != QUERY) && mismatches<C, NORMALIZE_FN>(src[srcLen-1], tail_char, doNormalize))
  52. return false;
  53. patLen--;
  54. srcLen--;
  55. if (patIdx == patLen)
  56. return true;
  57. }
  58. //The remaining pattern must match at least one character
  59. while (srcIdx < srcLen)
  60. {
  61. if (doWildMatch<C, NORMALIZE_FN, QUERY, ASTERISK>(src, srcLen, srcIdx, pat, patLen, patIdx, doNormalize))
  62. return true;
  63. srcIdx++;
  64. }
  65. return false;
  66. default:
  67. if (srcIdx == srcLen)
  68. return false;
  69. if (mismatches<C, NORMALIZE_FN>(src[srcIdx], next_char, doNormalize))
  70. return false;
  71. srcIdx++;
  72. break;
  73. }
  74. }
  75. return (srcIdx == srcLen);
  76. }
  77. template<typename C, C NORMALIZE_FN(C), C QUERY, C ASTERISK, C BLANK>
  78. inline bool wildTrimMatch(const C * src, unsigned srcLen, const C * pat, unsigned patLen, bool doNormalize)
  79. {
  80. while (srcLen && src[srcLen - 1] == BLANK)
  81. --srcLen;
  82. while (patLen && pat[patLen - 1] == BLANK)
  83. --patLen;
  84. if (patLen == 0)
  85. return (srcLen == 0);
  86. return doWildMatch<C, NORMALIZE_FN, QUERY, ASTERISK>(src, srcLen, 0, pat, patLen, 0, doNormalize);
  87. }
  88. template<typename C, C NORMALIZE_FN(C), C QUERY, C ASTERISK>
  89. inline bool wildMatch(const C * src, unsigned srcLen, const C * pat, unsigned patLen, bool doNormalize)
  90. {
  91. if (patLen == 0)
  92. return (srcLen == 0);
  93. return doWildMatch<C, NORMALIZE_FN, QUERY, ASTERISK>(src, srcLen, 0, pat, patLen, 0, doNormalize);
  94. }