windows-nt/Source/XPSP1/NT/admin/wmi/wbem/winmgmt/wbemcomn/like.cpp
2020-09-26 16:20:57 +08:00

177 lines
3.4 KiB
C++

//***************************************************************************
//
// (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;
}