//*************************************************************************** // // (c) 2000-2001 by Microsoft Corp. All Rights Reserved. // // like.cpp // // a-davcoo 28-Feb-00 Implements the SQL like operation. // //*************************************************************************** #include "precomp.h" #include "like.h" #include "corex.h" #define WILDCARD L'%' #define ANYSINGLECHAR L'_' CLike::CLike (LPCWSTR expression, WCHAR escape) : m_expression(NULL) { SetExpression( expression, escape ); } CLike& CLike::operator=( const CLike& rOther ) { if ( rOther.m_expression != NULL ) { SetExpression( rOther.m_expression, rOther.m_escape ); } else { delete [] m_expression; m_expression = NULL; } return *this; } CLike::~CLike (void) { delete [] m_expression; } void CLike::SetExpression( LPCWSTR string, WCHAR escape ) { delete [] m_expression; m_expression = new WCHAR[wcslen(string)+1]; if ( m_expression == NULL ) { throw CX_MemoryException(); } wcscpy( m_expression, string ); m_escape = escape; } bool CLike::Match( LPCWSTR string ) { bool bRes; if ( m_expression != NULL ) { bRes = DoLike( m_expression, string, m_escape ); } else { bRes = false; } return bRes; } bool CLike::DoLike (LPCWSTR pattern, LPCWSTR string, WCHAR escape) { bool like=false; while (!like && *pattern && *string) { // Wildcard match. if (*pattern==WILDCARD) { pattern++; do { like=DoLike (pattern, string, escape); if (!like) string++; } while (*string && !like); } // Set match. else if (*pattern=='[') { int skip; if (MatchSet (pattern, string, skip)) { pattern+=skip; string++; } else { break; } } // Single character match. else { if (escape!='\0' && *pattern==escape) pattern++; if (towupper(*pattern)==towupper(*string) || *pattern==ANYSINGLECHAR) { pattern++; string++; } else { break; } } } // Skip any trailing wildcard characters. while (*pattern==WILDCARD) pattern++; // It's a match if we reached the end of both strings, or a recursion // succeeded. return (!(*pattern) && !(*string)) || like; } bool CLike::MatchSet (LPCWSTR pattern, LPCWSTR string, int &skip) { // Skip the opening '['. LPCWSTR pos=pattern+1; // See if we are matching a [^] set. bool notinset=(*pos=='^'); if (notinset) pos++; // See if the target character matches any character in the set. bool matched=false; WCHAR lastchar='\0'; while (*pos && *pos!=']' && !matched) { // A range of characters is indicated by a '-' unless it's the first // character in the set (in which case it's just a character to be // matched. if (*pos=='-' && lastchar!='\0') { pos++; if (*pos && *pos!=']') { matched=(towupper(*string)>=lastchar && towupper(*string)<=towupper(*pos)); lastchar=towupper(*pos); pos++; } } else { // Match a normal character in the set. lastchar=towupper(*pos); matched=(towupper(*pos)==towupper(*string)); if (!matched) pos++; } } // Skip the trailing ']'. If the set did not contain a closing ']' // we return a failed match. while (*pos && *pos!=']') pos++; if (*pos==']') pos++; if (!*pos) matched=false; // Done. skip=(int)(pos-pattern); return matched==!notinset; }