Source code of Windows XP (NT5)
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.
|
|
//***************************************************************************
//
// (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; }
|