275 lines
6.3 KiB
C++
275 lines
6.3 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999, Microsoft Corp. All rights reserved.
|
|
//
|
|
// FILE
|
|
//
|
|
// regex.cpp
|
|
//
|
|
// SYNOPSIS
|
|
//
|
|
// Defines the class RegularExpression.
|
|
//
|
|
// MODIFICATION HISTORY
|
|
//
|
|
// 03/10/1999 Original version.
|
|
// 05/27/1999 Check return value of SysAllocString in setPattern.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <ias.h>
|
|
#include <regex.h>
|
|
#include <regexp.h>
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CLASS
|
|
//
|
|
// FastCoCreator
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// Wraps a class factory to allow instances of a particular coclass to
|
|
// be created 'fast'.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
class FastCoCreator
|
|
{
|
|
public:
|
|
FastCoCreator(REFCLSID rclsid, DWORD dwClsContext) throw ();
|
|
~FastCoCreator() throw ();
|
|
|
|
HRESULT createInstance(
|
|
LPUNKNOWN pUnkOuter,
|
|
REFIID riid,
|
|
LPVOID* ppv
|
|
) throw ();
|
|
|
|
void destroyInstance(IUnknown* pUnk) throw ();
|
|
|
|
protected:
|
|
REFCLSID clsid;
|
|
DWORD context;
|
|
CRITICAL_SECTION monitor;
|
|
ULONG refCount;
|
|
IClassFactory* factory;
|
|
|
|
private:
|
|
FastCoCreator(FastCoCreator&) throw ();
|
|
FastCoCreator& operator=(FastCoCreator&) throw ();
|
|
};
|
|
|
|
FastCoCreator::FastCoCreator(REFCLSID rclsid, DWORD dwClsContext)
|
|
: clsid(rclsid),
|
|
context(dwClsContext),
|
|
refCount(0),
|
|
factory(NULL)
|
|
{
|
|
InitializeCriticalSection(&monitor);
|
|
}
|
|
|
|
FastCoCreator::~FastCoCreator() throw ()
|
|
{
|
|
if (factory) { factory->Release(); }
|
|
|
|
DeleteCriticalSection(&monitor);
|
|
}
|
|
|
|
HRESULT FastCoCreator::createInstance(
|
|
LPUNKNOWN pUnkOuter,
|
|
REFIID riid,
|
|
LPVOID* ppv
|
|
) throw ()
|
|
{
|
|
HRESULT hr;
|
|
|
|
EnterCriticalSection(&monitor);
|
|
|
|
// Get a new class factory if necessary.
|
|
if (!factory)
|
|
{
|
|
hr = CoGetClassObject(
|
|
clsid,
|
|
context,
|
|
NULL,
|
|
__uuidof(IClassFactory),
|
|
(PVOID*)&factory
|
|
);
|
|
}
|
|
|
|
if (factory)
|
|
{
|
|
hr = factory->CreateInstance(
|
|
pUnkOuter,
|
|
riid,
|
|
ppv
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// We successfully created an object, so bump the ref. count.
|
|
++refCount;
|
|
}
|
|
else if (refCount == 0)
|
|
{
|
|
// Don't hang on to the factory if the ref. count is zero.
|
|
factory->Release();
|
|
factory = NULL;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&monitor);
|
|
|
|
return hr;
|
|
}
|
|
|
|
void FastCoCreator::destroyInstance(IUnknown* pUnk) throw ()
|
|
{
|
|
if (pUnk)
|
|
{
|
|
EnterCriticalSection(&monitor);
|
|
|
|
if (--refCount == 0)
|
|
{
|
|
// Last object went away, so release the class factory.
|
|
factory->Release();
|
|
factory = NULL;
|
|
}
|
|
|
|
LeaveCriticalSection(&monitor);
|
|
|
|
pUnk->Release();
|
|
}
|
|
}
|
|
|
|
/////////
|
|
// Macro that ensures the internal RegExp object has been initalize.
|
|
/////////
|
|
#define CHECK_INIT() \
|
|
{ HRESULT hr = checkInit(); if (FAILED(hr)) { return hr; }}
|
|
|
|
FastCoCreator RegularExpression::theCreator(
|
|
__uuidof(RegExp),
|
|
CLSCTX_INPROC_SERVER
|
|
);
|
|
|
|
RegularExpression::RegularExpression() throw ()
|
|
: regex(NULL)
|
|
{ }
|
|
|
|
RegularExpression::~RegularExpression() throw ()
|
|
{
|
|
theCreator.destroyInstance(regex);
|
|
}
|
|
|
|
HRESULT RegularExpression::setIgnoreCase(BOOL fIgnoreCase) throw ()
|
|
{
|
|
return setBooleanProperty(10002, fIgnoreCase);
|
|
}
|
|
|
|
HRESULT RegularExpression::setGlobal(BOOL fGlobal) throw ()
|
|
{
|
|
return setBooleanProperty(10003, fGlobal);
|
|
}
|
|
|
|
HRESULT RegularExpression::setPattern(PCWSTR pszPattern) throw ()
|
|
{
|
|
CHECK_INIT();
|
|
|
|
HRESULT hr;
|
|
BSTR bstr = SysAllocString(pszPattern);
|
|
if (bstr)
|
|
{
|
|
hr = regex->put_Pattern(bstr);
|
|
SysFreeString(bstr);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT RegularExpression::replace(
|
|
BSTR sourceString,
|
|
BSTR replaceString,
|
|
BSTR* pDestString
|
|
) const throw ()
|
|
{
|
|
return regex->Replace(sourceString, replaceString, pDestString);
|
|
}
|
|
|
|
BOOL RegularExpression::testBSTR(BSTR sourceString) const throw ()
|
|
{
|
|
// Test the regular expression.
|
|
VARIANT_BOOL fMatch = VARIANT_FALSE;
|
|
regex->Test(sourceString, (BOOLEAN*)&fMatch);
|
|
return fMatch;
|
|
}
|
|
|
|
BOOL RegularExpression::testString(PCWSTR sourceString) const throw ()
|
|
{
|
|
// ByteLen of the BSTR.
|
|
DWORD nbyte = wcslen(sourceString) * sizeof(WCHAR);
|
|
|
|
// We need room for the string, the ByteLen, and the null-terminator.
|
|
PDWORD p = (PDWORD)_alloca(nbyte + sizeof(DWORD) + sizeof(WCHAR));
|
|
|
|
// Store the ByteLen.
|
|
*p++ = nbyte;
|
|
|
|
// Copy in the sourceString.
|
|
memcpy(p, sourceString, nbyte + sizeof(WCHAR));
|
|
|
|
// Test the regular expression.
|
|
VARIANT_BOOL fMatch = VARIANT_FALSE;
|
|
regex->Test((BSTR)p, (BOOLEAN*)&fMatch);
|
|
|
|
return fMatch;
|
|
}
|
|
|
|
void RegularExpression::swap(RegularExpression& obj) throw ()
|
|
{
|
|
IRegExp* tmp = obj.regex;
|
|
obj.regex = regex;
|
|
regex = tmp;
|
|
}
|
|
|
|
HRESULT RegularExpression::checkInit() throw ()
|
|
{
|
|
// Have we already initialized?
|
|
return regex ? S_OK : theCreator.createInstance(
|
|
NULL,
|
|
__uuidof(IRegExp),
|
|
(PVOID*)®ex
|
|
);
|
|
}
|
|
|
|
HRESULT RegularExpression::setBooleanProperty(
|
|
DISPID dispId,
|
|
BOOL newVal
|
|
) throw ()
|
|
{
|
|
CHECK_INIT();
|
|
|
|
VARIANTARG vararg;
|
|
VariantInit(&vararg);
|
|
V_VT(&vararg) = VT_BOOL;
|
|
V_BOOL(&vararg) = newVal ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
DISPID dispid = DISPID_PROPERTYPUT;
|
|
|
|
DISPPARAMS parms = { &vararg, &dispid, 1, 1 };
|
|
|
|
return regex->Invoke(
|
|
dispId,
|
|
IID_NULL,
|
|
0,
|
|
DISPATCH_PROPERTYPUT,
|
|
&parms,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|