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.

177 lines
3.7 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 2000-2001 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. #include "corex.h"
  13. #define WILDCARD L'%'
  14. #define ANYSINGLECHAR L'_'
  15. CLike::CLike (LPCWSTR expression, WCHAR escape)
  16. : m_expression(NULL)
  17. {
  18. SetExpression( expression, escape );
  19. }
  20. CLike& CLike::operator=( const CLike& rOther )
  21. {
  22. if ( rOther.m_expression != NULL )
  23. {
  24. SetExpression( rOther.m_expression, rOther.m_escape );
  25. }
  26. else
  27. {
  28. delete [] m_expression;
  29. m_expression = NULL;
  30. }
  31. return *this;
  32. }
  33. CLike::~CLike (void)
  34. {
  35. delete [] m_expression;
  36. }
  37. void CLike::SetExpression( LPCWSTR string, WCHAR escape )
  38. {
  39. delete [] m_expression;
  40. size_t stringSize = wcslen(string)+1;
  41. m_expression = new WCHAR[stringSize];
  42. if ( m_expression == NULL )
  43. {
  44. throw CX_MemoryException();
  45. }
  46. StringCchCopyW( m_expression, stringSize, string );
  47. m_escape = escape;
  48. }
  49. bool CLike::Match( LPCWSTR string )
  50. {
  51. bool bRes;
  52. if ( m_expression != NULL )
  53. {
  54. bRes = DoLike( m_expression, string, m_escape );
  55. }
  56. else
  57. {
  58. bRes = false;
  59. }
  60. return bRes;
  61. }
  62. bool CLike::DoLike (LPCWSTR pattern, LPCWSTR string, WCHAR escape)
  63. {
  64. bool like=false;
  65. while (!like && *pattern && *string)
  66. {
  67. // Wildcard match.
  68. if (*pattern==WILDCARD)
  69. {
  70. pattern++;
  71. do
  72. {
  73. like=DoLike (pattern, string, escape);
  74. if (!like) string++;
  75. }
  76. while (*string && !like);
  77. }
  78. // Set match.
  79. else if (*pattern=='[')
  80. {
  81. int skip;
  82. if (MatchSet (pattern, string, skip))
  83. {
  84. pattern+=skip;
  85. string++;
  86. }
  87. else
  88. {
  89. break;
  90. }
  91. }
  92. // Single character match.
  93. else
  94. {
  95. if (escape!='\0' && *pattern==escape) pattern++;
  96. if (wbem_towupper(*pattern)==wbem_towupper(*string) || *pattern==ANYSINGLECHAR)
  97. {
  98. pattern++;
  99. string++;
  100. }
  101. else
  102. {
  103. break;
  104. }
  105. }
  106. }
  107. // Skip any trailing wildcard characters.
  108. while (*pattern==WILDCARD) pattern++;
  109. // It's a match if we reached the end of both strings, or a recursion
  110. // succeeded.
  111. return (!(*pattern) && !(*string)) || like;
  112. }
  113. bool CLike::MatchSet (LPCWSTR pattern, LPCWSTR string, int &skip)
  114. {
  115. // Skip the opening '['.
  116. LPCWSTR pos=pattern+1;
  117. // See if we are matching a [^] set.
  118. bool notinset=(*pos=='^');
  119. if (notinset) pos++;
  120. // See if the target character matches any character in the set.
  121. bool matched=false;
  122. WCHAR lastchar='\0';
  123. while (*pos && *pos!=']' && !matched)
  124. {
  125. // A range of characters is indicated by a '-' unless it's the first
  126. // character in the set (in which case it's just a character to be
  127. // matched.
  128. if (*pos=='-' && lastchar!='\0')
  129. {
  130. pos++;
  131. if (*pos && *pos!=']')
  132. {
  133. matched=(wbem_towupper(*string)>=lastchar && wbem_towupper(*string)<=wbem_towupper(*pos));
  134. lastchar=wbem_towupper(*pos);
  135. pos++;
  136. }
  137. }
  138. else
  139. {
  140. // Match a normal character in the set.
  141. lastchar=wbem_towupper(*pos);
  142. matched=(wbem_towupper(*pos)==wbem_towupper(*string));
  143. if (!matched) pos++;
  144. }
  145. }
  146. // Skip the trailing ']'. If the set did not contain a closing ']'
  147. // we return a failed match.
  148. while (*pos && *pos!=']') pos++;
  149. if (*pos==']') pos++;
  150. if (!*pos) matched=false;
  151. // Done.
  152. skip=(int)(pos-pattern);
  153. return matched==!notinset;
  154. }