Figure 2 FormatResults.cpp
////////////////
// 将匹配结果格式化为 MFC CString。
// 来自 RegexTest 未使用包装器的原来版本。
// 示范一种灵巧的方式来调用使用托管扩展的托管对象。
//
CString FormatResults(LPCTSTR lpszRegex, LPCTSTR lpszInput)
{
CString result;
CString temp;
Regex* r = new Regex(lpszRegex);
MatchCollection* mc = r->Matches(lpszInput);
int n = mc->Count;
temp.Format(_T("Number of Matches: %d\n"), n);
result += temp;
for (int i=0; i<n; i++) { // for each lpszInput:
Match *m = mc->Item[i];
temp.Format(_T("Match %d at %d: %s\n"), i, m->Index,
CString(m->Value));
result += temp;
// Show groups
GroupCollection *gc = m->Groups;
for (int j=0; j<gc->Count; j++) {
Group *g = gc->Item[j];
if (g->Success) {
temp.Format(_T(" Group %d match at %d: %s\n"), j, g->Index,
CString(g->Value));
} else {
temp.Format(_T(" Group %d failure\n"), j);
}
result += temp;
}
// Show captures
CaptureCollection *cc = m->Captures;
for (j=0; j<cc->Count; j++) {
Capture *c = cc->Item[j];
temp.Format(_T(" Capture at %d: %s\n"), c->Index,
CString(c->Value));
result += temp;
}
result += _T("\n");
}
// Use Regex to convert all newlines to \r\n for edit control
r = new Regex("\n");
result = r->Replace(result,"\r\n");
return result;
}
Figure 4 CMObject—First Pass //////////////////
// 实现 CMObject 的首要企图, 所有包装器的基类。
// 类声明 — .h 文件
//
class CMObject {
protected:
gcroot<Object*> m_handle; // handle to managed object
public:
// fns whose signatures use managed types
CMObject(Object* o) : m_handle(o) { }
Object* ThisObject() const { return (Object*)m_handle; }
Object* operator->() const { return ThisObject(); }
// fns whose signatures use native types
CMObject() { }
CMObject(const CMObject& o) : m_handle(o.m_handle) { }
CMObject& operator=(const CMObject& r) {
m_handle = r.m_handle; // copies underlying GCHandle.Target
return *this;
}
// wrapped methods/properties
CString ToString() const {
return (*this)->ToString();
}
};
Figure 5 CMObject
CMObject.h //////////////////
// Object 包装器, .NET 类层次的基类。
// CMObject 不使用 DECLARE_WRAPPER,因为它没有基类。
//
class CMObject {
protected:
GCHANDLE(Object*) m_handle;
public:
#ifdef _MANAGED
// visible to managed clients only: anything that deals with __gc
// objects
CMObject(Object* o) : m_handle(o) { }
Object* ThisObject() const { return (Object*)m_handle; }
Object* operator->() const { return ThisObject(); }
#endif
// visible to all clients
CMObject();
CMObject(const CMObject& o);
BOOL operator==(const CMObject& r) const;
BOOL operator!=(const CMObject& r) const { return ! operator==(r); }
CMObject& operator=(const CMObject& r);
CString ToString() const;
CString TypeName() const;
};
CMObject.cpp ////////////////
// CMObject 实现, 来自 ManWrap.cpp
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio .NET 2003 on Windows XP. Tab size=3.
//
CMObject::CMObject()
{
// default ctor must be here and not inline, so m_handle is
// appropriately initialized to a NULL GCHandle. Otherwise it will
// have unpredictable values since native code sees it as intptr_t
}
CMObject::CMObject(const CMObject& o) : m_handle(o.m_handle)
{
// See remarks above
}
CMObject& CMObject::operator=(const CMObject& r)
{
m_handle = r.m_handle; // copies underlying GCHandle.Target
return *this;
}
BOOL CMObject::operator==(const CMObject& r) const
{
return (*this)->Equals(r.ThisObject());
}
CString CMObject::ToString() const
{
return (*this)->ToString();
}
CString CMObject::TypeName() const
{
return (*this)->GetType()->Name;
}
Figure 6 declare_wrapper.h
// DECLARE_WRAPPER macro from ManWrap.h
#ifdef _MANAGED
// 此声明为 DECLARE_WRAPPER 的托管部分。仅内部使用。
// 使用 DECLARE_WRAPPER。
//
#define DECLARE_WRAPPER_M(MT,BT) \
public: \
CM##MT(MT* o) : CM##BT(o) { } \
MT* ThisObject() const \
{ \
return static_cast<MT*>((Object*)m_handle); \
} \
MT* operator->() const \
{ \
return ThisObject(); \
} \
CM##MT& operator=(MT* o) \
{ \
m_handle = o; \
return *this; \
} \
#else // NOT _MANAGED
// 本机代码不可见的托管机制: 这个宏什么也不做
#define DECLARE_WRAPPER_M(MT,BT)
#endif // _MANAGED
//////////////////
// 用来的、声明包装器类。声明需要基本的构造函数和操作符,使用时要想类型安全这是必须的。
// MT=托管类型, BT=基(托管)类型。
// 你必须遵循的命名规范:CMFoo = Foo 的包装器。
//
#define DECLARE_WRAPPER(MT,BT) \
public: \
CM##MT() { } \
CM##MT(const CM##MT& o) : CM##BT(o) { } \
CM##MT& operator=(const CM##MT &r) \
{ \
CM##BT::operator=(r); \
return *this; \
} \
DECLARE_WRAPPER_M(MT,BT) \
Figure 7 RegexWrap.h
////////////////////////////////////////////////////////////////
// MSDN Magazine — February 2004
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio .NET 2003 on Windows XP. Tab size=3.
//
// 该文件声明 RegexWrap 所有包装器。实现部分在 RegexWrap.cpp。
//
#pragma once
#include "ManWrap.h"
#ifdef _MANAGED
using namespace System::Runtime::InteropServices;
using namespace System::Text::RegularExpressions;
#endif
//////////////////
// 为了初始化 RegexWrap.dll,在调用任何 RegexWrap DLL 函数之前,
// 你必须在应用程序的某个地方实例化其中之一。
// 使用托管扩展的 DLLs 以及 MFN/ATL 需要进行专门初始化,因为它们不
// 使用调用 DllMain 的标准启动代码。最好是在函数范围之外的某个地方或者
// 是在CWinApp派生的应用程序类(MFC)中创建一个静态实例。
//
class WREXPORT CRegexWrapInit {
public:
CRegexWrapInit();
~CRegexWrapInit();
};
//////////////////
// Wrapper for .NET Capture class
//
class WREXPORT CMCapture : public CMObject
{
DECLARE_WRAPPER(Capture, Object);
public:
// wrapped properties/methods
int Index() const;
int Length() const;
CString Value() const;
};
//////////////////
// Wrapper for Group.
//
class WREXPORT CMGroup : public CMCapture
{
DECLARE_WRAPPER(Group, Capture);
public:
// wrapped properties/methods
bool Success() const;
CMCaptureCollection Captures() const;
};
//////////////////
// Wrapper for Match.
//
class WREXPORT CMMatch : public CMGroup
{
DECLARE_WRAPPER(Match, Group);
public:
// wrapped properties/methods
CMMatch NextMatch() const;
CString Result(CString sReplace) const;
CMGroupCollection Groups() const;
static const CMMatch Empty; // constant empty match
typedef CString (CALLBACK* evaluator)(const CMMatch&, void* param);
};
//////////////////
// Regex 包装器. 所有好东东都在这里。
//
class WREXPORT CMRegex : public CMObject {
DECLARE_WRAPPER(Regex,Object);
public:
enum Options {
None = 0,
.
.
};
CMRegex(LPCTSTR s);
CMRegex(LPCTSTR s, Options opt);
CMMatch Match(LPCTSTR input);
static CMMatch Match(LPCTSTR input, LPCTSTR pattern);
.
. // lots more
.
};
Figure 8 GroupCollection.cpp
//////////////////
// ManWrap wrapper for GroupCollection.
//
// In header, RegexWrap.h
class WREXPORT CMGroupCollection : public CMObject
{
DECLARE_COLLECTION(GroupCollection, Object);
public:
CMGroup operator[](int i);
CMGroup operator[](LPCTSTR name);
};
// In module, RegexWrap.cpp
IMPLEMENT_COLLECTION(GroupCollection, Object)
CMGroup CMGroupCollection::operator[](int i)
{
return (*this)->Item[i];
}
CMGroup CMGroupCollection::operator[](LPCTSTR name)
{
return (*this)->Item[name];
}
Figure 11 WordMess
Scrambler Function
//////////////////
// 匹配求值会调用:该函数接收一个匹配并返回要用来替代的文本。
// 算法是:打乱单词中间的字母。
//
// - 少于四个字母的单词不改变.
// - 四个字母的单词将其中间两个字母交换.
// - 五个字母的单词保留其第一个和最后一个字母不变.
// - 长单词保留开始和结尾两个字母不变.
//
// 瞧瞧使用 STL 算法一切变得多容易!!——swap 和 random_shuffle.
// Scrambler 在 CString 中报告其行为,该 CString 通过 void* param 传递.
//
CString CALLBACK Scrambler(const CMMatch& m, void* param)
{
tstring word = m.Value(); // STL 字符串比 CString 容易处理
size_t len = word.size();
if (len>=4) {
if (len==4) {
swap(word[1],word[2]); // 使用 STL swap 算法!
} else {
// STL 洗牌算法!
random_shuffle(word.begin()+(len <=5 ? 1 : 2), word.end()-1);
}
}
if (param) {
CString temp;
temp.Format(_T("Scramble: '%s' -> '%s'\n"), m.Value(),
word.c_str());
(*(CString*)param) += temp;
}
return word.c_str();
}
|