Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
3.1 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 2000 by Microsoft Corp. All Rights Reserved.
  4. //
  5. // like.cpp
  6. //
  7. // a-davcoo 28-Feb-00 Implements the SQL like operation.
  8. //
  9. //***************************************************************************
  10. #include "precomp.h"
  11. #include "like.h"
  12. #define WILDCARD L'%'
  13. #define ANYSINGLECHAR L'_'
  14. CLike::CLike (LPCWSTR expression, WCHAR escape)
  15. {
  16. size_t cchTmp = wcslen(expression)+1;
  17. m_expression = new WCHAR[cchTmp];
  18. if(m_expression)
  19. StringCchCopyW(m_expression,cchTmp, expression);
  20. m_escape=escape;
  21. }
  22. CLike::~CLike (void)
  23. {
  24. delete [] m_expression;
  25. }
  26. bool CLike::Match (LPCWSTR string)
  27. {
  28. // m_expression might be NULL in out-of-memory
  29. return DoLike (m_expression, string, m_escape);
  30. }
  31. bool CLike::DoLike (LPCWSTR pattern, LPCWSTR string, WCHAR escape)
  32. {
  33. // pattern might be NULL in out-of-memory
  34. if(pattern == NULL)
  35. return false;
  36. bool like=false;
  37. while (!like && *pattern && *string)
  38. {
  39. // Wildcard match.
  40. if (*pattern==WILDCARD)
  41. {
  42. pattern++;
  43. do
  44. {
  45. like=DoLike (pattern, string, escape);
  46. if (!like) string++;
  47. }
  48. while (*string && !like);
  49. }
  50. // Set match.
  51. else if (*pattern=='[')
  52. {
  53. int skip;
  54. if (MatchSet (pattern, string, skip))
  55. {
  56. pattern+=skip;
  57. string++;
  58. }
  59. else
  60. {
  61. break;
  62. }
  63. }
  64. // Single character match.
  65. else
  66. {
  67. if (escape!='\0' && *pattern==escape) pattern++;
  68. if (towupper(*pattern)==towupper(*string) || *pattern==ANYSINGLECHAR)
  69. {
  70. pattern++;
  71. string++;
  72. }
  73. else
  74. {
  75. break;
  76. }
  77. }
  78. }
  79. // Skip any trailing wildcard characters.
  80. while (*pattern==WILDCARD) pattern++;
  81. // It's a match if we reached the end of both strings, or a recursion
  82. // succeeded.
  83. return (!(*pattern) && !(*string)) || like;
  84. }
  85. bool CLike::MatchSet (LPCWSTR pattern, LPCWSTR string, int &skip)
  86. {
  87. // Skip the opening '['.
  88. LPCWSTR pos=pattern+1;
  89. // See if we are matching a [^] set.
  90. bool notinset=(*pos=='^');
  91. if (notinset) pos++;
  92. // See if the target character matches any character in the set.
  93. bool matched=false;
  94. WCHAR lastchar='\0';
  95. while (*pos && *pos!=']' && !matched)
  96. {
  97. // A range of characters is indicated by a '-' unless it's the first
  98. // character in the set (in which case it's just a character to be
  99. // matched.
  100. if (*pos=='-' && lastchar!='\0')
  101. {
  102. pos++;
  103. if (*pos && *pos!=']')
  104. {
  105. matched=(towupper(*string)>=lastchar && towupper(*string)<=towupper(*pos));
  106. lastchar=towupper(*pos);
  107. pos++;
  108. }
  109. }
  110. else
  111. {
  112. // Match a normal character in the set.
  113. lastchar=towupper(*pos);
  114. matched=(towupper(*pos)==towupper(*string));
  115. if (!matched) pos++;
  116. }
  117. }
  118. // Skip the trailing ']'. If the set did not contain a closing ']'
  119. // we return a failed match.
  120. while (*pos && *pos!=']') pos++;
  121. if (*pos==']') pos++;
  122. if (!*pos) matched=false;
  123. // Done.
  124. skip=(int)(pos-pattern);
  125. return matched==!notinset;
  126. }