MFC文件操作大全

1.创建文件夹

CreateDirectory(%%1,NULL);

2.创建文件

CFile file;

file.Open(%%1,CFile::modeCreate|CFile::modeWrite);

3.删除文件

DeleteFile(%%1);

4.删除文件夹

RemoveDirectory(%%1);

5.删除一个目录下所有的文件夹

CFileFind finder;

CString path;

path.Format("%s//*.*",%%1);

BOOL bWorking = finder.FindFile(path);

while (bWorking)

{

bWorking = finder.FindNextFile();

if (finder.IsDirectory() &&!finder.IsDots())

{

RemoveDirectory(finder.GetFilePath());

}

}

6.清空文件夹

RemoveDirectory(%%1);

CreateDirectory(%%1,NULL);

7.读取文件

char sRead[5120];

CFile mFile(_T(%%1),CFile::modeRead);

while (sRead!=NULL)

{

mFile.Read(sRead,5120);

CString %%2(sRead);

%%3

}

mFile.Close();

8.写入文件

CFile mFile(_T(%%1),CFile::modeWrite|CFile::modeCreate);

mFile.Write(%%2,sizeof(%%2));

mFile.Flush();

mFile.Close();

9.写入随机文件

char szTempPath[_MAX_PATH],szTempfile[_MAX_PATH];

GetTempPath(_MAX_PATH, szTempPath);

GetTempFileName(szTempPath,_T("my_"),0,szTempfile);

CFile m_tempFile(szTempfile,CFile::modeCreate|CFile:: modeWrite);

char m_char='a';

m_tempFile.Write(&m_char,2);

m_tempFile.Close();

//循环写入多个值

strTempA;

int i;

int nCount=6;

//共有6个文件名需要保存

for (i=0;i{strTemp.Format("%d",i);

strTempA=文件名;

//文件名可以从数组,列表框等处取得.

::WritePrivateProfileString("UseFileName","FileName"+strTemp,strTempA,

c://usefile//usefile.ini);

}

strTemp.Format("%d",nCount);

::WritePrivateProfileString("FileCount","Count",strTemp,"c://usefile//usefile.ini");

//将文件总数写入,以便读出.

//读出

nCount=::GetPrivateProfileInt("FileCount","Count",0,"c://usefile//usefile.ini");

for(i=0;i{strTemp.Format("%d",i);

strTemp="FileName"+strTemp;

::GetPrivateProfileString("CurrentIni",strTemp,"default.fil",strTempA.GetBuffer(MAX_PATH),MAX_PATH,"c://usefile//usefile.ini");

//使用strTempA中的内容.

}

1.Seek

Seek(100L,CFile::begin);//移动到文件开始后100字节处

Seek(100L,CFile::end);

Seek(100L,CFile::current);

2.GetPosition

得到文件当前位置,返回32位文件指针

DWORD pos=file.GetPostition();

file.Seek(pos,CFile::begin);

3.GetLength()

10.读取文件属性

DWORD dwAttrs = GetFileAttributes(%%1);

if(dwAttrs & FILE_ATTRIBUTE_READONLY) {

 %%2

}

if(dwAttrs & FILE_ATTRIBUTE_NORMAL){

 %%3

}

11.写入属性

SetFileAttributes(%%1,dwAttrs |FILE_ATTRIBUTE_READONLY);

12.枚举一个目录下所有文件夹

CFileFind finder;

CString path;

path.Format("%s//*.*",%%1);

BOOL bWorking = finder.FindFile(path);

while (bWorking) {

bWorking = finder.FindNextFile();

if(finder.IsDirectory() &&!finder.IsDots()){

CString %%1=finder.GetFilePath();

%%2

}

}

13.复制文件夹

/*

#include <deque>

using namespace std;

*/

deque<CString>ctr;

WIN32_FIND_DATA FileData;

HANDLE hSearch;

DWORD dwAttrs;

char szDirPath[] = %%2;

char szNewPath[MAX_PATH];

BOOL fFinished = FALSE;

if (!CreateDirectory(szDirPath, NULL)) {

//不能创建新的目录

 return;

}

CString path;

path.Format("%s//*.*",%%1);

hSearch = FindFirstFile(path, &FileData);

if (hSearch == INVALID_HANDLE_VALUE) {

 return;

}

while (ctr.size>0) {

if(!fFinished)

 lstrcpy(szNewPath, szDirPath);

 lstrcat(szNewPath, FileData.cFileName);

 if(CopyFile(FileData.cFileName, szNewPath, FALSE)) {

 dwAttrs= GetFileAttributes(FileData.cFileName);

 if(!(dwAttrs & FILE_ATTRIBUTE_READONLY)) {

 SetFileAttributes(szNewPath,

 dwAttrs| FILE_ATTRIBUTE_READONLY);

 }

 }

 else {

 //不能复制文件

 return;

 }

 if(!FindNextFile(hSearch, &FileData)) {

 if(GetLastError() == ERROR_NO_MORE_FILES) {

 //遍历文件夹完成

 fFinished = TRUE;

 }

 else {

 //找不到下一个文件

 return;

 }

 }

}

}

FindClose(hSearch);

14.复制一个目录下所有的文件夹到另一个文件夹下

/*

#include <deque>

using namespace std;

*/

deque<CString>ctr;

WIN32_FIND_DATA FileData;

HANDLE hSearch;

DWORD dwAttrs;

char szDirPath[] = %%2;

char szNewPath[MAX_PATH];

BOOL fFinished = FALSE;

if (!CreateDirectory(szDirPath,NULL))

{

//不能创建新的目录

return;

}

CString path;

CFileFind finder;

path.Format("%s//*.*",%%1);

BOOL bWorking = finder.FindFile(path);

while (bWorking)

{

bWorking = finder.FindNextFile();

if(finder.IsDirectory() &&!finder.IsDots()){

hSearch =FindFirstFile(finder.GetFilePath()+"//*.*", &FileData);

if (hSearch == INVALID_HANDLE_VALUE)

{

return;

}

while (!fFinished)

{

lstrcpy(szNewPath, szDirPath);

lstrcat(szNewPath, FileData.cFileName);

if (CopyFile(FileData.cFileName, szNewPath,FALSE))

{

dwAttrs =GetFileAttributes(FileData.cFileName);

if (!(dwAttrs & FILE_ATTRIBUTE_READONLY))

{

SetFileAttributes(szNewPath,

dwAttrs | FILE_ATTRIBUTE_READONLY);

}

}

else

{

//不能复制文件

return;

}

if (!FindNextFile(hSearch, &FileData))

{

if (GetLastError() == ERROR_NO_MORE_FILES)

{

//遍历文件夹完成

fFinished = TRUE;

}

else

{

//找不到下一个文件

return;

}

}

}

FindClose(hSearch);

}

}

15.移动文件夹

/*

#include <deque>

using namespace std;

*/

deque<CString>ctr;

WIN32_FIND_DATA FileData;

HANDLE hSearch;

DWORD dwAttrs;

char szDirPath[] = %%2;

char szNewPath[MAX_PATH];

BOOL fFinished = FALSE;

if (!CreateDirectory(szDirPath, NULL))

{

//不能创建新的目录

return;

}

CString path;

path.Format("%s//*.*",%%1);

hSearch = FindFirstFile(path, &FileData);

if (hSearch == INVALID_HANDLE_VALUE)

{

return;

}

while (!fFinished)

{

lstrcpy(szNewPath, szDirPath);

lstrcat(szNewPath, FileData.cFileName);

if (CopyFile(FileData.cFileName, szNewPath,FALSE))

{

dwAttrs =GetFileAttributes(FileData.cFileName);

if (!(dwAttrs & FILE_ATTRIBUTE_READONLY))

{

SetFileAttributes(szNewPath,

dwAttrs | FILE_ATTRIBUTE_READONLY);

}

}

else

{

//不能复制文件

return;

}

if (!FindNextFile(hSearch, &FileData))

{

if (GetLastError() == ERROR_NO_MORE_FILES)

{

//遍历文件夹完成

fFinished = TRUE;

}

else

{

//找不到下一个文件

return;

}

}

}

FindClose(hSearch);

RemoveDirectory(%%1);

16.移动一个文件夹下所有的文件夹到另一个目录下

/*

#include <deque>

using namespace std;

*/

deque<CString>ctr;

WIN32_FIND_DATA FileData;

HANDLE hSearch;

DWORD dwAttrs;

char szDirPath[] = %%2;

char szNewPath[MAX_PATH];

BOOL fFinished = FALSE;

if (!CreateDirectory(szDirPath,NULL))

{

//不能创建新的目录

return;

}

CString path;

path.Format("%s//*.*",%%1);

BOOL bWorking = finder.FindFile(path);

while (bWorking)

{

bWorking = finder.FindNextFile();

if(finder.IsDirectory() &&!finder.IsDots()){

hSearch =FindFirstFile(finder.GetFilePath()+"//*.*", &FileData);

if (hSearch == INVALID_HANDLE_VALUE)

{

return;

}

while (!fFinished)

{

lstrcpy(szNewPath, szDirPath);

lstrcat(szNewPath, FileData.cFileName);

if (CopyFile(FileData.cFileName, szNewPath,FALSE))

{

dwAttrs =GetFileAttributes(FileData.cFileName);

if (!(dwAttrs & FILE_ATTRIBUTE_READONLY))

{

SetFileAttributes(szNewPath,

dwAttrs | FILE_ATTRIBUTE_READONLY);

}

}

else

{

//不能复制文件

return;

}

if (!FindNextFile(hSearch, &FileData))

{

if (GetLastError() == ERROR_NO_MORE_FILES)

{

//遍历文件夹完成

fFinished = TRUE;

}

else

{

//找不到下一个文件

return;

}

}

}

FindClose(hSearch);

RemoveDirectory(finder.GetFilePath().GetBuffer(0));

}

}

17.以一个文件夹的框架在另一个目录创建文件夹和空文件

/*

#include <deque>

using namespace std;

*/

deque<CString>ctr;

WIN32_FIND_DATA FileData;

HANDLE hSearch;

DWORD dwAttrs;

char szDirPath[] = %%2;

char szNewPath[MAX_PATH];

BOOL fFinished = FALSE;

if (!CreateDirectory(szDirPath, NULL))

{

//不能创建新的目录

return;

}

CString path;

path.Format("%s//*.*",%%1);

hSearch = FindFirstFile(path, &FileData);

if (hSearch == INVALID_HANDLE_VALUE)

{

return;

}

while (!fFinished)

{

lstrcpy(szNewPath, szDirPath);

lstrcat(szNewPath, FileData.cFileName);

HANDLE hFile=CreateFileHandlehFile=CreateFile(szNewPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);

if(!hFile)

{

//不能创建文件

return;

}

if (!FindNextFile(hSearch, &FileData))

{

if (GetLastError() == ERROR_NO_MORE_FILES)

{

//遍历文件夹完成

fFinished = TRUE;

}

else

{

//找不到下一个文件

return;

}

}

}

FindClose(hSearch);

18.复制文件

CopyFile(%%1,%%2,true);

19.复制一个文件夹下所有的文件到另一个目录

/*

#include <string>

using std::string;

*/

char sep='/';

#ifdef _WIN32

sep='//';

#endif

CFileFind finder;

CString path;

path.Format("%s//*.*",%%1);

BOOL bWorking = finder.FindFile(path);

while (bWorking)

{

bWorking = finder.FindNextFile();

if(!finder.IsDirectory() || finder.IsDots()){

string s(finder.GetFileName());

if(s.rfind(sep,s.length())!=string::npos)

{

char *file=substr(i+1,s.length()-i).c_str();

CString sourcefile;

sourcefile.Format("%s%c%s",%%1,sep,file);

CString targetfile;

targetfile.Format("%s%c%s",%%2,file);

CopyFile(sourcefile,targetfile,true);

}

}

}

20.提取扩展名

CString path(%%1);

CString %%2=path.Mid(path.ReverseFind('.'));

21.提取文件名

CString path(%%1);

CString %%2=path.Mid(path.ReverseFind('//')+1);

22.提取文件路径

char appName[MAX_PATH];

GetModualFileName(NULL,appName,MAX_PATH);

CString %%1(appName);

23.替换扩展名

/*

#include <string>

using std::string;

*/

string s(%%1);

string newExt(%%2);

string::size_type i=s.rfind('.',s.length());

if(i!=string::npos)

s.replace(i+1,newExt.length(),newExt);

CString %%3(s);

24.追加路径

/*

#include <string>

#include <cstdlib>

#include<boost/filesystem/operations.hpp>

#include <boost/filesystem/fstream.hpp>

using namespace std;

using namespace boost::filesystem;

*/

try {

path p1=complete(path(%%2,native),

path(%%1,native));

path p2=system_complete(path(%%2,native));

CString %%3(p3);

%%4

}

catch(exception& e){

//e.what();

}

25.移动文件

MoveFile(%%1,%%2);

26.移动一个文件夹下所有文件到另一个目录

/*

#include <string>

using std::string;

*/

char sep='/';

#ifdef _WIN32

sep='//';

#endif

CFileFind finder;

CString path;

path.Format("%s//*.*",%%1);

BOOL bWorking = finder.FindFile(path);

while (bWorking)

{

bWorking = finder.FindNextFile();

if(!finder.IsDirectory() || finder.IsDots()){

string s(finder.GetFileName());

CString sourcefile(%%1);

if(s.rfind(sep,s.length())!=string::npos)

{

sourcefile=sourcefile+"//"+s.substr(i+1,s.length()-i);

CString targetfile(s.substr(i+1,s.length()-i));

targetfile=%%2+"//"+targetfile/;

MoveFile(sourcefile.GetBuffer(0),targetfile.GetBuffer(0),true);

}

}

}

27.指定目录下搜索文件

CString strFileTitle;

CFileFind finder;

BOOL bWorking = finder.FindFile(%%1);//"C://windows//sysbkup//*.cab"

while(bWorking)

{

bWorking=finder.FindNextFile();

strFileTitle=finder.GetFileTitle();

}

28.打开对话框

CString %%1;

CFileDialog dlg(TRUE);///TRUEOPEN对话框,FALSESAVE AS对话框

//dlg.m_ofn.lpstrInitialDir=_T("d://");//这里就设置了对话框的默认目录d

dlg.m_ofn.lpstrFilter="Document/0*.doc/0AllFiles(*.*)/0*.*/0/0";

if(dlg.DoModal()==IDOK)

%%1=dlg.GetPathName();

29.文件分割

CFile m_File;

CString m_Filename,m_FileTitle,m_FilePath;

m_FileName=%%1;

char pBuf[4096];

if(m_File.Open(m_FileName,CFile::modeRead |CFile::shareDenyWrite))

{

m_FileName=m_File.GetPathName();

m_FileTitle=m_File.GetFileTitle();

DWORD FileLength=m_File.GetLength();

DWORD PartLength=FileLength/2+FileLength%2;

int nCount=1;

CString strName;

CFile wrFile;

DWORD ReadBytes;

while(true)

{

ReadBytes=m_File.Read(pBuf,PartLength);

strName.Format("%s%d",m_FIleTitle,nCount);

wrFile.Open(strName,CFile::modeWrite |CFile::modeCreate);

wrFile.Write(pBuf,ReadBytes);

wrFile.Close();

if(ReadBytes<PartLength)

break;

nCount++;

}

m_File.Close();

}

else

AfxMessageBox("不能打开文件");

30.文件合并

//#include <string>

using std::string;

string s(%%1);

char sep='/';

#ifdef _WIN32

sep='//';

#endif

size_t sz=s.rfind(sep,s.length());

if(sz!=string::npos)

{

CFile Out;

CStringstrFilename(s.substr(i+1,s.length()-i));

if(Out.Open(%%2+"//"+strfilename,cfile::modewrite%7ccfile::modecreate)){

for(int i=1;i<=2;i++)

{

CString Filename;

Filename.Format("%s//%s%d",%%2,strfilename,atoi(i));

CFile In;

if(In.Open(Filename,CFile::modeRead)){

char cbBuffer[4096];

int nFilesize=In.GetLength();

while(nFilesize>0){

int nSize=sizeof(cbBuffer);

if(nSize>nFilesize)

nSize=nFilesize;

try{

In.Read(cbBuffer,nSize);

}

catch(CFileException *e){

char *lpMsgBuf;

if(FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER |

FORMAT_MESSAGE_FROM_SYSTEM,

NULL,e->m_lOsError,

MAKELANGID(LANG_NEUTRAL,

SUBLANG_DEFAULT),

(LPSTR)&lpMsgBuf,0,NULL)>0){

AfxMessageBox(lpMsgBuf);

LocalFree(lpMsgBuf);

}

e->Delete();

return;

}

try{

Out.Write(cbBuffer,nSize);

}

catch(CFileException *e){

char *lpMsgBuf;

if(FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER |

FORMAT_MESSAGE_FROM_SYSTEM,

NULL,e->m_lOsError,

MAKELANGID(LANG_NEUTRAL,

SUBLANG_DEFAULT),

(LPSTR)&lpMsgBuf,0,NULL)>0){

AfxMessageBox(lpMsgBuf);

LocalFree(lpMsgBuf);

}

e->Delete();

return;

}

nFilesize=nSize;

}

}

else

AfxMessageBox("不能打开"+Filename);

}

}

}

else

AfxMessageBox("不能创建输出文件");

31.文件简单加密

//#include <string>

using std::string;

string s(%%1);

char sep='/';

#ifdef _WIN32

sep='//';

#endif

size_t sz=s.rfind(sep,s.length());

CString outfile;

if(sz!=string::npos)

{

CFile Out,In;

int nFIlesize;

char *lpMsgBuf;

CStringstrFilename(s.substr(i+1,s.length()-i));

if(!in.Open(%%1,CFile::modeRead)){

//不能打开输入文件

return;

}

outfile.Format("//enc_",%%2,strfilename);

if(!Out.Open(outfile,CFile::modewrite|CFile::modeCreate)){

//不能打开输出文件

return;

}

}

nFilesize=In.GetLength();

lpBuffer=new char[nFilesize];

if(lpBuffer==NULL){

//不能分配复制缓存

return;

}

CFileStatus rStatus;

In.GetStatus(%%1,rStatus);

try{

In.Read(cbBuffer,nFilesize);

}

catch(CFileException *e){

char *lpMsgBuf;

if(FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER |

FORMAT_MESSAGE_FROM_SYSTEM,

NULL,e->m_lOsError,

MAKELANGID(LANG_NEUTRAL,

SUBLANG_DEFAULT),

(LPSTR)&lpMsgBuf,0,NULL)>0){

AfxMessageBox(lpMsgBuf);

LocalFree(lpMsgBuf);

}

e->Delete();

return;

}

for(int i=0;i<nFilesize;i++)

{

int ibt=lpBuffer[i];

ibt+=100;

ibt%=256;

bpBuffer[i]=(char)ibt;

}

try{

Out.Write(cbBuffer,nFilesize);

}

catch(CFileException *e){

char *lpMsgBuf;

if(FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER |

FORMAT_MESSAGE_FROM_SYSTEM,

NULL,e->m_lOsError,

MAKELANGID(LANG_NEUTRAL,

SUBLANG_DEFAULT),

(LPSTR)&lpMsgBuf,0,NULL)>0){

AfxMessageBox(lpMsgBuf);

LocalFree(lpMsgBuf);

}

e->Delete();

return;

}

Out.Close();

//In.Close();

CFile::SetStatus(outfile,rstatus);

delete[] lpBuffer;

}

32.文件简单解密

//#include <string>

using std::string;

string s(%%1);

char sep='/';

#ifdef _WIN32

sep='//';

#endif

size_t sz=s.rfind(sep,s.length());

CString infile;

if(sz!=string::npos)

{

CFile Out,In;

int nFIlesize;

char *lpMsgBuf;

CStringstrFilename(s.substr(i+1,s.length()-i));

infile.Format("%s//enc_%s",%%2,strfilename)

if(!in.Open(infile,CFile::moderead)){

//不能打开输入文件

return;

}

if(!Out.Open(%%1,CFile::modeWrite|CFile::modeCreate)){

//不能打开输出文件

return;

}

nFilesize=In.GetLength();

lpBuffer=new char[nFilesize];

if(lpBuffer==NULL){

//不能分配复制缓存

return;

}

CFileStatus rStatus;

In.GetStatus(infile,rstatus);

try{

In.Read(cbBuffer,nFilesize);

}

catch(CFileException *e){

char *lpMsgBuf;

if(FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM,

NULL,e->m_lOsError,

MAKELANGID(LANG_NEUTRAL,

SUBLANG_DEFAULT),

(LPSTR)&lpMsgBuf,0,NULL)>0){

AfxMessageBox(lpMsgBuf);

LocalFree(lpMsgBuf);

}

e->Delete();

return;

}

for(int i=0;i<nFilesize;i++)

{

int ibt=lpBuffer[i];

ibt-=100;ibt+=256;

ibt%=256;

bpBuffer[i]=(char)ibt;

}

try{

Out.Write(cbBuffer,nFilesize);

}

catch(CFileException *e){

char *lpMsgBuf;

if(FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM,

NULL,e->m_lOsError,

MAKELANGID(LANG_NEUTRAL,

SUBLANG_DEFAULT),

(LPSTR)&lpMsgBuf,0,NULL)>0){

AfxMessageBox(lpMsgBuf);

LocalFree(lpMsgBuf);

}

e->Delete();

return;

}

Out.Close();

//In.Close();

CFile::SetStatus(%%1,rStatus);

delete[] lpBuffer;

}

33.读取ini文件属性

CStdioFile inifile(%%1,CFile::modeRead);

CString path = inifile.GetFilePath();

inifile.Close();

char key[1024];

DWORD bytes = GetPrivateProfileString(%%2,%%3,%%4,key,1024,path);

if(bytes < 1024)

key[bytes] = '/0';

CString %%5(key);

34.合并一个目录下所有的文件

CString Directory;

Directory.Format("%s//*.*",%%1);

CFileFind FFile;

CFile Out;

if(Out.Open(%%2,CFile::modeWrite|CFile::modeCreate)){

BOOL bFound=FFile.FindFile(Directory);

while(bFound)

{

bFound=FFile.FileNextFile();

if(!FFile.IsDirectory() &&!FFile.IsDots())

{

CString Filename=FFile.GetFileName();

CFile In;

if(In.Open(Filename,CFile::modeRead)){

char cbBuffer[4096];

int nFIlesize=In.GetLength();

while(nFIlesize>0){

{

int nSize=sizeof(cbBuffer);

if(nSize>nFilesize)

nSize=nFilesize;

try {

In.Read(cbBuffer,nSize);

}

catch(CFileException *e){

char *lpMsgBuf;

if(FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER |

FORMAT_MESSAGE_FROM_SYSTEM,

NULL,e->m_lOsError,

MAKELANGID(LANG_NEUTRAL,

SUBLANG_DEFAULT),

(LPSTR)&lpMsgBuf,0,NULL)>0){

AfxMessageBox(lpMsgBuf);

LocalFree(lpMsgBuf);

}

e->Delete();

return;

}

try {

Out.Write(cbBuffer,nSize);

}

catch(CFileException *e){

char *lpMsgBuf;

if(FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM,

NULL,e->m_lOsError,

MAKELANGID(LANG_NEUTRAL,

SUBLANG_DEFAULT),

(LPSTR)&lpMsgBuf,0,NULL)>0){

AfxMessageBox(lpMsgBuf);

LocalFree(lpMsgBuf);

}

e->Delete();

return;

}

nFilesize=nSize;

}

}

else

AfxMessageBox("不能打开"+Filename);

}

}

}

}

else

AfxMessageBox("不能创建输出文件");

35.写入ini文件属性

/*

CStdioFile inifile(%%1,CFile::modeRead);

CString path = inifile.GetFilePath();

inifile.Close();

int bytes =GetPrivateProfileInt(%%2,%%3,%%4,path);

*/

WritePrivateProfileString(%%2,%%3,%%4,path);

36.获得当前路径

TCHAR szDir[MAX_PATH];

GetCurrentDirectory(MAX_PATH,szDir);

CString %%1;

%%1.Format("%s",szDir);

 

37.读取XML数据库

/*

#include <string>

using namespace std;

*/

char sRead[5192];

const char* name="Name";

const char* name2="author";

const char* root="ProductData";

const char* subNodeTag="Product";

const char* ID="pid";

//%%2="ProductData"//%%4="pid" //%%6="author"

//%%3="Product"//%%5="Name"

char sRead[5192];

CFile mFile(_T(%%1),CFile::modeRead);

mFile.Read(sRead,5192);

if(sRead!=NULL)

{

string tmp;

while(sRead!=NULL)

{

tmp.append(sRead);

mFile.Read(sRead,5192);

}

stringtarget("001"),globalTag;globalTag.append("<");globalTag.appendoot);globalTag.append(">");

stringpropTag1;propTag1.append("<");propTag1.append(name);propTag1.append(">");

string endTag1;endTag1.append("</");endTag1.append(name);endTag1.append(">");

stringpropTag2;propTag2.append("<");propTag2.append(name2);propTag2.append(">");

stringendTag2;endTag2.append("</");endTag2.append(name2);endTag2.append(">");

int offset=tmp.find_first_of(globalTag);

while(offset)

{

offset=tmp.find_first_of(globalTag);

string description;

tmp.copy(description.begin(),tmp.find_first_of("/"",offset+1)-offset);

if(target.compare(description)==0)

{

string prop,prop2;

offset=tmp.find_first_of(propTag1,offset)+strlen(name)+2;

tmp.copy(prop.begin(),tmp.find_first_of(endTag1,offset)-offset,offset);

offset=tmp.find_first_of(propTag2,offset)+strlen(name2)+2;

tmp.copy(prop2.begin(),tmp.find_first_of(endTag2,offset)-offset,offset);

//CString %%8(prop),%%9(prop2);

//%%10

return 0;

}

}

}

else

return -1;

 

38.写入XML数据库

/*

#include <string>

using namespace std;

*/

char sRead[5192];

int no;

const char* name="Name";

const char* name2="author";

const char* root="ProductData";

const char* subNodeTag="Product";

const char* ID="pid";

//%%2="ProductData"//%%4="pid" //%%6="port"

//%%3="Product"//%%5="Name" //%%7="author"

CString temp;

char sRead[5192];

string description;

CFile mFile(_T(%%1),CFile::modeRead);

mFile.Read(sRead,5192);

if(sRead!=NULL)

{

string tmp;

while(sRead!=NULL)

{

tmp.append(sRead);

memset(sRead,0,5192);

mFile.Read(sRead,5192);

}

temp.Format("<%s%s",subNodeTag,ID);

intoffset=tmp.find_last_of(temp)+strlen(subNodeTag) +strlen(ID)+4;

temp.Format("/"><%s",name);

tmp.copy(description.begin(),tmp.find_last_of(temp)-offset,offset);

no=atoi(description.c_str())+1;

mFile.Close();

temp.Format("</%s>",root);

CString temp2;

temp2.Format("<%s%s=/"%d/"><%s>%s</%s><%s>%s</%s",subNodeTag,ID,no,name,"bbbbbbbbbbbbbbbb",name,name2,"cccccccccccccc",name2);

tmp.insert(tmp.find_last_of(temp),temp2);

CFilefile(_T("Produces.xml"),CFile::modeWrite);

file.Write(tmp.c_str(),tmp.size());

file.Flush();

file.Close();

}

else

{

CFilefile(_T(%%1),CFile::modeWrite|CFile::modeCreate);

temp.Format("<?xmlversion=/"1.0/" encoding=/"gb2312/"?><%s><%s%s=/"0/"><%s>%s</%s><%s>%s</%s></%s></%s>",root,subNodeTag,ID,name,"bbbbbbbbbbbbbbbb",name,name2,"cccccccccccccc",name2,subNodeTag,root);

file.Write(temp.GetBuffer(0),temp.GetLength());

file.Flush();

file.Close();

}

 

39.ZIP压缩文件

//www.zlib.net

/*

#ifdef _DEBUG

#pragma comment(lib,"zlibd.lib")

#else

#pragma comment(lib,"zlib.lib")

#endif

#include "zlib.h"

#include "zconf.h"

*/

HANDLE hFile, hFileToWrite;

CString strFilePath;

m_ctrEdit.GetWindowText(strFilePath);

//打开要进行压缩的文件

hFile = CreateFile(strFilePath, // file name

GENERIC_READ, // open for reading

FILE_SHARE_READ, // share for reading

NULL, // no security

OPEN_EXISTING, // existing file only

FILE_ATTRIBUTE_NORMAL, // normal file

NULL

); // no attr. template

if (hFile == INVALID_HANDLE_VALUE)

{

AfxMessageBox("Could not open file toread"); // process error

return;

}

HANDLE hMapFile, hMapFileToWrite;

//创建一个文件映射

hMapFile = CreateFileMapping(hFile, // Currentfile handle.

NULL, // Default security.

PAGE_READONLY, // Read/write permission.

0, // Max. object size.

0, // Size of hFile.

"ZipTestMappingObjectForRead"

); // Name of mapping object.

if (hMapFile == NULL)

{

AfxMessageBox("Could not create filemapping object");

return;

}

LPVOID lpMapAddress, lpMapAddressToWrite;

//创建一个文件映射的视图用来作为source

lpMapAddress = MapViewOfFile(hMapFile, //Handle to mapping object.

FILE_MAP_READ, // Read/write permission

0, // Max. object size.

0, // Size of hFile.

0); // Map entire file.

if (lpMapAddress == NULL)

{

AfxMessageBox("Could not map view offile");

return;

}

DWORD dwFileLength,dwFileLengthToWrite;

dwFileLength = GetFileSize(hFile, NULL);

m_dwSourceFileLength = dwFileLength;

//因为压缩函数的输出缓冲必须比输入大0.1% + 12然后一个DWORD用来保存压缩前的大小,

//解压缩的时候用,当然还可以保存更多的信息,这里用不到

dwFileLengthToWrite =(double)dwFileLength*1.001 + 12 +sizeof(DWORD);

//以下是创建一个文件,用来保存压缩后的文件

hFileToWrite =CreateFile("demoFile.rar", // demoFile.rar

GENERIC_WRITE|GENERIC_READ, // open for writing

0, // do not share

NULL, // no security

CREATE_ALWAYS, // overwrite existing

FILE_ATTRIBUTE_NORMAL , // normal file

NULL); // no attr. template

if (hFileToWrite == INVALID_HANDLE_VALUE)

{

AfxMessageBox("Could not open file towrite"); // process error

return;

}

hMapFileToWrite =CreateFileMapping(hFileToWrite, // Current file handle.

NULL, // Default security.

PAGE_READWRITE, // Read/write permission.

0, // Max. object size.

dwFileLengthToWrite, // Size of hFile.

"ZipTestMappingObjectForWrite"); //Name of mapping object.

if (hMapFileToWrite == NULL)

{

AfxMessageBox("Could not create filemapping object for write");

return;

}

lpMapAddressToWrite =MapViewOfFile(hMapFileToWrite, //Handle to mapping object.FILE_MAP_WRITE, //Read/write permission0, // Max. object size.

0, // Size of hFile.

0

); // Map entire file.

if (lpMapAddressToWrite == NULL)

{

AfxMessageBox("Could not map view of file");

return;

}

//这里是将压缩前的大小保存在文件的第一个DWORD里面

LPVOID pBuf = lpMapAddressToWrite;

(*(DWORD*)pBuf) = dwFileLength;

pBuf = (DWORD*)pBuf + 1;

//这里就是最重要的,zlib里面提供的一个方法,将源缓存的数据压缩至目的缓存

//原形如下:

//int compress (Bytef *dest, uLongf *destLen,const Bytef*source, uLong sourceLen);

//参数destLen返回实际压缩后的文件大小。

compress((Bytef*)pBuf,&dwFileLengthToWrite,(Bytef*)lpMapAddress, dwFileLength);

UnmapViewOfFile(lpMapAddress);

CloseHandle(hMapFile);

CloseHandle(hFile);

UnmapViewOfFile(lpMapAddressToWrite);

CloseHandle(hMapFileToWrite);

//这里将文件大小重新设置一下

SetFilePointer(hFileToWrite,dwFileLengthToWrite+ sizeof(DWORD) ,NULL,FILE_BEGIN);

SetEndOfFile(hFileToWrite);

CloseHandle(hFileToWrite);

 

40.ZIP解压缩

//www.zlib.net

/*

#ifdef _DEBUG

#pragma comment(lib,"zlibd.lib")

#else

#pragma comment(lib,"zlib.lib")

#endif

#include "zlib.h"

#include "zconf.h"

*/

HANDLE hFile, hFileToWrite;

CString strFilePath=%%1;

//打开要进行解压缩的文件

hFile = CreateFile(strFilePath, // file name

GENERIC_READ, // open for reading

FILE_SHARE_READ, // share for reading

NULL, // no security

OPEN_EXISTING, // existing file only

FILE_ATTRIBUTE_NORMAL, // normal file

NULL

); // no attr. template

if (hFile == INVALID_HANDLE_VALUE)

{

AfxMessageBox("Could not open file toread"); // process error

return;

}

HANDLE hMapFile, hMapFileToWrite;

//创建一个文件映射

hMapFile = CreateFileMapping(hFile, // Currentfile handle.

NULL, // Default security.

PAGE_READONLY, // Read/write permission.

0, // Max. object size.

0, // Size of hFile.

"ZipTestMappingObjectForRead"); //Name of mapping object.

if (hMapFile == NULL)

{

AfxMessageBox("Could not create filemapping object");

return;

}

LPVOID lpMapAddress, lpMapAddressToWrite;

//创建一个文件映射的视图用来作为source

lpMapAddress = MapViewOfFile(hMapFile, //Handle to mapping

object.FILE_MAP_READ, // Read/write permission

0, // Max. object size.

0, // Size of hFile.

0); // Map entire file.

if (lpMapAddress == NULL)

{

AfxMessageBox("Could not map view offile");

return;

}

DWORD dwFileLength,dwFileLengthToWrite;

dwFileLength = GetFileSize(hFile, NULL) -sizeof(DWORD);

//因为压缩函数的输出缓冲必须比输入大0.1% + 12然后一个DWORD用来保存压缩前的大小,

//解压缩的时候用,当然还可以保存更多的信息,这里用不到

// dwFileLengthToWrite =(double)dwFileLength*1.001 + 12 +sizeof(DWORD);

dwFileLengthToWrite = (*(DWORD*)lpMapAddress);

LPVOID pSourceBuf = lpMapAddress;

pSourceBuf = (DWORD*)pSourceBuf + 1;

//以下是创建一个文件,用来保存压缩后的文件

hFileToWrite = CreateFile(%%2, // createdemo.gz

GENERIC_WRITE|GENERIC_READ, // open for writing

0, // do not share

NULL, // no security

CREATE_ALWAYS, // overwrite existing

FILE_ATTRIBUTE_NORMAL , // normal file

NULL

); // no attr. template

if (hFileToWrite == INVALID_HANDLE_VALUE)

{

AfxMessageBox("Could not open file towrite"); //process error

return;

}

hMapFileToWrite =CreateFileMapping(hFileToWrite, // Currentfile handle.

NULL, // Default security.

PAGE_READWRITE, // Read/write permission.

0, // Max. object size.

dwFileLengthToWrite, // Size of hFile.

"ZipTestMappingObjectForWrite"); //Name of mapping object.

if (hMapFileToWrite == NULL)

{

AfxMessageBox("Could not create filemapping object for write");

return;

}

lpMapAddressToWrite =MapViewOfFile(hMapFileToWrite, //Handle to mapping object.

FILE_MAP_WRITE, // Read/write permission

0, // Max. object size.

0, // Size of hFile.

0

); // Map entire file.

if (lpMapAddressToWrite == NULL)

{

AfxMessageBox("Could not map view of file");

return;

}

//这里是将压缩前的大小保存在文件的第一个DWORD里面

LPVOID pBuf = lpMapAddressToWrite;

//这里就是最重要的,zlib里面提供的一个方法,将源缓存的数据压缩至目的缓存

//原形如下:

//int compress (Bytef *dest, uLongf *destLen,const Bytef *source, uLong sourceLen);

//参数destLen返回实际压缩后的文件大小。

uncompress((Bytef*)pBuf,&dwFileLengthToWrite,(Bytef*)pSourceBuf, dwFileLength);

UnmapViewOfFile(lpMapAddress);

CloseHandle(hMapFile);

CloseHandle(hFile);

UnmapViewOfFile(lpMapAddressToWrite);

CloseHandle(hMapFileToWrite);

//这里将文件大小重新设置一下

SetFilePointer(hFileToWrite,dwFileLengthToWrite,NULL,FILE_BEGIN);

SetEndOfFile(hFileToWrite);

CloseHandle(hFileToWrite);

41.获得应用程序完整路径

char appName[MAX_PATH];

GetModuleFileName(NULL,appName,MAX_PATH);

CString %%1(appName);

 

42.递归删除目录中的文件

CString Directory(%%1);

CStringArray csa;

int count=0;

if(Directory.Right(1)!="//")

Directory+="//";

Directory+="*.*";

CFileFInd FFile;

csa.add(Directory);

while(count<csa.GetSize())

{

if(FFile.FindFile(csa.GetAt(i)))

{

bFound=FFile.FindNextFile();

if(!FFile.IsDirectory() &&!FFile.IsDots())

{

DeleteFile(FFile.GetFilePath());

}

else if(FFile.IsDirectory())

{

csa.Add(FilePath+"//*.*");

}

}

else

count++;

}

43.ZIP压缩文件夹

//www.zlib.net

/*

#include <stdio.h>

#include <string.h>

#include <assert.h>

#include <dos.h>

#include <direct.h>

#include <zlib.h>

#if defined(MSDOS) || defined(OS2) ||defined(WIN32) ||

defined(__CYGWIN__)

# include <fcntl.h>

# include <io.h>

# define SET_BINARY_MODE(file)setmode(fileno(file),O_BINARY)

#else

# define SET_BINARY_MODE(file)

#endif

#define CHUNK 16384

//#define USE_TAG

#ifdef USE_TAG

#define COMPRESS_FILE_TAG_HEAD"<<<"

#define COMPRESS_FILE_TAG_TAIL">>>"

#define COMPRESS_FILE_TAG_END_LEN 3 // must bestrlen

(COMPRESS_FILE_TAG_HEAD) =strlen(COMPRESS_FILE_TAG_TAIL)

#else

#define COMPRESS_FILE_TAG_HEAD ""

#define COMPRESS_FILE_TAG_TAIL ""

#define COMPRESS_FILE_TAG_END_LEN 0 // must bestrlen

(COMPRESS_FILE_TAG_HEAD) =strlen(COMPRESS_FILE_TAG_TAIL)

#endif

*/

/**//**//**//* Compress from file source tofile dest until EOF on source.

def() returns Z_OK on success, Z_MEM_ERROR ifemory could not be allocated for processing, Z_STREAM_ERROR if an invalidcompression

level is supplied, Z_VERSION_ERROR if theversion of zlib. And the version of the library linked do not matc, or Z_ERRNOif there isan error reading or writing the files. */

static it def(FILE *source, FILE *dest, intlevel)

int ret, flush;

unsigned have;

z_stream strm;

unsigned char in[CHUNK];

unsigned char out[CHUNK];

 

/**//**//**//* allocate deflate state */

strm.zalloc = Z_NULL;

strm.zfree = Z_NULL;

strm.opaque = Z_NULL;

ret = deflateInit(&strm, level);

if (ret != Z_OK)

return ret;

 

/**//**//**//* compress until end of file */

do {

strm.avail_in = fread(in, 1, CHUNK, source);

if (ferror(source)) {

(void)deflateEnd(&strm);

return Z_ERRNO;

}

flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;

strm.next_in = in;

 

/**//**//**//* run deflate() on input untiloutput

 

 buffernot full, finish

compression if all of source has been read in*/

do {

strm.avail_out = CHUNK;

strm.next_out = out;

ret = deflate(&strm, flush); /**//**//**//*no

 

bad return value */

assert(ret != Z_STREAM_ERROR); /**//**//**//*

 

state not clobbered */

have = CHUNK - strm.avail_out;

if (fwrite(out, 1, have, dest) != have ||ferror

 

(dest)) {

(void)deflateEnd(&strm);

return Z_ERRNO;

}

} while (strm.avail_out == 0);

assert(strm.avail_in == 0); /**//**//**//* all

 

input will be used */

 

/**//**//**//* done when last data in fileprocessed

 

*/

} while (flush != Z_FINISH);

assert(ret == Z_STREAM_END); /**//**//**//*stream

 

will be complete */

 

/**//**//**//* clean up and return */

(void)deflateEnd(&strm);

return Z_OK;

}

/**//**//**//* Decompress from file source tofile dest until stream ends or EOF. inf() returns Z_OK on success, Z_MEM_ERRORif memory could not be allocated for processing, Z_DATA_ERROR if the deflatedata is invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and theversion of the library linked do not match, or Z_ERRNO

if there is an error reading or writing thefiles. */

static int inf(FILE *source, FILE *dest)

{

int ret;

unsigned have;

z_stream strm;

unsigned char in[CHUNK];

unsigned char out[CHUNK];

 

/**//**//**//* allocate inflate state */

strm.zalloc = Z_NULL;

strm.zfree = Z_NULL;

strm.opaque = Z_NULL;

strm.avail_in = 0;

strm.next_in = Z_NULL;

ret = inflateInit(&strm);

if (ret != Z_OK)

return ret;

 

/**//**//**//* decompress until deflate streamends or end

 

of file */

do {

strm.avail_in = fread(in, 1, CHUNK, source);

if (ferror(source)) {

(void)inflateEnd(&strm);

return Z_ERRNO;

}

if (strm.avail_in == 0)

break;

strm.next_in = in;

 

/**//**//**//* run inflate() on input untiloutput

 

buffer not full */

do {

strm.avail_out = CHUNK;

strm.next_out = out;

ret = inflate(&strm, Z_NO_FLUSH);

assert(ret != Z_STREAM_ERROR); /**//**//**//*

 

state not clobbered */

switch (ret) {

case Z_NEED_DICT:

ret = Z_DATA_ERROR; /**//**//**//* and

 

fall through */

case Z_DATA_ERROR:

case Z_MEM_ERROR:

(void)inflateEnd(&strm);

return ret;

}

have = CHUNK - strm.avail_out;

if (fwrite(out, 1, have, dest) != have ||ferror

 

(dest)) {

(void)inflateEnd(&strm);

return Z_ERRNO;

}

} while (strm.avail_out == 0);

 

/**//**//**//* done when inflate() says it'sdone */

} while (ret != Z_STREAM_END);

 

/**//**//**//* clean up and return */

(void)inflateEnd(&strm);

return ret == Z_STREAM_END ? Z_OK :Z_DATA_ERROR;

}

/**//**//**//* report a zlib or i/o error */

static void zerr(int ret)

{

fputs("zpipe: ", stderr);

switch (ret) {

case Z_ERRNO:

if (ferror(stdin))

fputs("error reading stdin ",stderr);

if (ferror(stdout))

fputs("error writing stdout ",stderr);

break;

case Z_STREAM_ERROR:

fputs("invalid compression level ",stderr);

break;

case Z_DATA_ERROR:

fputs("invalid or incomplete deflate data", stderr);

break;

case Z_MEM_ERROR:

fputs("out of memory ", stderr);

break;

case Z_VERSION_ERROR:

fputs("zlib version mismatch! ",stderr);

}

}

//以上就是zpipe.c的几个主要函数:def()inf()zerr()def()是压缩函数,主要使用了zlibdeflate()接口;inf()是压缩函数,主要使用了zlibinflate()接口;zerr()是错误打印函数。

static int write_zfile_file_header(const char*file,FILE *zfile)

{

int len;

len = strlen(file);

if (fwrite(COMPRESS_FILE_TAG_HEAD, 1,COMPRESS_FILE_TAG_END_LEN,zfile) != COMPRESS_FILE_TAG_END_LEN || ferror(zfile))

{

fprintf(stderr,"When writing file or dirheader to zfile: write error. ");

return 1;

}

if (fwrite(file, 1, len, zfile) != len||ferror(zfile))

{

fprintf(stderr,"When writing file or dirheader to zfile: write error. ");

return 1;

}

if (fwrite(COMPRESS_FILE_TAG_TAIL,1,COMPRESS_FILE_TAG_END_LEN, zfile) != COMPRESS_FILE_TAG_END_LEN ||ferror(zfile))

{

fprintf(stderr,"When writing file or dirheader to

 

zfile: write error. ");

 return1;

}

return 0;

}

/**//* compress or decompress from stdin tostdout */

static int compress_dir(char *file_in,FILE*fd_out)

{

FILE *fd_in;

struct _finddata_t find_data;

char file[128];

long lf;

int ret;

write_zfile_file_header(file_in,fd_out);

sprintf(file,"%s%s",file_in,"/*");

if((lf = _findfirst(file,&find_data))==-1l) // LOOKOUT:not eleven, but one andlowercase 'L'

{

fprintf(stdout,"file not found. ");

}

else

{

do

{

if(!strcmp(find_data.name,".") ||!strcmp(find_data.name,".."))

continue;

fprintf(stdout,"%s",find_data.name);

sprintf(file,"%s%s%s",file_in,"/",find_data.name);

if(find_data.attrib & _A_SUBDIR)

{

fprintf(stdout," ---directory--- ");

ret = compress_dir(file,fd_out);

}

else

{

write_zfile_file_header(file,fd_out);

if(access(file, 2) != 0) //W_OK=2

{

int attrib;

attrib = _chmod(file,0);

_chmod(file,1,attrib & ~_A_RDONLY);

fprintf(stderr,"When writing file: Noprivilege to write file %s. ",file);

return -1;

}

fd_in = fopen(file,"rb+");

SET_BINARY_MODE(fd_in);

ret = def(fd_in, fd_out,Z_DEFAULT_COMPRESSION);

if (ret != Z_OK)

zerr(ret);

else

fprintf(stdout," zip over ");

fclose(fd_in);

}

}while( _findnext(lf, &find_data ) == 0 );

}

return 0;

}

//int argc, char **argv

struct _finddata_t find_data;

FILE *fd_in;

FILE *fd_out;

const char *file_dir;

char file_out[100];

int ret;

if (argc == 2)

{

file_dir = argv[1];

if(_findfirst(file_dir,&find_data)==-1l) //LOOKOUT: not eleven, but one andlowercase 'L'

{

fprintf(stderr,"File or dir %s notfound.",file_dir);

return 1;

}

if(find_data.attrib & _A_SUBDIR)

{

sprintf(file_out,"%s%s",file_dir,".z");

fd_out = fopen(file_out,"wb+");

SET_BINARY_MODE(fd_out);

fprintf(stdout,"Dir %s being Compressed...",file_dir);

ret = compress_dir(file_dir,fd_out);

fclose(fd_out);

}

else

{

fprintf(stdout,"File %s being Compressed...",file_dir);

sprintf(file_out,"%s%s",file_dir,".z");

fd_in = fopen(file_dir,"rb+");

fd_out = fopen(file_out,"wb+");

SET_BINARY_MODE(fd_in);

SET_BINARY_MODE(fd_out);

ret = def(fd_in, fd_out,Z_DEFAULT_COMPRESSION);

fclose(fd_in);

fclose(fd_out);

}

if (ret != 0)

{

fprintf(stderr,"Compress Error!!!!!!!!!!!!!! ");

zerr(ret);

}

else

fprintf(stdout,"Compress OK---------------");

}

else {

fprintf(stdout,"zod usage: zod[file]/[directory] ");

}

getch();

 

44.验证DTD

/*

#include <stdexcept> // runtime_error

#include<xercesc/sax2/DefaultHandler.hpp>

*/

using namespace std;

using namespace xercesc;

try {

// Initialize Xerces and obtain a SAX2 parser

XercesInitializer init;

auto_ptr<SAX2XMLReader>

parser(XMLReaderFactory::createXMLReader());

// Enable validation

parser->setFeature(XMLUni::fgSAX2CoreValidation,true);

// Register error handler to receivenotifications

// of DTD violations

CircusErrorHandler error;

parser->setErrorHandler(&error);

parser->parse("animals.xml");

} catch (const SAXException& e) {

cout << "xml error: " <<toNative(e.getMessage()) << "/n";

return EXIT_FAILURE;

} catch (const XMLException& e) {

cout << "xml error: " <<toNative(e.getMessage()) << "/n";

return EXIT_FAILURE;

} catch (const exception& e) {

cout << e.what() << "/n";

return EXIT_FAILURE;

}

45.Schema验证

/*

#include<xercesc/sax2/XMLReaderFactory.hpp>

#include <xercesc/sax2/SAX2XMLReader.hpp>

#include<xercesc/sax2/DefaultHandler.hpp>

Handy definitions of constants.

#include <xercesc/util/XMLUni.hpp>

Create a SAX2 parser object.

*/

SAX2XMLReader* parser =XMLReaderFactory::createXMLReader();

// Set the appropriate features on the parser.Enable namespaces, schema validation, and the checking of all Schemaconstraints. We refer to these as "common features" in followingexamples.

parser->setFeature(XMLUni::fgSAX2CoreNameSpaces,true);

parser->setFeature(XMLUni::fgSAX2CoreValidation,true);

parser->setFeature(XMLUni::fgXercesDynamic,false);

parser->setFeature(XMLUni::fgXercesSchema,true);

parser->setFeature(XMLUni::fgXercesSchemaFullChecking,true);

// Set appropriate ContentHandler,ErrorHandler, and EntityResolver.

// These will be referred to as "commonhandlers" in subsequent examples.

// You will use a default handler provided byXerces-C++ (no op action).

// Users should write their own handlers andinstall them.

DefaultHandler handler;

parser->setContentHandler(&handler);

// The object parser calls when it detectsviolations of the schema.

parser->setErrorHandler(&handler);

// The object parser calls to find the schemaand

// resolve schema imports/includes.

parser->setEntityResolver(&handler);

// Parse the XML document.

// Document content sent to registeredContentHandler instance.

parser->parse(xmlFile);

// Delete the parser instance.

delete parser;

46.Grep

/*

#include<string>

#include "regexpr2.h"

using namespace std;

using namespace regex;

*/

match_results results;

rpattern pat(%%2);

char sRead[5120];

CFile mFile(_T(%%1),CFile::modeRead);

CString content;

while(sRead!=NULL)

{

mFile.Read(sRead,5120);

content+=CString(sRead);

}

mFile.Close();

CString line;

CString sub;

char seperator='/n';

for(intpos=0;AfxExtractSubString(line,content,pos,seperator);++pos)

{

if(line.Trim()!="")

{

string str(line);

match_results::backref_typebr=pat.match(str,results);

if(br.matched){

//br

}

}

}

/*

//+---------------------------------------------------------------------------

//

// Copyright ( C ) Microsoft, 1994 - 2002.

//

// File: restack.h

//

// Functions: a quick-'n'-dirty, type-unsafestack used by the iterative

// regular expression algorithm

//

// Notes: Care must be taken when using thisstack. You must pop off

// the correct type of object, otherwise youget garbage. Also,

// if you push anything that has a non-trivialdestructor, then

// be sure to explicitely pop everything offthe stack and don't

// use the unsafe_long_jump method.

//

// Author: Eric Niebler ( ericne@microsoft.com)

//

// History: 11/15/2001 ericne Created

//

//----------------------------------------------------------------------------

#ifndef HETERO_STACK_H

#define HETERO_STACK_H

#include <string>

#include <utility>

#include <typeinfo>

#include <stdexcept>

#include <functional>

#ifndef REGEX_CDECL

#ifdef _MSC_VER

#define REGEX_CDECL __cdecl

#else

#define REGEX_CDECL

#endif

#endif

#define COMMA ,

#if !defined(_MSC_VER) | 1200 < _MSC_VER

# define REGEX_VC6(x)

# define REGEX_NVC6(x) x

#else

# define REGEX_VC6(x) x

# define REGEX_NVC6(x)

#endif

namespace regex

{

namespace detail

{

// For compile-time assertions that generate

// no run-time overhead.

template< bool f > struct static_assert;

template<> structstatic_assert<true> { static_assert() {} };

// Work-around for a template-templateparameter problem on VC7.0

template< typename T > struct type2type {typedef T type; };

template< bool F > struct bool2type {enum { value = F }; };

typedef bool2type<true> true_t;

typedef bool2type<false> false_t;

#ifdef _MSC_VER

// warning C4127: conditional expression isconstant

// warning C4189: local variable is initializedbut not referenced

// warning C4244: conversion from 'T' to 'int',possible loss of data

// warning C4510: default constructor could notbe generated

// warning C4610: struct can never beinstantiated - user defined constructor required

// warning C4800: forcing value to bool 'true'or 'false' (performance warning)

#pragma warning( push )

#pragma warning( disable : 4127 4189 4244 45104610 4800 )

// Make sure nobody has tampered with thepacking before defining the

// alignof structure

#pragma pack( push )

#pragma pack() // use the default packing

#endif

template< typename T >

class alignof

{

struct helper

{

helper();

char m_c;

T m_t;

};

public:

enum { value = sizeof(helper)-sizeof(T) <sizeof(T) ? sizeof(helper)-sizeof(T) : sizeof(T) };

};

#ifdef _MSC_VER

#pragma pack( pop )

#endif

//

// Type traits

//

typedef char (&yes_type)[1];

typedef char (&no_type)[2];

template< bool >

struct select_helper

{

template< typename T, typename U >

struct nested

{

typedef T type;

};

};

template<>

struct select_helper<false>

{

template< typename T, typename U >

struct nested

{

typedef U type;

};

};

// For use in conditional typedefs

template< bool F, typename T, typename U>

struct select

{

typedef typenameselect_helper<F>::template nested<T,U>::type type;

};

template< typename U >

struct convertible_helper

{

static yes_type check( U );

static no_type REGEX_CDECL check(...);

};

template< typename T >

struct factory

{

static T& make();

};

template< typename T, typename U >

struct is_convertible

{

enum { value =(sizeof(convertible_helper<U>::check(factory<T>::make()))==sizeof(yes_type))};

};

template< size_t N >

struct is_power_of_two

{

enum { value = 1==N || 0==(N%2) &&is_power_of_two<N/2>::value };

};

template<>

struct is_power_of_two<0>

{

enum { value = false };

};

// Very primative implementation of is_scalar.This doesn't work

// for void, reference types, array types orfunction types, but

// we don't use those types from hetero_stack.

struct bool_convertible {bool_convertible(bool); };

template< typename T >

struct is_scalar

{

enum { value =is_convertible<T,bool_convertible>::value };

};

template< typename T >

struct has_trivial_copy

{

enum { value = is_scalar<T>::value };

};

template< typename T >

struct has_trivial_assignment

{

enum { value = is_scalar<T>::value };

};

template< typename T >

struct has_trivial_destructor

{

enum { value = is_scalar<T>::value };

};

template< bool > struct destroyer_helper

{

template< typename T >

static void destroy( T const * pT )

{

pT, pT->~T();

}

};

template<> structdestroyer_helper<true>

{

template< typename T >

static void destroy( T const * )

{

}

};

template< typename T >

void destroy( T const * pT )

{

destroyer_helper<has_trivial_destructor<T>::value>::destroy(pT );

}

struct type_vtable

{

std::type_info const * typeinfo_ptr;

size_t size;

size_t aligned_size;

void (*destroy)( void * );

void (*copy)( void *, void const * );

};

template< typename T, size_t AlignmentT >

class type_info_ex

{

static void destroy( void * pv )

{

T const * pT = static_cast<T const*>( pv);

regex::detail::destroy( pT );

(void)pv;

(void)pT;

}

static void copy( void * dst, void const * src)

{

new ( dst ) T( *static_cast<T const *>(src ) );

}

public:

static type_vtable const vtable;

static bool equals( type_vtable const * ptm )

{

return ptm == & vtable ||*ptm->typeinfo_ptr == typeid(T);

}

};

template< typename T,size_t AlignmentT >

type_vtable consttype_info_ex<T,AlignmentT>::vtable =

{

&typeid(T),

sizeof(T),

( sizeof(T) + AlignmentT - 1 ) & ~(AlignmentT - 1 ),

has_trivial_destructor<T>::value ? 0 :&type_info_ex<T,AlignmentT>::destroy,

&type_info_ex<T,AlignmentT>::copy

};

template< typename T >

inline T & to_type( void * pv )

{

return *static_cast<T*>( pv );

}

} // namespace detail

//--------------------------------------------------------------------------

//

// Class: hetero_stack

//

// Description: Fast, heterogeneous stack.

//

// Methods: allocate - reserve space on stack

// unwind - unwind the stack

// hetero_stack - c'tor

// ~hetero_stack - d'tor, release all dynamicmemory

// push - push an object on the stack

// pop - pop an object from the stack

//

// Members: m_first_node -

// m_current_node -

//

// Typedefs: byte_t -

//

// History: 10/19/2001 - ericne - Created

//

//--------------------------------------------------------------------------

template

size_t AlignmentT = sizeof(void*),

bool RuntimeTypeCheckT = true, // should weperform run-time type checking?

bool AssumePodT = false, // assume non-throwingcopy/assign/destroy for better perf

size_t DynamicBlockSizeT = 4096, // blocksallocated from heap are this size

size_t StaticBlockSizeT = 1024 // initial blockon stack is this size

class hetero_stack

{

typedef unsigned char byte_t;

typedef detail::type_vtable const* vtable_ptr;

public:

typedefhetero_stack<AlignmentT,RuntimeTypeCheckT,AssumePodT,DynamicBlockSizeT,StaticBlockSizeT>stack_type;

template< typename T >

struct aligned_sizeof

{

enum

{

// round up sizeof(T) to the nearest multipleof AlignmentT

no_rtti = ( sizeof( T ) + AlignmentT - 1 )& ~( AlignmentT - 1 ),

with_rtti = RuntimeTypeCheckT ?

no_rtti +aligned_sizeof<vtable_ptr>::no_rtti :

no_rtti

};

};

private:

struct stack_node

{

struct header

{

stack_node * m_back;

stack_node * m_next;

byte_t * m_current; // ptr into m_mem. allocfrom here

byte_t * m_end; // ptr to last+1 byte_t inm_mem

};

union

{

header m_head;

byte_t m_align[ aligned_sizeof<header>::no_rtti];

};

// This is the buffer into which values will bepushed and popped.

// It is guaranteed to meet the AlignmentTrequirements because of

// the union above.

byte_t m_mem[1];

size_t size() const // throw()

{

return static_cast<size_t>( m_head.m_end- m_mem );

}

};

enum

{

DYNAMIC_BLOCK_SIZE =

DynamicBlockSizeT > sizeof( stack_node ) ?

DynamicBlockSizeT : sizeof( stack_node )

};

union

{

stack_node m_node;

byte_t m_buf[aligned_sizeof<stack_node::header>::no_rtti + StaticBlockSizeT ];

} m_first_node;

stack_node * m_current_node;

// Cache these for faster access

byte_t * m_begin;

byte_t * m_current;

byte_t * m_end;

byte_t * grow( size_t size ) //throw(std::bad_alloc)

{

// write the cached value of current into thenode.

// OK to do this even if later statementsthrow.

m_current_node->m_head.m_current =m_current;

// Do we have a node with available memoryalready?

if( m_current_node->m_head.m_next )

{

// Does this node have enough room?

if( size <=m_current_node->m_head.m_next->size() )

{

m_current_node =m_current_node->m_head.m_next;

m_current = m_current_node->m_head.m_current= m_current_node->m_mem + size;

m_end = m_current_node->m_head.m_end;

return m_begin = m_current_node->m_mem;

}

// Create a new node and insert it into thelist

stack_node * new_node =static_cast<stack_node*>(

::operator new( size + offsetof( stack_node,m_mem ) ) );

new_node->m_head.m_back = m_current_node;

new_node->m_head.m_next =m_current_node->m_head.m_next;

m_current = m_end =new_node->m_head.m_current =

new_node->m_head.m_end = new_node->m_mem+ size;

m_current_node->m_head.m_next->m_head.m_back= new_node;

m_current_node->m_head.m_next = new_node;

m_current_node = new_node;

return m_begin = m_current_node->m_mem;

}

// We need to create a new node from scratch

size_t new_size = detail::regex_max( size,

static_cast<size_t>(DYNAMIC_BLOCK_SIZE) -offsetof( stack_node, m_mem ) );

stack_node * new_node =static_cast<stack_node*>(

::operator new( new_size + offsetof(stack_node, m_mem ) ) );

new_node->m_head.m_back = m_current_node;

new_node->m_head.m_next = 0;

m_current = new_node->m_head.m_current =new_node->m_mem + size;

m_end = new_node->m_head.m_end =new_node->m_mem + new_size;

m_current_node->m_head.m_next = new_node;

m_current_node = new_node;

return m_begin = m_current_node->m_mem;

}

byte_t * allocate( size_t size ) //throw(std::bad_alloc)

{

// This is the ptr to return

byte_t * mem = m_current;

// Advance the high-water mark

m_current += size;

// Check to see if we have overflowed thisbuffer

if( std::less<void*>()( m_end, m_current) ) // if( m_end < m_current )

{

// oops, back this out.

m_current = mem;

// allocate a new block and return a ptr to thenew memory

return grow( size );

}

return mem;

}

byte_t * unwind( byte_t * pb ) // throw()

{

// roll back the stack

m_current = pb;

// If we've unwound this whole block, then makethe

// previous node the current node

if( m_current == m_begin )

{

// write the cached value of m_current intom_current_node

m_current_node->m_head.m_current =m_current;

m_current_node =m_current_node->m_head.m_back;

// update the cache

m_begin = m_current_node->m_mem;

m_current =m_current_node->m_head.m_current;

m_end = m_current_node->m_head.m_end;

}

return pb;

}

byte_t * unwind( size_t size ) // throw()

{

return unwind( m_current - size );

}

void long_jump_impl( void * jump_ptr,detail::bool2type<true> ) // throw()

{

safe_long_jump( jump_ptr );

}

void long_jump_impl( void * jump_ptr,detail::bool2type<false> ) // throw()

{

unsafe_long_jump( jump_ptr );

}

struct real_unwinder;

friend struct real_unwinder;

struct real_unwinder

{

real_unwinder( stack_type * pstack, size_t size) // throw()

: m_pstack(pstack), m_size(size) {}

~real_unwinder() // throw()

{

if( m_pstack )

m_pstack->unwind( m_size );

}

void dismiss() // throw()

{

m_pstack = 0;

}

private:

real_unwinder( real_unwinder const & );

real_unwinder & operator=( real_unwinderconst & );

stack_type * m_pstack;

size_t m_size;

};

struct dummy_unwinder

{

dummy_unwinder( stack_type *, size_t ) {} //throw()

void dismiss() {} // throw()

};

// Disallow these for now. Might implement themlater.

hetero_stack( hetero_stack const & );

hetero_stack & operator=( hetero_stackconst & );

public:

class type_error : public std::logic_error

{

std::type_info const * m_prequested_type;

std::type_info const * m_pactual_type;

public:

type_error

(

std::type_info const & requested_type,

std::type_info const & actual_type,

std::string const & s = "type error inhetero_stack"

) // throw()

: std::logic_error( s + " (requested type:" + requested_type.name()

+ ", actual type: " +actual_type.name() + ")" )

, m_prequested_type( &requested_type )

, m_pactual_type( &actual_type )

{

}

std::type_info const & requested_type()const // throw()

{

return *m_prequested_type;

}

std::type_info const & actual_type() const// throw()

{

return *m_pactual_type;

}

};

hetero_stack() // throw()

: m_current_node( &m_first_node.m_node )

{

m_first_node.m_node.m_head.m_back = &m_first_node.m_node;

m_first_node.m_node.m_head.m_next = 0;

m_begin = m_current =m_first_node.m_node.m_head.m_current = m_first_node.m_node.m_mem;

m_end = m_first_node.m_node.m_head.m_end =m_first_node.m_buf + sizeof( m_first_node );

}

~hetero_stack() // throw()

{

// AlignmentT must be a power of two

detail::static_assert<detail::is_power_of_two<AlignmentT>::value > const align_test;

// Call any destructors for objects still onthe stack

if( RuntimeTypeCheckT && ! AssumePodT )

{

long_jump( m_first_node.m_node.m_mem );

}

// delete all the memory blocks

m_current_node =m_first_node.m_node.m_head.m_next;

for( stack_node * next_node; m_current_node;m_current_node = next_node )

{

next_node = m_current_node->m_head.m_next;

::operator delete( static_cast<void*>(m_current_node ) );

}

}

template< typename T >

inline void push( T const & t ) //throw(std::bad_alloc,...)

{

// Make sure that the alignment for type T isnot worse

// than our declared alignment.

detail::static_assert<( AlignmentT >=detail::alignof<T>::value )> const align_test;

static_cast<void>(align_test);

// If T won't throw in copy c'tor then we don'tneed to use an unwinder object.

typedef typename detail::select< AssumePodT|| detail::has_trivial_copy<T>::value,

dummy_unwinder, real_unwinder >::typeunwinder;

// If this throws, it doesn't change state,

// so there is nothing to roll back.

byte_t * pb = allocate(aligned_sizeof<T>::with_rtti );

// Rolls back the allocate if later steps throw

// BUGBUG we can do the alloc, but not updatem_current until after

// the copy c'tor to avoid the need for anunwinder object

unwinder guard( this, aligned_sizeof<T>::with_rtti);

new ( pb ) T( t ); // Could throw if !has_trivial_copy<T>::value

// If we are debugging the stack, then push apointer to the type_info

// for this type T. It will be checked inpop().

if( RuntimeTypeCheckT )

{

detail::to_type<vtable_ptr>( pb +aligned_sizeof<T>::no_rtti ) = &detail::type_info_ex<T,AlignmentT>::vtable;

}

// ok, everything succeeded -- dismiss theguard

guard.dismiss();

}

template< typename T >

inline void pop( T & t ) // throw(...)

{

detail::static_assert<( AlignmentT >= detail::alignof<T>::value)> const align_test;

static_cast<void>(align_test);

// If we are debugging the stack, then inpush() we pushed a pointer

// to the type_info struct for this type T.Check it now.

if( RuntimeTypeCheckT )

{

byte_t * pti = m_current -aligned_sizeof<vtable_ptr>::no_rtti;

if( !detail::type_info_ex<T,AlignmentT>::equals(detail::to_type<vtable_ptr>( pti ) ) )

throw type_error( typeid( T ),*detail::to_type<vtable_ptr>( pti )->typeinfo_ptr );

}

// Don't change state yet because assignment opcould throw!

byte_t * pT = m_current -aligned_sizeof<T>::with_rtti;

t = detail::to_type<T const>( pT ); //could throw

T const & ref = detail::to_type<Tconst>( pT );

regex::detail::destroy( &ref );

unwind( pT );

}

// Call this version of pop when you don't needthe popped value

template< typename T >

inline void pop(REGEX_VC6(detail::type2type<T> COMMA int) ) // throw(type_error,...)

{

detail::static_assert<( AlignmentT >=detail::alignof<T>::value )> const align_test;

static_cast<void>(align_test);

// If we are debugging the stack, then inpush() we pushed a pointer

// to the type_info struct for this type T.Check it now.

if( RuntimeTypeCheckT )

{

byte_t * pti = m_current -aligned_sizeof<vtable_ptr>::no_rtti;

if( ! detail::type_info_ex<T,AlignmentT>::equals(detail::to_type<vtable_ptr>( pti ) ) )

throw type_error( typeid( T ),*detail::to_type<vtable_ptr>( pti )->typeinfo_ptr );

}

byte_t * pv = unwind(aligned_sizeof<T>::with_rtti );

T const & ref = detail::to_type<Tconst>( pv );

regex::detail::destroy( &ref );

}

// Call this version of pop when you don't needthe popped value and

// throwing an exception isn't an option

template< typename T >

inline bool pop( std::nothrow_t const & )// throw()

{

detail::static_assert<( AlignmentT >=detail::alignof<T>::value )> const align_test;

static_cast<void>(align_test);

// If we are debugging the stack, then inpush() we pushed a pointer

// to the type_info struct for this type T.Check it now.

if( RuntimeTypeCheckT )

{

byte_t * pti = m_current - aligned_sizeof<vtable_ptr>::no_rtti;

if( !detail::type_info_ex<T,AlignmentT>::equals(detail::to_type<vtable_ptr>( pti ) ) )

return false; // type error, can't throw sobail.

}

byte_t * pv = unwind(aligned_sizeof<T>::with_rtti );

T const & ref = detail::to_type<T const>(pv );

regex::detail::destroy( &ref );

return true;

}

template< typename T >

inline T & top(REGEX_VC6(detail::type2type<T>) ) const // throw(type_error,...)

{

detail::static_assert<( AlignmentT >=detail::alignof<T>::value )> const align_test;

static_cast<void>(align_test);

if( RuntimeTypeCheckT )

{

// If we are debugging the stack, then the topof the stack is a

// pointer to a type_info struct. Assert thatwe have the correct type.

byte_t * pti = m_current -aligned_sizeof<vtable_ptr>::no_rtti;

if( !detail::type_info_ex<T,AlignmentT>::equals(detail::to_type<vtable_ptr>( pti ) ) )

throw type_error( typeid( T ),*detail::to_type<vtable_ptr>( pti )->typeinfo_ptr );

}

byte_t * pT = m_current -aligned_sizeof<T>::with_rtti;

return detail::to_type<T>( pT );

}

// Fetch the type_info for the element at thetop of the stack

std::type_info const & top_type() const //throw()

{

detail::static_assert< RuntimeTypeCheckT> const type_check;

static_cast<void>(type_check);

byte_t * pti = m_current - aligned_sizeof<vtable_ptr>::no_rtti;

return *detail::to_type<vtable_ptr>( pti)->typeinfo_ptr;

}

// Get a pointer to the top of the stack

void * set_jump() const // throw()

{

return m_current;

}

// Quick and dirty stack unwind. Does not calldestructors.

void unsafe_long_jump( void *const jump_ptr )// throw()

{

for( ;; )

{

if( std::less<void*>()( jump_ptr,m_current_node->m_mem ) ||

std::less<void*>()(m_current_node->m_head.m_end, jump_ptr ) )

{

m_current_node->m_head.m_current =m_current_node->m_mem;

m_current_node =m_current_node->m_head.m_back;

}

else

{

m_begin = m_current_node->m_mem;

m_current = m_current_node->m_head.m_current= static_cast<byte_t*>( jump_ptr );

m_end = m_current_node->m_head.m_end;

return;

}

}

}

// Safe long jump; does call destructors ifRuntimeTypeCheckT is true.

void safe_long_jump( void *const jump_ptr ) //throw()

{

detail::static_assert< RuntimeTypeCheckT> const type_check;

static_cast<void>(type_check);

while( m_current != jump_ptr )

{

// The top of the stack is a pointer to atype_vtable struct.

m_current -=aligned_sizeof<vtable_ptr>::no_rtti;

vtable_ptr pvtable =detail::to_type<vtable_ptr>( m_current );

// find the start of the object

m_current -= pvtable->aligned_size;

// call the destructor for T

if( pvtable->destroy )

{

pvtable->destroy( m_current );

}

// move to the previous buffer if necessary

if( m_current == m_begin && m_current!= jump_ptr )

{

m_current_node->m_head.m_current =m_current;

m_current_node =m_current_node->m_head.m_back;

m_begin = m_current_node->m_mem;

m_current =m_current_node->m_head.m_current;

m_end = m_current_node->m_head.m_end;

}

}

}

// Stack unwind. If RuntimeTypeCheckT&& !AssumePodT, then destructors

// are called. Otherwise they are not.

void long_jump( void * jump_ptr ) // throw()

{

long_jump_impl( jump_ptr,detail::bool2type<RuntimeTypeCheckT && !AssumePodT>() );

}

struct stack_guard

{

stack_type * m_ps;

void * m_jump_ptr;

explicit stack_guard( stack_type * ps )

: m_ps( ps )

, m_jump_ptr( ps->set_jump() )

{

}

~stack_guard()

{

m_ps->long_jump( m_jump_ptr );

}

};

bool empty() const // throw()

{

return m_current == m_first_node.m_node.m_mem;

}

// Use scoped_push for automaticallypushing/popping

// things to and from the stack. This isespecially useful

// if you want to push a bunch of things"atomically". For

// instance:

//

// typedef hetero_stack<>::scoped_popscoped_pop;

// scoped_pop p1 = stack.scoped_push( int(1) );// could throw

// scoped_pop p2 = stack.scoped_push(std::string("foo") ); // could throw

// stack.push( float(3.14159) ); // could throw

// p2.dismiss(); // ok, nothing threw, so ...

// p1.dismiss(); // ... dismiss the scoped_pops

//

// If p2 and p1 are not dismissed, as in thecase when an

// exception gets thrown, then theyautomatically pop their

// arguments from the stack.

class scoped_pop_base

{

scoped_pop_base & operator=(scoped_pop_base const & ); // disallow assignment

protected:

mutable stack_type * m_pstack;

explicit scoped_pop_base( stack_type * pstack )// throw(std::bad_alloc,...)

: m_pstack( pstack )

{

}

scoped_pop_base( scoped_pop_base const &right ) // throw() // destructive copy

: m_pstack( right.m_pstack )

{

right.dismiss();

}

public:

void dismiss() const // throw()

{

m_pstack = 0;

}

};

template< typename T >

class scoped_pop_t : public scoped_pop_base

{

scoped_pop_t & operator=( scoped_pop_tconst & ); // disallow assignment

public:

scoped_pop_t( stack_type * pstack, T const& t ) // throw(std::bad_alloc,...)

: scoped_pop_base( pstack )

{

// Note that if this throws an exception thedestructor

// will not get called, which is what we want.

m_pstack->push( t );

}

~scoped_pop_t() // throw()

{

// If we own this stack space, pop it.

if( m_pstack )

m_pstack->template pop<T>(std::nothrow );

}

};

template< typename T >

scoped_pop_t<T> scoped_push( T const& t ) // throw(...)

{

return scoped_pop_t<T>( this, t );

}

typedef scoped_pop_base const & scoped_pop;

};

#ifdef _MSC_VER

#pragma warning( pop )

#endif

} // namespace regex

#endif

//+---------------------------------------------------------------------------

//

// Copyright ( C ) Microsoft, 1994 - 2002.

//

// File: syntax2.h

//

// Contents: syntax modules for regexpr

//

// Classes: perl_syntax, posix_syntax

//

// Author: Eric Niebler ( ericne@microsoft.com)

//

// History: 3-29-00ericne Created

//

//----------------------------------------------------------------------------

#ifndef SYNTAX_H

#define SYNTAX_H

#ifdef _MSC_VER

#pragma warning( push )

// warning C4786: identifier was truncated to'255' characters in the debug information

#pragma warning( disable : 4786 )

#endif

#include <map>

#include <iosfwd>

#include <string>

#include <cctype>

#include <cwctype>

#include <cassert>

#include <iterator>

#include <stdexcept>

#ifndef ARRAYSIZE

# define ARRAYSIZE( a )(sizeof(a)/sizeof((a)[0]))

#endif

#ifndef UCHAR_MAX

# define UCHAR_MAX 0xff

#endif

#ifndef WCHAR_MAX

# define WCHAR_MAX ((wchar_t)-1)

#endif

#ifdef _MSC_VER

# include <crtdbg.h>

# define REGEX_ASSERT(x) _ASSERTE(x)

# define REGEX_FORCEINLINE __forceinline

# define REGEX_SELECTANY __declspec(selectany)

# define REGEX_CDECL __cdecl

# define REGEX_SEH_TRY __try

# define REGEX_SEH_EXCEPT(x) __except( x )

# define REGEX_RESET_STK_OFLW() _resetstkoflw()

# if 1200 < _MSC_VER

# define REGEX_NOINLINE __declspec(noinline)

# define REGEX_DEPRECATED__declspec(deprecated)

# define REGEX_DEPENDENT_TYPENAME typename

# else

# define REGEX_NOINLINE

# define REGEX_DEPRECATED

# define REGEX_DEPENDENT_TYPENAME

# endif

#else

# include <cassert>

# define REGEX_ASSERT(x) assert(x)

# define REGEX_NOINLINE

# define REGEX_FORCEINLINE inline

# define REGEX_SELECTANY

# define REGEX_CDECL

# define REGEX_SEH_TRY

# define REGEX_SEH_EXCEPT(x) if( false )

# define REGEX_RESET_STK_OFLW() ((void)0)

# define REGEX_DEPRECATED

# define REGEX_DEPENDENT_TYPENAME typename

#endif

#define REGEX_STRING(CharT,sz) (::regex::detail::literal<CharT>::string(sz, L##sz ))

#define REGEX_CHAR(CharT,ch)(static_cast<CharT>(::regex::detail::literal<CharT>::templatecharacter<ch,L##ch>::value))

#if defined(_MSC_VER) & _CPPLIB_VER <=310

namespace std

{

template<>

struct iterator_traits< char * >

{ // get traits from iterator _Iter

typedef random_access_iterator_tagiterator_category;

typedef char value_type;

typedef ptrdiff_t difference_type;

typedef difference_type distance_type; //retained

typedef char * pointer;

typedef char & reference;

};

template<>

struct iterator_traits< char const * >

{ // get traits from iterator _Iter

typedef random_access_iterator_tagiterator_category;

typedef char value_type;

typedef ptrdiff_t difference_type;

typedef difference_type distance_type; //retained

typedef char * pointer;

typedef char & reference;

};

template<>

struct iterator_traits< wchar_t * >

{ // get traits from iterator _Iter

typedef random_access_iterator_tagiterator_category;

typedef wchar_t value_type;

typedef ptrdiff_t difference_type;

typedef difference_type distance_type; //retained

typedef wchar_t * pointer;

typedef wchar_t & reference;

};

template<>

struct iterator_traits< wchar_t const * >

{ // get traits from iterator _Iter

typedef random_access_iterator_tagiterator_category;

typedef wchar_t value_type;

typedef ptrdiff_t difference_type;

typedef difference_type distance_type; //retained

typedef wchar_t * pointer;

typedef wchar_t & reference;

};

}

#endif

namespace regex

{

class bad_regexpr : publicstd::invalid_argument

{

public:

explicit bad_regexpr( std::string const & s)

: std::invalid_argument( s ) {}

virtual ~bad_regexpr() throw() {}

};

//

// Flags to control how matching occurs

//

enum REGEX_FLAGS

{

NOFLAGS = 0x0000,

NOCASE = 0x0001, // ignore case

GLOBAL = 0x0002, // match everywhere in thestring

MULTILINE = 0x0004, // ^ and $ can matchinternal line breaks

SINGLELINE = 0x0008, // . can match newlinecharacter

RIGHTMOST = 0x0010, // start matching at theright of the string

NOBACKREFS = 0x0020, // only meaningful whenused with GLOBAL and substitute

FIRSTBACKREFS = 0x0040, // only meaningful whenused with GLOBAL

ALLBACKREFS = 0x0080, // only meaningful whenused with GLOBAL

NORMALIZE = 0x0100, // Preprocess patterns:"//n" => "/n", etc.

EXTENDED = 0x0200, // ignore whitespace inpattern

};

// For backwards compatibility

REGEX_FLAGS const noflags = NOFLAGS;

// helper functions to make it easier tocombine

// the regex flags.

inline REGEX_FLAGS operator|( REGEX_FLAGS f1,REGEX_FLAGS f2 )

{

return ( REGEX_FLAGS ) ( ( unsigned )f1 | (unsigned )f2 );

}

inline REGEX_FLAGS & operator|=(REGEX_FLAGS & f1, REGEX_FLAGS f2 )

{

return f1 = ( f1 | f2 );

}

inline REGEX_FLAGS operator&( REGEX_FLAGSf1, REGEX_FLAGS f2 )

{

return ( REGEX_FLAGS ) ( ( unsigned )f1 & (unsigned )f2 );

}

inline REGEX_FLAGS & operator&=(REGEX_FLAGS & f1, REGEX_FLAGS f2 )

{

return f1 = ( f1 & f2 );

}

#if !defined(_MSC_VER) | 1200 < _MSC_VER

inline REGEX_FLAGS operator~( REGEX_FLAGS f )

{

return ( REGEX_FLAGS ) ~( unsigned )f;

}

#endif

//

// The following are the tokens that can beemitted by the syntax module.

// Don't reorder this list!!!

//

enum TOKEN

{

NO_TOKEN = 0,

// REGULAR TOKENS

BEGIN_GROUP,

END_GROUP,

ALTERNATION,

BEGIN_LINE,

END_LINE,

BEGIN_CHARSET,

MATCH_ANY,

ESCAPE,

// QUANTIFICATION TOKENS

ONE_OR_MORE,

ZERO_OR_MORE,

ZERO_OR_ONE,

ONE_OR_MORE_MIN,

ZERO_OR_MORE_MIN,

ZERO_OR_ONE_MIN,

BEGIN_RANGE,

RANGE_SEPARATOR,

END_RANGE,

END_RANGE_MIN,

// ESCAPE SEQUENCES

ESC_DIGIT,

ESC_NOT_DIGIT,

ESC_SPACE,

ESC_NOT_SPACE,

ESC_WORD,

ESC_NOT_WORD,

ESC_BEGIN_STRING,

ESC_END_STRING,

ESC_END_STRING_z,

ESC_WORD_BOUNDARY,

ESC_NOT_WORD_BOUNDARY,

ESC_WORD_START,

ESC_WORD_STOP,

ESC_QUOTE_META_ON,

ESC_QUOTE_META_OFF,

// SUBSTITUTION TOKENS

SUBST_BACKREF,

SUBST_PREMATCH,

SUBST_POSTMATCH,

SUBST_MATCH,

SUBST_ESCAPE,

SUBST_QUOTE_META_ON,

SUBST_UPPER_ON,

SUBST_UPPER_NEXT,

SUBST_LOWER_ON,

SUBST_LOWER_NEXT,

SUBST_ALL_OFF,

// CHARSET TOKENS

CHARSET_NEGATE,

CHARSET_ESCAPE,

CHARSET_RANGE,

CHARSET_BACKSPACE,

CHARSET_END,

CHARSET_ALNUM,

CHARSET_NOT_ALNUM,

CHARSET_ALPHA,

CHARSET_NOT_ALPHA,

CHARSET_BLANK,

CHARSET_NOT_BLANK,

CHARSET_CNTRL,

CHARSET_NOT_CNTRL,

CHARSET_DIGIT,

CHARSET_NOT_DIGIT,

CHARSET_GRAPH,

CHARSET_NOT_GRAPH,

CHARSET_LOWER,

CHARSET_NOT_LOWER,

CHARSET_PRINT,

CHARSET_NOT_PRINT,

CHARSET_PUNCT,

CHARSET_NOT_PUNCT,

CHARSET_SPACE,

CHARSET_NOT_SPACE,

CHARSET_UPPER,

CHARSET_NOT_UPPER,

CHARSET_XDIGIT,

CHARSET_NOT_XDIGIT,

// EXTENSION TOKENS

EXT_NOBACKREF,

EXT_POS_LOOKAHEAD,

EXT_NEG_LOOKAHEAD,

EXT_POS_LOOKBEHIND,

EXT_NEG_LOOKBEHIND,

EXT_INDEPENDENT,

EXT_COMMENT,

EXT_CONDITION,

EXT_RECURSE,

EXT_UNKNOWN

};

namespace detail

{

template< typename CharT > structliteral;

template<> struct literal<char>

{

static char const * string( char const * sz,wchar_t const * ) { return sz; }

template< char ch, wchar_t > structcharacter { enum { value = ch }; };

};

template<> struct literal<wchar_t>

{

static wchar_t const * string( char const *,wchar_t const * sz ) { return sz; }

template< char, wchar_t ch > structcharacter { enum { value = ch }; };

};

struct posix_charset_type

{

char const * m_szcharset;

size_t cchars;

};

extern posix_charset_type constg_rgposix_charsets[];

extern size_t const g_cposix_charsets;

template< typename IterT >

bool is_posix_charset( IterT icur, IterT iend,char const * szcharset )

{

for( ; iend != icur && char() !=*szcharset; ++icur, ++szcharset )

{

if( *icur != *szcharset )

return false;

}

return char() == *szcharset;

}

// Forward-declare the class that holds all theinformation

// about the set of characters that can bematched by a charset

struct charset;

void free_charset( charset const * );

template< typename CharT >

struct charset_map_node

{

std::basic_string<CharT> m_str;

charset const * m_rgcharsets[2]; // 0==case,1==nocase

charset_map_node()

{

m_rgcharsets[0] = m_rgcharsets[1] = 0;

}

charset_map_node( charset_map_node const &node )

{

*this = node;

}

charset_map_node & operator=(charset_map_node const & node )

{

m_str = node.m_str;

m_rgcharsets[0] = node.m_rgcharsets[0];

m_rgcharsets[1] = node.m_rgcharsets[1];

return *this;

}

void set( std::basic_string<CharT> const& str )

{

clear();

m_str = str;

}

void clear()

{

std::basic_string<CharT>().swap( m_str );

free_charset( m_rgcharsets[0] );

free_charset( m_rgcharsets[1] );

m_rgcharsets[0] = m_rgcharsets[1] = 0;

}

};

template< typename CharT >

class charset_map

{

std::map<CharT,charset_map_node<CharT> > m_map;

public:

typedef typename std::map<CharT,charset_map_node<CharT> >::iterator iterator;

~charset_map()

{

for( iterator iter = m_map.begin(); m_map.end()!= iter; ++iter )

iter->second.clear();

}

charset_map_node<CharT> & operator[](CharT ch ) { return m_map[ ch ]; }

iterator begin() { return m_map.begin(); }

iterator end() { return m_map.end(); }

iterator find( CharT ch ) { return m_map.find(ch ); }

void erase( iterator iter ) { m_map.erase( iter); }

};

inline detail::charset_map<char> &get_perl_charset_map( char )

{

static detail::charset_map<char>s_charset_map;

return s_charset_map;

}

inline detail::charset_map<wchar_t> &get_perl_charset_map( wchar_t )

{

static detail::charset_map<wchar_t>s_charset_map;

return s_charset_map;

}

inline detail::charset_map<char> &get_posix_charset_map( char )

{

static detail::charset_map<char>s_charset_map;

return s_charset_map;

}

inline detail::charset_map<wchar_t> &get_posix_charset_map( wchar_t )

{

static detail::charset_map<wchar_t>s_charset_map;

return s_charset_map;

}

inline bool regex_isspace( char ch )

{

using namespace std;

return 0 != isspace( ch );

}

inline bool regex_isspace( wchar_t wch )

{

using namespace std;

return 0 != iswspace( wch );

}

template< typename T >

T const & regex_max( T const & lhs, Tconst & rhs )

{

return ( lhs > rhs ) ? lhs : rhs;

}

template< typename T >

T const & regex_min( T const & lhs, Tconst & rhs )

{

return ( lhs < rhs ) ? lhs : rhs;

}

} // namespace detail

//

// The perl_syntax class encapsulates the Perl5 regular expression syntax. It is

// used as a template parameter tobasic_rpattern. To customize regex syntax, create

// your own syntax class and use it as atemplate parameter instead.

//

class perl_syntax_base

{

protected:

perl_syntax_base()

{

}

static TOKEN const s_rgreg[ UCHAR_MAX + 1 ];

static TOKEN const s_rgescape[ UCHAR_MAX + 1 ];

static TOKEN look_up( char ch, TOKEN const rg[])

{

return rg[ static_cast<unsigned char>( ch) ];

}

static TOKEN look_up( wchar_t ch, TOKEN const rg[])

{

return UCHAR_MAX < ch ? NO_TOKEN : rg[static_cast<unsigned char>( ch ) ];

}

};

//--------------------------------------------------------------------------

//

// Class: perl_syntax

//

// Description: Module that encapsulates thePerl syntax

//

// Methods: eat_whitespace -

// min_quant -

// perl_syntax -

// perl_syntax -

// set_flags -

// get_flags -

// reg_token -

// quant_token -

// charset_token -

// subst_token -

// ext_token -

// get_charset_map -

// invalid_charset -

// register_intrinsic_charset -

// _invalid_charset -

// _invalid_charset -

//

// Members: m_flags -

// s_charset_map -

//

// Typedefs: iterator -

// const_iterator -

// char_type -

//

// History: 11/16/2001 - ericne - Created

//

//--------------------------------------------------------------------------

template< typename CharT >

class perl_syntax : protected perl_syntax_base

{

public:

typedef typenamestd::basic_string<CharT>::iterator iterator;

typedef typenamestd::basic_string<CharT>::const_iterator const_iterator;

typedef CharT char_type;

template< typename OtherT > struct rebind{ typedef perl_syntax<OtherT> other; };

private:

REGEX_FLAGS m_flags;

const_iterator eat_whitespace( iterator &icur, const_iterator iend )

{

if( m_flags & EXTENDED )

{

while( iend != icur && ( REGEX_CHAR(CharT,'#')== *icur || detail::regex_isspace( *icur ) ) )

{

if( REGEX_CHAR(CharT,'#') == *icur++ )

{

while( iend != icur &&REGEX_CHAR(CharT,'/n') != *icur++ ) {}

}

else

{

for( ; iend != icur &&detail::regex_isspace( *icur ); ++icur ) {}

}

}

}

return icur;

}

bool min_quant( iterator & icur,const_iterator iend )

{

return ( iend != eat_whitespace( ++icur, iend )&& REGEX_CHAR(CharT,'?') == *icur ? ( ++icur, true ) : false );

}

public:

perl_syntax( REGEX_FLAGS flags )

: m_flags( flags )

{

}

perl_syntax( perl_syntax<CharT> const& sy )

: m_flags( sy.m_flags )

{

}

void set_flags( REGEX_FLAGS flags )

{

m_flags = flags;

}

REGEX_FLAGS get_flags() const

{

return m_flags;

}

TOKEN reg_token( iterator & icur,const_iterator iend )

{

REGEX_ASSERT( iend != icur );

if( iend == eat_whitespace( icur, iend ) )

return NO_TOKEN;

TOKEN tok = look_up( *icur, s_rgreg );

if( tok )

++icur;

if( ESCAPE == tok && iend != icur )

{

tok = look_up( *icur, s_rgescape );

if( tok )

++icur;

else

tok = ESCAPE;

}

return tok;

}

TOKEN quant_token( iterator & icur,const_iterator iend )

{

REGEX_ASSERT( iend != icur );

if( iend == eat_whitespace( icur, iend ) )

return NO_TOKEN;

TOKEN tok = NO_TOKEN;

switch( *icur )

{

case REGEX_CHAR(CharT,'*'):

tok = min_quant( icur, iend ) ?ZERO_OR_MORE_MIN : ZERO_OR_MORE;

break;

case REGEX_CHAR(CharT,'+'):

tok = min_quant( icur, iend ) ? ONE_OR_MORE_MIN: ONE_OR_MORE;

break;

case REGEX_CHAR(CharT,'?'):

tok = min_quant( icur, iend ) ? ZERO_OR_ONE_MIN: ZERO_OR_ONE;

break;

case REGEX_CHAR(CharT,'}'):

tok = min_quant( icur, iend ) ? END_RANGE_MIN :END_RANGE;

break;

case REGEX_CHAR(CharT,'{'):

tok = BEGIN_RANGE;

++icur;

break;

case REGEX_CHAR(CharT,','):

tok = RANGE_SEPARATOR;

++icur;

break;

}

return tok;

}

TOKEN charset_token( iterator & icur,const_iterator iend )

{

REGEX_ASSERT( iend != icur );

TOKEN tok = NO_TOKEN;

switch( *icur )

{

case REGEX_CHAR(CharT,'-'):

tok = CHARSET_RANGE;

++icur;

break;

case REGEX_CHAR(CharT,'^'):

tok = CHARSET_NEGATE;

++icur;

break;

case REGEX_CHAR(CharT,']'):

tok = CHARSET_END;

++icur;

break;

case REGEX_CHAR(CharT,'//'):

tok = CHARSET_ESCAPE;

if( iend == ++icur )

break;

switch( *icur )

{

case REGEX_CHAR(CharT,'b'):

tok = CHARSET_BACKSPACE;

++icur;

break;

case REGEX_CHAR(CharT,'d'):

tok = ESC_DIGIT;

++icur;

break;

case REGEX_CHAR(CharT,'D'):

tok = ESC_NOT_DIGIT;

++icur;

break;

case REGEX_CHAR(CharT,'s'):

tok = ESC_SPACE;

++icur;

break;

case REGEX_CHAR(CharT,'S'):

tok = ESC_NOT_SPACE;

++icur;

break;

case REGEX_CHAR(CharT,'w'):

tok = ESC_WORD;

++icur;

break;

case REGEX_CHAR(CharT,'W'):

tok = ESC_NOT_WORD;

++icur;

break;

}

break;

case REGEX_CHAR(CharT,'['):

if( REGEX_CHAR(CharT,':') == *( ++icur )-- )

{

for( size_t i=0; !tok && i <detail::g_cposix_charsets; ++i )

{

if(detail::is_posix_charset<const_iterator>( icur, iend, detail::g_rgposix_charsets[i].m_szcharset) )

{

tok = TOKEN( CHARSET_ALNUM + i );

std::advance( icur,detail::g_rgposix_charsets[i].cchars );

}

}

}

break;

}

return tok;

}

TOKEN subst_token( iterator & icur,const_iterator iend )

{

REGEX_ASSERT( iend != icur );

TOKEN tok = NO_TOKEN;

switch( *icur )

{

case REGEX_CHAR(CharT,'//'):

tok = SUBST_ESCAPE;

if( iend != ++icur )

switch( *icur )

{

case REGEX_CHAR(CharT,'Q'):

tok = SUBST_QUOTE_META_ON;

++icur;

break;

case REGEX_CHAR(CharT,'U'):

tok = SUBST_UPPER_ON;

++icur;

break;

case REGEX_CHAR(CharT,'u'):

tok = SUBST_UPPER_NEXT;

++icur;

break;

case REGEX_CHAR(CharT,'L'):

tok = SUBST_LOWER_ON;

++icur;

break;

case REGEX_CHAR(CharT,'l'):

tok = SUBST_LOWER_NEXT;

++icur;

break;

case REGEX_CHAR(CharT,'E'):

tok = SUBST_ALL_OFF;

++icur;

break;

}

break;

case REGEX_CHAR(CharT,'$'):

tok = SUBST_BACKREF;

if( iend != ++icur )

switch( *icur )

{

case REGEX_CHAR(CharT,'&'):

tok = SUBST_MATCH;

++icur;

break;

case REGEX_CHAR(CharT,'`'):

tok = SUBST_PREMATCH;

++icur;

break;

case REGEX_CHAR(CharT,'/''):

tok = SUBST_POSTMATCH;

++icur;

break;

}

break;

}

return tok;

}

TOKEN ext_token( iterator & icur,const_iterator iend )

{

REGEX_ASSERT( iend != icur );

if( iend == eat_whitespace( icur, iend ) )

return NO_TOKEN;

bool finclude;

TOKEN tok = NO_TOKEN;

if( REGEX_CHAR(CharT,'?') == *icur )

{

tok = EXT_UNKNOWN;

++icur;

if( m_flags & EXTENDED )

for( ; iend != icur &&detail::regex_isspace( *icur ); ++icur ) {}

if( iend != icur )

{

switch( *icur )

{

case REGEX_CHAR(CharT,':'):

tok = EXT_NOBACKREF;

++icur;

break;

case REGEX_CHAR(CharT,'='):

tok = EXT_POS_LOOKAHEAD;

++icur;

break;

case REGEX_CHAR(CharT,'!'):

tok = EXT_NEG_LOOKAHEAD;

++icur;

break;

case REGEX_CHAR(CharT,'#'):

tok = EXT_COMMENT;

++icur;

break;

case REGEX_CHAR(CharT,'('):

tok = EXT_CONDITION;

++icur;

break;

case REGEX_CHAR(CharT,'R'):

tok = EXT_RECURSE;

++icur;

break;

case REGEX_CHAR(CharT,'<'):

if( iend == eat_whitespace( ++icur, iend ) )

break;

switch( *icur )

{

case REGEX_CHAR(CharT,'='):

tok = EXT_POS_LOOKBEHIND;

++icur;

break;

case REGEX_CHAR(CharT,'!'):

tok = EXT_NEG_LOOKBEHIND;

++icur;

break;

}

break;

case REGEX_CHAR(CharT,'>'):

tok = EXT_INDEPENDENT;

++icur;

break;

default:

finclude = true;

do

{

if( REGEX_CHAR(CharT,':') == *icur )

{

tok = EXT_NOBACKREF;

++icur;

break;

}

if( REGEX_CHAR(CharT,')') == *icur )

{

tok = EXT_NOBACKREF;

break;

}

if( REGEX_CHAR(CharT,'-') == *icur &&finclude )

finclude = false;

else if( REGEX_CHAR(CharT,'i') == *icur )

m_flags = ( REGEX_FLAGS ) ( finclude ? (m_flags | NOCASE ) : ( m_flags & ~NOCASE ) );

else if( REGEX_CHAR(CharT,'m') == *icur )

m_flags = ( REGEX_FLAGS ) ( finclude ? (m_flags | MULTILINE ) : ( m_flags & ~MULTILINE ) );

else if( REGEX_CHAR(CharT,'s') == *icur )

m_flags = ( REGEX_FLAGS ) ( finclude ? (m_flags | SINGLELINE ) : ( m_flags & ~SINGLELINE ) );

else if( REGEX_CHAR(CharT,'x') == *icur )

m_flags = ( REGEX_FLAGS ) ( finclude ? (m_flags | EXTENDED ) : ( m_flags & ~EXTENDED ) );

else

break;

} while( iend != eat_whitespace( ++icur, iend ));

break;

}

}

}

return tok;

}

// Functions used for making user-definedintrinsic character sets

static detail::charset_map<CharT> &get_charset_map()

{

return detail::get_perl_charset_map( CharT() );

}

static bool invalid_charset( CharT ch )

{

return _invalid_charset( ch );

}

static void register_intrinsic_charset( CharTch, std::basic_string<CharT> const & str ) //throw( bad_regexpr,std::bad_alloc )

{

perl_syntax sy( NOFLAGS );

if( invalid_charset( ch ) )

throw bad_regexpr( "invalid characterspecified to register_intrinsic_charset" );

std::basic_string<CharT> pat = str;

typenamestd::basic_string<CharT>::iterator ibegin = pat.begin();

if( BEGIN_CHARSET != sy.reg_token( ibegin,pat.end() ) )

throw bad_regexpr( "expecting beginning ofcharset" );

regex::detail::charset_map<CharT> &charset_map = get_charset_map();

regex::detail::charset_map_node<CharT>& map_node = charset_map[ ch ];

map_node.set( std::basic_string<CharT>(ibegin, pat.end() ) );

}

private:

static bool _invalid_charset( char ch )

{

using namespace std;

return NO_TOKEN != s_rgescape[static_cast<unsigned char>( ch ) ]

|| isdigit( ch ) || 'e' == ch || 'x' == ch ||'c' == ch;

}

static bool _invalid_charset( wchar_t ch )

{

return UCHAR_MAX >= ch &&_invalid_charset( static_cast<char>( ch ) );

}

};

//--------------------------------------------------------------------------

//

// Class: posix_syntax

//

// Description: Implements the basic POSIXregular expression syntax

//

// Methods: posix_syntax -

// posix_syntax -

// get_flags -

// set_flags -

// reg_token -

// quant_token -

// charset_token -

// subst_token -

// ext_token -

// get_charset_map -

// invalid_charset -

// register_intrinsic_charset -

//

// Members: m_flags -

// s_charset_map -

//

// Typedefs: iterator -

// const_iterator -

// char_type -

//

// History: 11/16/2001 - ericne - Created

//

// --------------------------------------------------------------------------

template< typename CharT >

class posix_syntax

{

REGEX_FLAGS m_flags;

public:

typedef typenamestd::basic_string<CharT>::iterator iterator;

typedef typenamestd::basic_string<CharT>::const_iterator const_iterator;

typedef CharT char_type;

template< typename OtherT > struct rebind{ typedef posix_syntax<OtherT> other; };

posix_syntax( REGEX_FLAGS flags )

: m_flags( flags )

{

}

posix_syntax( posix_syntax<CharT> const& sy )

: m_flags( sy.m_flags )

{

}

REGEX_FLAGS get_flags() const

{

return m_flags;

}

void set_flags( REGEX_FLAGS flags )

{

m_flags = flags;

}

TOKEN reg_token( iterator & icur,const_iterator iend )

{

TOKEN tok = NO_TOKEN;

switch( *icur )

{

case REGEX_CHAR(CharT,'.'):

tok = MATCH_ANY;

++icur;

break;

case REGEX_CHAR(CharT,'^'):

tok = BEGIN_LINE;

++icur;

break;

case REGEX_CHAR(CharT,'$'):

tok = END_LINE;

++icur;

break;

case REGEX_CHAR(CharT,'['):

tok = BEGIN_CHARSET;

++icur;

break;

case REGEX_CHAR(CharT,'//'):

tok = ESCAPE;

++icur;

if( iend != icur )

{

switch( *icur )

{

case REGEX_CHAR(CharT,'('):

tok = BEGIN_GROUP;

++icur;

break;

case REGEX_CHAR(CharT,')'):

tok = END_GROUP;

++icur;

break;

case REGEX_CHAR(CharT,'|'):

tok = ALTERNATION;

++icur;

break;

}

}

break;

}

return tok;

}

TOKEN quant_token( iterator & icur,const_iterator iend )

{

TOKEN tok = NO_TOKEN;

switch( *icur )

{

case REGEX_CHAR(CharT,'*'):

tok = ZERO_OR_MORE;

++icur;

break;

case REGEX_CHAR(CharT,','):

tok = RANGE_SEPARATOR;

++icur;

break;

case REGEX_CHAR(CharT,'//'):

++icur;

if( iend != icur )

{

switch( *icur )

{

case REGEX_CHAR(CharT,'?'):

tok = ZERO_OR_ONE;

++icur;

break;

case REGEX_CHAR(CharT,'+'):

tok = ONE_OR_MORE;

++icur;

break;

case REGEX_CHAR(CharT,'{'):

tok = BEGIN_RANGE;

++icur;

break;

case REGEX_CHAR(CharT,'}'):

tok = END_RANGE;

++icur;

break;

default:

--icur;

break;

}

}

else

{

--icur;

}

}

return tok;

}

TOKEN charset_token( iterator & icur,const_iterator iend )

{

TOKEN tok = NO_TOKEN;

switch( *icur )

{

case REGEX_CHAR(CharT,'^'):

tok = CHARSET_NEGATE;

++icur;

break;

case REGEX_CHAR(CharT,'-'):

tok = CHARSET_RANGE;

++icur;

break;

case REGEX_CHAR(CharT,']'):

tok = CHARSET_END;

++icur;

break;

case REGEX_CHAR(CharT,'['):

if( REGEX_CHAR(CharT,':') == *( ++icur )-- )

{

for( size_t i=0; !tok && i <detail::g_cposix_charsets; ++i )

{

if(detail::is_posix_charset<const_iterator>( icur, iend,detail::g_rgposix_charsets[i].m_szcharset ) )

{

tok = TOKEN( CHARSET_ALNUM + i );

std::advance( icur,detail::g_rgposix_charsets[i].cchars );

}

}

}

break;

}

return tok;

}

TOKEN subst_token( iterator & icur,const_iterator iend )

{

TOKEN tok = NO_TOKEN;

if( REGEX_CHAR(CharT,'//') == *icur )

{

tok = SUBST_ESCAPE;

++icur;

if( iend != icur &&REGEX_CHAR(CharT,'0') <= *icur && REGEX_CHAR(CharT,'9') >= *icur)

{

tok = SUBST_BACKREF;

}

}

return tok;

}

TOKEN ext_token( iterator &, const_iterator)

{

return NO_TOKEN;

}

// Functions for making user-defined intrinsiccharacter sets

static detail::charset_map<CharT> &get_charset_map()

{

return detail::get_posix_charset_map( CharT());

}

static bool invalid_charset( CharT ch )

{

return _invalid_charset( ch );

}

static void register_intrinsic_charset( CharTch, std::basic_string<CharT> const & str ) //throw( bad_regexpr,std::bad_alloc )

{

posix_syntax sy( NOFLAGS );

if( invalid_charset( ch ) )

throw bad_regexpr( "invalid characterspecified to register_intrinsic_charset" );

std::basic_string<CharT> pat = str;

typenamestd::basic_string<CharT>::iterator ibegin = pat.begin();

if( BEGIN_CHARSET != sy.reg_token( ibegin,pat.end() ) )

throw bad_regexpr( "expecting beginning ofcharset" );

regex::detail::charset_map<CharT> &charset_map = get_charset_map();

regex::detail::charset_map_node<CharT>& map_node = charset_map[ ch ];

map_node.set( std::basic_string<CharT>(ibegin, pat.end() ) );

}

private:

static bool _invalid_charset( char ch )

{

static char const s_invalid[] ="0123456789()|?+{}//exc";

return 0 !=std::char_traits<CharT>::find( s_invalid, ARRAYSIZE( s_invalid ) - 1, ch);

}

static bool _invalid_charset( wchar_t ch )

{

return UCHAR_MAX >= ch && _invalid_charset(static_cast<char>( ch ) );

}

};

} // namespace regex

#ifdef _MSC_VER

#pragma warning( pop )

#endif

#endif

//+---------------------------------------------------------------------------

//

// Copyright ( C ) Microsoft, 1994 - 2002.

//

// File: reimpl2.h

//

// Functions: helpers for matching andsubstituting regular expressions

//

// Notes: implementation details that reallybelong in a cpp file,

// but can't because of template weirdness

//

// Author: Eric Niebler ( ericne@microsoft.com)

//

// History: 8/15/2001 ericne Created

//

//----------------------------------------------------------------------------

#ifndef REIMPL_H

#define REIMPL_H

//

// Helper functions for match and substitute

//

namespace detail

{

// For use while doing uppercase/lowercaseconversions:

inline char regex_toupper( char ch ) { usingnamespace std; return ( char )toupper( ch ); }

inline char regex_tolower( char ch ) { usingnamespace std; return ( char )tolower( ch ); }

inline wchar_t regex_toupper( wchar_t ch ) {using namespace std; return ( wchar_t )towupper( ch ); }

inline wchar_t regex_tolower( wchar_t ch ) {using namespace std; return ( wchar_t )towlower( ch ); }

template< typename IBeginT, typename IEndT>

inline void regex_toupper( IBeginT ibegin,IEndT iend )

{

typedef typenamestd::iterator_traits<IEndT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

for( ; iend != ibegin; ++ibegin )

traits_type::assign( *ibegin, regex_toupper(*ibegin ) );

}

template< typename IBeginT, typename IEndT>

inline void regex_tolower( IBeginT ibegin,IEndT iend )

{

typedef typenamestd::iterator_traits<IEndT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

for( ; iend != ibegin; ++ibegin )

traits_type::assign( *ibegin, regex_tolower(*ibegin ) );

}

//

// Helper fn for swapping two auto_ptr's

//

template< typename T >

inline void swap_auto_ptr(std::auto_ptr<T> & left, std::auto_ptr<T> & right )

{

std::auto_ptr<T> temp( left );

left = right;

right = temp;

}

template< typename T >

inline void reset_auto_ptr(std::auto_ptr<T> & left )

{

std::auto_ptr<T> temp( 0 );

left = temp;

}

template< typename T, typename U >

inline void reset_auto_ptr(std::auto_ptr<T> & left, U * right )

{

std::auto_ptr<T> temp( right );

left = temp;

}

typedef int instantiator;

inline instantiator REGEX_CDECLinstantiator_helper( ... )

{

return instantiator();

}

//--------------------------------------------------------------------------

//

// Class: match_param

//

// Description: Struct that contains the stateof the matching operation.

// Passed by reference to allrecursive_match_all and recursive_match_this routines.

//

// Methods: match_param - ctor

//

// Members: ibufferbegin - start of the buffer

// ibegin - start of this iteration

// iend - end of the string

// prgbackrefs - pointer to backref array

//

// History: 8/14/2000 - ericne - Created

//

//--------------------------------------------------------------------------

template< typename IterT >

struct match_param

{

typedef backref_tag<IterT> backref_type;

typedef sub_expr_base<IterT> const *sub_expr_ptr;

// for performance reasons, the most frequentlyused fields

// are placed at offsets which are a power of 2(assuming

// a 32-bit architecture, and iterators whichare 32 bits).

backref_type * m_prgbackrefs; // offsetof == 0

IterT m_iend; // offsetof == 4

IterT m_icur; // offsetof == 8

size_t m_cbackrefs;

sub_expr_ptr m_pnext; // offsetof == 16

IterT m_ibufferbegin;

IterT m_imatchbegin;

sub_expr_ptr m_pfirst;

unsafe_stack * m_pstack; // offsetof == 32

bool m_no0len;

bool m_reserved;

match_param

(

IterT ibufferbegin,

IterT imatchbegin,

IterT iend,

backref_type * prgbackrefs,

size_t cbackrefs

)

: m_prgbackrefs( prgbackrefs )

, m_iend( iend )

, m_icur( imatchbegin )

, m_cbackrefs( cbackrefs )

, m_pnext( 0 )

, m_ibufferbegin( ibufferbegin )

, m_imatchbegin( imatchbegin )

, m_pfirst( 0 )

, m_pstack( 0 )

, m_no0len( false )

, m_reserved( false )

{

}

};

//--------------------------------------------------------------------------

//

// Class: arena_allocator

//

// Description: A small, fast allocator forspeeding up pattern compilation.

// Every basic_rpattern object has an arena asa member.

// sub_expr objects can only be allocated fromthis arena.

// Memory is alloc'ed in chunks using theunderlying allocator.

// Chunks are freed en-masse when clear() orfinalize() is called.

//

// History: 8/17/2001 - ericne - Created

//

// Notes: This is NOT a std-compliant allocatorand CANNOT be used with

// STL containers. arena_allocator objectsmaintain state, and

// STL containers are allowed to assume theirallocators do

// not maintain state. In regexpr2.cpp, Idefine slist<>, a simple

// arena-friendly singly-linked list for usewith the arena

// allocator.

//

//--------------------------------------------------------------------------

template< typename AllocT =std::allocator<char> >

struct pool_impl

{

typedef typename rebind<AllocT,char>::type char_allocator_type;

struct mem_block

{

size_t m_offset;

size_t m_blocksize;

mem_block * m_pnext;

unsigned char m_data[ 1 ];

};

#if !defined(_MSC_VER) | 1200 < _MSC_VER

struct pool_data : char_allocator_type

{

pool_data( size_t default_size,char_allocator_type const & alloc )

: char_allocator_type( alloc )

, m_pfirst( 0 )

, m_default_size( default_size )

{

}

mem_block * m_pfirst;

size_t m_default_size;

char_allocator_type & get_allocator()

{

return *this;

}

} m_data;

#else

struct pool_data

{

pool_data( size_t default_size,char_allocator_type const & alloc )

: m_alloc( alloc )

, m_pfirst( 0 )

, m_default_size( default_size )

{

}

char_allocator_type m_alloc;

mem_block * m_pfirst;

size_t m_default_size;

char_allocator_type & get_allocator()

{

return m_alloc;

}

} m_data;

#endif

void new_block( size_t size );

void clear();

void * allocate( size_t size );

explicit pool_impl( size_t default_size,char_allocator_type const & alloc = char_allocator_type() );

~pool_impl();

char_allocator_type get_allocator() const

{

returnconst_cast<pool_impl*>(this)->m_data.get_allocator();

}

};

template< typename T, typename AllocT =std::allocator<char> >

class arena_allocator

{

public:

typedef size_t size_type;

typedef ptrdiff_t difference_type;

typedef T *pointer;

typedef T const *const_pointer;

typedef T & reference;

typedef T const & const_reference;

typedef T value_type;

typedef typename rebind<AllocT, char>::typechar_alloc_type;

typedef pool_impl<AllocT> pool_impl_t;

typedef typename rebind<AllocT,pool_impl_t>::type pool_alloc_type;

explicit arena_allocator( size_t default_size,char_alloc_type const & alloc = char_alloc_type() )

: m_pool( 0 )

{

char_alloc_type char_alloc( alloc );

pool_alloc_type pool_alloc(convert_allocator<pool_impl_t>( char_alloc, 0 ) );

m_pool = pool_alloc.allocate( 1, 0 );

pool_alloc.construct( m_pool, pool_impl_t(default_size, char_alloc ) ); // can't throw

}

#if !defined(_MSC_VER) | 1200 < _MSC_VER

arena_allocator( arena_allocator const &that )

: m_pool( that.m_pool )

{

}

#endif

template< typename U >

arena_allocator( arena_allocator<U> const& that )

: m_pool( that.m_pool )

{

}

~arena_allocator()

{ // Many arena_allocators may point to m_pool,so don't delete it.

} // Rather, wait for someone to callfinalize().

pointer allocate( size_type size, void const *=0 )

{

return static_cast<T*>(m_pool->allocate( size * sizeof(T) ) );

}

void deallocate( void *, size_type )

{ // no-op. deallocation happens when pool isfinalized or cleared.

}

void construct( pointer p, T const & t )

{

new( static_cast<void*>(p) ) T( t );

}

void destroy( pointer p )

{

regex::detail::destroy( p );

}

#if !defined(_MSC_VER) | 1200 < _MSC_VER

template< typename U > struct rebind

{

typedef arena_allocator<U> other;

};

#endif

void clear()

{

m_pool->clear();

}

void finalize()

{

char_alloc_type char_alloc(m_pool->get_allocator() );

pool_alloc_type pool_alloc(convert_allocator<pool_impl_t>( char_alloc, 0 ) );

pool_alloc.destroy( m_pool );

pool_alloc.deallocate( m_pool, 1 );

m_pool = 0;

}

void swap( arena_allocator & that )

{

using std::swap;

swap( m_pool, that.m_pool );

}

// the pool lives here

pool_impl_t * m_pool;

};

// Dummy struct used by the pool allocator toalign returned pointers

struct not_pod

{

virtual ~not_pod() {}

};

template< typename AllocT >

inline pool_impl<AllocT>::pool_impl(size_t default_size, char_allocator_type const & alloc )

: m_data( default_size, alloc )

{

}

template< typename AllocT >

inline pool_impl<AllocT>::~pool_impl()

{

clear();

}

template< typename AllocT >

inline void pool_impl<AllocT>::clear()

{

for( mem_block * pnext; m_data.m_pfirst;m_data.m_pfirst = pnext )

{

pnext = m_data.m_pfirst->m_pnext;

m_data.get_allocator().deallocate(reinterpret_cast<char*>( m_data.m_pfirst ),m_data.m_pfirst->m_blocksize );

}

}

template< typename AllocT >

inline void pool_impl<AllocT>::new_block(size_t size )

{

size_t blocksize = regex_max(m_data.m_default_size, size ) + offsetof( mem_block, m_data );

mem_block * pnew =reinterpret_cast<mem_block*>( m_data.get_allocator().allocate( blocksize,0 ) );

if( 0 == pnew )

{

throw std::bad_alloc();

}

pnew->m_offset = 0;

pnew->m_blocksize = blocksize;

pnew->m_pnext = m_data.m_pfirst;

m_data.m_pfirst = pnew;

}

template< typename AllocT >

inline void *pool_impl<AllocT>::allocate( size_t size )

{

if( 0 == size )

size = 1;

if( 0 == m_data.m_pfirst ||m_data.m_pfirst->m_offset + size > m_data.m_default_size )

new_block( size );

void * pnew = m_data.m_pfirst->m_data +m_data.m_pfirst->m_offset;

// ensure returned pointers are always suitablyaligned

m_data.m_pfirst->m_offset += ( ( size +alignof<not_pod>::value - 1 )

& ~( alignof<not_pod>::value - 1 ) );

return pnew;

}

// The regex_arena is a basic, vanilla arena_allocator.

typedef arena_allocator<char>regex_arena;

template< typename T >

type_with_size<3> allocator_picker(arena_allocator<T> const &, int );

template<> struct rebind_helper<3>

{

template< typename, typename ElemT>

struct inner

{

typedef arena_allocator<ElemT> type;

};

};

//--------------------------------------------------------------------------

//

// Class: sub_expr_base

//

// Description: patterns are"compiled" into a directed graph of sub_expr_base

// structs. Matching is accomplished by traversingthis graph.

//

// Methods: ~sub_expr_base - virt dtor socleanup happens correctly

// recursive_match_all - match thissub-expression and all following

// sub-expression

//

// History: 8/14/2000 - ericne - Created

//

// --------------------------------------------------------------------------

template< typename IterT >

struct sub_expr_base

{

virtual bool recursive_match_all_s(match_param<IterT> &, IterT ) const = 0; //throw() (offset 0)

virtual bool recursive_match_all_c(match_param<IterT> &, IterT ) const = 0; //throw() (offset 4)

virtual bool iterative_match_this_s(match_param<IterT> & ) const = 0; //throw() (offset 8)

virtual bool iterative_match_this_c(match_param<IterT> & ) const = 0; //throw() (offset 12)

virtual bool iterative_rematch_this_s(match_param<IterT> & ) const = 0; //throw() (offset 16)

virtual bool iterative_rematch_this_c(match_param<IterT> & ) const = 0; //throw() (offset 20)

virtual ~sub_expr_base() = 0; // (offset 24)

// Use the regex_arena for memory management

static void * operator new( size_t size,regex_arena & arena )

{

return arena.allocate( size );

}

static void operator delete( void *,regex_arena & )

{

}

// Invoke the d'tor, but don't bother freeingmemory. That will

// happen automatically when the arena objectgets destroyed.

static void operator delete( void * )

{

}

// For choosing an appropriate virtual functionbased on a compile time constant

bool recursive_match_all(match_param<IterT> & param, IterT icur, false_t ) const //throw()

{

return recursive_match_all_s( param, icur );

}

bool recursive_match_all(match_param<IterT> & param, IterT icur, true_t ) const //throw()

{

return recursive_match_all_c( param, icur );

}

bool iterative_match_this(match_param<IterT> & param, false_t ) const //throw()

{

return iterative_match_this_s( param );

}

bool iterative_match_this(match_param<IterT> & param, true_t ) const //throw()

{

return iterative_match_this_c( param );

}

bool iterative_rematch_this(match_param<IterT> & param, false_t ) const //throw()

{

return iterative_rematch_this_s( param );

}

bool iterative_rematch_this(match_param<IterT> & param, true_t ) const //throw()

{

return iterative_rematch_this_c( param );

}

private:

// don't allocate sub-expressions directly onthe heap; they should

// be allocated from an arena

static void * operator new( size_t size )throw( std::bad_alloc );

// disable all the vector new's and delete's.

static void * operator new[]( size_t size,regex_arena & arena ) throw( std::bad_alloc );

static void operator delete[]( void *, regex_arena& );

static void * operator new[]( size_t size )throw( std::bad_alloc );

static void operator delete[]( void * );

};

template< typename IterT >

inlinesub_expr_base<IterT>::~sub_expr_base()

{

}

//--------------------------------------------------------------------------

//

// Class: subst_node

//

// Description: Substitution strings are parsedinto an array of these

// structures in order to speed up substoperations.

//

// Members: stype - type of this struct

// .m_subst_string - do a string substitution

// .m_subst_backref - do a bacref substitution

// op - execute an operation

//

// History: 8/14/2000 - ericne - Created

//

//--------------------------------------------------------------------------

struct subst_node

{

enum

{

PREMATCH = -1,

POSTMATCH = -2

};

enum subst_type

{

SUBST_STRING,

SUBST_BACKREF,

SUBST_OP

};

enum op_type

{

UPPER_ON = SUBST_UPPER_ON,

UPPER_NEXT = SUBST_UPPER_NEXT,

LOWER_ON = SUBST_LOWER_ON,

LOWER_NEXT = SUBST_LOWER_NEXT,

ALL_OFF = SUBST_ALL_OFF

};

struct string_offsets

{

ptrdiff_t m_rstart;

ptrdiff_t m_rlength;

};

subst_type m_stype;

union

{

string_offsets m_subst_string;

size_t m_subst_backref;

op_type m_op;

};

};

typedef std::list<subst_node>subst_list_type;

size_t DEFAULT_BLOCK_SIZE();

template< typename IterT >

class boyer_moore;

//--------------------------------------------------------------------------

//

// Class: basic_rpattern_base_impl

//

// Description:

//

// Methods: basic_rpattern_base_impl - ctor

// flags - get the state of the flags

// uses_backrefs - true if the backrefs arereferenced

// get_first_subexpression - return ptr tofirst sub_expr struct

// get_width - get min/max nbr chars thispattern can match

// loops - if false, we only need to try tomatch at 1st position

// cgroups - number of visible groups

// _cgroups_total - total number of groups,including hidden ( ?: ) groups

// get_pat - get string representing thepattern

// get_subst - get string representing thesubstitution string

// get_subst_list - get the list of subst nodes

// _normalize_string - perform characterescaping

//

// Members: m_fuses_backrefs - true if subststring refers to backrefs

// m_floop - false if pat only needs to bematched in one place

// m_cgroups - total count of groups

// m_cgroups_visible - count of visible groups

// m_flags - the flags

// m_nwidth - width of this pattern

// m_pat - pattern string

// m_subst - substitution string

// m_subst_list - list of substitution nodes

// m_pfirst - ptr to first subexpression tomatch

//

// Typedefs: char_type -

// string_type -

// size_type -

//

// History: 8/14/2000 - ericne - Created

//

//--------------------------------------------------------------------------

template< typename IterT >

class basic_rpattern_base_impl

{

basic_rpattern_base_impl(basic_rpattern_base_impl<IterT> const & );

basic_rpattern_base_impl & operator=(basic_rpattern_base_impl<IterT> const & );

protected:

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

typedef std::basic_string<char_type> string_type;

typedef size_t size_type;

typedef backref_tag<IterT> backref_type;

typedef std::vector<backref_type>backref_vector;

friend struct regex_access<IterT>;

explicit basic_rpattern_base_impl

(

REGEX_FLAGS flags = NOFLAGS,

REGEX_MODE mode = MODE_DEFAULT,

string_type const & pat = string_type(),

string_type const & subst = string_type()

) //throw()

: m_arena( DEFAULT_BLOCK_SIZE() )

, m_fuses_backrefs( false )

, m_floop( true )

, m_fok_to_recurse( true )

, m_cgroups( 0 )

, m_cgroups_visible( 0 )

, m_flags( flags )

, m_mode( mode )

, m_nwidth( uninit_width() )

, m_pat( new string_type( pat ) )

, m_subst( new string_type( subst ) )

, m_subst_list()

, m_pfirst( 0 )

, m_invisible_groups()

, m_search( 0 )

{

}

virtual ~basic_rpattern_base_impl()

{

// We're not going to be calling destructorsbecause all allocated

// memory associated with the parsed patternresides in the arena.

// The memory will be freed when the arena getsdestroyed.

//delete m_pfirst;

reset_auto_ptr( m_pat );

reset_auto_ptr( m_subst );

m_arena.finalize();

}

regex_arena m_arena; // The sub_expr arena

bool m_fuses_backrefs; // true if thesubstitution uses backrefs

bool m_floop; // false ifm_pfirst->recursive_match_all only needs to be called once

bool m_fok_to_recurse; // false if the patternwould recurse too deeply

size_t m_cgroups; // number of groups ( alwaysat least one )

size_t m_cgroups_visible; // number of visiblegroups

REGEX_FLAGS m_flags; // flags used to customizesearch/replace

REGEX_MODE m_mode; // Used to pick the fast orsafe algorithm

width_type m_nwidth; // width of the pattern

std::auto_ptr<string_type> m_pat; //contains the unparsed pattern

std::auto_ptr<string_type> m_subst; //contains the unparsed substitution

subst_list_type m_subst_list; // used to speedup substitution

sub_expr_base<IterT> const * m_pfirst; //first subexpression in pattern

std::list<size_t> m_invisible_groups; //groups w/o backrefs

boyer_moore<typenamestring_type::const_iterator> * m_search;

size_t _cgroups_total() const //throw()

{

return m_cgroups;

}

bool _loops() const //throw()

{

return m_floop;

}

size_t _get_next_group_nbr()

{

return m_cgroups++;

}

void _normalize_string( string_type & str )const //throw()

{

if( NORMALIZE & flags() )

process_escapes( str, true );

}

bool _save_backrefs() const //throw()

{

return m_fuses_backrefs || ! ( flags() &NOBACKREFS );

}

sub_expr_base<IterT> const *_get_first_subexpression() const //throw()

{

return m_pfirst;

}

REGEX_FLAGS flags() const //throw()

{

return m_flags;

}

REGEX_MODE mode() const // throw()

{

return m_mode;

}

width_type get_width() const //throw()

{

return m_nwidth;

}

size_t cgroups() const //throw()

{

return m_cgroups_visible;

}

string_type const & get_pat() const//throw()

{

return *m_pat;

}

string_type const & get_subst() const//throw()

{

return *m_subst;

}

bool _ok_to_recurse() const; //throw();

void swap(basic_rpattern_base_impl<IterT> & that ); // throw();

enum { npos = static_cast<size_type>( -1) };

static instantiator instantiate()

{

typedef basic_rpattern_base_impl this_type;

return instantiator_helper

(

&this_type::_ok_to_recurse,

&this_type::swap

);

}

};

template< typename IterT >

struct regex_access

{

typedef basic_rpattern_base_impl< IterT >rpattern_type;

typedef typename rpattern_type::size_typesize_type;

typedef typename rpattern_type::char_typechar_type;

typedef typename rpattern_type::traits_typetraits_type;

typedef typename rpattern_type::backref_typebackref_type;

static bool _do_match_iterative_helper_s

(

sub_expr_base<IterT> const * expr,

match_param<IterT> & param,

IterT icur

);

static bool _do_match_iterative_helper_c

(

sub_expr_base<IterT> const * expr,

match_param<IterT> & param,

IterT icur

);

static bool _do_match_recursive_s

(

sub_expr_base<IterT> const * expr,

match_param<IterT> & param,

IterT icur

);

static bool _do_match_recursive_c

(

sub_expr_base<IterT> const * expr,

match_param<IterT> & param,

IterT icur

);

static bool _do_match_impl

(

rpattern_type const & pat,

match_param<IterT> & param,

bool const use_null

);

static bool _do_match_with_stack

(

rpattern_type const & pat,

match_param<IterT> & param,

bool const use_null

);

template< typename Alloc1T, typename Alloc2T>

static void _fixup_backrefs

(

std::vector<backref_type,Alloc1T> &rgbackrefs,

std::list<size_t,Alloc2T> const &invisible

)

{

typedef typenamestd::list<size_t,Alloc2T>::const_iterator iter_type;

// Remove information about the"invisible" groups

if( rgbackrefs[0].matched )

{

size_t dropped = 0;

iter_type const end = invisible.end();

iter_type curr = invisible.begin(), next =invisible.begin();

for( ; end != curr; curr = next, ++dropped )

{

if( end == ++next )

{

std::copy(

rgbackrefs.begin() + *curr + 1,

rgbackrefs.end(),

rgbackrefs.begin() + *curr - dropped );

}

else

{

std::copy(

rgbackrefs.begin() + *curr + 1,

rgbackrefs.begin() + *next,

rgbackrefs.begin() + *curr - dropped );

}

}

rgbackrefs.resize( rgbackrefs.size() - dropped);

}

else

{

rgbackrefs.resize( rgbackrefs.size() -invisible.size() );

}

}

template< typename AllocT >

static bool _do_try_match

(

rpattern_type const & pat,

match_param<IterT> & param,

std::vector<backref_type,AllocT> &rgbackrefs,

bool const use_null

)

{

bool success;

rgbackrefs.resize( pat._cgroups_total() );

param.m_prgbackrefs = & rgbackrefs[0];

param.m_cbackrefs = rgbackrefs.size();

REGEX_SEH_TRY

{

if( pat._ok_to_recurse() )

{

success = _do_match_impl( pat, param, use_null);

}

else

{

success = _do_match_with_stack( pat, param,use_null );

}

}

REGEX_SEH_EXCEPT( REGEX_SEH_STACK_OVERFLOW ==_exception_code() )

{

// we have overflowed the stack. reset theguard page.

REGEX_RESET_STK_OFLW();

// This match fails silently.

for( size_t i=0; i < param.m_cbackrefs; ++i)

{

param.m_prgbackrefs[i] =static_init<backref_type>::value;

}

success = false;

}

_fixup_backrefs( rgbackrefs,pat.m_invisible_groups );

return success;

}

template< typename AllocT >

static bool _do_match

(

rpattern_type const & pat,

basic_match_results<IterT,AllocT> &results,

IterT ibegin,

IterT iend,

bool use_null

)

{

typedef typenamebasic_match_results<IterT,AllocT>::backref_vector backref_vector;

results.m_ibegin = ibegin;

match_param<IterT> param( ibegin, ibegin,iend, 0, 0 );

if( GLOBAL & pat.flags() ) // do a globalfind

{

// The NOBACKREFS flag is ignored in the matchmethod.

bool const fAll = ( ALLBACKREFS == (ALLBACKREFS & pat.flags() ) );

bool const fFirst = ( FIRSTBACKREFS == (FIRSTBACKREFS & pat.flags() ) );

backref_vector rgtempbackrefs(results.m_rgbackrefs.get_allocator() );

while( _do_try_match( pat, param,results.m_rgbackrefs, use_null ) )

{

backref_type const & br =param.m_prgbackrefs[0];

// Handle specially the backref flags

if( fFirst )

{

rgtempbackrefs.push_back( br );

}

else if( fAll )

{

rgtempbackrefs.insert(

rgtempbackrefs.end(),

results.m_rgbackrefs.begin(),

results.m_rgbackrefs.end() );

}

else

{

rgtempbackrefs.swap( results.m_rgbackrefs );

}

param.m_imatchbegin = br.second;

param.m_no0len = ( br.first == br.second );

}

// restore the backref vectors

results.m_rgbackrefs.swap( rgtempbackrefs );

return ! results.m_rgbackrefs.empty();

}

else

{

return _do_try_match( pat, param, results.m_rgbackrefs,use_null );

}

}

template< typename AllocT >

static bool _do_match_c

(

rpattern_type const & pat,

basic_match_results<IterT,AllocT> &results,

char_type const * szbegin

)

{

if( RIGHTMOST & pat.flags() )

{

// We need to know the end of the string ifwe're doing a

// RIGHTMOST match.

char_type const * szend = szbegin;

std::advance( szend, traits_type::length(szbegin ) );

return _do_match( pat, results, szbegin, szend,false );

}

else

{

return _do_match( pat, results, szbegin, 0,true );

}

}

static size_t _do_count

(

rpattern_type const & pat,

IterT ibegin,

IterT iend,

bool use_null

)

{

size_t cmatches = 0;

std::vector<backref_type> rgbackrefs;

// If your compile breaks here, it is becauseCharT const * is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

match_param<IterT> param( ibegin, ibegin,iend, 0, 0 );

while( _do_try_match( pat, param, rgbackrefs,use_null ) )

{

backref_type const & br =param.m_prgbackrefs[0];

++cmatches;

param.m_imatchbegin = br.second;

param.m_no0len = ( br.first == br.second );

}

return cmatches;

}

template< typename CharT, typename TraitsT,typename AllocT >

static size_t _do_split

(

rpattern_type const & pat,

basic_split_results<CharT, TraitsT,AllocT> & results,

IterT ibegin,

IterT iend,

int limit,

bool use_null

)

{

typedef typename basic_split_results<CharT,TraitsT, AllocT>::string_type string_type;

typedef typename rebind<AllocT,backref_type>::type backref_allocator;

std::vector<backref_type,backref_allocator>rgbackrefs(

convert_allocator<backref_type>(results.strings().get_allocator(), 0 ) );

typedef typename rebind<AllocT,CharT>::type char_allocator_type;

char_allocator_type char_allocator =

convert_allocator<CharT>(results.strings().get_allocator(), 0 );

// reserve some initial space

results.strings().clear();

results.strings().reserve( 10 );

match_param<IterT> param( ibegin, ibegin,iend, 0, 0 );

while( 1 != limit && _do_try_match(pat, param, rgbackrefs, use_null ) )

{

backref_type const & br =param.m_prgbackrefs[0];

param.m_no0len = ( br.first == br.second );

// discard zero-width matches at the beginningand end of the buffer

if( param.m_no0len )

{

// if we're at the beginning, skip

if( br.first == param.m_ibufferbegin )

continue;

// if we're at the end, break

if( use_null ? 0 == *param.m_imatchbegin :param.m_imatchbegin == param.m_iend )

break;

}

string_type tmp( param.m_imatchbegin, br.first,char_allocator );

results.strings().push_back( tmp );

param.m_imatchbegin = br.second;

// add any groups

for( size_t i = 1; i < rgbackrefs.size();++i )

{

backref_type const & br = rgbackrefs[i];

string_type tmp( br.first, br.second,char_allocator );

results.strings().push_back( tmp );

}

if( limit > 0 )

--limit;

}

// append the last string, unless it's emptyand limit is 0

if( use_null )

{

if( *param.m_imatchbegin || 0 != limit )

results.strings().push_back( string_type(&*param.m_imatchbegin, char_allocator ) );

}

else

{

if( param.m_imatchbegin != param.m_iend || 0 !=limit )

results.strings().push_back( string_type(param.m_imatchbegin, param.m_iend, char_allocator ) );

}

// remove trailing empty fields

if( 0 == limit )

{

while( results.size() &&results.back().empty() )

{

results.strings().pop_back();

}

}

return results.size();

}

template< typename CharT, typename TraitsT,typename AllocT >

static size_t _do_subst_internal

(

std::basic_string<CharT, TraitsT, AllocT>& str,

basic_subst_results<CharT, TraitsT,AllocT> const & results,

rpattern_type const & pat,

size_type strpos,

size_type strlen

)

{

typedef subst_list_type::const_iterator iter_type;

enum { UPPER = -1, NIL, LOWER } next = NIL,rest = NIL;

bool first = true;

size_t old_strpos = strpos;

typename std::basic_string<CharT, TraitsT,AllocT>::iterator itstrlen = str.begin();

std::advance( itstrlen, strpos + strlen );

std::basic_string<char_type> const &subst = pat.get_subst();

for( iter_type isubst =pat.m_subst_list.begin(); pat.m_subst_list.end() != isubst; ++isubst )

{

size_t sublen = 0;

typename std::basic_string<CharT, TraitsT,AllocT>::const_iterator itsubpos1; // iter into str

typename std::basic_string<CharT, TraitsT,AllocT>::const_iterator itsublen1;

typenamestd::basic_string<char_type>::const_iterator itsubpos2; // iter intosubst string

typenamestd::basic_string<char_type>::const_iterator itsublen2;

typename std::basic_string<CharT, TraitsT,AllocT>::iterator itstrpos = str.begin();

std::advance( itstrpos, strpos );

switch( isubst->m_stype )

{

case subst_node::SUBST_STRING:

itsubpos2 = subst.begin();

std::advance( itsubpos2,isubst->m_subst_string.m_rstart );

itsublen2 = itsubpos2;

std::advance( itsublen2,isubst->m_subst_string.m_rlength );

if( first )

str.replace( itstrpos, itstrlen, itsubpos2,itsublen2 );

else

str.insert( itstrpos, itsubpos2, itsublen2 );

sublen = std::distance( itsubpos2, itsublen2 );

break;

case subst_node::SUBST_BACKREF:

switch( isubst->m_subst_backref )

{

case subst_node::PREMATCH:

itsubpos1 = results.backref_str().begin();

itsublen1 = itsubpos1;

std::advance( itsublen1, sublen =results.rstart() );

break;

case subst_node::POSTMATCH:

itsubpos1 = results.backref_str().begin();

std::advance( itsubpos1, results.rstart() +results.rlength() );

itsublen1 = results.backref_str().end();

break;

default:

itsubpos1 = results.backref_str().begin();

std::advance( itsubpos1, results.rstart(isubst->m_subst_backref ) );

itsublen1 = itsubpos1;

std::advance( itsublen1, results.rlength(isubst->m_subst_backref ) );

break;

}

if( first )

str.replace( itstrpos, itstrlen, itsubpos1,itsublen1 );

else

str.insert( itstrpos, itsubpos1, itsublen1 );

sublen = std::distance( itsubpos1, itsublen1 );

break;

case subst_node::SUBST_OP:

switch( isubst->m_op )

{

case subst_node::UPPER_ON:

rest = UPPER;

break;

case subst_node::UPPER_NEXT:

next = UPPER;

break;

case subst_node::LOWER_ON:

rest = LOWER;

break;

case subst_node::LOWER_NEXT:

next = LOWER;

break;

case subst_node::ALL_OFF:

rest = NIL;

break;

default:

REGEX_ASSERT(false);

break;

}

continue; // jump to the next item in the list

default:

REGEX_ASSERT(false);

break;

}

first = false;

// Are we upper- or lower-casing this string?

if( rest )

{

typename std::basic_string<CharT, TraitsT,AllocT>::iterator ibegin = str.begin();

std::advance( ibegin, strpos );

typename std::basic_string<CharT, TraitsT,AllocT>::const_iterator iend = ibegin;

std::advance( iend, sublen );

switch( rest )

{

case UPPER:

regex_toupper( ibegin, iend );

break;

case LOWER:

regex_tolower( ibegin, iend );

break;

default:

REGEX_ASSERT(false);

break;

}

}

// Are we upper- or lower-casing the nextcharacter?

if( next )

{

switch( next )

{

case UPPER:

traits_type::assign( str[strpos],regex_toupper( str[strpos] ) );

break;

case LOWER:

traits_type::assign( str[strpos],regex_tolower( str[strpos] ) );

break;

default:

REGEX_ASSERT(false);

break;

}

next = NIL;

}

strpos += sublen;

}

// If *first* is still true, then we never calledstr.replace, and the substitution

// string is empty. Erase the part of thestring that the pattern matched.

if( first )

str.erase( strpos, strlen );

// return length of the substitution

return strpos - old_strpos;

}

template< typename CharT, typename TraitsT,typename AllocT >

static size_t _do_subst

(

rpattern_type const & pat,

std::basic_string<CharT, TraitsT, AllocT>& str,

basic_subst_results<CharT, TraitsT,AllocT> & results,

size_type pos,

size_type len

)

{

typedef std::basic_string<CharT, TraitsT,AllocT> string_type;

typedef typename basic_subst_results<CharT,TraitsT, AllocT>::backref_vector backref_vector;

results.m_pbackref_str = pat._save_backrefs() ?&( results.m_backref_str = str ) : &str;

results.m_ibegin =results.m_pbackref_str->begin();

size_t csubst = 0;

size_type stop_offset =results.m_pbackref_str->size();

if( len != rpattern_type::npos )

stop_offset = regex_min( size_t( pos + len ),stop_offset );

match_param<IterT> param(results.m_ibegin, results.m_ibegin, results.m_ibegin, 0, 0 );

std::advance( param.m_imatchbegin, pos );

std::advance( param.m_iend, stop_offset );

param.m_ibufferbegin = param.m_imatchbegin;

if( GLOBAL & pat.flags() )

{

bool const fAll = ( ALLBACKREFS == (ALLBACKREFS & pat.flags() ) );

bool const fFirst = ( FIRSTBACKREFS == (FIRSTBACKREFS & pat.flags() ) );

backref_vector rgtempbackrefs(results.m_rgbackrefs.get_allocator() ); // temporary vector used iffsave_backrefs

size_type pos_offset = 0; // keep track of howmuch the backref_str and

// the current string are out of sync

while( _do_try_match( pat, param,results.m_rgbackrefs, false ) )

{

backref_type const & br =param.m_prgbackrefs[0];

++csubst;

size_type match_length = std::distance(br.first, br.second );

pos = std::distance( results.m_ibegin, br.first);

size_type subst_length = _do_subst_internal(str, results, pat, pos + pos_offset, match_length );

if( pat._save_backrefs() )

{

pos += match_length;

pos_offset += ( subst_length - match_length );

// Handle specially the backref flags

if( fFirst )

{

rgtempbackrefs.push_back( br );

}

else if( fAll )

{

rgtempbackrefs.insert(

rgtempbackrefs.end(),

results.m_rgbackrefs.begin(),

results.m_rgbackrefs.end() );

}

else

{

rgtempbackrefs.swap( results.m_rgbackrefs );

}

}

else

{

pos += subst_length;

stop_offset += ( subst_length - match_length );

results.m_ibegin =results.m_pbackref_str->begin();

// we're not saving backref information, so wedon't

// need to do any special backref maintenancehere

}

// prevent a pattern that matches 0 charactersfrom matching

// again at the same point in the string

param.m_no0len = ( 0 == match_length );

param.m_imatchbegin = results.m_ibegin;

std::advance( param.m_imatchbegin, pos ); //ineffecient for bidirectional iterators.

param.m_iend = results.m_ibegin;

std::advance( param.m_iend, stop_offset ); //ineffecient for bidirectional iterators.

}

// If we did special backref handling, swap thebackref vectors

if( pat._save_backrefs() )

{

results.m_rgbackrefs.swap( rgtempbackrefs );

}

else if( ! results.m_rgbackrefs[0].matched )

{

results.m_rgbackrefs.clear();

}

}

else if( _do_try_match( pat, param,results.m_rgbackrefs, false ) )

{

backref_type const & br =param.m_prgbackrefs[0];

++csubst;

_do_subst_internal(

str, results, pat,

std::distance( results.m_ibegin, br.first ),

std::distance( br.first, br.second ) );

results.m_ibegin =results.m_pbackref_str->begin();

}

if( NOBACKREFS == ( pat.flags() &NOBACKREFS ) )

{

results.m_rgbackrefs.clear();

}

return csubst;

}

static instantiator instantiate()

{

return instantiator_helper

(

&regex_access::_do_match_iterative_helper_s,

&regex_access::_do_match_iterative_helper_c,

&regex_access::_do_match_recursive_s,

&regex_access::_do_match_recursive_c,

&regex_access::_do_match_with_stack,

&regex_access::_do_match_impl

);

}

};

//

// Some helper functions needed byprocess_escapes

//

template< typename CharT >

inline bool regex_isxdigit( CharT ch )

{

return ( REGEX_CHAR(CharT,'0') <= ch&& REGEX_CHAR(CharT,'9') >= ch )

|| ( REGEX_CHAR(CharT,'a') <= ch &&REGEX_CHAR(CharT,'f') >= ch )

|| ( REGEX_CHAR(CharT,'A') <= ch &&REGEX_CHAR(CharT,'F') >= ch );

}

template< typename CharT >

inline int regex_xdigit2int( CharT ch )

{

if( REGEX_CHAR(CharT,'a') <= ch &&REGEX_CHAR(CharT,'f') >= ch )

return ch - REGEX_CHAR(CharT,'a') + 10;

if( REGEX_CHAR(CharT,'A') <= ch &&REGEX_CHAR(CharT,'F') >= ch )

return ch - REGEX_CHAR(CharT,'A') + 10;

return ch - REGEX_CHAR(CharT,'0');

}

} // namespace detail

//--------------------------------------------------------------------------

//

// Function: process_escapes

//

// Description: Turn the escape sequnces /f /n/r /t /v // into their

// ASCII character equivalents. Also,optionally process

// perl escape sequences.

//

// Returns: void

//

// Arguments: str - the string to process

// fPattern - true if the string is to beprocessed as a regex

//

// Notes: When fPattern is true, the perlescape sequences are not

// processed. If there is an octal or hexexcape sequence, we

// don't want to turn it into a regexmetacharacter here. We

// leave it unescaped so the regex parsercorrectly interprests

// it as a character literal.

//

// History: 8/1/2001 - ericne - Created

//

//--------------------------------------------------------------------------

template< typename CharT, typename TraitsT,typename AllocT >

inline void process_escapes(std::basic_string<CharT, TraitsT, AllocT> & str, bool fPattern )//throw()

{

typedef typename std::basic_string<CharT,TraitsT, AllocT>::size_type size_type;

size_type i = 0;

size_type const npos =std::basic_string<CharT, TraitsT, AllocT>::npos;

if( str.empty() )

return;

while( npos != ( i = str.find(REGEX_CHAR(CharT,'//'), i ) ) )

{

if( str.size() - 1 == i )

return;

switch( str[i+1] )

{

case REGEX_CHAR(CharT,'a'):

str.replace( i, 2, 1, REGEX_CHAR(CharT,'/a') );

break;

case REGEX_CHAR(CharT,'b'):

if( ! fPattern )

str.replace( i, 2, 1, REGEX_CHAR(CharT,'/b') );

else

++i;

break;

case REGEX_CHAR(CharT,'e'):

str.replace( i, 2, 1, CharT( 27 ) );

break;

case REGEX_CHAR(CharT,'f'):

str.replace( i, 2, 1, REGEX_CHAR(CharT,'/f') );

break;

case REGEX_CHAR(CharT,'n'):

str.replace( i, 2, 1, REGEX_CHAR(CharT,'/n') );

break;

case REGEX_CHAR(CharT,'r'):

str.replace( i, 2, 1, REGEX_CHAR(CharT,'/r') );

break;

case REGEX_CHAR(CharT,'t'):

str.replace( i, 2, 1, REGEX_CHAR(CharT,'/t') );

break;

case REGEX_CHAR(CharT,'v'):

str.replace( i, 2, 1, REGEX_CHAR(CharT,'/v') );

break;

case REGEX_CHAR(CharT,'//'):

if( fPattern )

{

if( i+3 < str.size() &&REGEX_CHAR(CharT,'//') == str[i+2] && REGEX_CHAR(CharT,'//') ==str[i+3] )

str.erase( i, 2 );

++i;

}

else

str.erase( i, 1 );

break;

case REGEX_CHAR(CharT,'0'): caseREGEX_CHAR(CharT,'1'): case REGEX_CHAR(CharT,'2'): case REGEX_CHAR(CharT,'3'):

case REGEX_CHAR(CharT,'4'): caseREGEX_CHAR(CharT,'5'): case REGEX_CHAR(CharT,'6'): case REGEX_CHAR(CharT,'7'):

if( ! fPattern )

{

size_t j=i+2;

CharT ch = CharT( str[i+1] -REGEX_CHAR(CharT,'0') );

for( ; j-i < 4 && j < str.size()&& REGEX_CHAR(CharT,'0') <= str[j] && REGEX_CHAR(CharT,'7')>= str[j]; ++j )

ch = CharT( ch * 8 + ( str[j] -REGEX_CHAR(CharT,'0') ) );

str.replace( i, j-i, 1, ch );

}

break;

case REGEX_CHAR(CharT,'x'):

if( ! fPattern )

{

CharT ch = 0;

size_t j=i+2;

for( ; j-i < 4 && j < str.size()&& detail::regex_isxdigit( str[j] ); ++j )

ch = CharT( ch * 16 + detail::regex_xdigit2int(str[j] ) );

str.replace( i, j-i, 1, ch );

}

break;

case REGEX_CHAR(CharT,'c'):

if( ! fPattern && i+2 < str.size() )

{

CharT ch = str[i+2];

if( REGEX_CHAR(CharT,'a') <= ch &&REGEX_CHAR(CharT,'z') >= ch )

ch = detail::regex_toupper( ch );

str.replace( i, 3, 1, CharT( ch ^ 0x40 ) );

}

break;

default:

if( fPattern )

++i;

else

str.erase( i, 1 );

break;

}

++i;

if( str.size() <= i )

return;

}

}

#endif

//+---------------------------------------------------------------------------

//

// Copyright ( C ) Microsoft, 1994 - 2002.

//

// File: syntax2.cpp

//

// Contents: data definitions for the syntaxmodules

//

// Classes:

//

// Functions:

//

// Coupling:

//

// Notes:

//

// Author: Eric Niebler ( ericne@microsoft.com)

//

// History: 3-29-00ericne Created

//

//----------------------------------------------------------------------------

#include "syntax2.h"

namespace regex

{

REGEX_SELECTANY TOKEN constperl_syntax_base::s_rgreg[ UCHAR_MAX + 1 ] =

{

/* 0*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 8*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 16*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 24*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 32*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,END_LINE, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 40*/ BEGIN_GROUP, END_GROUP, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, MATCH_ANY, NO_TOKEN,

/* 48*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 56*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 64*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 72*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 80*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 88*/ NO_TOKEN, NO_TOKEN, NO_TOKEN,BEGIN_CHARSET, ESCAPE, NO_TOKEN, BEGIN_LINE, NO_TOKEN,

/* 96*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/*104*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/*112*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/*120*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,ALTERNATION, NO_TOKEN, NO_TOKEN, NO_TOKEN

// and the rest are 0...

};

REGEX_SELECTANY TOKEN constperl_syntax_base::s_rgescape[ UCHAR_MAX + 1 ] =

{

/* 0*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 8*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 16*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 24*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 32*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 40*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 48*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 56*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 64*/ NO_TOKEN, ESC_BEGIN_STRING,ESC_NOT_WORD_BOUNDARY, NO_TOKEN,

ESC_NOT_DIGIT, ESC_QUOTE_META_OFF, NO_TOKEN,NO_TOKEN,

/* 72*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 80*/ NO_TOKEN, ESC_QUOTE_META_ON, NO_TOKEN,ESC_NOT_SPACE,

NO_TOKEN, NO_TOKEN, NO_TOKEN, ESC_NOT_WORD,

/* 88*/ NO_TOKEN, NO_TOKEN, ESC_END_STRING,NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/* 96*/ NO_TOKEN, NO_TOKEN, ESC_WORD_BOUNDARY, NO_TOKEN,

ESC_DIGIT, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/*104*/ NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN,

/*112*/ NO_TOKEN, NO_TOKEN, NO_TOKEN,ESC_SPACE,

NO_TOKEN, NO_TOKEN, NO_TOKEN, ESC_WORD,

/*120*/ NO_TOKEN, NO_TOKEN, ESC_END_STRING_z,NO_TOKEN,

NO_TOKEN, NO_TOKEN, NO_TOKEN, NO_TOKEN

// and the rest are 0...

};

namespace detail

{

REGEX_SELECTANY extern posix_charset_type constg_rgposix_charsets[] =

{

{ "[:alnum:]", 9 },

{ "[:^alnum:]", 10 },

{ "[:alpha:]", 9 },

{ "[:^alpha:]", 10 },

{ "[:blank:]", 9 },

{ "[:^blank:]", 10 },

{ "[:cntrl:]", 9 },

{ "[:^cntrl:]", 10 },

{ "[:digit:]", 9 },

{ "[:^digit:]", 10 },

{ "[:graph:]", 9 },

{ "[:^graph:]", 10 },

{ "[:lower:]", 9 },

{ "[:^lower:]", 10 },

{ "[:print:]", 9 },

{ "[:^print:]", 10 },

{ "[:punct:]", 9 },

{ "[:^punct:]", 10 },

{ "[:space:]", 9 },

{ "[:^space:]", 10 },

{ "[:upper:]", 9 },

{ "[:^upper:]", 10 },

{ "[:xdigit:]", 10 },

{ "[:^xdigit:]", 11 }

};

REGEX_SELECTANY extern size_t constg_cposix_charsets = ARRAYSIZE( g_rgposix_charsets );

} // namespace detail

} // namespace regex

/***

*resetstk - Recover from Stack overflow.

*

* Copyright (c) Microsoft Corporation. Allrights reserved.

*

*Purpose:

* Defines the _resetstkoflw() function.

*

*******************************************************************************/

#if defined(_MSC_VER) & _MSC_VER < 1300

#include <stdlib.h>

#include <malloc.h>

#include <windows.h>

#define MIN_STACK_REQ_WIN9X 0x11000

#define MIN_STACK_REQ_WINNT 0x2000

#ifdef _WIN64

typedef unsigned __int64 REGEX_DWORD_PTR;

#else

typedef unsigned __int32 REGEX_DWORD_PTR;

#endif

struct osplatform_getter

{

int m_osplatform;

osplatform_getter() : m_osplatform( 0 )

{

OSVERSIONINFOA osvi;

osvi.dwOSVersionInfoSize =sizeof(OSVERSIONINFOA);

if( GetVersionExA( & osvi ) )

m_osplatform = osvi.dwPlatformId;

}

};

inline int get_osplatform()

{

static osplatform_getter consts_osplatform_getter;

return s_osplatform_getter.m_osplatform;

};

/***

* void _resetstkoflw(void) - Recovers fromStack Overflow

*

* Purpose:

* Sets the guard page to its position beforethe stack overflow.

*

* Exit:

* Returns nonzero on success, zero on failure

*

*******************************************************************************/

extern "C" int __cdecl_resetstkoflw(void)

{

LPBYTE pStack, pGuard, pStackBase, pMinGuard;

MEMORY_BASIC_INFORMATION mbi;

SYSTEM_INFO si;

DWORD PageSize;

DWORD flNewProtect;

DWORD flOldProtect;

// Use _alloca() to get the current stackpointer

pStack = static_cast<LPBYTE>( _alloca(1));

// Find the base of the stack.

if (VirtualQuery(pStack, &mbi, sizeof mbi)== 0)

return 0;

pStackBase = static_cast<LPBYTE>(mbi.AllocationBase );

// Find the page just below where the stackpointer currently points.

// This is the new guard page.

GetSystemInfo(&si);

PageSize = si.dwPageSize;

pGuard = (LPBYTE) (((REGEX_DWORD_PTR)pStack& ~(REGEX_DWORD_PTR)(PageSize - 1))

- PageSize);

// If the potential guard page is too close tothe start of the stack

// region, abandon the reset effort for lack ofspace. Win9x has a

// larger reserved stack requirement.

pMinGuard = pStackBase + ((get_osplatform() ==VER_PLATFORM_WIN32_WINDOWS)

? MIN_STACK_REQ_WIN9X

: MIN_STACK_REQ_WINNT);

if (pGuard < pMinGuard)

return 0;

// On a non-Win9x system, release the stackregion below the new guard

// page. This can't be done for Win9x becauseof OS limitations.

if (get_osplatform() !=VER_PLATFORM_WIN32_WINDOWS) {

if (pGuard > pStackBase)

VirtualFree(pStackBase, pGuard - pStackBase,MEM_DECOMMIT);

VirtualAlloc(pGuard, PageSize, MEM_COMMIT,PAGE_READWRITE);

}

// Enable the new guard page.

flNewProtect = get_osplatform() ==VER_PLATFORM_WIN32_WINDOWS

? PAGE_NOACCESS

: PAGE_READWRITE | PAGE_GUARD;

return VirtualProtect(pGuard, PageSize,flNewProtect, &flOldProtect);

}

#endif

//+---------------------------------------------------------------------------

//

// Copyright ( C ) Microsoft, 1994 - 2002.

//

// File: regexpr2.h

//

// Contents: classes for regular expressionpattern matching a-la perl

//

// Classes: basic_rpattern_base

//

// Functions: rpattern::match

// rpattern::substitute

// match_results::cbackrefs

// match_results::backref

// match_results::all_backrefs

// match_results::backref_str

//

// Author: Eric Niebler ( ericne@microsoft.com)

//

//----------------------------------------------------------------------------

#ifndef REGEXPR_H

#define REGEXPR_H

#ifdef _MSC_VER

// warning C4189: local variable is initializedbut not referenced

// warning C4290: C++ exception specificationignored except to indicate a function is not __declspec(nothrow)

// warning C4702: unreachable code

// warning C4710: function 'blah' not inlined

// warning C4786: identifier was truncated to'255' characters in the debug information

# pragma warning( push )

# pragma warning( disable : 4189 4290 4702 47104786 )

# define REGEX_SEH_STACK_OVERFLOW 0xC00000FDL

# if 1200 < _MSC_VER

# include <malloc.h> // for _resetstkoflw

# else

extern "C" int __cdecl_resetstkoflw(void);

# endif

extern "C" unsigned long __cdecl_exception_code(void);

#endif

#include <list>

#include <iosfwd>

#include <string>

#include <vector>

#include <memory>

#include <cwctype>

#include "syntax2.h"

#include "restack.h"

namespace regex

{

// This is the default alignment for the unsafeheterogeneous stack.

// If you are getting a compiler error in oneof the unsafe_stack

// methods, then compile with-DREGEX_STACK_ALIGNMENT=16 or 32

#ifndef REGEX_STACK_ALIGNMENT

# define REGEX_STACK_ALIGNMENT sizeof( void* )

#endif

#if !defined( REGEX_DEBUG ) & ( defined(DEBUG ) | defined( _DEBUG ) | defined( DBG ) )

# define REGEX_DEBUG 1

#else

# define REGEX_DEBUG 0

#endif

#if !defined( REGEX_DEBUG_ITERATORS ) &defined( _HAS_ITERATOR_DEBUGGING )

# define REGEX_DEBUG_ITERATORS 1

#else

# define REGEX_DEBUG_ITERATORS 0

#endif

namespace detail

{

#if REGEX_DEBUG | REGEX_DEBUG_ITERATORS

// Turn on hetero_stack's run-time typechecking

typedefhetero_stack<REGEX_STACK_ALIGNMENT,true,false,32,0> unsafe_stack;

#else

// Assume that all types pushed on stack havetrivial destructors.

typedefhetero_stack<REGEX_STACK_ALIGNMENT,false,true,4096,1024> unsafe_stack;

#endif

// Used to initialize variables with the samevalue they would have

// if they were initialized as a static global.( Ptrs get NULL,

// integer types get 0, etc, etc )

template< typename T > struct static_init{ static T const value; };

template< typename T > T conststatic_init<T>::value = T();

//

// Forward declarations

//

template< typename IterT > classsub_expr;

template< typename IterT > classmatch_group_base;

template< typename IterT > classbasic_rpattern_base_impl;

template< typename IterT > structmatch_param;

template< typename IterT > structsub_expr_base;

template< typename IterT > structregex_access;

// an iterator that keeps track of whether itis singular or not.

template< typename IterT > structsmart_iter

{

IterT m_iter;

bool m_valid;

smart_iter()

: m_iter( static_init<IterT>::value )

, m_valid( false )

{

}

smart_iter( smart_iter const & rhs )

: m_iter( rhs.m_iter )

, m_valid( rhs.m_valid )

{

}

smart_iter( IterT iter ) // implicit conversionOK!

: m_iter( iter )

, m_valid( true )

{

}

smart_iter & operator=( smart_iter const& rhs )

{

m_iter = rhs.m_iter;

m_valid = rhs.m_valid;

return *this;

}

friend bool operator==( smart_iter const &lhs, smart_iter const & rhs )

{

if( !lhs.m_valid || !rhs.m_valid )

return lhs.m_valid == rhs.m_valid;

else

return lhs.m_iter == rhs.m_iter;

}

friend bool operator!=( smart_iter const &lhs, smart_iter const & rhs )

{

return ! operator==( lhs, rhs );

}

};

template< typename IterT > structiter_select

{

typedef typename select

REGEX_DEBUG_ITERATORS &&!is_scalar<IterT>::value,

smart_iter<IterT>,

IterT

>::type type;

};

template< int SizeT > structtype_with_size { char buffer[ SizeT ]; };

// make up for the fact that the VC6std::allocator does

// not have template constructors

template< typename ToT, typename FromT >

std::allocator<ToT> convert_allocator(std::allocator<FromT>, int )

{

return std::allocator<ToT>();

}

template< typename ToT, typename FromT >

FromT const & REGEX_CDECLconvert_allocator( FromT const & from, ... )

{

return from;

}

template< int > struct rebind_helper;

// unknown allocator

template< typename T >

type_with_size<1> REGEX_CDECLallocator_picker( T const &, ... );

template<> struct rebind_helper<1>

{

template< typename AllocT, typename ElemT>

struct inner

{

REGEX_NVC6( typedef typename AllocT::templaterebind<ElemT>::other type; )

};

};

// std::allocator

template< typename T >

type_with_size<2> allocator_picker(std::allocator<T> const &, int );

template<> struct rebind_helper<2>

{

template< typename, typename ElemT >

struct inner

{

typedef std::allocator<ElemT> type;

};

};

template< typename AllocT, typename ElemT>

struct rebind

{

enum { alloc_type =sizeof(allocator_picker(factory<AllocT>::make(),0)) };

typedef typenamerebind_helper<alloc_type>::template inner<AllocT,ElemT>::type type;

};

}

//--------------------------------------------------------------------------

//

// Class: width_type

//

// Description: represents the width of asub-expression

//

// Members: m_min - smallest number ofcharacters a sub-expr can span

// m_max - largest number of characters asub-expr can span

//

// History: 8/14/2000 - ericne - Created

//

//--------------------------------------------------------------------------

struct width_type

{

size_t m_min;

size_t m_max;

};

inline width_type const uninit_width()

{

width_type const width = { size_t( -1 ),size_t( -1 ) };

return width;

}

// Helper function for processing escapesequences

template< typename CharT, typename TraitsT,typename AllocT >

void process_escapes( std::basic_string<CharT,TraitsT, AllocT> & str, bool fPattern = false ); //throw()

//--------------------------------------------------------------------------

//

// Class: backref_tag

//

// Description: Struct which contains aback-reference. It is a template

// on the iterator type.

//

// Methods: backref_tag - c'tor

// operator bool - so that if( br ) is true ifthis br matched

// operator! - inverse of operator bool()

//

// Members: reserved - move along, nothing tosee here

//

// History: 8/9/2001 - ericne - Created

//

//--------------------------------------------------------------------------

template< typename IterT >

class backref_tag : public std::pair<IterT,IterT>

{

struct detail_t { detail_t * d; };

template< typename OStreamT, typename OtherT>

void REGEX_CDECL _do_print( OStreamT &sout, OtherT, ... ) const

{

typedef typename OStreamT::char_type char_type;

typedef typename OStreamT::traits_typetraits_type;

std::ostreambuf_iterator<char_type,traits_type> iout( sout );

for( IterT iter = first; iter != second; ++iter,++iout )

*iout = *iter;

}

// overload that is optimized for bare char*

template< typename OStreamT >

void _do_print( OStreamT & sout, typenameOStreamT::char_type const *, int ) const

{

sout.write( first,static_cast<std::streamsize>( std::distance( first, second ) ) );

}

public:

typedef IterT iterator_type;

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef std::basic_string<char_type>string_type;

typedef typenamedetail::iter_select<IterT>::type smart_iter_type;

explicit backref_tag

(

IterT i1 =detail::static_init<IterT>::value,

IterT i2 =detail::static_init<IterT>::value

)

: std::pair<IterT, IterT>( i1, i2 )

, matched( false )

, reserved1( i1 )

, reserved2( 0 )

, reserved3( false )

, reserved4( detail::static_init<smart_iter_type>::value)

, reserved5(detail::static_init<smart_iter_type>::value )

{

}

IterT begin() const

{

return first;

}

IterT end() const

{

return second;

}

string_type const str() const

{

return matched ? string_type( first, second ) :string_type();

}

// Use the "safe bool" idiom. Thisallows implicit conversion to bool,

// but not to int. It also disallows conversionto void*.

typedef detail_t * detail_t::* bool_type;

operator bool_type() const //throw()

{

return matched ? &detail_t::d : 0;

}

bool operator!() const //throw()

{

return ! matched;

}

template< typename CharT, typename TraitsT>

std::basic_ostream<CharT, TraitsT> &print( std::basic_ostream<CharT, TraitsT> & sout ) const

{

_do_print( sout, IterT(), 0 );

return sout;

}

bool matched;

//private:

IterT reserved1; // used for internalbook-keeping

size_t reserved2; // used for internalbook-keeping

bool reserved3; // used for internalbook-keeping

smart_iter_type reserved4; // used for internalbook-keeping

smart_iter_type reserved5; // used for internalbook-keeping

};

//namespace detail

//{

// indexing into the backref vector is fasterif the backref_tag struct

// has a size that is a power of 2.

//staticstatic_assert<32==sizeof(backref_tag<char*>)> constcheck_backref_size;

//}

// --------------------------------------------------------------------------

//

// Class: basic_match_results

//

// Description: Use this structure forreturning match/substitute results

// out from the match()/substitute() methods.

//

// Methods: cbackrefs -

// backref -

// all_backrefs -

// rlength -

//

// Members: m_rgbackrefs -

//

// Typedefs: const_iterator -

// backref_type -

// backref_vector -

//

// History: 8/8/2001 - ericne - Created

//

//--------------------------------------------------------------------------

template

typename IterT,

typename AllocT = std::allocator<REGEX_DEPENDENT_TYPENAME std::iterator_traits<IterT>::value_type >

struct basic_match_results

{

// const_iterator is deprecated. Useiterator_type instead.

REGEX_DEPRECATED typedef IterT const_iterator;

typedef IterT iterator_type;

typedef backref_tag<IterT> backref_type;

typedef typename detail::rebind<AllocT,backref_type>::type allocator_type;

typedef std::vector<backref_type,allocator_type> backref_vector;

friend struct detail::regex_access<IterT>;

explicit basic_match_results( allocator_typeconst & alloc = allocator_type() )

: m_rgbackrefs( alloc )

{

}

virtual ~basic_match_results()

{

}

size_t cbackrefs() const //throw()

{

return m_rgbackrefs.size();

}

backref_type const & backref( size_t cbackref) const //throw( std::out_of_range )

{

return m_rgbackrefs.at( cbackref );

}

backref_vector const & all_backrefs() const//throw()

{

return m_rgbackrefs;

}

size_t rstart( size_t cbackref = 0 ) const//throw( std::out_of_range )

{

return std::distance( m_ibegin,m_rgbackrefs.at( cbackref ).first );

}

size_t rlength( size_t cbackref = 0 ) const//throw( std::out_of_range )

{

return std::distance( m_rgbackrefs.at( cbackref).first, m_rgbackrefs.at( cbackref ).second );

}

private:

backref_vector m_rgbackrefs;

IterT m_ibegin;

};

// Unnecessary and deprecated

template< typename CharT, typename AllocT =std::allocator<CharT> >

struct basic_match_results_c : publicbasic_match_results<CharT const *, AllocT>

{

typedef basic_match_results<CharT const *,AllocT> base;

REGEX_DEPRECATED typedef typenamebase::const_iterator const_iterator;

typedef typename base::iterator_typeiterator_type;

typedef typename base::backref_typebackref_type;

typedef typename base::allocator_typeallocator_type;

typedef typename base::backref_vectorbackref_vector;

explicit basic_match_results_c( allocator_typeconst & alloc = allocator_type() )

: basic_match_results<CharT const *,AllocT>( alloc )

{

}

};

template< typename CharT, typename TraitsT,typename AllocT >

struct subst_results_base

{

typedef typename detail::rebind<AllocT,CharT>::type char_allocator_type;

typedef std::basic_string<CharT, TraitsT,char_allocator_type> string_type;

typedef typename string_type::const_iteratoriterator_type;

typedef basic_match_results<iterator_type,AllocT>type;

};

//

// For storing the results of a substitute()operation

//

template

typename CharT,

typename TraitsT =std::char_traits<CharT>,

typename AllocT = std::allocator<CharT>

struct basic_subst_results : publicsubst_results_base<CharT, TraitsT, AllocT>::type

{

typedef typename detail::rebind<AllocT,CharT>::type char_allocator_type;

typedef std::basic_string<CharT, TraitsT,char_allocator_type> string_type;

typedef typename string_type::const_iteratoriterator_type;

typedef basic_match_results<iterator_type,AllocT> base;

typedef typename base::backref_typebackref_type;

typedef typename base::allocator_typeallocator_type;

typedef typename base::backref_vectorbackref_vector;

friend structdetail::regex_access<iterator_type>;

explicit basic_subst_results( allocator_typeconst & alloc = allocator_type() )

: basic_match_results< iterator_type, AllocT>( alloc )

, m_backref_str(detail::convert_allocator<CharT>( alloc, 0 ) )

, m_pbackref_str( &m_backref_str )

{

}

string_type const & backref_str() const//throw()

{

return *m_pbackref_str;

}

private:

string_type m_backref_str;

string_type const * m_pbackref_str;

};

template< typename CharT, typename TraitsT,typename AllocT >

struct split_results_base

{

typedef typename detail::rebind<AllocT,CharT>::type char_allocator_type;

typedef std::basic_string<CharT, TraitsT,char_allocator_type> string_type;

typedef typename detail::rebind<AllocT,string_type>::type allocator_type;

typedefstd::vector<string_type,allocator_type> type;

};

//

// For storing the results of a split()operation

//

template

typename CharT,

typename TraitsT =std::char_traits<CharT>,

typename AllocT = std::allocator<CharT>

struct basic_split_results : privatesplit_results_base<CharT, TraitsT, AllocT>::type

{

typedef CharT char_type;

typedef typename detail::rebind<AllocT,CharT>::type char_allocator_type;

typedef std::basic_string<CharT, TraitsT,char_allocator_type> string_type;

typedef typename detail::rebind<AllocT,string_type>::type allocator_type;

typedef std::vector<string_type,allocator_type>string_vector;

typedef string_vector base;

explicit basic_split_results( allocator_typeconst & alloc = allocator_type() )

: base( alloc )

{

}

#if !defined(_MSC_VER) | 1200 < _MSC_VER

typedef typename allocator_type::pointerpointer;

typedef typename allocator_type::const_pointerconst_pointer;

#else

typedef string_type * pointer;

typedef string_type const * const_pointer;

#endif

// shortcuts to the most basic read-onlycontainer operations

typedef typename base::size_type size_type;

typedef typename base::difference_typedifference_type;

typedef typename base::value_type value_type;

typedef typename base::reference reference;

typedef typename base::const_referenceconst_reference;

typedef typename base::iterator iterator;

typedef typename base::const_iteratorconst_iterator;

typedef typename base::reverse_iteratorreverse_iterator;

typedef typename base::const_reverse_iteratorconst_reverse_iterator;

using base::begin;

using base::end;

using base::rbegin;

using base::rend;

using base::operator[];

using base::at;

using base::size;

using base::front;

using base::back;

string_vector & strings()

{

return *this;

}

string_vector const & strings() const

{

return *this;

}

};

//

// The REGEX_MODE is a way of controlling howmatching occurs.

//

enum REGEX_MODE

{

MODE_FAST, // Uses the fast, recursivealgorithm. Could overflow stack.

MODE_SAFE, // Uses the slow, iterativealgorithm. Can't overflow stack.

MODE_MIXED, // Uses a heuristic toautomatically determine which algorithm

// is the most appropriate for this pattern.

// MS VC++ has structured exception handling,which makes the

// consequences of a stack overflow much lesssevere. Because of this,

// it is possible to use the "fast"algorithm always on MS platforms,

#ifdef _MSC_VER

MODE_DEFAULT = MODE_FAST

#else

MODE_DEFAULT = MODE_MIXED

#endif

};

//

// helper function for resetting the intrinsiccharacter sets.

// This should be called after changing thelocale with setlocale()

//

template< typename CharT >

void reset_intrinsic_charsets( CharT ch =CharT( 0 ) );

// This is for implementation details thatreally belong in the

// cpp file, but can't go there because oftemplate strangeness.

#include "reimpl2.h"

//--------------------------------------------------------------------------

//

// Class: basic_rpattern_base

//

// Description:

//

// Methods: basic_rpattern_base - c'tor

// basic_rpattern_base -

// basic_rpattern_base -

// init - ( re )initialize the pattern

// init -

// set_substitution - set the substitutionstring

// _find_next_group - parse the next group ofthe pattern

// _find_next - parse the next sub_expr of thepattern

// _find_atom - parse the next atom of thepattern

// _quantify - quantify the sub_expr

// _common_init - perform some commoninitialization tasks

// _parse_subst - parse the substitution string

// _add.m_subst_backref - add a backref node tothe subst list

//

// Members: m_invisible_groups - list of hiddengroups

//

// Typedefs: syntax_type -

// backref_type -

// backref_vector -

// string_type -

// size_type -

//

// History: 8/14/2000 - ericne - Created

// 8/5/2001 - ericne - complete overhaul

//

//--------------------------------------------------------------------------

template< typename IterT, typename SyntaxT>

class basic_rpattern_base : protected detail::basic_rpattern_base_impl<IterT>

{

protected:

typedefdetail::basic_rpattern_base_impl<IterT> impl;

public:

typedef SyntaxT syntax_type;

typedef typename impl::char_type char_type;

typedef typename impl::traits_type traits_type;

typedef typename impl::string_type string_type;

typedef typename impl::size_type size_type;

typedef typename impl::backref_typebackref_type;

typedef typename impl::backref_vectorbackref_vector;

void init

(

string_type const & pat,

REGEX_FLAGS flags = NOFLAGS,

REGEX_MODE mode = MODE_DEFAULT

); //throw( bad_regexpr, std::bad_alloc );

void init

(

string_type const & pat,

string_type const & subst,

REGEX_FLAGS flags = NOFLAGS,

REGEX_MODE mode = MODE_DEFAULT

); //throw( bad_regexpr, std::bad_alloc );

void set_substitution

(

string_type const & subst

); //throw( bad_regexpr, std::bad_alloc );

using impl::flags;

using impl::mode;

using impl::get_width;

using impl::cgroups;

using impl::get_pat;

using impl::get_subst;

using impl::swap;

using impl::npos;

protected:

basic_rpattern_base() //throw()

:detail::basic_rpattern_base_impl<IterT>()

{

}

basic_rpattern_base(basic_rpattern_base<IterT, SyntaxT> const & that ) //throw()

:detail::basic_rpattern_base_impl<IterT>( that.flags(), that.mode(),that.get_pat(), that.get_subst() )

{

// Don't call _normalize_string(). Ifthat.flags()&NORMALIZE,

// then subst has already been normalized.

_common_init( this->m_flags );

_parse_subst( *this->m_subst,this->m_fuses_backrefs, this->m_subst_list ); // must come after_common_init

}

explicit basic_rpattern_base

(

string_type const & pat,

REGEX_FLAGS flags = NOFLAGS,

REGEX_MODE mode = MODE_DEFAULT

) //throw( bad_regexpr, std::bad_alloc )

:detail::basic_rpattern_base_impl<IterT>( flags, mode, pat )

{

_common_init( this->m_flags );

}

basic_rpattern_base

(

string_type const & pat,

string_type const & subst,

REGEX_FLAGS flags = NOFLAGS,

REGEX_MODE mode = MODE_DEFAULT

) //throw( bad_regexpr, std::bad_alloc )

:detail::basic_rpattern_base_impl<IterT>( flags, mode, pat, subst )

{

_common_init( this->m_flags );

_normalize_string( *this->m_subst );

_parse_subst( *this->m_subst,this->m_fuses_backrefs, this->m_subst_list ); // must come after_common_init

}

basic_rpattern_base & operator=

(

basic_rpattern_base<IterT, SyntaxT> const& that

) //throw( bad_regexpr, std::bad_alloc )

{

basic_rpattern_base<IterT, SyntaxT> temp(that );

swap( temp );

return *this;

}

detail::match_group_base<IterT> *_find_next_group

(

typename string_type::iterator & ipat,

detail::match_group_base<IterT> * pgroup,syntax_type & sy,

std::vector<detail::match_group_base<IterT>*>& rggroups

);

bool _find_next

(

typename string_type::iterator & ipat,

detail::match_group_base<IterT> * pgroup,syntax_type & sy,

std::vector<detail::match_group_base<IterT>*>& rggroups

);

void _find_atom

(

typename string_type::iterator & ipat,

detail::match_group_base<IterT> * pgroup,

syntax_type & sy

);

void _quantify

(

std::auto_ptr<detail::sub_expr<IterT>> & pnew,

typename string_type::iterator & ipat,

bool is_group,

syntax_type & sy

);

void _add_subst_backref

(

detail::subst_node & snode,

size_t nbackref,

ptrdiff_t rstart,

bool & uses_backrefs,

detail::subst_list_type & subst_list

) const;

void _parse_subst

(

string_type & subst,

bool & uses_backrefs,

detail::subst_list_type & subst_list

) const;

void _common_init( REGEX_FLAGS flags );

static detail::instantiator instantiate()

{

typedef basic_rpattern_base this_type;

return detail::instantiator_helper

(

&detail::basic_rpattern_base_impl<IterT>::instantiate,

static_cast<void (this_type::*)( string_typeconst &, REGEX_FLAGS, REGEX_MODE )>( &this_type::init ),

static_cast<void (this_type::*)( string_typeconst &, string_type const &, REGEX_FLAGS, REGEX_MODE )>(&this_type::init ),

&this_type::set_substitution,

&this_type::_find_next_group,

&this_type::_find_next,

&this_type::_find_atom,

&this_type::_add_subst_backref,

&this_type::_parse_subst,

&this_type::_common_init

);

}

};

//--------------------------------------------------------------------------

//

// Class: basic_rpattern

//

// Description: generic regex pattern object

//

// Methods: basic_rpattern - c'tor

// basic_rpattern -

// basic_rpattern -

// match - match from begin iter to end iter

// match - match a null-terminated string

// match - match a std::string

// count - count matches from begin iter to enditer

// count - count matches in a null-terminatedstring

// count - count matches in a std::string

// substitute - do substitutions in astd::string

// _do_match - internal implementation

// _do_count - internal implementation

//

// History: 8/13/2001 - ericne - Created

//

//--------------------------------------------------------------------------

template

typename IterT,

typename SyntaxT =perl_syntax<REGEX_DEPENDENT_TYPENAMEstd::iterator_traits<IterT>::value_type>

class basic_rpattern : public basic_rpattern_base<IterT,SyntaxT>

{

typedefdetail::basic_rpattern_base_impl<IterT> impl;

template< typename CharT >

static void same_char_types( CharT, CharT ) {}

public:

typedef typename basic_rpattern_base<IterT,SyntaxT>::syntax_type syntax_type;

typedef typename basic_rpattern_base<IterT,SyntaxT>::char_type char_type;

typedef typename basic_rpattern_base<IterT,SyntaxT>::traits_type traits_type;

typedef typename basic_rpattern_base<IterT,SyntaxT>::string_type string_type;

typedef typename basic_rpattern_base<IterT,SyntaxT>::size_type size_type;

typedef typename basic_rpattern_base<IterT,SyntaxT>::backref_type backref_type;

typedef typename basic_rpattern_base<IterT,SyntaxT>::backref_vector backref_vector;

basic_rpattern() //throw()

: basic_rpattern_base<IterT, SyntaxT>()

{

}

basic_rpattern( basic_rpattern const & that)

: basic_rpattern_base<IterT, SyntaxT>(that )

{

}

explicit basic_rpattern

(

string_type const & pat,

REGEX_FLAGS flags = NOFLAGS,

REGEX_MODE mode = MODE_DEFAULT

) //throw( bad_regexpr, std::bad_alloc )

: basic_rpattern_base<IterT, SyntaxT>(pat, flags, mode )

{

}

basic_rpattern

(

string_type const & pat,

string_type const & subst,

REGEX_FLAGS flags = NOFLAGS,

REGEX_MODE mode = MODE_DEFAULT

) //throw( bad_regexpr, std::bad_alloc )

: basic_rpattern_base<IterT, SyntaxT>(pat, subst, flags, mode )

{

}

basic_rpattern & operator=(basic_rpattern<IterT, SyntaxT> const & that ) //throw( bad_regexpr,std::bad_alloc )

{

basic_rpattern_base<IterT,SyntaxT>::operator=( that );

return *this;

}

// Iter2 must be convertible to type IterT

template< typename OtherT, typename AllocT>

backref_type const & match

(

OtherT ibegin,

OtherT iend,

basic_match_results<IterT, AllocT> &results

) const

{

// If your compile breaks here, it is becauseOtherT is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

detail::static_assert<detail::is_convertible<OtherT,IterT>::value > constiterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

if( detail::regex_access<IterT>::_do_match(*this, results, ibegin, iend, false ) )

{

return results.backref(0);

}

else

{

returndetail::static_init<backref_type>::value;

}

}

template< typename CharT, typename AllocT>

backref_type const & match

(

CharT * szbegin,

basic_match_results<IterT, AllocT> &results

) const

{

// If your compile breaks here, it is becauseCharT* is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

detail::static_assert<detail::is_convertible<CharT*,IterT>::value > const iterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

if(detail::regex_access<IterT>::_do_match_c( *this, results, szbegin ) )

{

return results.backref(0);

}

else

{

returndetail::static_init<backref_type>::value;

}

}

template< typename CharT, typename TraitsT,typename AllocT >

backref_type const & match

(

std::basic_string<CharT, TraitsT, AllocT>const & str,

basic_match_results<IterT, AllocT> &results,

size_type pos = 0,

size_type len =static_cast<size_type>(-1)

) const

{

// If your compile breaks here, it is becauseiter_type is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

typedef typename std::basic_string<CharT,TraitsT, AllocT>::const_iterator iter_type;

detail::static_assert< detail::is_convertible<iter_type,IterT>::value> const iterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

IterT ibegin = str.begin(), iend = str.begin();

if( len == npos || pos + len >= str.size() )

iend = IterT(str.end());

else

std::advance( iend, pos + len );

std::advance( ibegin, pos );

return match( ibegin, iend, results );

}

template< typename OtherT >

size_t count( OtherT ibegin, OtherT iend )const

{

// If your compile breaks here, it is becauseOtherT is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

detail::static_assert<detail::is_convertible<OtherT,IterT>::value > constiterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

returndetail::regex_access<IterT>::_do_count( *this, ibegin, iend, false );

}

template< typename CharT >

size_t count( CharT * szbegin ) const

{

// If your compile breaks here, it is becauseCharT* is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

detail::static_assert<detail::is_convertible<CharT*,IterT>::value > constiterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

returndetail::regex_access<IterT>::_do_count( *this, szbegin, (CharT*)0, true);

}

template< typename CharT, typename TraitsT,typename AllocT >

size_t count

(

std::basic_string<CharT, TraitsT, AllocT>const & str,

size_type pos = 0,

size_type len =static_cast<size_type>(-1)

) const

{

// If your compile breaks here, it is becauseiter_type is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

typedef typename std::basic_string<CharT,TraitsT, AllocT>::const_iterator iter_type;

detail::static_assert<detail::is_convertible<iter_type,IterT>::value > constiterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

IterT ibegin = str.begin(), iend = str.begin();

if( len == npos || pos + len >= str.size() )

iend = IterT(str.end());

else

std::advance( iend, pos + len );

std::advance( ibegin, pos );

return count( ibegin, iend );

}

template< typename OtherT, typename CharT,typename TraitsT, typename AllocT >

size_t split

(

OtherT ibegin,

OtherT iend,

basic_split_results<CharT, TraitsT,AllocT> & results,

int limit = 0

) const

{

// If your compile breaks here, it is becauseOtherT is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

detail::static_assert<detail::is_convertible<OtherT,IterT>::value > constiterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

return detail::regex_access<IterT>::_do_split(*this, results, ibegin, iend, limit, false );

}

template< typename Char1T, typename Char2T,typename TraitsT, typename AllocT >

size_t split

(

Char1T * szbegin,

basic_split_results<Char2T, TraitsT,AllocT> & results,

int limit = 0

) const

{

// If your compile breaks here, it is becauseIter2 is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

detail::static_assert<detail::is_convertible<Char1T*,IterT>::value > constiterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

// If your compile breaks here, it's becausethe string you passed in doesn't have

// the same character type as yoursplit_results struct

same_char_types( Char1T(), Char2T() );

// If your compile breaks here, it is becauseCharT const * is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

returndetail::regex_access<IterT>::_do_split( *this, results, szbegin,(Char1T*)0, limit, true );

}

template< typename CharT, typename TraitsT,typename AllocT >

size_t split

(

std::basic_string<CharT, TraitsT, AllocT>const & str,

basic_split_results<CharT, TraitsT,AllocT> & results,

int limit = 0,

size_type pos = 0,

size_type len =static_cast<size_type>(-1)

) const

{

// If your compile breaks here, it is becauseiter_type is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

typedef typename std::basic_string<CharT,TraitsT, AllocT>::const_iterator iter_type;

detail::static_assert<detail::is_convertible<iter_type,IterT>::value > constiterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

IterT ibegin = str.begin(), iend = str.begin();

if( len == npos || pos + len >= str.size() )

iend = IterT(str.end());

else

std::advance( iend, pos + len );

std::advance( ibegin, pos );

return split( ibegin, iend, results, limit );

}

template< typename CharT, typename TraitsT,typename AllocT >

size_t substitute

(

std::basic_string<CharT, TraitsT, AllocT>& str,

basic_subst_results<CharT, TraitsT, AllocT>& results,

size_type pos = 0,

size_type len =static_cast<size_type>(-1)

) const

{

// If your compile breaks here, it is becauseiter_type is not

// convertible to type IterT. Check thedeclaration of your rpattern object.

typedef typename std::basic_string<CharT,TraitsT, AllocT>::const_iterator iter_type;

detail::static_assert<detail::is_convertible<iter_type,IterT>::value > constiterator_types_are_not_convertible;

( void ) iterator_types_are_not_convertible;

return detail::regex_access<IterT>::_do_subst(*this, str, results, pos, len );

}

};

//--------------------------------------------------------------------------

//

// Class: basic_rpattern_c

//

// Description: a pattern object optimized formatching C-style, NULL-

// terminated strings. It treats thenull-terminator as

// the end-of-string condition.

//

// Methods: basic_rpattern_c - c'tor

// basic_rpattern_c -

// basic_rpattern_c -

// match - match a null-terminated string

// count - count matches in a null-terminatedstring

// _do_match_c - internal implementation

//

// History: 8/13/2001 - ericne - Created

//

//--------------------------------------------------------------------------

template< typename CharT, typename SyntaxT =perl_syntax<CharT> >

class basic_rpattern_c : public basic_rpattern_base<CharTconst *, SyntaxT>

{

typedefdetail::basic_rpattern_base_impl<CharT const *> impl;

public:

typedef typename basic_rpattern_base<CharTconst *, SyntaxT>::syntax_type syntax_type;

typedef typename basic_rpattern_base<CharTconst *, SyntaxT>::char_type char_type;

typedef typename basic_rpattern_base<CharTconst *, SyntaxT>::traits_type traits_type;

typedef typename basic_rpattern_base<CharTconst *, SyntaxT>::string_type string_type;

typedef typename basic_rpattern_base<CharTconst *, SyntaxT>::size_type size_type;

typedef typename basic_rpattern_base<CharTconst *, SyntaxT>::backref_type backref_type;

typedef typename basic_rpattern_base<CharTconst *, SyntaxT>::backref_vector backref_vector;

basic_rpattern_c() //throw()

: basic_rpattern_base<CharT const *,SyntaxT>()

{

}

basic_rpattern_c( basic_rpattern_c const &that )

: basic_rpattern_base<CharT const *,SyntaxT>( that )

{

}

explicit basic_rpattern_c

(

string_type const & pat,

REGEX_FLAGS flags = NOFLAGS,

REGEX_MODE mode = MODE_DEFAULT

) //throw( bad_regexpr, std::bad_alloc )

: basic_rpattern_base<CharT const *,SyntaxT>( pat, flags, mode )

{

}

basic_rpattern_c & operator=(basic_rpattern_c<CharT, SyntaxT> const & that )

{

basic_rpattern_base<CharT const *,SyntaxT>::operator=( that );

return *this;

}

template< typename AllocT >

backref_type const & match

(

CharT const * szbegin,

basic_match_results_c<CharT, AllocT>& results

) const

{

if( detail::regex_access<CharTconst*>::_do_match_c( *this, results, szbegin ) )

{

return results.backref(0);

}

else

{

returndetail::static_init<backref_type>::value;

}

}

size_t count( CharT const * szbegin ) const

{

return detail::regex_access<CharTconst*>::_do_count( *this, szbegin, (CharT const*)0, true );

}

};

#if defined(UNICODE) | defined(_UNICODE)

typedef wchar_t rechar_t;

#else

typedef char rechar_t;

#endif

typedef std::basic_string<rechar_t>restring;

// On many implementations of the STL,string::iterator is not a typedef

// for char*. Rather, it is a wrapper class. Asa result, the regex code

// gets instantiated twice, once for barepointers (rpattern_c) and once for

// the wrapped pointers (rpattern). But ifthere is a conversion from the

// bare ptr to the wrapped ptr, then we onlyneed to instantiate the template

// for the wrapped ptr, and the code will workfor the bare ptrs, too.

// This can be a significant space savings. TheREGEX_FOLD_INSTANTIONS

// macro controls this optimization. Thedefault is "off" for backwards

// compatibility. To turn the optimization on,compile with:

// -DREGEX_FOLD_INSTANTIATIONS=1

#ifndef REGEX_FOLD_INSTANTIATIONS

#define REGEX_FOLD_INSTANTIATIONS 0

#endif

typedef ::regex::detail::select

REGEX_FOLD_INSTANTIATIONS &&

detail::is_convertible<rechar_t const*,restring::const_iterator>::value,

restring::const_iterator,

rechar_t const *

>::type lpctstr_t;

// For matching against null-terminated strings

typedef basic_rpattern<lpctstr_t,perl_syntax<rechar_t> > perl_rpattern_c;

typedef basic_rpattern<lpctstr_t,posix_syntax<rechar_t> > posix_rpattern_c;

// For matching against std::strings

typedefbasic_rpattern<restring::const_iterator, perl_syntax<rechar_t> >perl_rpattern;

typedefbasic_rpattern<restring::const_iterator, posix_syntax<rechar_t> >posix_rpattern;

// Default to perl syntax

typedef perl_rpattern rpattern;

typedef perl_rpattern_c rpattern_c;

// typedefs for the commonly used match_resultsand subst_results

typedefbasic_match_results<restring::const_iterator> match_results;

typedef basic_match_results<lpctstr_t>match_results_c;

typedef basic_subst_results<rechar_t>subst_results;

typedef basic_split_results<rechar_t>split_results;

#if defined(_MSC_VER) & 1200 < _MSC_VER

// These are no longer useful, and will go awayin a future release

// You should be using the version without the_c

# pragma deprecated( basic_rpattern_c )

# pragma deprecated( basic_match_results_c )

#endif

#define STATIC_RPATTERN_EX( type, var, params )/

static type const var params;

#define STATIC_RPATTERN( var, params ) /

STATIC_RPATTERN_EX( regex::rpattern, var,params )

#define STATIC_RPATTERN_C( var, params ) /

STATIC_RPATTERN_EX( regex::rpattern_c, var,params )

#if defined(_MSC_VER) & 1200 < _MSC_VER

#pragma deprecated(STATIC_RPATTERN_EX)

#endif

//

// ostream inserter operator forback-references

//

template< typename CharT, typename TraitsT,typename IterT >

inline std::basic_ostream<CharT, TraitsT>& operator<<

(

std::basic_ostream<CharT, TraitsT> &sout,

backref_tag<IterT> const & br

)

{

return br.print( sout );

}

} // namespace regex

//

// specializations for std::swap

//

namespace std

{

template<>

inline void swap( regex::detail::regex_arena& left, regex::detail::regex_arena & right )

{

left.swap( right );

}

template< typename IterT, typename SyntaxT>

inline void swap(regex::basic_rpattern_base<IterT, SyntaxT> & left, regex::basic_rpattern_base<IterT,SyntaxT> & right )

{

left.swap( right );

}

}

#ifdef _MSC_VER

#pragma warning( pop )

#endif

#endif

//+---------------------------------------------------------------------------

//

// Copyright ( C ) Microsoft, 1994 - 2002.

//

// File: regexpr2.cpp

//

// Contents: implementation for rpatternmethods, definitions for all the

// subexpression types used to perform thematching, the

// charset class definition .

//

// Classes: too many to list here

//

// Functions:

//

// Author: Eric Niebler ( ericne@microsoft.com)

//

// History: 12-11-1998ericne Created

// 01-05-2001 ericneRemoved dependency on VC's choice

// of STL iterator types.

// 08-15-2001 ericneRemoved regexpr class, moved match

// state to match_results container.

// 09-17-2001nathann Add DEBUG_HEAP_SUPPORT

// 11-16-2001 ericneAdd stack-conservative algorithm

//

//----------------------------------------------------------------------------

#ifdef _MSC_VER

// unlimited inline expansion ( compile with/Ob1 or /Ob2 )

# pragma inline_recursion( on )

# pragma inline_depth( 255 )

// warning C4127: conditional expression isconstant

// warning C4355: 'this' : used in base memberinitializer list

// warning C4702: unreachable code

// warning C4710: function 'blah' not inlined

// warning C4786: identifier was truncated to'255' characters in the debug information

# pragma warning( push )

# pragma warning( disable : 4127 4355 4702 47104786 )

#endif

#include <limits>

#include <cctype>

#include <cwchar>

#include <memory>

#include <cwctype>

#include <malloc.h>

#include <algorithm>

#ifdef __MWERKS__

# include <alloca.h>

#endif

// If the implementation file has been includedin the header, then we

// need to mark some functions as inline toprevent them from being multiply

// defined. But if the implementation file isnot included in the header,

// we can't mark them as inline, otherwise thelinker won't find them.

#ifdef REGEXPR_H

# define REGEXPR_H_INLINE inline

#else

# define REGEXPR_H_INLINE

# include "regexpr2.h"

#endif

#ifdef REGEX_TO_INCLUDE

# include REGEX_TO_INCLUDE

#endif

// $PORT$

// _alloca is not standard

#ifndef alloca

# define alloca _alloca

#endif

namespace regex

{

namespace detail

{

inline wctype_t REGEX_CDECL regex_wctype( charconst * sz )

{

using namespace std;

return wctype( sz );

}

namespace

{

#ifdef __GLIBC__

struct regex_ctype_t

{

int m_ctype;

wctype_t m_wctype;

};

#define REGEX_DECL_CTYPE(desc) /

inline regex_ctype_t const & wct_ ## desc()/

{ /

static regex_ctype_t const s_wct = { _IS ##desc, regex_wctype(#desc) };/

return s_wct; /

}

REGEX_DECL_CTYPE(alnum)

REGEX_DECL_CTYPE(alpha)

REGEX_DECL_CTYPE(blank)

REGEX_DECL_CTYPE(cntrl)

REGEX_DECL_CTYPE(digit)

REGEX_DECL_CTYPE(graph)

REGEX_DECL_CTYPE(lower)

REGEX_DECL_CTYPE(print)

REGEX_DECL_CTYPE(punct)

REGEX_DECL_CTYPE(space)

REGEX_DECL_CTYPE(upper)

REGEX_DECL_CTYPE(xdigit)

regex_ctype_t const wct_zero = { 0, 0 };

inline regex_ctype_t & operator |= (regex_ctype_t & lhs, regex_ctype_t const & rhs )

{

lhs.m_ctype |= rhs.m_ctype;

lhs.m_wctype |= rhs.m_wctype;

return lhs;

}

inline regex_ctype_t operator | ( regex_ctype_tlhs, regex_ctype_t const & rhs )

{

return lhs |= rhs;

}

inline int REGEX_CDECL regex_isctype( int ch,regex_ctype_t const & desc )

{

return __isctype( ch, desc.m_ctype );

}

inline int REGEX_CDECL regex_iswctype( wint_twc, regex_ctype_t desc )

{

using namespace std;

return iswctype( wc, desc.m_wctype );

}

inline bool operator == ( regex_ctype_t const& lhs, regex_ctype_t const & rhs )

{

return lhs.m_ctype == rhs.m_ctype &&lhs.m_wctype == rhs.m_wctype;

}

inline bool operator != ( regex_ctype_t const& lhs, regex_ctype_t const & rhs )

{

return lhs.m_ctype != rhs.m_ctype ||lhs.m_wctype != rhs.m_wctype;

}

#else

typedef wctype_t regex_ctype_t;

#define REGEX_DECL_CTYPE(desc) /

inline regex_ctype_t const wct_ ## desc() /

{ /

static regex_ctype_t const s_wct =regex_wctype(#desc); /

return s_wct; /

}

REGEX_DECL_CTYPE(alnum)

REGEX_DECL_CTYPE(alpha)

REGEX_DECL_CTYPE(cntrl)

REGEX_DECL_CTYPE(digit)

REGEX_DECL_CTYPE(graph)

REGEX_DECL_CTYPE(lower)

REGEX_DECL_CTYPE(print)

REGEX_DECL_CTYPE(punct)

REGEX_DECL_CTYPE(space)

REGEX_DECL_CTYPE(upper)

REGEX_DECL_CTYPE(xdigit)

regex_ctype_t const wct_zero = 0;

#if defined(_MSC_VER) & ( _MSC_VER==1200 |defined(_CPPLIB_VER) )

inline regex_ctype_t const wct_blank() { return_BLANK; } // work around for bug in VC++

inline int REGEX_CDECL regex_isctype( int ch,regex_ctype_t desc )

{

return _isctype( ch, static_cast<int>(desc ) );

}

#else

REGEX_DECL_CTYPE(blank)

inline int REGEX_CDECL regex_isctype( int ch,regex_ctype_t desc )

{

using namespace std;

return iswctype( btowc( ch ), desc );

}

#endif

inline int REGEX_CDECL regex_iswctype( wint_twc, regex_ctype_t desc )

{

using namespace std;

return iswctype( wc, desc );

}

#endif

} // unnamed namespace

template< typename CStringsT, typename IterT>

bool _do_match_iterative(sub_expr_base<IterT> const * expr, match_param<IterT> & param,IterT icur, CStringsT );

// NathanN:

// By defining the symbol REGEX_DEBUG_HEAP theallocator object

// no longer sub allocates memory. This enablesheap checking tools like

// AppVerifier & PageHeap to find errorslike buffer overruns

#if !defined( REGEX_DEBUG_HEAP ) &REGEX_DEBUG

# define REGEX_DEBUG_HEAP 1

#else

# define REGEX_DEBUG_HEAP 0

#endif

REGEXPR_H_INLINE size_t DEFAULT_BLOCK_SIZE()

{

#if REGEX_DEBUG_HEAP

// put each allocation in its own mem_block

return 1;

#else

// put multiple allocation in each mem_block

return 352;

#endif

}

template< typename IBeginT, typename IEndT>

inline size_t parse_int( IBeginT & ibegin,IEndT iend, size_t const max_ = size_t( -1 ) )

{

typedef typenamestd::iterator_traits<IEndT>::value_type char_type;

size_t retval = 0;

while( iend != ibegin &&REGEX_CHAR(char_type,'0') <= *ibegin && REGEX_CHAR(char_type,'9')>= *ibegin && max_ > retval )

{

retval *= 10;

retval += static_cast<size_t>( *ibegin -REGEX_CHAR(char_type,'0') );

++ibegin;

}

if( max_ < retval )

{

retval /= 10;

--ibegin;

}

return retval;

}

//--------------------------------------------------------------------------

//

// Class: boyer_moore

//

// Description: fast sub-string searchalgorithm

//

// Members: m_begin - iter to first char inpattern sequence

// m_last - iter to last char in patternsequence

// m_len - length of the pattern sequence

// m_off - array of offsets, indexed by ASCIIchar values

//

// History: 6/8/2003 - ericne - Created

//

//--------------------------------------------------------------------------

template< typename IterT >

class boyer_moore

{

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef typename std::char_traits<char_type>traits_type;

enum { OFFSET_SIZE = UCHAR_MAX + 1 };

IterT m_begin;

IterT m_last;

char_type const* m_low_last;

unsigned char m_len;

unsigned char m_off[ OFFSET_SIZE ];

static unsigned char hash_char( char ch ) {return static_cast<unsigned char>( ch ); }

static unsigned char hash_char( signed char ch) { return static_cast<unsigned char>( ch ); }

static unsigned char hash_char( unsigned charch ) { return ch; }

static unsigned char hash_char( wchar_t ch ) {return static_cast<unsigned char>( ch % OFFSET_SIZE ); }

template< typename CharT >

static unsigned char REGEX_VC6(REGEX_CDECL)hash_char( CharT ch REGEX_VC6(...) )

{

return static_cast<unsigned char>(std::char_traits<CharT>::to_int_type( ch ) % OFFSET_SIZE );

}

// case-sensitive Boyer-Moore search

template< typename OtherT >

OtherT find_with_case( OtherT begin, OtherT end) const

{

typedef typenamestd::iterator_traits<OtherT>::difference_type diff_type;

diff_type const endpos = std::distance( begin,end );

diff_type offset = m_len;

for( diff_type curpos = offset; curpos <endpos; curpos += offset )

{

std::advance( begin, offset );

IterT pat_tmp = m_last;

OtherT str_tmp = begin;

for( ; traits_type::eq( *str_tmp, *pat_tmp );

--pat_tmp, --str_tmp )

{

if( pat_tmp == m_begin )

{

return str_tmp;

}

}

offset = m_off[ hash_char( *begin ) ];

}

return end;

}

// case-insensitive Boyer-Moore search

template< typename OtherT >

OtherT find_without_case( OtherT begin, OtherTend ) const

{

typedef typenamestd::iterator_traits<OtherT>::difference_type diff_type;

diff_type const endpos = std::distance( begin,end );

diff_type offset = m_len;

for( diff_type curpos = offset; curpos <endpos; curpos += offset )

{

std::advance( begin, offset );

IterT pat_tmp = m_last;

char_type const* low_tmp = m_low_last;

OtherT str_tmp = begin;

for( ; traits_type::eq( *str_tmp, *pat_tmp ) ||traits_type::eq( *str_tmp, *low_tmp );

--pat_tmp, --str_tmp, --low_tmp )

{

if( pat_tmp == m_begin )

{

return str_tmp;

}

}

offset = m_off[ hash_char( *begin ) ];

}

return end;

}

public:

// initialize the Boyer-Moore search datastructure, using the

// search sub-sequence to prime the pump.

boyer_moore( IterT begin, IterT end, char_typeconst* lower = 0 )

: m_begin( begin )

, m_last( begin )

, m_low_last( lower )

{

typedef typename std::iterator_traits<IterT>::difference_typediff_type;

diff_type diff = std::distance( begin, end );

m_len = static_cast<unsigned char>(regex_min<diff_type>( diff, UCHAR_MAX ) );

std::fill_n( m_off, ARRAYSIZE( m_off ), m_len);

--m_len;

for( unsigned char offset = m_len; offset;--offset, ++m_last )

{

m_off[ hash_char( *m_last ) ] = offset;

}

if( m_low_last )

{

for( unsigned char offset = m_len; offset;--offset, ++m_low_last )

{

unsigned char hash = hash_char( *m_low_last );

m_off[ hash ] = regex_min( m_off[ hash ],offset );

}

}

}

template< typename OtherT >

OtherT find( OtherT begin, OtherT end ) const

{

if( m_low_last )

{

return find_without_case( begin, end );

}

else

{

return find_with_case( begin, end );

}

}

static void * operator new( size_t size,regex_arena & arena )

{

return arena.allocate( size );

}

static void operator delete( void *,regex_arena & )

{

}

};

// This class is used to speed up character setmatching by providing

// a bitset that spans the ASCII range.std::bitset is not used because

// the range-checking slows it down.

// Note: The division and modulus operationsare optimized by the compiler

// into bit-shift operations.

class ascii_bitvector

{

typedef unsigned int elem_type;

enum

{

CBELEM = CHAR_BIT * sizeof( elem_type ), //count of bits per element

CELEMS = ( UCHAR_MAX+1 ) / CBELEM // number ofelement in array

};

elem_type m_rg[ CELEMS ];

// Used to inline operations like: bv1 |= ~bv2;without creating temp bit vectors.

struct not_ascii_bitvector

{

ascii_bitvector const & m_ref;

not_ascii_bitvector( ascii_bitvector const& ref )

: m_ref( ref ) {}

private:

not_ascii_bitvector & operator=(not_ascii_bitvector const & );

};

ascii_bitvector( ascii_bitvector const & );

ascii_bitvector & operator=(ascii_bitvector const & );

public:

ascii_bitvector()

{

zero();

}

void zero()

{

std::fill_n( m_rg, ARRAYSIZE( m_rg ), 0 );

}

void set( unsigned char ch )

{

m_rg[ ( ch / CBELEM ) ] |= ( ( elem_type )1U<< ( ch % CBELEM ) );

}

bool operator[]( unsigned char ch ) const

{

return 0 != ( m_rg[ ( ch / CBELEM ) ] & ( (elem_type )1U << ( ch % CBELEM ) ) );

}

not_ascii_bitvector const operator~() const

{

return not_ascii_bitvector( *this );

}

ascii_bitvector & operator|=(ascii_bitvector const & that )

{

for( int i=0; i<CELEMS; ++i )

m_rg[ i ] |= that.m_rg[ i ];

return *this;

}

ascii_bitvector & operator|=(not_ascii_bitvector const & that )

{

for( int i=0; i<CELEMS; ++i )

m_rg[ i ] |= ~that.m_ref.m_rg[ i ];

return *this;

}

};

typedef std::pair<wchar_t, wchar_t>range_type;

// determines if one range is less thenanother.

// used in binary search of range vector

struct range_less

{

bool operator()( range_type const & rg1,range_type const & rg2 ) const

{

return rg1.second < rg2.first;

}

};

// A singly-linked list, which works even ifthe allocator

// has per-instance state.

template< typename T, typenameAllocT=std::allocator<T> >

class slist

{

struct cons

{

T car;

cons * cdr;

cons( T const & t, cons * nxt )

: car( t )

, cdr( nxt )

{

}

};

typedef typename rebind<AllocT,cons>::type cons_allocator;

typedef typename rebind<AllocT, char>::typechar_allocator;

#if !defined(_MSC_VER) | 1200 < _MCS_VER

// Use the empty base optimization to avoidreserving

// space for the allocator if it is empty.

struct slist_impl : cons_allocator

{

cons * m_lst;

slist_impl( cons_allocator const & alloc,cons *lst )

: cons_allocator( alloc )

, m_lst( lst )

{

}

cons_allocator & allocator()

{

return *this;

}

};

#else

struct slist_impl

{

cons_allocator m_alloc;

cons *m_lst;

slist_impl( cons_allocator const & alloc,cons *lst )

: m_alloc( alloc )

, m_lst( lst )

{

}

cons_allocator & allocator()

{

return m_alloc;

}

};

#endif

slist_impl m_impl;

// find the previous node in the list(*prev(lst)==lst)

cons ** prev( cons *lst, cons *hint = 0 )

{

if( m_impl.m_lst == lst )

return &m_impl.m_lst;

if( !hint || hint->cdr != lst )

for( hint=m_impl.m_lst; hint->cdr != lst;hint=hint->cdr )

{}

return &hint->cdr;

}

public:

typedef T value_type;

typedef T* pointer;

typedef T& reference;

typedef T const* const_pointer;

typedef T const& const_reference;

typedef size_t size_type;

struct iterator : publicstd::iterator<std::forward_iterator_tag, T>

{

friend class slist<T,AllocT>;

explicit iterator( cons * pcons = 0 )

: m_pcons( pcons )

{

}

T & operator*() const

{

return m_pcons->car;

}

T * operator->() const

{

return &m_pcons->car;

}

iterator & operator++()

{

m_pcons = m_pcons->cdr;

return *this;

}

iterator operator++( int )

{

iterator i( *this );

++*this;

return i;

}

bool operator==( iterator it )

{

return m_pcons == it.m_pcons;

}

bool operator!=( iterator it )

{

return m_pcons != it.m_pcons;

}

private:

cons * m_pcons;

};

// not ideal, but good enough for gov'mentwork....

typedef iterator const_iterator;

explicit slist( char_allocator const & al =char_allocator() )

: m_impl( convert_allocator<cons>( al, 0), 0 )

{

}

~slist()

{

clear();

}

void clear()

{

for( cons *nxt; m_impl.m_lst; m_impl.m_lst=nxt)

{

nxt = m_impl.m_lst->cdr;

m_impl.allocator().destroy( m_impl.m_lst );

m_impl.allocator().deallocate( m_impl.m_lst, 1);

}

}

void push_front( T const & t )

{

cons * lst = m_impl.allocator().allocate( 1, 0);

try

{

m_impl.allocator().construct( lst, cons( t,m_impl.m_lst ) );

}

catch(...)

{

m_impl.allocator().deallocate( lst, 1 );

throw;

}

m_impl.m_lst = lst;

}

template< typename PredT >

void sort( PredT pred )

{

// simple insertion sort

cons *rst=m_impl.m_lst;

m_impl.m_lst = 0;

while( rst )

{

cons *cur=m_impl.m_lst, *prv=0;

while( cur && ! pred( rst->car,cur->car ) )

prv=cur, cur=cur->cdr;

if( prv )

prv->cdr=rst, rst=rst->cdr,prv->cdr->cdr=cur;

else

m_impl.m_lst=rst, rst=rst->cdr, m_impl.m_lst->cdr=cur;

}

}

void sort()

{

this->sort( std::less<T>() );

}

iterator begin() const

{

return iterator( m_impl.m_lst );

}

iterator end() const

{

return iterator();

}

bool empty() const

{

return 0 == m_impl.m_lst;

}

size_t size() const

{

size_t len=0;

for( cons *lst=m_impl.m_lst; lst;lst=lst->cdr, ++len )

{}

return len;

}

iterator erase( iterator it, iterator hint =iterator() )

{

cons **prv = prev( it.m_pcons, hint.m_pcons );// *prv==it.p

*prv = it.m_pcons->cdr;

m_impl.allocator().destroy( it.m_pcons );

m_impl.allocator().deallocate( it.m_pcons, 1 );

return iterator( *prv );

}

void reverse()

{

cons *prv=0, *nxt;

while( m_impl.m_lst )

nxt = m_impl.m_lst->cdr,m_impl.m_lst->cdr = prv, prv = m_impl.m_lst, m_impl.m_lst = nxt;

m_impl.m_lst = prv;

}

};

template< typename AllocT >

struct basic_charset;

template< typename CharT >

struct posixcharsoff_pred

{

CharT m_ch;

posixcharsoff_pred( CharT ch )

: m_ch( ch )

{

}

bool operator()( regex_ctype_t desc ) const

{

return ! local_isctype( m_ch, desc );

}

static int local_isctype( char ch,regex_ctype_t desc )

{

return regex_isctype( ch, desc );

}

static int local_isctype( wchar_t ch,regex_ctype_t desc )

{

return regex_iswctype( ch, desc );

}

};

template< typename CharT, bool CaseT >

struct in_charset_pred

{

CharT m_ch;

in_charset_pred( CharT ch )

: m_ch( ch )

{

}

template< typename AllocT >

bool operator()( basic_charset<AllocT>const * pcs ) const

{

REGEX_VC6( return pcs->in( m_ch COMMAbool2type<CaseT>() ); )

REGEX_NVC6( return pcs->templatein<CaseT>( m_ch ); )

}

};

template< typename AllocT >

struct basic_charset

{

typedefbasic_charset<std::allocator<char> > other_type;

typedefslist<range_type,std::allocator<char> > other_ranges_type;

typedef slist<range_type,AllocT>ranges_type;

typedef slist<regex_ctype_t,AllocT>posixcharsoff_type;

typedef slist<other_type const*,AllocT>nestedcharsets_type;

typedef typename rebind<AllocT,char>::type char_allocator_type;

bool m_fcompliment;

bool m_fskip_extended_check;

ascii_bitvector m_ascii_bitvector;

regex_ctype_t m_posixcharson;

ranges_type m_ranges;

posixcharsoff_type m_posixcharsoff;

nestedcharsets_type m_nestedcharsets;

explicit basic_charset( char_allocator_typeconst & al = char_allocator_type() )

: m_fcompliment( false )

, m_fskip_extended_check( false )

, m_ascii_bitvector()

, m_posixcharson( wct_zero )

, m_ranges( al )

, m_posixcharsoff( al )

, m_nestedcharsets( al )

{

}

// We'll be inheriting from this, so a virtuald'tor is regretably necessary.

virtual ~basic_charset()

{

}

void clear()

{

m_fcompliment = false;

m_fskip_extended_check = false;

m_ascii_bitvector.zero();

m_posixcharson = wct_zero;

m_ranges.clear();

m_posixcharsoff.clear();

m_nestedcharsets.clear();

}

// merge one charset into another

basic_charset & operator|=( other_typeconst & that )

{

if( that.m_fcompliment )

{

// If no posix-style character sets are used,then we can merge this

// nested character set directly into theenclosing character set.

if( wct_zero == that.m_posixcharson &&

that.m_posixcharsoff.empty() &&

that.m_nestedcharsets.empty() )

{

m_ascii_bitvector |= ~ that.m_ascii_bitvector;

// append the inverse of that.m_ranges tothis->m_ranges

wchar_t chlow = UCHAR_MAX;

typedef typenameother_ranges_type::const_iterator iter_type;

for( iter_type prg = that.m_ranges.begin();that.m_ranges.end() != prg; ++prg )

{

if( UCHAR_MAX + 1 != prg->first )

m_ranges.push_front( range_type( wchar_t(chlow+1 ), wchar_t( prg->first-1 ) ) );

chlow = prg->second;

}

if( WCHAR_MAX != chlow )

m_ranges.push_front( range_type( wchar_t(chlow+1 ), WCHAR_MAX ) );

}

else

{

// There is no simple way to merge this nestedcharacter

// set into the enclosing character set, so wemust save

// a pointer to the nested character set in alist.

m_nestedcharsets.push_front( &that );

}

}

else

{

m_ascii_bitvector |= that.m_ascii_bitvector;

std::copy( that.m_ranges.begin(),

that.m_ranges.end(),

std::front_inserter( m_ranges ) );

m_posixcharson |= that.m_posixcharson;

std::copy( that.m_posixcharsoff.begin(),

that.m_posixcharsoff.end(),

std::front_inserter( m_posixcharsoff ) );

std::copy( that.m_nestedcharsets.begin(),

that.m_nestedcharsets.end(),

std::front_inserter( m_nestedcharsets ) );

}

return *this;

}

// Note overloading based on first parameter

void set_bit( char ch, bool const fnocase )

{

if( fnocase )

{

m_ascii_bitvector.set( static_cast<unsignedchar>( regex_tolower( ch ) ) );

m_ascii_bitvector.set( static_cast<unsignedchar>( regex_toupper( ch ) ) );

}

else

{

m_ascii_bitvector.set( static_cast<unsignedchar>( ch ) );

}

}

// Note overloading based on first parameter

void set_bit( wchar_t ch, bool const fnocase )

{

if( UCHAR_MAX >= ch )

set_bit( static_cast<char>( ch ), fnocase);

else

m_ranges.push_front( range_type( ch, ch ) );

}

// Note overloading based on first twoparameters

void set_bit_range( char ch1, char ch2, bool constfnocase )

{

if( static_cast<unsigned char>( ch1 )> static_cast<unsigned char>( ch2 ) )

throw bad_regexpr( "invalid rangespecified in character set" );

if( fnocase )

{

// i is unsigned int to prevent overflow if ch2is UCHAR_MAX

for( unsigned int i = static_cast<unsignedchar>( ch1 );

i <= static_cast<unsigned char>( ch2); ++i )

{

m_ascii_bitvector.set( static_cast<unsignedchar>( regex_toupper( (char) i ) ) );

m_ascii_bitvector.set( static_cast<unsignedchar>( regex_tolower( (char) i ) ) );

}

}

else

{

// i is unsigned int to prevent overflow if ch2is UCHAR_MAX

for( unsigned int i = static_cast<unsignedchar>( ch1 );

i <= static_cast<unsigned char>( ch2); ++i )

{

m_ascii_bitvector.set( static_cast<unsignedchar>( i ) );

}

}

}

// Note overloading based on first twoparameters

void set_bit_range( wchar_t ch1, wchar_t ch2,bool const fnocase )

{

if( ch1 > ch2 )

throw bad_regexpr( "invalid rangespecified in character set" );

if( UCHAR_MAX >= ch1 )

set_bit_range( static_cast<char>( ch1 ),static_cast<char>( regex_min<wchar_t>( UCHAR_MAX, ch2 ) ), fnocase);

if( UCHAR_MAX < ch2 )

m_ranges.push_front( range_type( regex_max(static_cast<wchar_t>( UCHAR_MAX + 1 ), ch1 ), ch2 ) );

}

void optimize( type2type<wchar_t> )

{

if( m_ranges.begin() != m_ranges.end() )

{

// this sorts on range_type.m_pfirst ( usesoperator<() for pair templates )

m_ranges.sort();

// merge ranges that overlap

typename ranges_type::iteratoricur=m_ranges.begin(), iprev=icur++;

while( icur != m_ranges.end() )

{

if( icur->first <= iprev->second + 1 )

{

iprev->second = regex_max( iprev->second,icur->second );

icur = m_ranges.erase( icur, iprev );

}

else

{

iprev=icur++;

}

}

}

// For the ASCII range, merge them_posixcharson info

// into the ascii_bitvector

if( wct_zero != m_posixcharson )

{

// BUGBUG this is kind of expensive. Think of abetter way.

for( unsigned int i=0; i<=UCHAR_MAX; ++i )

if( regex_isctype( i, m_posixcharson ) )

m_ascii_bitvector.set( static_cast<unsignedchar>( i ) );

}

// m_fskip_extended_check is a cache whichtells us whether we

// need to check the m_posixcharsoff andm_nestedcharsets vectors,

// which would only be used in nesteduser-defined character sets

m_fskip_extended_check =m_posixcharsoff.empty() && m_nestedcharsets.empty();

}

void optimize( type2type<char> )

{

optimize( type2type<wchar_t>() );

// the posixcharson info was merged into theascii bitvector,

// so we don't need to ever call regex_isctypeever again.

m_posixcharson = wct_zero;

}

template< bool CaseT, typename CharT >

bool extended_check( CharT ch REGEX_VC6(COMMAbool2type<CaseT>) ) const

{

REGEX_ASSERT( m_fskip_extended_check == (m_posixcharsoff.empty() && m_nestedcharsets.empty() ) );

if( m_fskip_extended_check )

{

return false;

}

return ( m_posixcharsoff.end() !=

std::find_if( m_posixcharsoff.begin(),m_posixcharsoff.end(),

posixcharsoff_pred<CharT>( ch ) ) )

|| ( m_nestedcharsets.end() !=

std::find_if( m_nestedcharsets.begin(),m_nestedcharsets.end(),

in_charset_pred<CharT, CaseT>( ch ) ) );

}

inline bool in_ranges( wchar_t ch, true_t )const

{

typedef typename ranges_type::const_iteratoriter_type;

iter_type ibegin = m_ranges.begin(), iend =m_ranges.end();

return ibegin != iend &&

std::binary_search( ibegin, iend, range_type(ch, ch ), range_less() );

}

inline bool in_ranges( wchar_t ch, false_t )const

{

typedef typename ranges_type::const_iteratoriter_type;

iter_type ibegin = m_ranges.begin(), iend =m_ranges.end();

if( ibegin == iend )

return false;

wchar_t const chup = regex_toupper( ch );

if( std::binary_search( ibegin, iend,range_type( chup, chup ), range_less() ) )

return true;

wchar_t const chlo = regex_tolower( ch );

if( chup == chlo )

return false;

return std::binary_search( ibegin, iend,range_type( chlo, chlo ), range_less() );

}

// Note overloading based on parameter

template< bool CaseT >

bool in( char ch REGEX_VC6(COMMAbool2type<CaseT>) ) const

{

// Whoops, forgot to call optimize() on thischarset

REGEX_ASSERT( wct_zero == m_posixcharson );

return m_fcompliment !=

(

( m_ascii_bitvector[ static_cast<unsignedchar>( ch ) ] )

|| ( extended_check REGEX_NVC6(<CaseT>) (ch REGEX_VC6(COMMA bool2type<CaseT>()) ) )

);

}

// Note overloading based on parameter

template< bool CaseT >

bool in( wchar_t ch REGEX_VC6(COMMAbool2type<CaseT>) ) const

{

// use range_match_type to see if this characteris within one of the

// ranges stored in m_rgranges.

return m_fcompliment !=

(

( ( UCHAR_MAX >= ch ) ?

( m_ascii_bitvector[ static_cast<unsignedchar>( ch ) ] ) :

( ( in_ranges( ch, bool2type<CaseT>() ) )

|| ( wct_zero != m_posixcharson &&regex_iswctype( ch, m_posixcharson ) ) ) )

|| ( extended_check REGEX_NVC6(<CaseT>) (ch REGEX_VC6(COMMA bool2type<CaseT>()) ) )

);

}

private:

basic_charset & operator=( basic_charsetconst & that );

basic_charset( basic_charset const & that);

};

// Intrinsic character sets are allocated onthe heap with the standard allocator.

// They are either the built-in character sets,or the user-defined ones.

struct charset : publicbasic_charset<std::allocator<char> >

{

charset()

{

}

private:

charset( charset const & );

charset & operator=( charset const & );

};

// charset is no longer an incomplete type sowe now

// know how to destroy one. free_charset() isused in syntax2.h

REGEXPR_H_INLINE void free_charset( charsetconst * pcharset )

{

delete pcharset;

}

// Custom character sets are the ones thatappear in patterns between

// square brackets. They are allocated in aregex_arena to speed up

// pattern compilation and to make rpatternclean-up faster.

struct custom_charset : publicbasic_charset<regex_arena>

{

static void * operator new( size_t size,regex_arena & arena )

{

return arena.allocate( size );

}

static void operator delete( void *,regex_arena & ) {}

static void operator delete( void * ) {}

custom_charset( regex_arena & arena )

: basic_charset<regex_arena>( arena )

{

}

private:

custom_charset( custom_charset const & );

custom_charset & operator=( custom_charsetconst & );

};

template< typename CharT >

class intrinsic_charsets

{

struct intrinsic_charset : public charset

{

intrinsic_charset( bool fcompliment, regex_ctype_tdesc, char const * sz )

{

reset( fcompliment, desc, sz );

}

void reset( bool fcompliment, regex_ctype_tdesc, char const * sz )

{

clear();

m_fcompliment = fcompliment;

m_posixcharson = desc;

for( ; *sz; ++sz )

m_ascii_bitvector.set( static_cast<unsignedchar>( *sz ) );

optimize( type2type<CharT>() );

}

private:

intrinsic_charset( intrinsic_charset const& );

intrinsic_charset & operator=(intrinsic_charset const & );

};

static intrinsic_charset &_get_word_charset()

{

static intrinsic_charset s_word_charset( false,wct_alpha()|wct_digit(), "_" );

return s_word_charset;

}

static intrinsic_charset &_get_digit_charset()

{

static intrinsic_charset s_digit_charset(false, wct_digit(), "" );

return s_digit_charset;

}

static intrinsic_charset & _get_space_charset()

{

static intrinsic_charset s_space_charset(false, wct_space(), "" );

return s_space_charset;

}

static intrinsic_charset &_get_not_word_charset()

{

static intrinsic_charset s_not_word_charset(true, wct_alpha()|wct_digit(), "_" );

return s_not_word_charset;

}

static intrinsic_charset &_get_not_digit_charset()

{

static intrinsic_charset s_not_digit_charset(true, wct_digit(), "" );

return s_not_digit_charset;

}

static intrinsic_charset &_get_not_space_charset()

{

static intrinsic_charset s_not_space_charset(true, wct_space(), "" );

return s_not_space_charset;

}

public:

static charset const & get_word_charset()

{

return _get_word_charset();

}

static charset const & get_digit_charset()

{

return _get_digit_charset();

}

static charset const & get_space_charset()

{

return _get_space_charset();

}

static charset const &get_not_word_charset()

{

return _get_not_word_charset();

}

static charset const &get_not_digit_charset()

{

return _get_not_digit_charset();

}

static charset const &get_not_space_charset()

{

return _get_not_space_charset();

}

static void reset()

{

_get_word_charset().reset( false,wct_alpha()|wct_digit(), "_" );

_get_digit_charset().reset( false, wct_digit(),"" );

_get_space_charset().reset( false, wct_space(),"" );

_get_not_word_charset().reset( true,wct_alpha()|wct_digit(), "_" );

_get_not_digit_charset().reset( true,wct_digit(), "" );

_get_not_space_charset().reset( true,wct_space(), "" );

}

};

//

// Operator implementations

//

// Evaluates the beginning-of-string condition

template< typename CStringsT >

struct bos_t

{

template< typename IterT >

static bool eval( match_param<IterT>const & param, IterT iter )

{

return param.m_ibufferbegin == iter;

}

};

// Find the beginning of a line, eitherbeginning of a string, or the character

// immediately following a newline

template< typename CStringsT >

struct bol_t

{

template< typename IterT >

static bool eval( match_param<IterT>const & param, IterT iter )

{

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

return param.m_ibufferbegin == iter ||traits_type::eq( REGEX_CHAR(char_type,'/n'), *--iter );

}

};

// Evaluates end-of-string condition forstring's

template< typename CStringsT >

struct eos_t

{

template< typename IterT >

static bool eval( match_param<IterT>const & param, IterT iter )

{

return param.m_iend == iter;

}

};

template<>

struct eos_t<true_t>

{

template< typename IterT >

static bool eval( match_param<IterT>const &, IterT iter )

{

typedef typename std::iterator_traits<IterT>::value_typechar_type;

typedef std::char_traits<char_type>traits_type;

return traits_type::eq( *iter, char_type() );

}

};

// Evaluates end-of-line conditions, either theend of the string, or a

// newline character.

template< typename CStringsT >

struct eol_t

{

template< typename IterT >

static bool eval( match_param<IterT>const & param, IterT iter )

{

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

return param.m_iend == iter

|| traits_type::eq( REGEX_CHAR(char_type,'/n'),*iter );

}

};

template<>

struct eol_t<true_t>

{

template< typename IterT >

static bool eval( match_param<IterT>const &, IterT iter )

{

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

return traits_type::eq( *iter, char_type() )

|| traits_type::eq( *iter,REGEX_CHAR(char_type,'/n') );

}

};

// Evaluates perl's end-of-string conditions,either the end of the string, or a

// newline character followed by end of string.( Only used by $ and /Z assertions )

template< typename CStringsT >

struct peos_t

{

template< typename IterT >

static bool eval( match_param<IterT>const & param, IterT iter )

{

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

return param.m_iend == iter

|| ( traits_type::eq(REGEX_CHAR(char_type,'/n'), *iter ) && param.m_iend == ++iter );

}

};

template<>

struct peos_t<true_t>

{

template< typename IterT >

static bool eval( match_param<IterT>const &, IterT iter )

{

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

return traits_type::eq( *iter, char_type() )

|| ( traits_type::eq( *iter, REGEX_CHAR(char_type,'/n'))

&& traits_type::eq( *++iter,char_type() ) );

}

};

// compare two characters, case-sensitive

template< typename CharT >

struct ch_neq_t

{

typedef CharT char_type;

typedef std::char_traits<char_type>traits_type;

static bool eval( register CharT ch1, registerCharT ch2 )

{

return ! traits_type::eq( ch1, ch2 );

}

};

// Compare two characters, disregarding case

template< typename CharT >

struct ch_neq_nocase_t

{

typedef CharT char_type;

typedef std::char_traits<char_type>traits_type;

static bool eval( register CharT ch1, registerCharT ch2 )

{

return ! traits_type::eq( regex_toupper( ch1 ),regex_toupper( ch2 ) );

}

};

//

// helper functions for dealing with widths.

//

inline size_t width_add( size_t a, size_t b )

{

return ( size_t( -1 ) == a || size_t( -1 ) == b? size_t( -1 ) : a + b );

}

inline size_t width_mult( size_t a, size_t b )

{

if( 0 == a || 0 == b )

return 0;

if( size_t( -1 ) == a || size_t( -1 ) == b )

return size_t( -1 );

return a * b;

}

inline bool operator==( width_type const & rhs,width_type const & lhs )

{

return ( rhs.m_min == lhs.m_min &&rhs.m_max == lhs.m_max );

}

inline bool operator!=( width_type const &rhs, width_type const & lhs )

{

return ( rhs.m_min != lhs.m_min || rhs.m_max !=lhs.m_max );

}

inline width_type operator+( width_type const& rhs, width_type const & lhs )

{

width_type width = { width_add( rhs.m_min,lhs.m_min ), width_add( rhs.m_max, lhs.m_max ) };

return width;

}

inline width_type operator*( width_type const& rhs, width_type const & lhs )

{

width_type width = { width_mult( rhs.m_min,lhs.m_min ), width_mult( rhs.m_max, lhs.m_max ) };

return width;

}

inline width_type & operator+=( width_type& rhs, width_type const & lhs )

{

rhs.m_min = width_add( rhs.m_min, lhs.m_min );

rhs.m_max = width_add( rhs.m_max, lhs.m_max );

return rhs;

}

inline width_type & operator*=( width_type& rhs, width_type const & lhs )

{

rhs.m_min = width_mult( rhs.m_min, lhs.m_min );

rhs.m_max = width_mult( rhs.m_max, lhs.m_max );

return rhs;

}

namespace

{

width_type const zero_width = { 0, 0 };

width_type const worst_width = { 0, size_t( -1) };

}

template< typename IterT >

struct width_param

{

std::vector<match_group_base<IterT>*>& m_rggroups;

std::list<size_t> const &m_invisible_groups;

width_type m_width;

width_param

(

std::vector<match_group_base<IterT>*>& rggroups,

std::list<size_t> const &invisible_groups

)

: m_rggroups( rggroups )

, m_invisible_groups( invisible_groups )

, m_width( zero_width )

{

}

private:

width_param & operator=( width_param const& );

};

template< typename CharT >

struct must_have

{

typedef std::basic_string<CharT>string_type;

typedef typename string_type::const_iteratorconst_iterator;

bool m_has;

const_iterator m_begin;

const_iterator m_end;

CharT const * m_lower;

};

template< typename CharT >

struct peek_param

{

// "chars" is a list of characters.If every alternate in a group

// begins with a character or string literal,the "chars" list can

// be used to speed up the matching of a group.

size_t m_cchars;

union

{

CharT m_rgchars[2];

CharT const * m_pchars;

};

// "must" is a string that mustappear in the match. It is used

// to speed up the search.

must_have<CharT> m_must_have;

};

//--------------------------------------------------------------------------

//

// Class: sub_expr

//

// Description: patterns are"compiled" into a directed graph of sub_expr

// structs. Matching is accomplished bytraversing this graph.

//

// Methods: sub_expr - construct a sub_expr

// recursive_match_this - does this sub_exprmatch at the given location

// width_this - what is the width of thissub_expr

// ~sub_expr - recursively delete the sub_exprgraph

// next - pointer to the next node in the graph

// next - pointer to the next node in the graph

// recursive_match_next - match the rest of thegraph

// recursive_match_all - recursive_match_thisand recursive_match_next

// is_assertion - true if this sub_expr is azero-width assertion

// get_width - find the width of the graph atthis sub_expr

//

// Members: m_pnext - pointer to the next nodein the graph

//

// History: 8/14/2000 - ericne - Created

//

//--------------------------------------------------------------------------

template< typename IterT >

class sub_expr : publicsub_expr_base<IterT>

{

sub_expr * m_pnext;

protected:

// Only derived classes can instantiate sub_expr's

sub_expr()

: m_pnext( 0 )

{

}

public:

typedef IterT iterator_type;

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

virtual ~sub_expr()

{

delete m_pnext;

}

sub_expr ** pnext()

{

return & m_pnext;

}

sub_expr const * next() const

{

return m_pnext;

}

virtual sub_expr * quantify( size_t, size_t,bool, regex_arena & )

{

throw bad_regexpr( "sub-expression cannotbe quantified" );

}

// Match this object and all subsequent objects

// If recursive_match_all returns false, itmust not change any of param's state

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return ( recursive_match_this_s( param, icur )&& recursive_match_next( param, icur, false_t() ) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const // for C-style strings

{

return ( recursive_match_this_c( param, icur )&& recursive_match_next( param, icur, true_t() ) );

}

// match this object only

virtual bool recursive_match_this_s(match_param<IterT> &, IterT & ) const

{

return true;

}

virtual bool recursive_match_this_c(match_param<IterT> &, IterT & ) const // for C-style strings

{

return true;

}

// Match all subsequent objects

template< typename CStringsT >

bool recursive_match_next(match_param<IterT> & param, IterT icur, CStringsT ) const

{

return m_pnext->recursive_match_all( param,icur, CStringsT() );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = next();

return true;

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const // for C-style strings

{

param.m_pnext = next();

return true;

}

virtual bool iterative_rematch_this_s(match_param<IterT> & ) const

{

return false;

}

virtual bool iterative_rematch_this_c(match_param<IterT> & ) const // for C-style strings

{

return false;

}

virtual bool is_assertion() const

{

return false;

}

width_type get_width( width_param<IterT>& param )

{

width_type temp_width = width_this( param );

if( m_pnext )

temp_width += m_pnext->get_width( param );

return temp_width;

}

virtual width_type width_this(width_param<IterT> & ) = 0;

virtual bool peek_this(peek_param<char_type> & ) const

{

return false;

}

};

// An object of type end_of_pattern is used tomark the

// end of the pattern. (Duh!) It is responsiblefor ending

// the recursion, or for letting the searchcontinue if

// the match is zero-width and we are trying tofind a

// non-zero-width match

template< typename IterT >

class end_of_pattern : publicsub_expr<IterT>

{

bool _do_match_this( match_param<IterT>& param, IterT icur ) const

{

return ! param.m_no0len || param.m_imatchbegin!= icur;

}

public:

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_match_this( param, icur );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const // for C-style strings

{

return _do_match_this( param, icur );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = 0;

return _do_match_this( param, param.m_icur );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const // for C-style strings

{

param.m_pnext = 0;

return _do_match_this( param, param.m_icur );

}

virtual width_type width_this(width_param<IterT> & )

{

return zero_width;

}

};

// Base class for sub-expressions which arezero-width

// ( i.e., assertions eat no characters duringmatching )

// Assertions cannot be quantified.

template< typename IterT >

class assertion : public sub_expr<IterT>

{

public:

virtual bool is_assertion() const

{

return true;

}

virtual width_type width_this(width_param<IterT> & )

{

return zero_width;

}

virtual bool peek_this(peek_param<char_type> & peek ) const

{

return this->next()->peek_this( peek );

}

};

template< typename OpT, typename OpCT >

struct opwrap

{

typedef OpT op_type;

typedef OpCT opc_type;

};

#define REGEX_OP(x) opwrap<x<false_t>, x<true_t> >

template< typename IterT, typename OpWrapT>

class assert_op : public assertion<IterT>

{

public:

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return ( assert_op::recursive_match_this_s(param, icur ) && this->recursive_match_next( param, icur, false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return ( assert_op::recursive_match_this_c(param, icur ) && this->recursive_match_next( param, icur, true_t() ));

}

virtual bool recursive_match_this_s(match_param<IterT> & param, IterT & icur ) const

{

return OpWrapT::op_type::eval( param, icur );

}

virtual bool recursive_match_this_c(match_param<IterT> & param, IterT & icur ) const

{

return OpWrapT::opc_type::eval( param, icur );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return OpWrapT::op_type::eval( param,param.m_icur );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return OpWrapT::opc_type::eval( param,param.m_icur );

}

};

template< typename IterT >

inline assertion<IterT> * create_bos(REGEX_FLAGS, regex_arena & arena )

{

return new( arena ) assert_op<IterT,REGEX_OP(bos_t) >();

}

template< typename IterT >

inline assertion<IterT> * create_eos(REGEX_FLAGS, regex_arena & arena )

{

return new( arena ) assert_op<IterT,REGEX_OP(peos_t) >();

}

template< typename IterT >

inline assertion<IterT> * create_eoz(REGEX_FLAGS, regex_arena & arena )

{

return new( arena ) assert_op<IterT,REGEX_OP(eos_t) >();

}

template< typename IterT >

inline assertion<IterT> * create_bol(REGEX_FLAGS flags, regex_arena & arena )

{

switch( MULTILINE & flags )

{

case 0:

return new( arena ) assert_op<IterT,REGEX_OP(bos_t) >();

case MULTILINE:

return new( arena ) assert_op<IterT,REGEX_OP(bol_t) >();

default:

REGEX_ASSERT(false);

return 0;

}

}

template< typename IterT >

inline assertion<IterT> * create_eol(REGEX_FLAGS flags, regex_arena & arena )

{

switch( MULTILINE & flags )

{

case 0:

return new( arena ) assert_op<IterT,REGEX_OP(peos_t) >();

case MULTILINE:

return new( arena ) assert_op<IterT, REGEX_OP(eol_t)>();

default:

REGEX_ASSERT(false);

return 0;

}

}

template< typename IterT, typename SubExprT= sub_expr<IterT> >

class match_wrapper : publicsub_expr<IterT>

{

match_wrapper & operator=( match_wrapperconst & );

public:

match_wrapper( SubExprT * psub )

: m_psub( psub )

{

}

virtual ~match_wrapper()

{

_cleanup();

}

virtual width_type width_this(width_param<IterT> & param )

{

return m_psub->width_this( param );

}

virtual bool peek_this(peek_param<char_type> & peek ) const

{

return m_psub->peek_this( peek );

}

protected:

void _cleanup()

{

delete m_psub;

m_psub = 0;

}

SubExprT * m_psub;

};

template< typename IterT, typename SubExprT= sub_expr<IterT> >

class match_quantifier : publicmatch_wrapper<IterT, SubExprT>

{

match_quantifier & operator=( match_quantifierconst & );

public:

match_quantifier( SubExprT * psub, size_tlbound, size_t ubound )

: match_wrapper<IterT, SubExprT>( psub )

, m_lbound( lbound )

, m_ubound( ubound )

{

}

virtual width_type width_this(width_param<IterT> & param )

{

width_type this_width = match_wrapper<IterT,SubExprT>::width_this( param );

width_type quant_width = { m_lbound, m_ubound};

return this_width * quant_width;

}

virtual bool peek_this(peek_param<char_type> & peek ) const

{

return 0 != m_lbound &&this->m_psub->peek_this( peek );

}

protected:

size_t const m_lbound;

size_t const m_ubound;

};

template< typename IterT, typename SubExprT>

class atom_quantifier : publicmatch_quantifier<IterT, SubExprT>

{

atom_quantifier & operator=(atom_quantifier const & );

public:

atom_quantifier( SubExprT * psub, size_tlbound, size_t ubound )

: match_quantifier<IterT, SubExprT>(psub, lbound, ubound )

{

}

protected:

void _push_frame( unsafe_stack * pstack, IterTcurr, size_t count ) const

{

std::pair<IterT, size_t> p( curr, count);

pstack->push( p );

}

void _pop_frame( match_param<IterT> &param ) const

{

std::pair<IterT, size_t> p;

param.m_pstack->pop( p );

param.m_icur = p.first;

}

};

template< typename IterT, typename SubExprT>

class max_atom_quantifier : public atom_quantifier<IterT,SubExprT>

{

max_atom_quantifier & operator=(max_atom_quantifier const & );

public:

max_atom_quantifier( SubExprT * psub, size_tlbound, size_t ubound )

: atom_quantifier<IterT, SubExprT>( psub,lbound, ubound )

{

}

// Why a macro instead of a template, you ask?Performance. Due to a known

// bug in the VC7 inline heuristic, I cannotget VC7 to inline the calls to

// m_psub methods unless I use these macros.And the performance win is

// nothing to sneeze at. It's on the order of a25% speed up to use a macro

// here instead of a template.

#defineDECLARE_RECURSIVE_MATCH_ALL(CSTRINGS,EXT) /

virtual bool recursive_match_all ## EXT(match_param<IterT> & param, IterT icur ) const /

{ /

typedef typenamestd::iterator_traits<IterT>::difference_type diff_type; /

/* In an ideal world, ibegin and cdiff would bemembers of a union */ /

/* to conserve stack, but I don't know if IterTis a POD type or not. */ /

IterT ibegin = icur; /

diff_type cdiff = 0; /* must be a signedintegral type */ /

size_t cmatches = 0; /

/* greedily match as much as we can*/ /

if( this->m_ubound &&this->m_psub->SubExprT::recursive_match_this ## EXT( param, icur ) ) /

{ /

if( 0 == ( cdiff = -std::distance( ibegin, icur) ) ) /

return this->recursive_match_next( param,icur, CSTRINGS() ); /

while( ++cmatches < this->m_ubound&& this->m_psub->SubExprT::recursive_match_this ## EXT( param,icur ) )/

{} /

} /

if( this->m_lbound > cmatches ) /

return false; /

/* try matching the rest of the pattern, andback off if necessary */ /

for( ; ; --cmatches, std::advance( icur, cdiff) ) /

{ /

if( this->recursive_match_next( param, icur,CSTRINGS() ) ) /

return true; /

if( this->m_lbound == cmatches ) /

return false; /

} /

}

#define DECLARE_ITERATIVE_MATCH_THIS(EXT) /

virtual bool iterative_match_this ## EXT(match_param<IterT> & param ) const /

{ /

IterT ibegin = param.m_icur; /

size_t cmatches = 0; /

if( this->m_ubound &&this->m_psub->SubExprT::iterative_match_this ## EXT( param ) ) /

{ /

if( 0 == std::distance( ibegin, param.m_icur )) /

{ /

cmatches = this->m_lbound; /

} /

else /

{ /

while( ++cmatches < this->m_ubound&& this->m_psub->SubExprT::iterative_match_this ## EXT( param ))/

{} /

} /

} /

if( cmatches >= this->m_lbound ) /

{ /

this->_push_frame( param.m_pstack, ibegin,cmatches ); /

param.m_pnext = this->next(); /

return true; /

} /

param.m_icur = ibegin; /

return false; /

}

#define DECLARE_ITERATIVE_REMATCH_THIS(EXT) /

virtual bool iterative_rematch_this ## EXT(match_param<IterT> & param ) const /

{ /

typedef std::pair<IterT, size_t> top_type;/

size_t & cmatches = REGEX_VC6(param.m_pstack->top( type2type<top_type>() ).second ) /

REGEX_NVC6( param.m_pstack->templatetop<top_type>().second ); /

if( this->m_lbound != cmatches ) /

{ /

--cmatches; /

this->m_psub->SubExprT::iterative_rematch_this## EXT( param ); /

param.m_pnext = this->next(); /

return true; /

} /

this->_pop_frame( param ); /

return false; /

}

DECLARE_RECURSIVE_MATCH_ALL(false_t,_s)

DECLARE_RECURSIVE_MATCH_ALL(true_t,_c)

DECLARE_ITERATIVE_MATCH_THIS(_s)

DECLARE_ITERATIVE_MATCH_THIS(_c)

DECLARE_ITERATIVE_REMATCH_THIS(_s)

DECLARE_ITERATIVE_REMATCH_THIS(_c)

#undef DECLARE_RECURSIVE_MATCH_ALL

#undef DECLARE_ITERATIVE_MATCH_THIS

#undef DECLARE_ITERATIVE_REMATCH_THIS

};

template< typename IterT, typename SubExprT>

class min_atom_quantifier : publicatom_quantifier<IterT, SubExprT>

{

min_atom_quantifier & operator=(min_atom_quantifier const & );

public:

min_atom_quantifier( SubExprT * psub, size_tlbound, size_t ubound )

: atom_quantifier<IterT, SubExprT>( psub,lbound, ubound )

{

}

// Why a macro instead of a template, you ask?Performance. Due to a known

// bug in the VC7 inline heuristic, I cannotget VC7 to inline the calls to

// m_psub methods unless I use these macros.And the performance win is

// nothing to sneeze at. It's on the order of a25% speed up to use a macro

// here instead of a template.

#defineDECLARE_RECURSIVE_MATCH_ALL(CSTRINGS,EXT) /

virtual bool recursive_match_all ## EXT(match_param<IterT> & param, IterT icur ) const /

{ /

IterT icur_tmp = icur; /

size_t cmatches = 0; /

if(this->m_psub->SubExprT::recursive_match_this ## EXT( param, icur_tmp ) )/

{ /

if( icur_tmp == icur ) /

return this->recursive_match_next( param,icur, CSTRINGS() ); /

if( this->m_lbound ) /

{ /

icur = icur_tmp; /

++cmatches; /

} /

for( ; cmatches < this->m_lbound;++cmatches ) /

{ /

if( !this->m_psub->SubExprT::recursive_match_this ## EXT( param, icur ) ) /

return false; /

} /

} /

else if( this->m_lbound ) /

{ /

return false; /

} /

do /

{ /

if( this->recursive_match_next( param, icur,CSTRINGS() ) ) /

return true; /

} /

while( cmatches < this->m_ubound&& /

( ++cmatches,this->m_psub->SubExprT::recursive_match_this ## EXT( param, icur ) ) ); /

return false; /

}

#define DECLARE_ITERATIVE_MATCH_THIS(EXT) /

virtual bool iterative_match_this ## EXT(match_param<IterT> & param ) const /

{ /

IterT ibegin = param.m_icur; /

size_t cmatches = 0; /

if(this->m_psub->SubExprT::iterative_match_this ## EXT( param ) ) /

{ /

if( 0 == std::distance( ibegin, param.m_icur )) /

{ /

cmatches = this->m_ubound; /

} /

else if( this->m_lbound ) /

{ /

for( ++cmatches; cmatches <this->m_lbound; ++cmatches ) /

{ /

if( !this->m_psub->SubExprT::iterative_match_this ## EXT( param ) ) /

{ /

param.m_icur = ibegin; /

return false; /

} /

} /

} /

else /

{ /

param.m_icur = ibegin; /

} /

} /

else if( this->m_lbound ) /

{ /

return false; /

} /

this->_push_frame( param.m_pstack, ibegin,cmatches ); /

param.m_pnext = this->next(); /

return true; /

}

#define DECLARE_ITERATIVE_REMATCH_THIS(EXT) /

virtual bool iterative_rematch_this ## EXT(match_param<IterT> & param ) const /

{ /

typedef std::pair<IterT, size_t>top_type; /

size_t & cmatches = REGEX_VC6(param.m_pstack->top( type2type<top_type>() ).second ) /

REGEX_NVC6( param.m_pstack->templatetop<top_type>().second ); /

if( cmatches == this->m_ubound || !this->m_psub->SubExprT::iterative_match_this ## EXT( param ) ) /

{ /

this->_pop_frame( param ); /

return false; /

} /

++cmatches; /

param.m_pnext = this->next(); /

return true; /

}

DECLARE_RECURSIVE_MATCH_ALL(false_t,_s)

DECLARE_RECURSIVE_MATCH_ALL(true_t,_c)

DECLARE_ITERATIVE_MATCH_THIS(_s)

DECLARE_ITERATIVE_MATCH_THIS(_c)

DECLARE_ITERATIVE_REMATCH_THIS(_s)

DECLARE_ITERATIVE_REMATCH_THIS(_c)

#undef DECLARE_RECURSIVE_MATCH_ALL

#undef DECLARE_ITERATIVE_MATCH_THIS

#undef DECLARE_ITERATIVE_REMATCH_THIS

};

template< typename CharT >

struct char_nocase

{

CharT m_chlo;

CharT m_chhi;

};

template< typename IterT >

class match_char : public sub_expr<IterT>

{

match_char & operator=( match_char const& );

public:

typedef typename sub_expr<IterT>::char_typechar_type;

virtual width_type width_this(width_param<IterT> & )

{

width_type width = { 1, 1 };

return width;

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

--param.m_icur;

return false;

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

--param.m_icur;

return false;

}

};

template< typename IterT, typename CharT>

class match_char_t : publicmatch_char<IterT>

{

match_char_t & operator=( match_char_tconst & );

public:

match_char_t( CharT const & ch )

: m_ch( ch )

{

}

virtual sub_expr<IterT> * quantify(size_t lbound, size_t ubound, bool greedy, regex_arena & arena )

{

if( greedy )

return new( arena )max_atom_quantifier<IterT, match_char_t<IterT, CharT> >( this,lbound, ubound );

else

return new( arena )min_atom_quantifier<IterT, match_char_t<IterT, CharT> >( this,lbound, ubound );

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return ( match_char_t::recursive_match_this_s(param, icur ) && this->recursive_match_next( param, icur, false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return ( match_char_t::recursive_match_this_c(param, icur ) && this->recursive_match_next( param, icur, true_t() ));

}

virtual bool recursive_match_this_s(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_this_c(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<false_t>) ( param, param.m_icur REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<true_t>) ( param, param.m_icur REGEX_VC6(COMMA true_t()) );

}

virtual bool peek_this(peek_param<char_type> & peek ) const

{

_do_peek_this( peek, m_ch );

return true;

}

private:

static bool eq( char_type left, char_type right)

{

return traits_type::eq( left, right );

}

static bool eq( char_type left,char_nocase<char_type> right )

{

return traits_type::eq( left, right.m_chlo ) ||

traits_type::eq( left, right.m_chhi );

}

static void _do_peek_this(peek_param<char_type> & peek, char_type ch )

{

peek.m_cchars = 1;

peek.m_rgchars[0] = ch;

peek.m_must_have.m_has = false;

}

static void _do_peek_this(peek_param<char_type> & peek, char_nocase<char_type> ch )

{

peek.m_cchars = 2;

peek.m_rgchars[0] = ch.m_chlo;

peek.m_rgchars[1] = ch.m_chhi;

peek.m_must_have.m_has = false;

}

template< typename CStringsT >

bool _do_match_this( match_param<IterT>& param, IterT & icur REGEX_VC6(COMMA CStringsT) ) const

{

if( eos_t<CStringsT>::eval( param, icur )|| ! eq( *icur, m_ch ) )

return false;

++icur;

return true;

}

CharT const m_ch;

};

template< typename IterT >

inline match_char<IterT> * create_char

(

typenamestd::iterator_traits<IterT>::value_type ch,

REGEX_FLAGS flags,

regex_arena & arena

)

{

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

typedef std::char_traits<char_type>traits_type;

switch( NOCASE & flags )

{

case 0:

return new( arena ) match_char_t<IterT,char_type>( ch );

case NOCASE:

{

char_nocase<char_type> nocase = {regex_tolower( ch ), regex_toupper( ch ) };

if( traits_type::eq( nocase.m_chlo,nocase.m_chhi ) )

return new( arena ) match_char_t<IterT,char_type>( ch );

else

return new( arena ) match_char_t<IterT,char_nocase<char_type> >( nocase );

}

default:

REGEX_ASSERT(false);

return 0;

}

}

template< typename IterT >

class match_literal : publicsub_expr<IterT>

{

match_literal & operator=( match_literalconst & );

public:

typedef typenamesub_expr<IterT>::char_type char_type;

typedef std::basic_string<char_type>string_type;

typedef typename string_type::iteratoriterator;

typedef typename string_type::const_iteratorconst_iterator;

typedef typename std::iterator_traits<IterT>::difference_typediff_type;

match_literal( const_iterator ibegin,const_iterator iend )

: m_ibegin( ibegin )

, m_iend( iend )

, m_dist( std::distance( m_ibegin, m_iend ) )

{

}

const_iterator const m_ibegin;

const_iterator const m_iend;

diff_type const m_dist; // must be signedintegral type

virtual width_type width_this(width_param<IterT> & )

{

width_type width = { static_cast<size_t>(m_dist ), static_cast<size_t>( m_dist ) };

return width;

}

virtual bool iterative_rematch_this_s( match_param<IterT>& param ) const

{

std::advance( param.m_icur, -m_dist );

return false;

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

std::advance( param.m_icur, -m_dist );

return false;

}

};

template< typename IterT >

class match_literal_t : publicmatch_literal<IterT>

{

match_literal_t & operator=(match_literal_t const & );

public:

typedef typenamematch_literal<IterT>::char_type char_type;

typedef typenamematch_literal<IterT>::string_type string_type;

typedef typename match_literal<IterT>::iteratoriterator;

typedef typenamematch_literal<IterT>::const_iterator const_iterator;

match_literal_t( const_iterator ibegin,const_iterator iend )

: match_literal<IterT>( ibegin, iend )

{

}

virtual sub_expr<IterT> * quantify(size_t lbound, size_t ubound, bool greedy, regex_arena & arena )

{

if( greedy )

return new( arena )max_atom_quantifier<IterT, match_literal_t<IterT> >( this, lbound,ubound );

else

return new( arena )min_atom_quantifier<IterT, match_literal_t<IterT> >( this, lbound,ubound );

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return (match_literal_t::recursive_match_this_s( param, icur ) &&this->recursive_match_next( param, icur, false_t() ) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return (match_literal_t::recursive_match_this_c( param, icur ) &&this->recursive_match_next( param, icur, true_t() ) );

}

virtual bool recursive_match_this_s(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_this_c(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<false_t>) ( param, param.m_icur REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<true_t>) ( param, param.m_icur REGEX_VC6(COMMA true_t()) );

}

virtual bool peek_this(peek_param<char_type> & peek ) const

{

peek.m_cchars = 1;

peek.m_rgchars[0] = *this->m_ibegin;

peek.m_must_have.m_has = true;

peek.m_must_have.m_begin = this->m_ibegin;

peek.m_must_have.m_end = this->m_iend;

peek.m_must_have.m_lower = 0;

return true;

}

private:

template< typename CStringsT >

bool _do_match_this( match_param<IterT>& param, IterT & icur REGEX_VC6(COMMA CStringsT) ) const

{

IterT icur_tmp = icur;

const_iterator ithis = this->m_ibegin;

for( ; this->m_iend != ithis; ++icur_tmp,++ithis )

{

if( eos_t<CStringsT>::eval( param,icur_tmp ) || ! traits_type::eq( *ithis, *icur_tmp ) )

return false;

}

icur = icur_tmp;

return true;

}

};

template< typename IterT >

class match_literal_nocase_t : publicmatch_literal<IterT>

{

match_literal_nocase_t & operator=(match_literal_nocase_t const & );

public:

typedef typename match_literal<IterT>::char_typechar_type;

typedef typenamematch_literal<IterT>::string_type string_type;

typedef typenamematch_literal<IterT>::iterator iterator;

typedef typenamematch_literal<IterT>::const_iterator const_iterator;

match_literal_nocase_t( iterator ibegin,const_iterator iend, regex_arena & arena )

: match_literal<IterT>( ibegin, iend )

, m_szlower( arena_allocator<char_type>(arena ).allocate( m_dist ) )

{

// Copy from ibegin to m_szlower

std::copy( this->m_ibegin, this->m_iend,m_szlower );

// Store the uppercase version of the literalin [ m_ibegin, m_iend ).

regex_toupper( ibegin, iend );

// Store the lowercase version of the literalin m_strlower.

regex_tolower( m_szlower, m_szlower +this->m_dist );

}

virtual sub_expr<IterT> * quantify(size_t lbound, size_t ubound, bool greedy, regex_arena & arena )

{

if( greedy )

return new( arena )max_atom_quantifier<IterT, match_literal_nocase_t<IterT> >( this,lbound, ubound );

else

return new( arena )min_atom_quantifier<IterT, match_literal_nocase_t<IterT> >( this,lbound, ubound );

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return (match_literal_nocase_t::recursive_match_this_s( param, icur ) &&this->recursive_match_next( param, icur, false_t() ) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return (match_literal_nocase_t::recursive_match_this_c( param, icur ) &&this->recursive_match_next( param, icur, true_t() ) );

}

virtual bool recursive_match_this_s( match_param<IterT>& param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_this_c(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_this REGEX_NVC6(<true_t>)( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<false_t>) ( param, param.m_icur REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<true_t>) ( param, param.m_icur REGEX_VC6(COMMA true_t()) );

}

virtual bool peek_this(peek_param<char_type> & peek ) const

{

peek.m_cchars = 2;

peek.m_rgchars[0] = *this->m_ibegin;

peek.m_rgchars[1] = *m_szlower;

peek.m_must_have.m_has = true;

peek.m_must_have.m_begin = this->m_ibegin;

peek.m_must_have.m_end = this->m_iend;

peek.m_must_have.m_lower = m_szlower;

return true;

}

private:

// Allocated from a regex arena. The memorywill be cleaned up

// when the arena is deallocated.

char_type *const m_szlower;

template< typename CStringsT >

bool _do_match_this( match_param<IterT>& param, IterT & icur REGEX_VC6(COMMA CStringsT) ) const

{

IterT icur_tmp = icur;

const_iterator ithisu = this->m_ibegin; //uppercase

char_type const * ithisl = m_szlower; //lowercase

for( ; this->m_iend != ithisu; ++icur_tmp,++ithisu, ++ithisl )

{

if( eos_t<CStringsT>::eval( param,icur_tmp ) ||

( ! traits_type::eq( *ithisu, *icur_tmp )&&

! traits_type::eq( *ithisl, *icur_tmp ) ) )

return false;

}

icur = icur_tmp;

return true;

}

};

template< typename IterT, typename IBeginT,typename IEndT >

inline sub_expr<IterT> * create_literal

(

IBeginT ibegin,

IEndT iend,

REGEX_FLAGS flags,

regex_arena & arena

)

{

// A match_char is faster than a match_literal,so prefer it

// when the literal to match is only 1 charwide.

if( 1 == std::distance<IEndT>( ibegin,iend ) )

{

return create_char<IterT>( *ibegin,flags, arena );

}

switch( NOCASE & flags )

{

case 0:

return new( arena )match_literal_t<IterT>( ibegin, iend );

case NOCASE:

return new( arena )match_literal_nocase_t<IterT>( ibegin, iend, arena );

default:

REGEX_ASSERT(false);

return 0;

}

}

template< typename IterT >

class match_any : public sub_expr<IterT>

{

public:

virtual width_type width_this(width_param<IterT> & )

{

width_type width = { 1, 1 };

return width;

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

--param.m_icur;

return false;

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

--param.m_icur;

return false;

}

};

template< typename IterT, typename EosWrapT>

class match_any_t : publicmatch_any<IterT>

{

bool _do_match_this_s( match_param<IterT>& param, IterT & icur ) const

{

if( EosWrapT::op_type::eval( param, icur ) )

return false;

++icur;

return true;

}

bool _do_match_this_c( match_param<IterT>& param, IterT & icur ) const

{

if( EosWrapT::opc_type::eval( param, icur ) )

return false;

++icur;

return true;

}

public:

virtual sub_expr<IterT> * quantify(size_t lbound, size_t ubound, bool greedy, regex_arena & arena )

{

if( greedy )

return new( arena )max_atom_quantifier<IterT, match_any_t<IterT, EosWrapT> >( this,lbound, ubound );

else

return new( arena )min_atom_quantifier<IterT, match_any_t<IterT, EosWrapT> >( this,lbound, ubound );

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return ( match_any_t::recursive_match_this_s(param, icur ) && this->recursive_match_next( param, icur, false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return ( match_any_t::recursive_match_this_c(param, icur ) && this->recursive_match_next( param, icur, true_t() ));

}

virtual bool recursive_match_this_s(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_this_s( param, icur );

}

virtual bool recursive_match_this_c(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_this_c( param, icur );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_this_s( param, param.m_icur );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_this_c( param, param.m_icur );

}

};

template< typename IterT >

inline match_any<IterT> * create_any(REGEX_FLAGS flags, regex_arena & arena )

{

switch( SINGLELINE & flags )

{

case 0:

return new( arena ) match_any_t<IterT, REGEX_OP(eol_t)>();

case SINGLELINE:

return new( arena ) match_any_t<IterT,REGEX_OP(eos_t) >();

default:

REGEX_ASSERT(false);

return 0;

}

}

template< typename IterT >

class match_charset : publicsub_expr<IterT>

{

public:

virtual width_type width_this( width_param<IterT>& )

{

width_type width = { 1, 1 };

return width;

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

--param.m_icur;

return false;

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

--param.m_icur;

return false;

}

};

template< typename IterT, typenameCharSetPtrT, bool CaseT >

class match_charset_t : publicmatch_charset<IterT>

{

CharSetPtrT const m_pcs;

match_charset_t & operator=(match_charset_t const & );

template< typename CStringsT >

bool _do_match_this( match_param<IterT>& param, IterT & icur REGEX_VC6(COMMA CStringsT) ) const

{

if( eos_t<CStringsT>::eval( param, icur )||

! m_pcs->REGEX_NVC6(template) inREGEX_NVC6(<CaseT>)( *icur REGEX_VC6(COMMA bool2type<CaseT>()) ) )

return false;

++icur;

return true;

}

public:

match_charset_t( CharSetPtrT pcs )

: m_pcs( pcs )

{

}

virtual sub_expr<IterT> * quantify(size_t lbound, size_t ubound, bool greedy, regex_arena & arena )

{

if( greedy )

return new( arena )max_atom_quantifier<IterT, match_charset_t<IterT, CharSetPtrT, CaseT>>( this, lbound, ubound );

else

return new( arena )min_atom_quantifier<IterT, match_charset_t<IterT, CharSetPtrT, CaseT>>( this, lbound, ubound );

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return (match_charset_t::recursive_match_this_s( param, icur ) &&this->recursive_match_next( param, icur, false_t() ) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return ( match_charset_t::recursive_match_this_c(param, icur ) && this->recursive_match_next( param, icur, true_t() ));

}

virtual bool recursive_match_this_s(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_this_c(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<false_t>) ( param, param.m_icur REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<true_t>) ( param, param.m_icur REGEX_VC6(COMMA true_t()) );

}

};

template< typename IterT >

inline match_charset<IterT> *create_charset

(

charset const & cs,

REGEX_FLAGS flags,

regex_arena & arena

)

{

switch( NOCASE & flags )

{

case 0:

return new( arena ) match_charset_t<IterT,charset const*, true>( &cs );

case NOCASE:

return new( arena ) match_charset_t<IterT,charset const*, false>( &cs );

default:

REGEX_ASSERT(false);

return 0;

}

}

template< typename IterT >

inline match_charset<IterT> *create_custom_charset

(

custom_charset const * pcs,

REGEX_FLAGS flags,

regex_arena & arena

)

{

typedef std::auto_ptr<custom_charsetconst> auto_charset;

auto_charset acs( pcs );

switch( NOCASE & flags )

{

case 0:

return new( arena ) match_charset_t<IterT,auto_charset, true>( acs );

case NOCASE:

return new( arena ) match_charset_t<IterT,auto_charset, false>( acs );

default:

REGEX_ASSERT(false);

return 0;

}

}

template< bool IsBoundaryT >

struct word_boundary

{

static bool eval( bool fprevword, bool fthisword)

{

return IsBoundaryT == ( fprevword != fthisword);

}

};

struct word_start

{

static bool eval( bool fprevword, boolfthisword )

{

return ! fprevword && fthisword;

}

};

struct word_stop

{

static bool eval( bool fprevword, boolfthisword )

{

return fprevword && ! fthisword;

}

};

template< typename IterT, typename CondT>

class word_assertion_t : publicassertion<IterT>

{

word_assertion_t & operator=(word_assertion_t const & );

public:

typedef typenameassertion<IterT>::char_type char_type;

word_assertion_t()

: m_isword(intrinsic_charsets<char_type>::get_word_charset() )

{

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return (word_assertion_t::recursive_match_this_s( param, icur ) &&this->recursive_match_next( param, icur, false_t() ) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return (word_assertion_t::recursive_match_this_c( param, icur ) &&this->recursive_match_next( param, icur, true_t() ) );

}

virtual bool recursive_match_this_s(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_this_c(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<false_t>) ( param, param.m_icur REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<true_t>) ( param, param.m_icur REGEX_VC6(COMMA true_t()) );

}

private:

bool _is_word( char_type ch ) const

{

return REGEX_VC6( m_isword.in( ch COMMAtrue_t() ) )

REGEX_NVC6( m_isword.template in<true>(ch ) );

}

template< typename CStringsT >

bool _do_match_this( match_param<IterT>& param, IterT icur REGEX_VC6(COMMA CStringsT) ) const

{

bool const fthisword = !eos_t<CStringsT>::eval( param, icur ) && _is_word( *icur );

bool const fprevword = !bos_t<CStringsT>::eval( param, icur ) && _is_word( *--icur );

return CondT::eval( fprevword, fthisword );

}

charset const & m_isword;

};

template< typename IterT >

inline assertion<IterT> *create_word_boundary

(

bool fisboundary,

REGEX_FLAGS, // flags

regex_arena & arena

)

{

if( fisboundary )

return new( arena ) word_assertion_t<IterT,word_boundary<true> >();

else

return new( arena ) word_assertion_t<IterT,word_boundary<false> >();

}

template< typename IterT >

inline assertion<IterT> *create_word_start( REGEX_FLAGS, regex_arena & arena )

{

return new( arena ) word_assertion_t<IterT,word_start>();

}

template< typename IterT >

inline assertion<IterT> *create_word_stop( REGEX_FLAGS, regex_arena & arena )

{

return new( arena ) word_assertion_t<IterT,word_stop>();

}

// an "extent" represents the rangeof backrefs that can be modified as the

// result of a look-ahead or look-behind

typedef std::pair<size_t, size_t>extent_type;

template< typename IterT > classmax_group_quantifier;

template< typename IterT > classmin_group_quantifier;

template< typename IterT >

class match_group_base : publicsub_expr<IterT>

{

protected:

typedef slist<sub_expr<IterT>*,regex_arena>alt_list_type;

private:

match_group_base & operator=(match_group_base const & );

void _push_frame( match_param<IterT>& param ) const

{

unsafe_stack * ps = param.m_pstack;

if( size_t( -1 ) != m_cgroup )

{

IterT & reserved1 = param.m_prgbackrefs[m_cgroup ].reserved1;

ps->push( reserved1 );

reserved1 = param.m_icur;

}

ps->push( m_rgalternates.begin() );

}

void _pop_frame( match_param<IterT> &param ) const

{

typedef typename alt_list_type::const_iteratoriter_type;

unsafe_stack * ps = param.m_pstack;

REGEX_VC6( ps->pop(type2type<iter_type>() COMMA 0 ); )

REGEX_NVC6( ps->templatepop<iter_type>(); )

if( size_t( -1 ) != m_cgroup )

ps->pop( param.m_prgbackrefs[ m_cgroup].reserved1 );

}

template< typename CStringsT >

bool _do_recursive_match_all( match_param<IterT>& param, IterT icur REGEX_VC6(COMMA CStringsT) ) const

{

typedef typename alt_list_type::const_iteratoriter_type;

if( 0 != m_peek_chars_begin &&

( eos_t<CStringsT>::eval( param, icur )||

m_peek_chars_end == std::find(m_peek_chars_begin, m_peek_chars_end, *icur ) ) )

{

return false;

}

if( size_t( -1 ) != m_cgroup ) // could be -1if this is a lookahead_assertion

{

IterT & reserved1 = param.m_prgbackrefs[m_cgroup ].reserved1;

IterT old_ibegin = reserved1;

reserved1 = icur;

for( iter_type ialt = m_rgalternates.begin();m_rgalternates.end() != ialt; ++ialt )

{

if( (*ialt)->recursive_match_all( param,icur, CStringsT() ) )

return true;

}

reserved1 = old_ibegin;

}

else

{

for( iter_type ialt = m_rgalternates.begin();m_rgalternates.end() != ialt; ++ialt )

{

if( (*ialt)->recursive_match_all( param,icur, CStringsT() ) )

return true;

}

}

return false;

}

template< typename CStringsT >

bool _do_iterative_match_this(match_param<IterT> & param REGEX_VC6(COMMA CStringsT) ) const

{

if( 0 != m_peek_chars_begin &&

( eos_t<CStringsT>::eval( param,param.m_icur ) ||

m_peek_chars_end == std::find(m_peek_chars_begin, m_peek_chars_end, *param.m_icur ) ) )

{

return false;

}

_push_frame( param );

param.m_pnext = *m_rgalternates.begin();

return true;

}

bool _do_iterative_rematch_this(match_param<IterT> & param ) const

{

typedef typename alt_list_type::const_iteratoriter_type;

iter_type next_iter =++param.m_pstack->REGEX_NVC6(template) top REGEX_NVC6(<iter_type>) (REGEX_VC6(type2type<iter_type>()) );

if( m_rgalternates.end() != next_iter )

{

param.m_pnext = *next_iter;

return true;

}

_pop_frame( param );

return false;

}

public:

typedef typenamesub_expr<IterT>::char_type char_type;

match_group_base( size_t cgroup, regex_arena& arena )

: m_rgalternates( arena_allocator<sub_expr<IterT>*>(arena ) )

, m_cgroup( cgroup )

, m_nwidth( uninit_width() )

, m_pptail( 0 )

, m_peek_chars_end( 0 )

{

}

// Derived classes that own the end_groupobject must have a

// destructor, and that destructor must call_cleanup().

virtual ~match_group_base() = 0;

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_all_c( match_param<IterT>& param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_this REGEX_NVC6(<false_t>)( param REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

return _do_iterative_match_thisREGEX_NVC6(<true_t>) ( param REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_rematch_this_s( match_param<IterT>& param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

size_t group_number() const

{

return m_cgroup;

}

void add_item( sub_expr<IterT> * pitem )

{

*m_pptail = pitem;

m_pptail = pitem->pnext();

}

void add_alternate()

{

m_rgalternates.push_front( 0 );

m_pptail = &*m_rgalternates.begin();

}

void end_alternate()

{

*m_pptail = _get_end_group();

}

void open_group()

{

add_alternate();

}

must_have<char_type> close_group(regex_arena & arena )

{

end_alternate();

m_rgalternates.reverse();

return get_peek_chars( arena );

}

must_have<char_type> get_peek_chars(regex_arena & arena )

{

m_peek_chars_begin = 0;

// optimization: find the lookahead charactersfor each alternate

size_t total_chars = 0;

peek_param<char_type> peek;

typename alt_list_type::const_iterator ialt;

for( ialt = m_rgalternates.begin();m_rgalternates.end() != ialt; ++ialt )

{

if( ! (*ialt)->peek_this( peek ) )

{

peek.m_must_have.m_has = false;

return peek.m_must_have;

}

total_chars += peek.m_cchars;

}

arena_allocator<char_type> alloc( arena);

m_peek_chars_begin = alloc.allocate(total_chars, 0 );

m_peek_chars_end = m_peek_chars_begin;

for( ialt = m_rgalternates.begin();m_rgalternates.end() != ialt; ++ialt )

{

(*ialt)->peek_this( peek );

char_type const * in = ( peek.m_cchars > 2 )? peek.m_pchars : peek.m_rgchars;

m_peek_chars_end = std::copy( in, in +peek.m_cchars, m_peek_chars_end );

}

std::sort( m_peek_chars_begin, m_peek_chars_end);

m_peek_chars_end = std::unique(m_peek_chars_begin, m_peek_chars_end );

if( 1 < m_rgalternates.size() )

peek.m_must_have.m_has = false;

return peek.m_must_have;

}

size_t calternates() const

{

return m_rgalternates.size();

}

virtual void set_extent( extent_type const& )

{

}

width_type group_width

(

std::vector<match_group_base<IterT>*>& rggroups,

std::list<size_t> const &invisible_groups

)

{

// This should only be called on the top node

REGEX_ASSERT( 0 == m_cgroup );

if( uninit_width() == m_nwidth )

{

width_param<IterT> param( rggroups,invisible_groups );

match_group_base<IterT>::width_this(param );

}

return m_nwidth;

}

virtual width_type width_this(width_param<IterT> & param )

{

typedef typename alt_list_type::const_iteratoriter_type;

width_type width = { size_t( -1 ), 0 };

for( iter_type ialt = m_rgalternates.begin();worst_width != width && m_rgalternates.end() != ialt; ++ialt )

{

// prevent possible infinite recursion

if( m_cgroup < param.m_rggroups.size() )

param.m_rggroups[ m_cgroup ] = 0;

width_type temp_width = ( *ialt)->get_width( param );

if( m_cgroup < param.m_rggroups.size() )

param.m_rggroups[ m_cgroup ] = this;

width.m_min = regex_min( width.m_min,temp_width.m_min );

width.m_max = regex_max( width.m_max, temp_width.m_max);

}

return m_nwidth = width;

}

virtual bool peek_this(peek_param<char_type> & peek ) const

{

if( 0 == m_peek_chars_begin )

return false;

peek.m_cchars = std::distance(m_peek_chars_begin, m_peek_chars_end );

if( 2 < peek.m_cchars )

peek.m_pchars = m_peek_chars_begin;

else

std::copy( m_peek_chars_begin,m_peek_chars_end, peek.m_rgchars );

peek.m_must_have.m_has = false;

if( 1 == m_rgalternates.size() )

{

peek_param<char_type> local_peek;

(*m_rgalternates.begin())->peek_this(local_peek );

peek.m_must_have = local_peek.m_must_have;

}

return true;

}

protected:

void _cleanup()

{

typedef typename alt_list_type::const_iteratoriter_type;

for( iter_type ialt = m_rgalternates.begin();m_rgalternates.end() != ialt; ++ialt )

delete *ialt;

m_rgalternates.clear();

}

virtual sub_expr<IterT> *_get_end_group() = 0;

alt_list_type m_rgalternates;

size_t const m_cgroup;

width_type m_nwidth;

union

{

sub_expr<IterT> ** m_pptail; // only usedwhen adding elements

char_type * m_peek_chars_begin;

};

char_type * m_peek_chars_end;

};

template< typename IterT >

inlinematch_group_base<IterT>::~match_group_base()

{

}

// A indestructable_sub_expr is an object thatbrings itself back

// to life after explicitly being deleted. Itis used

// to ease clean-up of the sub_expr graph,where most

// nodes are dynamically allocated, but somenodes are

// members of other nodes and are notdynamically allocated.

// The recursive delete of the sub_expr graphcauses

// delete to be ( incorrectly ) called on thesemembers.

// By inheriting these members fromindestructable_sub_expr,

// explicit attempts to delete the object willhave no

// effect. ( Actually, the object will bedestructed and

// then immediately reconstructed. ) This isaccomplished

// by calling placement new in operator delete.

template< typename IterT, typename T >

class indestructable_sub_expr : publicsub_expr<IterT>

{

static void * operator new( size_t, regex_arena& );

static void operator delete( void *,regex_arena & );

protected:

static void * operator new( size_t, void * pv ){ return pv; }

static void operator delete( void *, void * ){}

public:

virtual ~indestructable_sub_expr() {}

static void operator delete( void * pv ) {::new( pv ) T; }

};

template< typename IterT >

class match_group : public match_group_base<IterT>

{

match_group( match_group const & );

match_group & operator=( match_group const& );

public:

match_group( size_t cgroup, regex_arena &arena )

: match_group_base<IterT>( cgroup, arena)

, m_end_group( this )

{

}

virtual ~match_group()

{

this->_cleanup();

}

virtual sub_expr<IterT> * quantify(size_t lbound, size_t ubound, bool greedy, regex_arena & arena )

{

if( greedy )

return new( arena )max_group_quantifier<IterT>( this, lbound, ubound );

else

return new( arena )min_group_quantifier<IterT>( this, lbound, ubound );

}

protected:

typedef typenamematch_group_base<IterT>::alt_list_type alt_list_type;

struct old_backref

{

IterT m_ibegin;

IterT m_iend;

bool m_matched;

old_backref() {}

old_backref( backref_tag<IterT> const& br )

: m_ibegin( br.first )

, m_iend( br.second )

, m_matched( br.matched )

{

}

};

static void restore_backref(backref_tag<IterT> & br, old_backref const & old_br )

{

br.first = old_br.m_ibegin;

br.second = old_br.m_iend;

br.matched = old_br.m_matched;

}

template< typename CStringsT >

bool _do_call_back( match_param<IterT>& param, IterT icur REGEX_VC6(COMMA CStringsT) ) const

{

if( size_t( -1 ) != this->m_cgroup )

{

backref_tag<IterT> & br =param.m_prgbackrefs[ this->m_cgroup ];

// Save the relevant portions of the backref inan old_backref struct

old_backref old_br( br );

br.first = br.reserved1;

br.second = icur;

br.matched = true;

if( this->recursive_match_next( param, icur,CStringsT() ) )

return true;

// Restore the backref to its saved state

restore_backref( br, old_br );

}

else

{

if( this->recursive_match_next( param, icur,CStringsT() ) )

return true;

}

return false;

}

class end_group : publicindestructable_sub_expr<IterT, end_group>

{

match_group<IterT> const *const m_pgroup;

end_group & operator=( end_group const& );

void _push_frame( match_param<IterT>& param ) const

{

size_t cgroup = m_pgroup->group_number();

if( size_t( -1 ) != cgroup )

{

backref_tag<IterT> & br =param.m_prgbackrefs[ cgroup ];

old_backref old_br( br );

param.m_pstack->push( old_br );

br.first = br.reserved1;

br.second = param.m_icur;

br.matched = true;

}

}

void _pop_frame( match_param<IterT> &param ) const

{

size_t cgroup = m_pgroup->group_number();

if( size_t( -1 ) != cgroup )

{

old_backref old_br;

param.m_pstack->pop( old_br );

match_group<IterT>::restore_backref(param.m_prgbackrefs[ cgroup ], old_br );

}

}

bool _do_iterative_match_this(match_param<IterT> & param ) const

{

_push_frame( param );

param.m_pnext = m_pgroup->next();

return true;

}

bool _do_iterative_rematch_this(match_param<IterT> & param ) const

{

_pop_frame( param );

return false;

}

public:

end_group( match_group<IterT> const *pgroup = 0 )

: m_pgroup( pgroup )

{

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return m_pgroup->REGEX_NVC6(template)_do_call_back REGEX_NVC6(<false_t>)( param, icur REGEX_VC6(COMMAfalse_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return m_pgroup->REGEX_NVC6(template)_do_call_back REGEX_NVC6(<true_t>)( param, icur REGEX_VC6(COMMA true_t()));

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual width_type width_this(width_param<IterT> & )

{

return zero_width;

}

} m_end_group;

friend class end_group;

virtual sub_expr<IterT> *_get_end_group()

{

return & m_end_group;

}

};

template< typename IterT >

inline void save_backrefs( backref_tag<IterT>const * ibegin, backref_tag<IterT> const * iend, IterT * prgci )

{

for( ; ibegin != iend; ++ibegin, ++prgci )

{

new( prgci ) IterT( ibegin->reserved1 );

}

}

template< typename IterT >

inline void restore_backrefs(backref_tag<IterT> * ibegin, backref_tag<IterT> * iend, IterT const* prgci )

{

for( ; ibegin != iend; ++ibegin, ++prgci )

{

ibegin->reserved1 = *prgci;

prgci->~IterT();

}

}

template< typename IterT >

class group_wrapper : publicsub_expr<IterT>

{

match_group_base<IterT> const *const m_pgroup;

group_wrapper & operator=( group_wrapperconst & );

public:

group_wrapper( match_group_base<IterT>const * pgroup )

: m_pgroup( pgroup )

{

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return m_pgroup->match_group_base<IterT>::iterative_match_this_s(param );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

returnm_pgroup->match_group_base<IterT>::iterative_match_this_c( param );

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

returnm_pgroup->match_group_base<IterT>::iterative_rematch_this_s( param );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

returnm_pgroup->match_group_base<IterT>::iterative_rematch_this_c( param );

}

virtual width_type width_this(width_param<IterT> & )

{

return zero_width;

}

};

struct deleter

{

template< typename T >

void operator()( T const & t )

{

t.T::~T();

}

};

// Behaves like a lookahead assertion ifm_cgroup is -1, or like

// an independent group otherwise.

template< typename IterT >

class independent_group_base : publicmatch_group_base<IterT>

{

independent_group_base( independent_group_baseconst & );

independent_group_base & operator=(independent_group_base const & );

template< typename CStringsT >

bool _do_recursive_match_all(match_param<IterT> & param, IterT icur REGEX_VC6(COMMA CStringsT) )const

{

backref_tag<IterT> * prgbr = 0;

// Copy onto the stack the part of the backrefvector that could

// be modified by the lookahead.

if( m_extent.second )

{

prgbr =static_cast<backref_tag<IterT>*>( alloca( m_extent.second * sizeof(backref_tag<IterT> ) ) );

std::uninitialized_copy(

param.m_prgbackrefs + m_extent.first,

param.m_prgbackrefs + m_extent.first +m_extent.second,

prgbr );

}

// Match until the end of this group and thenreturn

// BUGBUG can the compiler optimize this?

bool const fdomatch = CStringsT::value ?

match_group_base<IterT>::recursive_match_all_c(param, icur ) :

match_group_base<IterT>::recursive_match_all_s(param, icur );

if( m_fexpected == fdomatch )

{

// If m_cgroup != 1, then this is not azero-width assertion.

if( fdomatch && size_t( -1 ) !=this->m_cgroup )

icur = param.m_prgbackrefs[ this->m_cgroup].second;

if( this->recursive_match_next( param, icur,CStringsT() ) )

{

std::for_each( prgbr, prgbr + m_extent.second,deleter() );

return true;

}

}

// if match_group::recursive_match_all returnedtrue, the backrefs must be restored

if( m_extent.second && fdomatch )

std::copy( prgbr, prgbr + m_extent.second,param.m_prgbackrefs + m_extent.first );

std::for_each( prgbr, prgbr + m_extent.second,deleter() );

return false;

}

template< typename CStringsT >

bool _do_iterative_match_this(match_param<IterT> & param REGEX_VC6(COMMA CStringsT) ) const

{

group_wrapper<IterT> expr( this );

_push_frame( param );

IterT ibegin = param.m_icur;

bool const fdomatch = _do_match_iterative(&expr, param, param.m_icur, CStringsT() );

if( m_fexpected == fdomatch )

{

// If m_cgroup == -1, then this is a zero-widthassertion.

if( fdomatch && size_t( -1 ) == this->m_cgroup)

param.m_icur = ibegin;

param.m_pnext = this->next();

return true;

}

_pop_frame( param );

return false;

}

bool _do_iterative_rematch_this(match_param<IterT> & param ) const

{

_pop_frame( param );

return false;

}

public:

independent_group_base( size_t cgroup,regex_arena & arena )

: match_group_base<IterT>( cgroup, arena)

, m_fexpected( true )

, m_extent( 0, 0 )

{

}

virtual void set_extent( extent_type const& ex )

{

m_extent = ex;

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_thisREGEX_NVC6(<false_t>) ( param REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c( match_param<IterT>& param ) const

{

return _do_iterative_match_thisREGEX_NVC6(<true_t>) ( param REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool peek_this(peek_param<char_type> & peek ) const

{

if( size_t( -1 ) == this->m_cgroup )

return false;

return match_group_base<IterT>::peek_this(peek );

}

protected:

void _push_frame( match_param<IterT>& param ) const

{

unsafe_stack * pstack = param.m_pstack;

typedef typenamematch_param<IterT>::backref_type backref_type;

backref_type * ibegin = param.m_prgbackrefs +m_extent.first;

backref_type * iend = ibegin + m_extent.second;

for( ; iend != ibegin; ++ibegin )

{

pstack->push( *ibegin );

}

pstack->push( param.m_icur );

}

void _pop_frame( match_param<IterT> &param ) const

{

unsafe_stack * pstack = param.m_pstack;

typedef typename match_param<IterT>::backref_typebackref_type;

backref_type * ibegin = param.m_prgbackrefs +m_extent.first;

backref_type * iend = ibegin + m_extent.second;

pstack->pop( param.m_icur );

while( iend != ibegin )

{

pstack->pop( *--iend );

}

}

independent_group_base( bool const fexpected,regex_arena & arena )

: match_group_base<IterT>( size_t( -1 ),arena )

, m_fexpected( fexpected )

{

}

bool const m_fexpected;

extent_type m_extent;

};

template< typename IterT >

class independent_group : publicindependent_group_base<IterT>

{

independent_group( independent_group const& );

independent_group & operator=(independent_group const & );

public:

independent_group( size_t cgroup, regex_arena& arena )

: independent_group_base<IterT>( cgroup,arena )

, m_end_group( this )

{

}

virtual ~independent_group()

{

this->_cleanup();

}

virtual sub_expr<IterT> * quantify(size_t lbound, size_t ubound, bool greedy, regex_arena & arena )

{

if( greedy )

return new( arena )max_group_quantifier<IterT>( this, lbound, ubound );

else

return new( arena )min_group_quantifier<IterT>( this, lbound, ubound );

}

protected:

independent_group( bool const fexpected,regex_arena & arena )

: independent_group_base<IterT>(fexpected, arena )

, m_end_group( this )

{

}

bool _do_call_back( match_param<IterT>& param, IterT icur ) const

{

if( size_t( -1 ) != this->m_cgroup )

{

backref_tag<IterT> & br =param.m_prgbackrefs[ this->m_cgroup ];

br.first = br.reserved1;

br.second = icur;

br.matched = true;

}

return true;

}

class end_group : public indestructable_sub_expr<IterT,end_group>

{

independent_group<IterT> const *constm_pgroup;

end_group & operator=( end_group const& );

bool _do_iterative_match_this(match_param<IterT> & param ) const

{

size_t cgroup = m_pgroup->group_number();

if( size_t( -1 ) != cgroup )

{

backref_tag<IterT> & br =param.m_prgbackrefs[ cgroup ];

br.first = br.reserved1;

br.second = param.m_icur;

br.matched = true;

}

param.m_pnext = 0;

return true;

}

public:

end_group( independent_group<IterT> const* pgroup = 0 )

: m_pgroup( pgroup )

{

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return m_pgroup->_do_call_back( param, icur);

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return m_pgroup->_do_call_back( param, icur);

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual width_type width_this(width_param<IterT> & )

{

return zero_width;

}

} m_end_group;

friend class end_group;

virtual sub_expr<IterT> *_get_end_group()

{

return & m_end_group;

}

};

template< typename IterT >

class lookahead_assertion : public independent_group<IterT>

{

lookahead_assertion( lookahead_assertion const& );

lookahead_assertion & operator=(lookahead_assertion const & );

public:

lookahead_assertion( bool const fexpected,regex_arena & arena )

: independent_group<IterT>( fexpected,arena )

{

}

virtual sub_expr<IterT> * quantify(size_t, size_t, bool, regex_arena & )

{

throw bad_regexpr( "look-ahead assertioncannot be quantified" );

}

virtual bool is_assertion() const

{

return true;

}

virtual width_type width_this(width_param<IterT> & param )

{

// calculate the group's width and store it,but return zero_width

match_group_base<IterT>::width_this(param );

return zero_width;

}

virtual bool peek_this(peek_param<char_type> & peek ) const

{

return this->next()->peek_this( peek );

}

};

template< typename IterT >

class lookbehind_assertion : publicindependent_group_base<IterT>

{

lookbehind_assertion( lookbehind_assertionconst & );

lookbehind_assertion & operator=(lookbehind_assertion const & );

template< typename CStringsT >

bool _do_recursive_match_all(match_param<IterT> & param, IterT icur REGEX_VC6(COMMA CStringsT) )const

{

typedef typenamestd::iterator_traits<IterT>::difference_type diff_type;

// This is the room in the string from thestart to the current position

diff_type room = std::distance(param.m_ibufferbegin, icur );

// If we don't have enough room to match thelookbehind, the match fails.

// If we wanted the match to fail, try to matchthe rest of the pattern.

if( this->m_nwidth.m_min >static_cast<size_t>( room ) )

return this->m_fexpected ? false :this->recursive_match_next( param, icur, CStringsT() );

backref_tag<IterT> * prgbr = 0;

// Copy onto the stack the part of the backrefvector that could

// be modified by the lookbehind.

if( this->m_extent.second )

{

prgbr = static_cast<backref_tag<IterT>*>(alloca( this->m_extent.second * sizeof( backref_tag<IterT> ) ) );

std::uninitialized_copy(

param.m_prgbackrefs + this->m_extent.first,

param.m_prgbackrefs + this->m_extent.first +this->m_extent.second,

prgbr );

}

IterT local_ibegin = icur;

std::advance( local_ibegin,-static_cast<diff_type>( regex_min<size_t>(this->m_nwidth.m_max, room ) ) );

IterT local_iend = icur;

std::advance( local_iend,-static_cast<diff_type>( this->m_nwidth.m_min ) );

// Create a local param struct that has icur asparam.m_iend

match_param<IterT> local_param(param.m_ibufferbegin, param.m_imatchbegin, icur, param.m_prgbackrefs,param.m_cbackrefs );

// Find the rightmost match that ends at icur.

for( IterT local_icur = local_ibegin; ;++local_icur )

{

// Match until the end of this group and thenreturn

// Note that we're callingrecursive_match_all_s regardless of the CStringsT switch.

// This is because for the lookbehindassertion, the termination condition is when

// icur == param.m_iend, not when *icur == '/0'

bool const fmatched =match_group_base<IterT>::recursive_match_all_s( local_param, local_icur);

// If the match results were what we wereexpecting, try to match the

// rest of the pattern. If that succeeds,return true.

if( this->m_fexpected == fmatched &&this->recursive_match_next( param, icur, CStringsT() ) )

{

std::for_each( prgbr, prgbr +this->m_extent.second, deleter() );

return true;

}

// if match_group::recursive_match_all returnedtrue, the backrefs must be restored

if( fmatched )

{

if( this->m_extent.second )

std::copy( prgbr, prgbr +this->m_extent.second, param.m_prgbackrefs + this->m_extent.first );

// Match succeeded. If this is a negativelookbehind, we didn't want it

// to succeed, so return false.

if( ! this->m_fexpected )

{

std::for_each( prgbr, prgbr +this->m_extent.second, deleter() );

return false;

}

}

if( local_icur == local_iend )

break;

}

// No variation of the lookbehind was satisfiedin a way that permited

// the rest of the pattern to matchsuccessfully, so return false.

std::for_each( prgbr, prgbr +this->m_extent.second, deleter() );

return false;

}

template< typename CStringsT >

bool _do_iterative_match_this(match_param<IterT> & param REGEX_VC6(COMMA CStringsT) ) const

{

typedef typenamestd::iterator_traits<IterT>::difference_type diff_type;

// Save the backrefs

this->_push_frame( param );

// This is the room in the string from thestart to the current position

diff_type room = std::distance(param.m_ibufferbegin, param.m_icur );

// If we don't have enough room to match thelookbehind, the match fails.

// If we wanted the match to fail, try to matchthe rest of the pattern.

if( this->m_nwidth.m_min >static_cast<size_t>( room ) )

{

if( this->m_fexpected )

{

this->_pop_frame( param );

return false;

}

param.m_pnext = this->next();

return true;

}

IterT local_ibegin = param.m_icur;

std::advance( local_ibegin,-static_cast<diff_type>( regex_min<size_t>(this->m_nwidth.m_max, room ) ) );

IterT local_iend = param.m_icur;

std::advance( local_iend,-static_cast<diff_type>( this->m_nwidth.m_min ) );

// Create a local param struct that has icur asparam.m_iend

match_param<IterT> local_param(param.m_ibufferbegin, param.m_imatchbegin, param.m_icur, param.m_prgbackrefs,param.m_cbackrefs );

local_param.m_pstack = param.m_pstack;

group_wrapper<IterT> expr( this );

// Find the rightmost match that ends at icur.

for( IterT local_icur = local_ibegin; ;++local_icur )

{

// Match until the end of this group and thenreturn

// Note that we're calling_do_match_iterative_helper_s regardless of the CStringsT switch.

// This is because for the lookbehindassertion, the termination condition is when

// icur == param.m_iend, not when *icur == '/0'

bool const fmatched =regex_access<IterT>::_do_match_iterative_helper_s( &expr,local_param, local_icur );

// If the match results were what we wereexpecting, try to match the

// rest of the pattern. If that succeeds,return true.

if( this->m_fexpected == fmatched )

{

param.m_pnext = this->next();

return true;

}

// if match_group::recursive_match_all returnedtrue, the backrefs must be restored

if( fmatched )

{

// Restore the backrefs

this->_pop_frame( param );

// Match succeeded. If this is a negativelookbehind, we didn't want it

// to succeed, so return false.

if( ! this->m_fexpected )

return false;

// Save the backrefs again.

this->_push_frame( param );

}

if( local_icur == local_iend )

break;

}

// No variation of the lookbehind was satisfiedin a way that permited

// the rest of the pattern to matchsuccessfully, so return false.

this->_pop_frame( param );

return false;

}

bool _do_iterative_rematch_this(match_param<IterT> & param ) const

{

this->_pop_frame( param );

return false;

}

public:

lookbehind_assertion( bool const fexpected,regex_arena & arena )

: independent_group_base<IterT>(fexpected, arena )

{

}

virtual ~lookbehind_assertion()

{

this->_cleanup();

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_thisREGEX_NVC6(<false_t>) ( param REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

return _do_iterative_match_thisREGEX_NVC6(<true_t>) ( param REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool is_assertion() const

{

return true;

}

virtual width_type width_this(width_param<IterT> & param )

{

// calculate the group's width and store it,but return zero_width

match_group_base<IterT>::width_this(param );

return zero_width;

}

virtual bool peek_this( peek_param<char_type>& peek ) const

{

return this->next()->peek_this( peek );

}

protected:

struct end_group : publicindestructable_sub_expr<IterT, end_group>

{

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return param.m_iend == icur;

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return param.m_iend == icur;

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = 0;

return param.m_iend == param.m_icur;

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

param.m_pnext = 0;

return param.m_iend == param.m_icur;

}

virtual width_type width_this(width_param<IterT> & )

{

return zero_width;

}

} m_end_group;

virtual sub_expr<IterT> *_get_end_group()

{

return & m_end_group;

}

};

template< typename IterT >

class group_quantifier : publicmatch_quantifier<IterT>

{

group_quantifier & operator=(group_quantifier const & );

bool _do_iterative_match_this(match_param<IterT> & param ) const

{

_push_frame( param );

param.m_pnext = this->m_psub->next(); //ptr to end_quant

return true;

}

bool _do_iterative_rematch_this(match_param<IterT> & param ) const

{

_pop_frame( param );

return false;

}

public:

group_quantifier

(

match_group_base<IterT> * psub,

size_t lbound,

size_t ubound,

sub_expr<IterT> * pend_quant

)

: match_quantifier<IterT>( psub, lbound,ubound )

, m_group( *psub )

{

*psub->pnext() = pend_quant;

}

// sub-classes of group_quantifer that own theend_quant

// object must declare a destructor, and itmust call _cleanup

virtual ~group_quantifier() = 0;

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

protected:

struct old_quant

{

typedef typenamebackref_tag<IterT>::smart_iter_type smart_iter_type;

size_t reserved2;

bool reserved3;

smart_iter_type reserved4;

smart_iter_type reserved5;

old_quant()

{

}

old_quant( backref_tag<IterT> const &br )

: reserved2( br.reserved2 )

, reserved3( br.reserved3 )

, reserved4( br.reserved4 )

, reserved5( br.reserved5 )

{

}

};

void _push_frame( match_param<IterT>& param ) const

{

typedef typenamebackref_tag<IterT>::smart_iter_type smart_iter_type;

backref_tag<IterT> & br =param.m_prgbackrefs[ group_number() ];

old_quant old_qt( br );

param.m_pstack->push( old_qt );

br.reserved2 = 0; // nbr of times this grouphas matched

br.reserved3 = true; // toggle used forbacktracking

br.reserved4 =static_init<smart_iter_type>::value;

br.reserved5 =static_init<smart_iter_type>::value;

}

void _pop_frame( match_param<IterT> &param ) const

{

backref_tag<IterT> & br =param.m_prgbackrefs[ group_number() ];

old_quant old_qt;

param.m_pstack->pop( old_qt );

br.reserved2 = old_qt.reserved2;

br.reserved3 = old_qt.reserved3;

br.reserved4 = old_qt.reserved4;

br.reserved5 = old_qt.reserved5;

}

size_t group_number() const

{

return m_group.group_number();

}

size_t & cmatches( match_param<IterT>& param ) const

{

return param.m_prgbackrefs[ group_number()].reserved2;

}

typenamebackref_tag<IterT>::smart_iter_type & highwater1(match_param<IterT> & param ) const

{

return param.m_prgbackrefs[ group_number()].reserved4;

}

typename backref_tag<IterT>::smart_iter_type& highwater2( match_param<IterT> & param ) const

{

return param.m_prgbackrefs[ group_number()].reserved5;

}

match_group_base<IterT> const &m_group;

};

template< typename IterT >

inlinegroup_quantifier<IterT>::~group_quantifier()

{

}

template< typename IterT >

class max_group_quantifier : publicgroup_quantifier<IterT>

{

max_group_quantifier & operator=(max_group_quantifier const & );

template< typename CStringsT >

bool _do_recursive_match_all(match_param<IterT> & param, IterT icur REGEX_VC6(COMMA CStringsT) )const

{

typedef typenamebackref_tag<IterT>::smart_iter_type smart_iter_type;

smart_iter_type old_highwater1 =this->highwater1( param );

smart_iter_type old_highwater2 =this->highwater2( param );

size_t old_cmatches = this->cmatches( param);

this->highwater1( param ) =static_init<smart_iter_type>::value;

this->highwater2( param ) = icur;

this->cmatches( param ) = 0;

if( _do_recurse REGEX_NVC6(<CStringsT>) (param, icur REGEX_VC6(COMMA CStringsT()) ) )

return true;

this->cmatches( param ) = old_cmatches;

this->highwater2( param ) = old_highwater2;

this->highwater1( param ) = old_highwater1;

return false;

}

public:

max_group_quantifier(match_group_base<IterT> * psub, size_t lbound, size_t ubound )

: group_quantifier<IterT>( psub, lbound,ubound, & m_end_quant )

, m_end_quant( this )

{

}

virtual ~max_group_quantifier()

{

// Must call _cleanup() here before theend_quant object

// gets destroyed.

this->_cleanup();

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

protected:

template< typename CStringsT >

bool _do_recurse( match_param<IterT>& param, IterT icur REGEX_VC6(COMMA CStringsT) ) const

{

if( this->m_ubound == this->cmatches(param ) )

return this->recursive_match_next( param,icur, CStringsT() );

++this->cmatches( param );

if( this->m_psub->recursive_match_all(param, icur, CStringsT() ) )

return true;

if( --this->cmatches( param ) <this->m_lbound )

return false;

return this->recursive_match_next( param,icur, CStringsT() );

}

class end_quantifier : publicindestructable_sub_expr<IterT, end_quantifier>

{

max_group_quantifier<IterT> const *constm_pquant;

end_quantifier & operator=( end_quantifierconst & );

void _push_frame( match_param<IterT>& param ) const

{

backref_tag<IterT> & br =param.m_prgbackrefs[ m_pquant->group_number() ];

param.m_pstack->push( br.reserved4 );

br.reserved4 = br.reserved5;

br.reserved5 = param.m_icur;

}

void _pop_frame( match_param<IterT> &param ) const

{

backref_tag<IterT> & br =param.m_prgbackrefs[ m_pquant->group_number() ];

br.reserved5 = br.reserved4;

param.m_pstack->pop( br.reserved4 );

}

template< typename CStringsT >

bool _do_recursive_match_all(match_param<IterT> & param, IterT icur REGEX_VC6(COMMA CStringsT) )const

{

typedef typename backref_tag<IterT>::smart_iter_typesmart_iter_type;

smart_iter_type old_highwater1 =m_pquant->highwater1( param );

if( icur == old_highwater1 )

return m_pquant->recursive_match_next(param, icur, CStringsT() );

m_pquant->highwater1( param ) =m_pquant->highwater2( param );

m_pquant->highwater2( param ) = icur;

if( m_pquant->REGEX_NVC6(template)_do_recurse REGEX_NVC6(<CStringsT>) ( param, icur REGEX_VC6(COMMACStringsT()) ) )

return true;

m_pquant->highwater2( param ) =m_pquant->highwater1( param );

m_pquant->highwater1( param ) =old_highwater1;

return false;

}

bool _do_iterative_match_this(match_param<IterT> & param ) const

{

backref_tag<IterT> & br =param.m_prgbackrefs[ m_pquant->group_number() ];

// forcibly break the infinite loop

if( param.m_icur == br.reserved4 )

{

_push_frame( param );

param.m_pnext = m_pquant->next();

return true;

}

_push_frame( param );

// If we've matched the max nbr of times, moveon to the next

// sub-expr.

if( m_pquant->m_ubound == br.reserved2 )

{

param.m_pnext = m_pquant->next();

br.reserved3 = false;

return true;

}

// Rematch the group.

br.reserved3 = true;

param.m_pnext = m_pquant->m_psub;

++br.reserved2;

return true;

}

bool _do_iterative_rematch_this(match_param<IterT> & param ) const

{

typedef typename backref_tag<IterT>::smart_iter_typesmart_iter_type;

backref_tag<IterT> & br =param.m_prgbackrefs[ m_pquant->group_number() ];

// infinite loop forcibly broken

if( param.m_icur ==param.m_pstack->REGEX_NVC6(template) top REGEX_NVC6(<smart_iter_type>)( REGEX_VC6(type2type<smart_iter_type>()) ) )

{

_pop_frame( param );

return false;

}

if( br.reserved3 )

{

--br.reserved2;

param.m_pnext = m_pquant->next();

if( m_pquant->m_lbound <= br.reserved2 )

{

br.reserved3 = false;

return true;

}

_pop_frame( param );

return false;

}

br.reserved3 = true;

_pop_frame( param );

return false;

}

public:

end_quantifier(max_group_quantifier<IterT> const * pquant = 0 )

: m_pquant( pquant )

{

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual width_type width_this(width_param<IterT> & )

{

return zero_width;

}

} m_end_quant;

friend class end_quantifier;

};

template< typename IterT >

class min_group_quantifier : publicgroup_quantifier<IterT>

{

min_group_quantifier & operator=(min_group_quantifier const & );

template< typename CStringsT >

bool _do_recursive_match_all(match_param<IterT> & param, IterT icur REGEX_VC6(COMMA CStringsT) )const

{

typedef typenamebackref_tag<IterT>::smart_iter_type smart_iter_type;

smart_iter_type old_highwater1 =this->highwater1( param );

smart_iter_type old_highwater2 =this->highwater2( param );

size_t old_cmatches = this->cmatches( param);

this->highwater1( param ) =static_init<smart_iter_type>::value;

this->highwater2( param ) = icur;

this->cmatches( param ) = 0;

if( _do_recurse REGEX_NVC6(<CStringsT>) (param, icur REGEX_VC6(COMMA CStringsT()) ) )

return true;

this->cmatches( param ) = old_cmatches;

this->highwater2( param ) = old_highwater2;

this->highwater1( param ) = old_highwater1;

return false;

}

public:

min_group_quantifier(match_group_base<IterT> * psub, size_t lbound, size_t ubound )

: group_quantifier<IterT>( psub, lbound,ubound, & m_end_quant )

, m_end_quant( this )

{

}

virtual ~min_group_quantifier()

{

// Must call _cleanup() here before theend_quant object

// gets destroyed.

this->_cleanup();

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_all_c( match_param<IterT>& param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

protected:

template< typename CStringsT >

bool _do_recurse( match_param<IterT>& param, IterT icur REGEX_VC6(COMMA CStringsT) ) const

{

if( this->m_lbound <= this->cmatches(param ) )

{

if( this->recursive_match_next( param, icur,CStringsT() ) )

return true;

}

if( this->m_ubound > this->cmatches(param ) )

{

++this->cmatches( param );

if( this->m_psub->recursive_match_all(param, icur, CStringsT() ) )

return true;

--this->cmatches( param );

}

return false;

}

class end_quantifier : publicindestructable_sub_expr<IterT, end_quantifier>

{

min_group_quantifier<IterT> const *constm_pquant;

end_quantifier & operator=( end_quantifierconst & );

void _push_frame( match_param<IterT>& param ) const

{

backref_tag<IterT> & br =param.m_prgbackrefs[ m_pquant->group_number() ];

param.m_pstack->push( br.reserved4 );

br.reserved4 = br.reserved5;

br.reserved5 = param.m_icur;

}

void _pop_frame( match_param<IterT> &param ) const

{

backref_tag<IterT> & br =param.m_prgbackrefs[ m_pquant->group_number() ];

br.reserved5 = br.reserved4;

param.m_pstack->pop( br.reserved4 );

}

template< typename CStringsT >

bool _do_recursive_match_all( match_param<IterT>& param, IterT icur REGEX_VC6(COMMA CStringsT) ) const

{

typedef typenamebackref_tag<IterT>::smart_iter_type smart_iter_type;

smart_iter_type old_highwater1 =m_pquant->highwater1( param );

if( icur == old_highwater1 )

return m_pquant->recursive_match_next(param, icur, CStringsT() );

m_pquant->highwater1( param ) =m_pquant->highwater2( param );

m_pquant->highwater2( param ) = icur;

if( m_pquant->REGEX_NVC6(template)_do_recurse REGEX_NVC6(<CStringsT>) ( param, icur REGEX_VC6(COMMA CStringsT())) )

return true;

m_pquant->highwater2( param ) =m_pquant->highwater1( param );

m_pquant->highwater1( param ) =old_highwater1;

return false;

}

bool _do_iterative_match_this(match_param<IterT> & param ) const

{

backref_tag<IterT> & br =param.m_prgbackrefs[ m_pquant->group_number() ];

// forcibly break the infinite loop

if( param.m_icur == br.reserved4 )

{

_push_frame( param );

param.m_pnext = m_pquant->next();

return true;

}

_push_frame( param );

if( m_pquant->m_lbound <= br.reserved2 )

{

br.reserved3 = false;

param.m_pnext = m_pquant->next();

return true;

}

++br.reserved2;

param.m_pnext = m_pquant->m_psub;

return true;

}

bool _do_iterative_rematch_this(match_param<IterT> & param ) const

{

typedef typenamebackref_tag<IterT>::smart_iter_type smart_iter_type;

backref_tag<IterT> & br =param.m_prgbackrefs[ m_pquant->group_number() ];

// infinite loop forcibly broken

if( param.m_icur ==param.m_pstack->REGEX_NVC6(template) top REGEX_NVC6(<smart_iter_type>)( REGEX_VC6(type2type<smart_iter_type>()) ) )

{

_pop_frame( param );

return false;

}

if( br.reserved3 )

{

--br.reserved2;

_pop_frame( param );

return false;

}

br.reserved3 = true;

if( m_pquant->m_ubound > br.reserved2 )

{

++br.reserved2;

param.m_pnext = m_pquant->m_psub;

return true;

}

_pop_frame( param );

return false;

}

public:

end_quantifier(min_group_quantifier<IterT> const * pquant = 0 )

: m_pquant( pquant )

{

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

return _do_iterative_match_this( param );

}

virtual bool iterative_rematch_this_s( match_param<IterT>& param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual width_type width_this(width_param<IterT> & )

{

return zero_width;

}

} m_end_quant;

friend class end_quantifier;

};

inline void fixup_backref( size_t &cbackref, std::list<size_t> const & invisible_groups )

{

std::list<size_t>::const_iterator iter =invisible_groups.begin();

for( ; invisible_groups.end() != iter&& cbackref >= *iter; ++iter )

{

++cbackref;

}

}

template< typename IterT >

class match_backref : publicsub_expr<IterT>

{

bool _do_iterative_rematch_this(match_param<IterT> & param ) const

{

typedef typenamestd::iterator_traits<IterT>::difference_type diff_type;

backref_tag<IterT> const & br =param.m_prgbackrefs[ m_nbackref ];

diff_type dist = std::distance( br.first,br.second );

std::advance( param.m_icur, -dist );

return false;

}

public:

match_backref( size_t nbackref )

: m_nbackref( nbackref )

{

}

// Return the width specifications of the groupto which this backref refers

virtual width_type width_this(width_param<IterT> & param )

{

// fix up the backref to take into account thenumber of invisible groups

fixup_backref( m_nbackref, param.m_invisible_groups);

if( m_nbackref >= param.m_rggroups.size() )

throw bad_regexpr( "reference tononexistent group" );

// If the entry in the backref vector has beennulled out, then we are

// calculating the width for this group.

if( 0 == param.m_rggroups[ m_nbackref ] )

return worst_width; // can't tell how wide thisgroup will be. :-(

return param.m_rggroups[ m_nbackref]->width_this( param );

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

protected:

size_t m_nbackref;

};

template< typename CmpT, typename IterT >

class match_backref_t : publicmatch_backref<IterT>

{

public:

match_backref_t( size_t nbackref )

: match_backref<IterT>( nbackref )

{

}

virtual sub_expr<IterT> * quantify(size_t lbound, size_t ubound, bool greedy, regex_arena & arena )

{

if( greedy )

return new( arena )max_atom_quantifier<IterT, match_backref_t<CmpT, IterT> >( this,lbound, ubound );

else

return new( arena )min_atom_quantifier<IterT, match_backref_t<CmpT, IterT> >( this,lbound, ubound );

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return ( match_backref_t::recursive_match_this_s(param, icur ) && this->recursive_match_next( param, icur, false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return (match_backref_t::recursive_match_this_c( param, icur ) &&this->recursive_match_next( param, icur, true_t() ) );

}

virtual bool recursive_match_this_s(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_this_c(match_param<IterT> & param, IterT & icur ) const

{

return _do_match_thisREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_thisREGEX_NVC6(<false_t>) ( param, param.m_icur REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

param.m_pnext = this->next();

return _do_match_this REGEX_NVC6(<true_t>)( param, param.m_icur REGEX_VC6(COMMA true_t()) );

}

protected:

template< typename CStringsT >

bool _do_match_this( match_param<IterT>& param, IterT & icur REGEX_VC6(COMMA CStringsT) ) const

{

// Pattern compilation should have failed ifthe following is false:

REGEX_ASSERT( this->m_nbackref <param.m_cbackrefs );

// Don't match a backref that hasn't matchanything

if( ! param.m_prgbackrefs[ this->m_nbackref].matched )

return false;

IterT ithis = param.m_prgbackrefs[this->m_nbackref ].first;

IterT const iend = param.m_prgbackrefs[this->m_nbackref ].second;

IterT icur_tmp = icur;

for( ; iend != ithis; ++icur_tmp, ++ithis )

{

if( eos_t<CStringsT>::eval( param,icur_tmp ) || CmpT::eval( *icur_tmp, *ithis ) )

return false;

}

icur = icur_tmp;

return true;

}

};

template< typename IterT >

inline match_backref<IterT> *create_backref(

size_t cbackref,

REGEX_FLAGS flags, regex_arena & arena )

{

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

switch( NOCASE & flags )

{

case 0:

return new( arena )match_backref_t<ch_neq_t<char_type>, IterT>( cbackref );

case NOCASE:

return new( arena )match_backref_t<ch_neq_nocase_t<char_type>, IterT>( cbackref );

default:

REGEX_ASSERT(false);

return 0;

}

}

template< typename IterT >

class match_recurse : publicsub_expr<IterT>

{

match_recurse & operator=( match_recurseconst & );

void _push_frame( match_param<IterT>& param ) const

{

typedef typenamematch_param<IterT>::backref_type backref_type;

unsafe_stack * pstack = param.m_pstack;

backref_type * ibegin = param.m_prgbackrefs;

backref_type * iend = ibegin +param.m_cbackrefs;

for( ; iend != ibegin; ++ibegin )

{

pstack->push( ibegin->reserved1 );

}

}

void _pop_frame( match_param<IterT> &param ) const

{

typedef typenamematch_param<IterT>::backref_type backref_type;

unsafe_stack * pstack = param.m_pstack;

backref_type * ibegin = param.m_prgbackrefs;

backref_type * iend = ibegin +param.m_cbackrefs;

while( iend != ibegin )

{

--iend;

pstack->pop( iend->reserved1 );

}

}

template< typename CStringsT >

bool _do_recursive_match_all(match_param<IterT> & param, IterT icur REGEX_VC6(COMMA CStringsT) )const

{

// Prevent infinite recursion. If icur ==param.m_prgbackrefs[ 0 ].reserved1,

// then the pattern has eaten 0 chars to date,and we would recurse forever.

if( icur == param.m_prgbackrefs[ 0 ].reserved1)

return this->recursive_match_next( param,icur, CStringsT() );

// copy the backref vector onto the stack

IterT * prgci = static_cast<IterT*>(alloca( param.m_cbackrefs * sizeof( IterT ) ) );

save_backrefs<IterT>( param.m_prgbackrefs,param.m_prgbackrefs + param.m_cbackrefs, prgci );

// Recurse.

if( param.m_pfirst->recursive_match_all(param, icur, CStringsT() ) )

{

// Restore the backref vector

restore_backrefs<IterT>(param.m_prgbackrefs, param.m_prgbackrefs + param.m_cbackrefs, prgci );

// Recursive match succeeded. Try to match therest of the pattern

// using the end of the recursive match as thestart of the next

return this->recursive_match_next( param,param.m_prgbackrefs[ 0 ].second, CStringsT() );

}

// Recursion failed

std::for_each( prgci, prgci +param.m_cbackrefs, deleter() );

return false;

}

template< typename CStringsT >

bool _do_iterative_match_this(match_param<IterT> & param REGEX_VC6(COMMA CStringsT) ) const

{

param.m_pstack->push( param.m_icur );

// Prevent infine recursion

if( param.m_icur == param.m_prgbackrefs[ 0].reserved1 )

{

param.m_pnext = this->next();

return true;

}

_push_frame( param );

if( _do_match_iterative( param.m_pfirst, param,param.m_icur, CStringsT() ) )

{

_pop_frame( param );

param.m_pnext = this->next();

return true;

}

_pop_frame( param );

param.m_pstack->pop( param.m_icur );

return false;

}

bool _do_iterative_rematch_this(match_param<IterT> & param ) const

{

param.m_pstack->pop( param.m_icur );

return false;

}

public:

match_recurse()

{

}

virtual sub_expr<IterT> * quantify(size_t, size_t, bool, regex_arena & )

{

throw bad_regexpr( "recursionsub-expression cannot be quantified" );

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_thisREGEX_NVC6(<false_t>) ( param REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

return _do_iterative_match_thisREGEX_NVC6(<true_t>) ( param REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

return _do_iterative_rematch_this( param );

}

virtual bool iterative_rematch_this_c( match_param<IterT>& param ) const

{

return _do_iterative_rematch_this( param );

}

virtual width_type width_this(width_param<IterT> & )

{

return worst_width;

}

};

template< typename IterT >

inline match_recurse<IterT> *create_recurse( regex_arena & arena )

{

return new( arena )match_recurse<IterT>();

}

template< typename IterT >

struct backref_condition

{

size_t m_cbackref;

backref_condition( size_t cbackref )

: m_cbackref( cbackref )

{

}

template< typename CStringsT >

bool recursive_match_this( match_param<IterT>& param, IterT, CStringsT ) const

{

return m_cbackref < param.m_cbackrefs&& param.m_prgbackrefs[ m_cbackref ].matched;

}

template< typename CStringsT >

bool iterative_match_this(match_param<IterT> & param, CStringsT ) const

{

return m_cbackref < param.m_cbackrefs&& param.m_prgbackrefs[ m_cbackref ].matched;

}

template< typename CStringsT >

bool iterative_rematch_this(match_param<IterT> &, CStringsT ) const

{

return false;

}

void width_this( width_param<IterT> &param )

{

// fix up the backref to take into account thenumber of invisible groups

fixup_backref( m_cbackref,param.m_invisible_groups );

}

};

template< typename IterT >

struct assertion_condition

{

std::auto_ptr<match_group_base<IterT>> m_passert;

assertion_condition( match_group_base<IterT>* passert , regex_arena & arena )

: m_passert( passert )

{

*passert->pnext() = new( arena )end_of_pattern<IterT>;

}

bool recursive_match_this(match_param<IterT> & param, IterT icur, false_t ) const

{

return m_passert->recursive_match_all_s(param, icur );

}

bool recursive_match_this(match_param<IterT> & param, IterT icur, true_t ) const

{

return m_passert->recursive_match_all_c(param, icur );

}

bool iterative_match_this(match_param<IterT> & param, false_t ) const

{

return m_passert->iterative_match_this_s(param );

}

bool iterative_match_this(match_param<IterT> & param, true_t ) const

{

return m_passert->iterative_match_this_c(param );

}

bool iterative_rematch_this(match_param<IterT> & param, false_t ) const

{

return m_passert->iterative_rematch_this_s(param );

}

bool iterative_rematch_this(match_param<IterT> & param, true_t ) const

{

return m_passert->iterative_rematch_this_c(param );

}

void width_this( width_param<IterT> &param )

{

( void ) m_passert->width_this( param );

}

};

template< typename IterT, typename CondT>

class match_conditional : publicmatch_group<IterT>

{

protected:

typedef typenamematch_group<IterT>::alt_list_type alt_list_type;

private:

match_conditional & operator=(match_conditional const & );

template< typename CStringsT >

bool _do_recursive_match_all(match_param<IterT> & param, IterT icur REGEX_VC6(COMMA CStringsT) )const

{

typedef typename alt_list_type::const_iteratoriter_type;

iter_type ialt =this->m_rgalternates.begin();

if( m_condition.recursive_match_this( param,icur, CStringsT() ) || this->m_rgalternates.end() != ++ialt )

{

return (*ialt)->recursive_match_all( param,icur, CStringsT() );

}

return this->recursive_match_next( param,icur, CStringsT() );

}

template< typename CStringsT >

bool _do_iterative_match_this(match_param<IterT> & param REGEX_VC6(COMMA CStringsT) ) const

{

typedef typename alt_list_type::const_iteratoriter_type;

iter_type ialt =this->m_rgalternates.begin();

if( m_condition.iterative_match_this( param,CStringsT() ) )

{

param.m_pstack->push( true );

param.m_pnext = *ialt;

return true;

}

param.m_pstack->push( false );

param.m_pnext = ( this->m_rgalternates.end()!= ++ialt ) ? *ialt : this->next();

return true;

}

template< typename CStringsT >

bool _do_iterative_rematch_this(match_param<IterT> & param REGEX_VC6(COMMA CStringsT) ) const

{

bool condition;

param.m_pstack->pop( condition );

if( condition )

m_condition.iterative_rematch_this( param,CStringsT() );

return false;

}

public:

typedef CondT condition_type;

match_conditional( size_t cgroup,condition_type condition, regex_arena & arena )

: match_group<IterT>( cgroup, arena )

, m_condition( condition )

{

}

virtual bool recursive_match_all_s(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<false_t>) ( param, icur REGEX_VC6(COMMA false_t()) );

}

virtual bool recursive_match_all_c(match_param<IterT> & param, IterT icur ) const

{

return _do_recursive_match_allREGEX_NVC6(<true_t>) ( param, icur REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_match_this_s(match_param<IterT> & param ) const

{

return _do_iterative_match_thisREGEX_NVC6(<false_t>) ( param REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_match_this_c(match_param<IterT> & param ) const

{

return _do_iterative_match_this REGEX_NVC6(<true_t>)( param REGEX_VC6(COMMA true_t()) );

}

virtual bool iterative_rematch_this_s(match_param<IterT> & param ) const

{

return _do_iterative_rematch_thisREGEX_NVC6(<false_t>) ( param REGEX_VC6(COMMA false_t()) );

}

virtual bool iterative_rematch_this_c(match_param<IterT> & param ) const

{

return _do_iterative_rematch_thisREGEX_NVC6(<true_t>) ( param REGEX_VC6(COMMA true_t()) );

}

virtual width_type width_this(width_param<IterT> & param )

{

typedef typename alt_list_type::const_iteratoriter_type;

iter_type ialt =this->m_rgalternates.begin();

width_type width = ( *ialt )->get_width(param );

if( this->m_rgalternates.end() != ++ialt )

{

width_type temp_width = ( *ialt)->get_width( param );

width.m_min = regex_min( width.m_min,temp_width.m_min );

width.m_max = regex_max( width.m_max,temp_width.m_max );

}

else

{

width.m_min = 0;

}

// Have the condition calculate its width, too.This is important

// if the condition is a lookbehind assertion.

m_condition.width_this( param );

return this->m_nwidth = width;

}

protected:

condition_type m_condition;

};

template< typename IterT >

inline match_conditional<IterT,backref_condition<IterT> > * create_backref_conditional(

size_t cgroup,

size_t cbackref,

regex_arena & arena )

{

backref_condition<IterT> cond( cbackref);

return new( arena ) match_conditional<IterT,backref_condition<IterT> >(

cgroup, cond, arena );

}

template< typename IterT >

inline match_conditional<IterT,assertion_condition<IterT> > * create_assertion_conditional(

size_t cgroup,

match_group_base<IterT> * passert,

regex_arena & arena )

{

assertion_condition<IterT> cond( passert,arena );

return new( arena ) match_conditional<IterT,assertion_condition<IterT> >(

cgroup, cond, arena );

}

//

// From basic_rpattern_base_impl

//

template< typename IterT >

REGEXPR_H_INLINE boolbasic_rpattern_base_impl<IterT>::_ok_to_recurse() const //throw()

{

switch( m_mode )

{

case MODE_FAST:

return true;

case MODE_SAFE:

return false;

case MODE_MIXED:

return m_fok_to_recurse;

default:

return false;

}

}

template< typename IterT >

REGEXPR_H_INLINE voidbasic_rpattern_base_impl<IterT>::swap(basic_rpattern_base_impl<IterT> & that ) // throw()

{

using std::swap;

swap( m_fuses_backrefs, that.m_fuses_backrefs);

swap( m_floop, that.m_floop );

swap( m_fok_to_recurse, that.m_fok_to_recurse);

swap( m_cgroups, that.m_cgroups );

swap( m_cgroups_visible, that.m_cgroups_visible);

swap( m_flags, that.m_flags );

swap( m_mode, that.m_mode );

swap( m_nwidth, that.m_nwidth );

swap( m_pfirst, that.m_pfirst );

swap( m_search, that.m_search );

swap_auto_ptr( m_pat, that.m_pat );

swap_auto_ptr( m_subst, that.m_subst );

m_subst_list.swap( that.m_subst_list );

m_invisible_groups.swap(that.m_invisible_groups );

m_arena.swap( that.m_arena );

}

// A helper class for automatically deallocatingthe arena when

// parsing the pattern results in an exception

class arena_guard

{

arena_guard( arena_guard const & );

arena_guard & operator=( arena_guard const& );

regex_arena * m_parena;

public:

explicit arena_guard( regex_arena & arena )

: m_parena( &arena )

{

}

~arena_guard()

{

if( m_parena )

m_parena->clear();

}

void dismiss()

{

m_parena = 0;

}

};

template< typename CatT >

struct is_random_access_helper

{

enum { value = false };

};

template<>

structis_random_access_helper<std::random_access_iterator_tag>

{

enum { value = true };

};

template< typename IterT >

struct is_random_access

{

typedef typenamestd::iterator_traits<IterT>::iterator_category cat_type;

enum { value =is_random_access_helper<cat_type>::value };

};

} // namespace detail

//

// Implementation of basic_rpattern_base:

//

template< typename IterT, typename SyntaxT>

REGEXPR_H_INLINE voidbasic_rpattern_base<IterT, SyntaxT>::init( string_type const & pat,REGEX_FLAGS flags, REGEX_MODE mode )

{

basic_rpattern_base<IterT, SyntaxT> temp(pat, flags, mode );

swap( temp );

}

template< typename IterT, typename SyntaxT>

REGEXPR_H_INLINE voidbasic_rpattern_base<IterT, SyntaxT>::init( string_type const & pat,string_type const & subst, REGEX_FLAGS flags, REGEX_MODE mode )

{

basic_rpattern_base<IterT, SyntaxT> temp(pat, subst, flags, mode );

swap( temp );

}

template< typename IterT, typename SyntaxT>

REGEXPR_H_INLINE voidbasic_rpattern_base<IterT, SyntaxT>::_common_init( REGEX_FLAGS flags )

{

this->m_cgroups = 0;

std::vector<detail::match_group_base<IterT>*>rggroups;

typename string_type::iterator ipat =this->m_pat->begin();

syntax_type sy( flags );

detail::match_group_base<IterT> * pgroup;

// Set up a sentry that will free the arenamemory

// automatically on parse failure.

{

detail::arena_guard guard( this->m_arena );

// This will throw on failure

pgroup = _find_next_group( ipat, 0, sy,rggroups );

// terminate the pattern with theend_of_pattern marker

*pgroup->pnext() = new( this->m_arena )detail::end_of_pattern<IterT>;

// The parse was successful. Dismiss the parsesentry

guard.dismiss();

}

REGEX_ASSERT( 0 == m_pfirst );

m_pfirst = pgroup;

// Calculate the width of the pattern and allgroups

this->m_nwidth = pgroup->group_width(rggroups, m_invisible_groups );

//

// determine if we can get away with onlycalling m_pfirst->recursive_match_all only once

//

this->m_floop = true;

// Optimization: if first character of patternstring is '^'

// and we are not doing a multiline match, thenwe only

// need to try recursive_match_all once

typename string_type::iterator icur =this->m_pat->begin();

if( MULTILINE != ( MULTILINE &this->m_flags ) &&

1 == pgroup->calternates() &&

this->m_pat->end() != icur &&

BEGIN_LINE == sy.reg_token( icur,this->m_pat->end() ) )

{

this->m_flags = ( REGEX_FLAGS ) ( m_flags& ~RIGHTMOST );

this->m_floop = false;

}

// Optimization: if first 2 characters ofpattern string are ".*" or ".+",

// then we only need to try recursive_match_allonce

icur = this->m_pat->begin();

if( RIGHTMOST != ( RIGHTMOST &this->m_flags ) &&

SINGLELINE == ( SINGLELINE &this->m_flags ) &&

1 == pgroup->calternates() &&

this->m_pat->end() != icur &&

MATCH_ANY == sy.reg_token( icur,this->m_pat->end() ) &&

this->m_pat->end() != icur )

{

switch( sy.quant_token( icur,this->m_pat->end() ) )

{

case ONE_OR_MORE:

case ZERO_OR_MORE:

case ONE_OR_MORE_MIN:

case ZERO_OR_MORE_MIN:

this->m_floop = false;

break;

default:

break;

}

}

}

template< typename IterT, typename SyntaxT>

REGEXPR_H_INLINE voidbasic_rpattern_base<IterT, SyntaxT>::set_substitution( string_type const& subst )

{

using std::swap;

std::auto_ptr<string_type> temp_subst(new string_type( subst ) );

detail::subst_list_type temp_subst_list;

bool uses_backrefs = false;

_normalize_string( *temp_subst );

basic_rpattern_base<IterT,SyntaxT>::_parse_subst( *temp_subst, uses_backrefs, temp_subst_list );

detail::swap_auto_ptr( temp_subst,this->m_subst );

swap( uses_backrefs, this->m_fuses_backrefs);

temp_subst_list.swap( this->m_subst_list );

}

template< typename IterT, typename SyntaxT>

inline detail::match_group_base<IterT> *basic_rpattern_base<IterT, SyntaxT>::_find_next_group(

typename string_type::iterator & ipat,

detail::match_group_base<IterT> *pgroup_enclosing, syntax_type & sy,

std::vector<detail::match_group_base<IterT>*>& rggroups )

{

std::auto_ptr<detail::match_group_base<IterT>> pgroup;

typename string_type::iterator itemp = ipat;

REGEX_FLAGS old_flags = sy.get_flags();

TOKEN tok = NO_TOKEN;

size_t extent_start = this->m_cgroups;

bool fconditional = false;

// Look for group extensions.

if( this->m_pat->end() != ipat &&NO_TOKEN != ( tok = sy.ext_token( ipat, this->m_pat->end() ) ) )

{

if( this->m_pat->begin() == itemp ||this->m_pat->end() == ipat )

throw bad_regexpr( "ill-formed regularexpression" );

// Is this a recursion element?

if( EXT_RECURSE == tok )

{

pgroup_enclosing->add_item(detail::create_recurse<IterT>( this->m_arena ) );

// This pattern could recurse deeply. Note thatfact here so that

// we can opt to use a stack-conservativealgorithm at match time.

this->m_fok_to_recurse = false;

}

// Don't process empty groups like (?:) or (?i)or (?R)

if( END_GROUP != sy.reg_token( itemp = ipat,this->m_pat->end() ) )

{

switch( tok )

{

case EXT_NOBACKREF:

// note that this group is not visible, so wecan fix

// up offsets into the backref vector later

m_invisible_groups.push_back(this->m_cgroups );

detail::reset_auto_ptr( pgroup, new(this->m_arena ) detail::match_group<IterT>( _get_next_group_nbr(),this->m_arena ) );

break;

case EXT_INDEPENDENT:

m_invisible_groups.push_back( this->m_cgroups);

detail::reset_auto_ptr( pgroup, new(this->m_arena ) detail::independent_group<IterT>(_get_next_group_nbr(), this->m_arena ) );

break;

case EXT_POS_LOOKAHEAD:

detail::reset_auto_ptr( pgroup, new(this->m_arena ) detail::lookahead_assertion<IterT>( true,this->m_arena ) );

break;

case EXT_NEG_LOOKAHEAD:

detail::reset_auto_ptr( pgroup, new(this->m_arena ) detail::lookahead_assertion<IterT>( false,this->m_arena ) );

break;

case EXT_POS_LOOKBEHIND:

detail::reset_auto_ptr( pgroup, new(this->m_arena ) detail::lookbehind_assertion<IterT>( true,this->m_arena ) );

break;

case EXT_NEG_LOOKBEHIND:

detail::reset_auto_ptr( pgroup, new(this->m_arena ) detail::lookbehind_assertion<IterT>( false,this->m_arena ) );

break;

case EXT_CONDITION:

fconditional = true;

m_invisible_groups.push_back(this->m_cgroups );

if( size_t cbackref = detail::parse_int( ipat,this->m_pat->end() ) &&

END_GROUP == sy.reg_token( ipat,this->m_pat->end() ) )

{

detail::reset_auto_ptr(

pgroup,detail::create_backref_conditional<IterT>(

_get_next_group_nbr(), cbackref,this->m_arena ) );

}

else

{

switch( sy.ext_token( itemp = ipat,this->m_pat->end() ) )

{

case EXT_POS_LOOKAHEAD:

case EXT_NEG_LOOKAHEAD:

case EXT_POS_LOOKBEHIND:

case EXT_NEG_LOOKBEHIND:

{

std::auto_ptr<detail::match_group_base<IterT>> pgroup_tmp(

_find_next_group( ipat, 0, sy, rggroups ) );

detail::reset_auto_ptr(

pgroup,detail::create_assertion_conditional<IterT>(

_get_next_group_nbr(), pgroup_tmp.get(),this->m_arena ) );

pgroup_tmp.release();

}

break;

default:

throw bad_regexpr( "bad extensionsequence" );

}

}

break;

case EXT_COMMENT:

while( END_GROUP != ( tok = sy.reg_token( ipat,this->m_pat->end() ) ) )

{

if( NO_TOKEN == tok &&this->m_pat->end() != ipat )

++ipat;

if( this->m_pat->end() == ipat )

throw bad_regexpr( "Expecting end ofcomment" );

}

break;

default:

throw bad_regexpr( "bad extensionsequence" );

}

}

else

{

// Skip over the END_GROUP token

ipat = itemp;

}

}

else

{

detail::reset_auto_ptr( pgroup, new(this->m_arena ) detail::match_group<IterT>( _get_next_group_nbr(),this->m_arena ) );

++this->m_cgroups_visible;

}

if( 0 != pgroup.get() )

{

detail::must_have<char_type> must;

pgroup->open_group();

while( _find_next( ipat, pgroup.get(), sy,rggroups ) ) {}

must = pgroup->close_group( this->m_arena);

// if this is a conditional group, then theremust be at

// most 2 alternates.

if( fconditional && 2 <pgroup->calternates() )

throw bad_regexpr( "Too many alternates inconditional subexpression" );

// if this is the top-level group and itreturned a "must have"

// string, then use that to initialize aboyer-moore search structure

if(detail::is_random_access<IterT>::value && must.m_has && 0== pgroup->group_number() )

{

typedef typename string_type::const_iteratoriter_type;

m_search = new( this->m_arena ) detail::boyer_moore<iter_type>

( must.m_begin, must.m_end, must.m_lower );

}

// Add this group to the rggroups array

if( size_t( -1 ) != pgroup->group_number() )

{

if( pgroup->group_number() >=rggroups.size() )

rggroups.resize( pgroup->group_number() + 1,0 );

rggroups[ pgroup->group_number() ] =pgroup.get();

}

// tell this group how many groups arecontained within it

pgroup->set_extent( detail::extent_type(extent_start, this->m_cgroups - extent_start ) );

// If this is not a pattern modifier, restorethe

// flags to their previous settings. Thiscauses

// pattern modifiers to have the scope of their

// enclosing group.

sy.set_flags( old_flags );

}

return pgroup.release();

}

namespace detail

{

// If we reached the end of the string beforefinding the end of the

// character set, then this is an ill-formedregex

template< typename IterT >

inline void check_iter( IterT icur, IterT iend)

{

if( iend == icur )

throw bad_regexpr( "expecting end ofcharacter set" );

}

template< typename IBeginT, typename IEndT>

inline typenamestd::iterator_traits<IEndT>::value_type get_escaped_char( IBeginT &icur, IEndT iend, bool normalize )

{

typedef typenamestd::iterator_traits<IEndT>::value_type char_type;

char_type ch = 0, i;

check_iter<IEndT>( icur, iend );

switch( *icur )

{

// octal escape sequence

case REGEX_CHAR(char_type,'0'): caseREGEX_CHAR(char_type,'1'): case REGEX_CHAR(char_type,'2'): caseREGEX_CHAR(char_type,'3'):

case REGEX_CHAR(char_type,'4'): caseREGEX_CHAR(char_type,'5'): case REGEX_CHAR(char_type,'6'): caseREGEX_CHAR(char_type,'7'):

ch = char_type( *icur++ -REGEX_CHAR(char_type,'0') );

for( i=0; i<2 &&REGEX_CHAR(char_type,'0') <= *icur && REGEX_CHAR(char_type,'7')>= *icur; check_iter<IEndT>( ++icur, iend ) )

ch = char_type( ch * 8 + ( *icur - REGEX_CHAR(char_type,'0')) );

break;

// bell character

case REGEX_CHAR(char_type,'a'):

if( ! normalize )

goto default_;

ch = REGEX_CHAR(char_type,'/a');

++icur;

break;

// control character

case REGEX_CHAR(char_type,'c'):

check_iter<IEndT>( ++icur, iend );

ch = *icur++;

if( REGEX_CHAR(char_type,'a') <= ch&& REGEX_CHAR(char_type,'z') >= ch )

ch = detail::regex_toupper( ch );

ch ^= 0x40;

break;

// escape character

case REGEX_CHAR(char_type,'e'):

ch = 27;

++icur;

break;

// formfeed character

case REGEX_CHAR(char_type,'f'):

if( ! normalize )

goto default_;

ch = REGEX_CHAR(char_type,'/f');

++icur;

break;

// newline

case REGEX_CHAR(char_type,'n'):

if( ! normalize )

goto default_;

ch = REGEX_CHAR(char_type,'/n');

++icur;

break;

// return

case REGEX_CHAR(char_type,'r'):

if( ! normalize )

goto default_;

ch = REGEX_CHAR(char_type,'/r');

++icur;

break;

// horizontal tab

case REGEX_CHAR(char_type,'t'):

if( ! normalize )

goto default_;

ch = REGEX_CHAR(char_type,'/t');

++icur;

break;

// vertical tab

case REGEX_CHAR(char_type,'v'):

if( ! normalize )

goto default_;

ch = REGEX_CHAR(char_type,'/v');

++icur;

break;

// hex escape sequence

case REGEX_CHAR(char_type,'x'):

for( ++icur, ch=i=0; i<2 &&detail::regex_isxdigit( *icur ); check_iter<IEndT>( ++icur, iend ) )

ch = char_type( ch * 16 +detail::regex_xdigit2int( *icur ) );

break;

// backslash

case REGEX_CHAR(char_type,'//'):

if( ! normalize )

goto default_;

ch = REGEX_CHAR(char_type,'//');

++icur;

break;

// all other escaped characters representthemselves

default: default_:

ch = *icur;

++icur;

break;

}

return ch;

}

template< typename CharT, typename CharSetT,typename SyntaxT >

inline void parse_charset(

std::auto_ptr<CharSetT> & pnew,

typenamestd::basic_string<CharT>::iterator & icur,

typenamestd::basic_string<CharT>::const_iterator iend,

SyntaxT & sy )

{

typedef CharT char_type;

typedef std::basic_string<CharT>string_type;

typedef typename string_type::const_iteratoriter_type;

typename string_type::iterator itemp = icur;

bool const normalize = ( NORMALIZE == (NORMALIZE & sy.get_flags() ) );

if( iend != itemp && CHARSET_NEGATE ==sy.charset_token( itemp, iend ) )

{

pnew->m_fcompliment = true;

icur = itemp;

}

TOKEN tok;

char_type ch_prev = 0;

bool fhave_prev = false;

charset const * pcharset = 0;

typename string_type::iterator iprev = icur;

bool const fnocase = ( NOCASE == ( NOCASE &sy.get_flags() ) );

check_iter<iter_type>( icur, iend );

// remember the current position and grab thenext token

tok = sy.charset_token( icur, iend );

do

{

check_iter<iter_type>( icur, iend );

if( CHARSET_RANGE == tok && fhave_prev)

{

// remember the current position

typename string_type::iterator iprev2 = icur;

fhave_prev = false;

// ch_prev is lower bound of a range

switch( sy.charset_token( icur, iend ) )

{

case CHARSET_RANGE:

case CHARSET_NEGATE:

icur = iprev2; // un-get these tokens and fallthrough

case NO_TOKEN:

pnew->set_bit_range( ch_prev, *icur++,fnocase );

continue;

case CHARSET_ESCAPE: // BUGBUG user-definedcharset?

pnew->set_bit_range( ch_prev,get_escaped_char( icur, iend, normalize ), fnocase );

continue;

case CHARSET_BACKSPACE:

pnew->set_bit_range( ch_prev, char_type( 8), fnocase ); // backspace

continue;

case CHARSET_END: // fall through

default: // not a range.

icur = iprev; // backup to range token

pnew->set_bit( ch_prev, fnocase );

pnew->set_bit( *icur++, fnocase );

continue;

}

}

if( fhave_prev )

pnew->set_bit( ch_prev, fnocase );

fhave_prev = false;

switch( tok )

{

// None of the intrinsic charsets arecase-sensitive,

// so no special handling must be done when theNOCASE

// flag is set.

case CHARSET_RANGE:

case CHARSET_NEGATE:

case CHARSET_END:

icur = iprev; // un-get these tokens

ch_prev = *icur++;

fhave_prev = true;

continue;

case CHARSET_BACKSPACE:

ch_prev = char_type( 8 ); // backspace

fhave_prev = true;

continue;

case ESC_DIGIT:

*pnew |=intrinsic_charsets<char_type>::get_digit_charset();

continue;

case ESC_NOT_DIGIT:

*pnew |=intrinsic_charsets<char_type>::get_not_digit_charset();

continue;

case ESC_SPACE:

*pnew |=intrinsic_charsets<char_type>::get_space_charset();

continue;

case ESC_NOT_SPACE:

*pnew |=intrinsic_charsets<char_type>::get_not_space_charset();

continue;

case ESC_WORD:

*pnew |=intrinsic_charsets<char_type>::get_word_charset();

continue;

case ESC_NOT_WORD:

*pnew |=intrinsic_charsets<char_type>::get_not_word_charset();

continue;

case CHARSET_ALNUM:

pnew->m_posixcharson |= ( wct_alnum() );

continue;

case CHARSET_NOT_ALNUM:

pnew->m_posixcharsoff.push_front(wct_alnum() );

continue;

case CHARSET_ALPHA:

pnew->m_posixcharson |= ( wct_alpha() );

continue;

case CHARSET_NOT_ALPHA:

pnew->m_posixcharsoff.push_front(wct_alpha() );

continue;

case CHARSET_BLANK:

pnew->m_posixcharson |= ( wct_blank() );

continue;

case CHARSET_NOT_BLANK:

pnew->m_posixcharsoff.push_front(wct_blank() );

continue;

case CHARSET_CNTRL:

pnew->m_posixcharson |= ( wct_cntrl() );

continue;

case CHARSET_NOT_CNTRL:

pnew->m_posixcharsoff.push_front(wct_cntrl() );

continue;

case CHARSET_DIGIT:

pnew->m_posixcharson |= ( wct_digit() );

continue;

case CHARSET_NOT_DIGIT:

pnew->m_posixcharsoff.push_front( wct_digit());

continue;

case CHARSET_GRAPH:

pnew->m_posixcharson |= ( wct_graph() );

continue;

case CHARSET_NOT_GRAPH:

pnew->m_posixcharsoff.push_front(wct_graph() );

continue;

case CHARSET_LOWER:

if( NOCASE == ( NOCASE & sy.get_flags() ) )

pnew->m_posixcharson |= (wct_lower()|wct_upper() );

else

pnew->m_posixcharson |= ( wct_lower() );

continue;

case CHARSET_NOT_LOWER:

if( NOCASE == ( NOCASE & sy.get_flags() ) )

pnew->m_posixcharsoff.push_front(wct_lower()|wct_upper() );

else

pnew->m_posixcharsoff.push_front( wct_lower());

continue;

case CHARSET_PRINT:

pnew->m_posixcharson |= ( wct_print() );

continue;

case CHARSET_NOT_PRINT:

pnew->m_posixcharsoff.push_front(wct_print() );

continue;

case CHARSET_PUNCT:

pnew->m_posixcharson |= ( wct_punct() );

continue;

case CHARSET_NOT_PUNCT:

pnew->m_posixcharsoff.push_front(wct_punct() );

continue;

case CHARSET_SPACE:

pnew->m_posixcharson |= ( wct_space() );

continue;

case CHARSET_NOT_SPACE:

pnew->m_posixcharsoff.push_front(wct_space() );

continue;

case CHARSET_UPPER:

if( NOCASE == ( NOCASE & sy.get_flags() ) )

pnew->m_posixcharson |= (wct_upper()|wct_lower() );

else

pnew->m_posixcharson |= ( wct_upper() );

continue;

case CHARSET_NOT_UPPER:

if( NOCASE == ( NOCASE & sy.get_flags() ) )

pnew->m_posixcharsoff.push_front( wct_upper()|wct_lower());

else

pnew->m_posixcharsoff.push_front(wct_upper() );

continue;

case CHARSET_XDIGIT:

pnew->m_posixcharson |= ( wct_xdigit() );

continue;

case CHARSET_NOT_XDIGIT:

pnew->m_posixcharsoff.push_front(wct_xdigit() );

continue;

case CHARSET_ESCAPE:

// Maybe this is a user-defined intrinsiccharset

pcharset = get_altern_charset( *icur, sy );

if( 0 != pcharset )

{

*pnew |= *pcharset;

++icur;

continue;

}

else

{

ch_prev = get_escaped_char( icur, iend,normalize );

fhave_prev = true;

}

continue;

default:

ch_prev = *icur++;

fhave_prev = true;

continue;

}

}

while( check_iter<iter_type>( iprev =icur, iend ),

CHARSET_END != ( tok = sy.charset_token( icur,iend ) ) );

if( fhave_prev )

pnew->set_bit( ch_prev, fnocase );

pnew->optimize( type2type<char_type>());

}

template< typename CharT, typename SyntaxT>

inline charset const * get_altern_charset(CharT ch, SyntaxT & sy )

{

typedef std::basic_string<CharT>string_type;

charset const * pcharset = 0;

regex::detail::charset_map<CharT> &charset_map = sy.get_charset_map();

typenameregex::detail::charset_map<CharT>::iterator iter = charset_map.find( ch);

if( charset_map.end() != iter )

{

bool const fnocase = ( NOCASE == (sy.get_flags() & NOCASE ) );

pcharset = iter->second.m_rgcharsets[fnocase ];

if( 0 == pcharset )

{

// tmp takes ownership of any ptrs.

charset_map_node<CharT> tmp =iter->second;

charset_map.erase( iter ); // prevent possibleinfinite recursion

typename string_type::iterator ibegin =tmp.m_str.begin();

std::auto_ptr<charset> pnew( new charset);

std::auto_ptr<charset const> pold(tmp.m_rgcharsets[ !fnocase ] );

parse_charset<CharT, charset>( pnew,ibegin, tmp.m_str.end(), sy );

tmp.m_rgcharsets[ fnocase ] = pcharset =pnew.get();

charset_map[ ch ] = tmp; // could throw

// charset_map has taken ownership of thesepointers now.

pnew.release();

pold.release();

}

}

return pcharset;

}

} // namespace detail

//

// Read ahead through the pattern and treatsequential atoms

// as a single atom, making sure to handlequantification

// correctly. Warning: dense code ahead.

//

template< typename IterT, typename SyntaxT>

inline void basic_rpattern_base<IterT,SyntaxT>::_find_atom(

typename string_type::iterator & ipat,

detail::match_group_base<IterT> * pgroup,

syntax_type & sy )

{

typedef typename string_type::iteratoriter_type;

typedef typenamestd::iterator_traits<iter_type>::difference_type diff_type;

iter_type itemp = ipat, ibegin;

diff_type const nstart = std::distance(this->m_pat->begin(), ipat );

do

{

if( itemp != ipat ) // Is there whitespace toskip?

{

diff_type dist = std::distance(this->m_pat->begin(), ipat );

this->m_pat->erase( ipat, itemp ); //erase the whitespace from the patttern

std::advance( ipat =this->m_pat->begin(), dist );

if( this->m_pat->end() == ( itemp = ipat) ) // are we at the end of the pattern?

break;

}

switch( sy.quant_token( itemp,this->m_pat->end() ) )

{

// if {, } can't be interpreted as quantifiers,treat them as regular chars

case BEGIN_RANGE:

std::advance( ibegin =this->m_pat->begin(), nstart );

if( ibegin != ipat ) // treat as a quantifier

goto quantify;

case NO_TOKEN:

case END_RANGE:

case END_RANGE_MIN:

case RANGE_SEPARATOR:

break;

default:

std::advance( ibegin =this->m_pat->begin(), nstart );

if( ibegin == ipat ) // must be able toquantify something.

throw bad_regexpr( "quantifier notexpected" );

quantify: if( ibegin != --ipat )

pgroup->add_item(detail::create_literal<IterT>( ibegin, ipat, sy.get_flags(),this->m_arena ) );

std::auto_ptr<detail::sub_expr<IterT>> pnew( detail::create_char<IterT>( *ipat++, sy.get_flags(),this->m_arena ) );

_quantify( pnew, ipat, false, sy );

pgroup->add_item( pnew.release() );

return;

}

} while( this->m_pat->end() != ++ipat&& ! sy.reg_token( itemp = ipat, this->m_pat->end() ) );

std::advance( ibegin =this->m_pat->begin(), nstart );

REGEX_ASSERT( ipat != ibegin );

pgroup->add_item(detail::create_literal<IterT>( ibegin, ipat, sy.get_flags(),this->m_arena ) );

}

template< typename IterT, typename SyntaxT>

inline bool basic_rpattern_base<IterT,SyntaxT>::_find_next(

typename string_type::iterator & ipat,

detail::match_group_base<IterT> * pgroup,

syntax_type & sy,

std::vector<detail::match_group_base<IterT>*>& rggroups )

{

std::auto_ptr<detail::sub_expr<IterT>> pnew;

std::auto_ptr<detail::custom_charset>pcs;

typename string_type::iterator ibegin, itemp;

bool fdone, is_group = false;

bool const normalize = ( NORMALIZE == (NORMALIZE & sy.get_flags() ) );

if( this->m_pat->end() == ipat )

{

if( 0 != pgroup->group_number() )

throw bad_regexpr( "mismatchedparenthesis" );

return false;

}

switch( sy.reg_token( ipat,this->m_pat->end() ) )

{

case NO_TOKEN: // not a token. Must be an atom

if( this->m_pat->end() == ipat )

{

if( 0 != pgroup->group_number() )

throw bad_regexpr( "mismatchedparenthesis" );

return false;

}

_find_atom( ipat, pgroup, sy );

return true;

case END_GROUP:

if( 0 == pgroup->group_number() )

throw bad_regexpr( "mismatchedparenthesis" );

return false;

case ALTERNATION:

pgroup->end_alternate();

pgroup->add_alternate();

return true;

case BEGIN_GROUP:

// Find next group. could return NULL if thegroup is really

// a pattern modifier, like: ( ?s-i )

detail::reset_auto_ptr( pnew, _find_next_group(ipat, pgroup, sy, rggroups ) );

is_group = true;

break;

case BEGIN_LINE:

detail::reset_auto_ptr( pnew,detail::create_bol<IterT>( sy.get_flags(), this->m_arena ) );

break;

case END_LINE:

detail::reset_auto_ptr( pnew,detail::create_eol<IterT>( sy.get_flags(), this->m_arena ) );

break;

case BEGIN_CHARSET:

detail::reset_auto_ptr( pcs, new(this->m_arena ) detail::custom_charset( this->m_arena ) );

detail::parse_charset<char_type,detail::custom_charset>(

pcs, ipat, this->m_pat->end(), sy );

detail::reset_auto_ptr( pnew,

detail::create_custom_charset<IterT>(pcs.get(), sy.get_flags(), this->m_arena ) );

pcs.release();

break;

case MATCH_ANY:

detail::reset_auto_ptr( pnew,detail::create_any<IterT>( sy.get_flags(), this->m_arena ) );

break;

case ESC_WORD_BOUNDARY:

detail::reset_auto_ptr( pnew,detail::create_word_boundary<IterT>( true, sy.get_flags(),this->m_arena ) );

break;

case ESC_NOT_WORD_BOUNDARY:

detail::reset_auto_ptr( pnew,detail::create_word_boundary<IterT>( false, sy.get_flags(),this->m_arena ) );

break;

case ESC_WORD_START:

detail::reset_auto_ptr( pnew,detail::create_word_start<IterT>( sy.get_flags(), this->m_arena ) );

break;

case ESC_WORD_STOP:

detail::reset_auto_ptr( pnew,detail::create_word_stop<IterT>( sy.get_flags(), this->m_arena ) );

break;

case ESC_DIGIT:

detail::reset_auto_ptr( pnew,detail::create_charset<IterT>(detail::intrinsic_charsets<char_type>::get_digit_charset(),sy.get_flags(), this->m_arena ) );

break;

case ESC_NOT_DIGIT:

detail::reset_auto_ptr( pnew,detail::create_charset<IterT>(detail::intrinsic_charsets<char_type>::get_not_digit_charset(),sy.get_flags(), this->m_arena ) );

break;

case ESC_WORD:

detail::reset_auto_ptr( pnew,detail::create_charset<IterT>(detail::intrinsic_charsets<char_type>::get_word_charset(),sy.get_flags(), this->m_arena ) );

break;

case ESC_NOT_WORD:

detail::reset_auto_ptr( pnew,detail::create_charset<IterT>( detail::intrinsic_charsets<char_type>::get_not_word_charset(),sy.get_flags(), this->m_arena ) );

break;

case ESC_SPACE:

detail::reset_auto_ptr( pnew,detail::create_charset<IterT>(detail::intrinsic_charsets<char_type>::get_space_charset(),sy.get_flags(), this->m_arena ) );

break;

case ESC_NOT_SPACE:

detail::reset_auto_ptr( pnew,detail::create_charset<IterT>(detail::intrinsic_charsets<char_type>::get_not_space_charset(),sy.get_flags(), this->m_arena ) );

break;

case ESC_BEGIN_STRING:

detail::reset_auto_ptr( pnew, detail::create_bos<IterT>(sy.get_flags(), this->m_arena ) );

break;

case ESC_END_STRING:

detail::reset_auto_ptr( pnew,detail::create_eos<IterT>( sy.get_flags(), this->m_arena ) );

break;

case ESC_END_STRING_z:

detail::reset_auto_ptr( pnew, detail::create_eoz<IterT>(sy.get_flags(), this->m_arena ) );

break;

case ESCAPE:

if( this->m_pat->end() == ipat )

{

// BUGBUG what if the escape sequence is morethat 1 character?

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( *--ipat, sy.get_flags(), this->m_arena ));

++ipat;

}

else if( REGEX_CHAR(char_type,'0') <= *ipat&& REGEX_CHAR(char_type,'9') >= *ipat )

{

// Parse at most 3 decimal digits.

size_t nbackref = detail::parse_int( itemp =ipat, this->m_pat->end(), 999 );

// If the resulting number could conceivably bea backref, then it is.

if( REGEX_CHAR(char_type,'0') != *ipat&& ( 10 > nbackref || nbackref < _cgroups_total() ) )

{

detail::reset_auto_ptr( pnew,detail::create_backref<IterT>( nbackref, sy.get_flags(), this->m_arena) );

ipat = itemp;

}

else

{

// It's an octal character escape sequence. If*ipat is 8 or 9, insert

// a NULL character, and leave the 8 or 9 as acharacter literal.

char_type ch = 0, i = 0;

for( ; i < 3 &&this->m_pat->end() != ipat && REGEX_CHAR(char_type,'0') <=*ipat && REGEX_CHAR(char_type,'7') >= *ipat; ++i, ++ipat )

ch = char_type( ch * 8 + ( *ipat -REGEX_CHAR(char_type,'0') ) );

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( ch, sy.get_flags(), this->m_arena ) );

}

}

else if( REGEX_CHAR(char_type,'e') == *ipat )

{

++ipat;

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( char_type( 27 ), sy.get_flags(),this->m_arena ) );

}

else if( REGEX_CHAR(char_type,'x') == *ipat )

{

char_type ch = 0, i = 0;

for( ++ipat; i < 2 &&this->m_pat->end() != ipat && detail::regex_isxdigit( *ipat );++i, ++ipat )

ch = char_type( ch * 16 +detail::regex_xdigit2int( *ipat ) );

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( ch, sy.get_flags(), this->m_arena ) );

}

else if( REGEX_CHAR(char_type,'c') == *ipat )

{

if( this->m_pat->end() == ++ipat )

throw bad_regexpr( "incomplete escapesequence //c" );

char_type ch = *ipat++;

if( REGEX_CHAR(char_type,'a') <= ch&& REGEX_CHAR(char_type,'z') >= ch )

ch = detail::regex_toupper( ch );

detail::reset_auto_ptr( pnew, detail::create_char<IterT>(char_type( ch ^ 0x40 ), sy.get_flags(), this->m_arena ) );

}

else if( REGEX_CHAR(char_type,'a') == *ipat&& normalize )

{

++ipat;

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( REGEX_CHAR(char_type,'/a'), sy.get_flags(),this->m_arena ) );

}

else if( REGEX_CHAR(char_type,'f') == *ipat&& normalize )

{

++ipat;

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( REGEX_CHAR(char_type,'/f'), sy.get_flags(),this->m_arena ) );

}

else if( REGEX_CHAR(char_type,'n') == *ipat&& normalize )

{

++ipat;

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( REGEX_CHAR(char_type,'/n'), sy.get_flags(),this->m_arena ) );

}

else if( REGEX_CHAR(char_type,'r') == *ipat&& normalize )

{

++ipat;

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( REGEX_CHAR(char_type,'/r'), sy.get_flags(),this->m_arena ) );

}

else if( REGEX_CHAR(char_type,'t') == *ipat&& normalize )

{

++ipat;

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( REGEX_CHAR(char_type,'/t'), sy.get_flags(),this->m_arena ) );

}

else if( REGEX_CHAR(char_type,'//') == *ipat&& normalize )

{

++ipat;

detail::reset_auto_ptr( pnew,detail::create_char<IterT>( REGEX_CHAR(char_type,'//'), sy.get_flags(),this->m_arena ) );

}

else

{

// Is this a user-defined intrinsic characterset?

detail::charset const * pcharset =detail::get_altern_charset( *ipat, sy );

if( 0 != pcharset )

detail::reset_auto_ptr( pnew,detail::create_charset<IterT>( *pcharset, sy.get_flags(),this->m_arena ) );

else

detail::reset_auto_ptr( pnew, detail::create_char<IterT>(*ipat, sy.get_flags(), this->m_arena ) );

++ipat;

}

break;

// If quotemeta, loop until we find quotemetaoff or end of string

case ESC_QUOTE_META_ON:

for( ibegin = itemp = ipat, fdone = false;!fdone && this->m_pat->end() != ipat; )

{

switch( sy.reg_token( ipat,this->m_pat->end() ) )

{

case ESC_QUOTE_META_OFF:

fdone = true;

break;

case NO_TOKEN:

if( this->m_pat->end() != ipat )

++ipat; // fallthrough

default:

itemp = ipat;

break;

}

}

if( itemp != ibegin )

pgroup->add_item( detail::create_literal<IterT>(ibegin, itemp, sy.get_flags(), this->m_arena ) );

// skip the quantification code below

return true;

// Should never get here for valid patterns

case ESC_QUOTE_META_OFF:

throw bad_regexpr( "quotemeta turned off,but was never turned on" );

default:

REGEX_ASSERT( ! "Unhandled tokentype" );

break;

}

// If pnew is null, then the currentsubexpression is a no-op.

if( pnew.get() )

{

// Look for quantifiers

_quantify( pnew, ipat, is_group, sy );

// Add the item to the group

pgroup->add_item( pnew.release() );

}

return true;

}

template< typename IterT, typename SyntaxT>

inline void basic_rpattern_base<IterT,SyntaxT>::_quantify(

std::auto_ptr<detail::sub_expr<IterT>> & pnew,

typename string_type::iterator & ipat,

bool is_group,

syntax_type & sy )

{

if( this->m_pat->end() != ipat &&! pnew->is_assertion() )

{

typename string_type::iterator itemp = ipat,itemp2;

bool fmin = false;

// Since size_t is unsigned, -1 is really thelargest size_t

size_t lbound = ( size_t )-1;

size_t ubound = ( size_t )-1;

size_t ubound_tmp;

switch( sy.quant_token( itemp,this->m_pat->end() ) )

{

case ZERO_OR_MORE_MIN:

fmin = true;

case ZERO_OR_MORE:

lbound = 0;

break;

case ONE_OR_MORE_MIN:

fmin = true;

case ONE_OR_MORE:

lbound = 1;

break;

case ZERO_OR_ONE_MIN:

fmin = true;

case ZERO_OR_ONE:

lbound = 0;

ubound = 1;

break;

case BEGIN_RANGE:

lbound = detail::parse_int( itemp,this->m_pat->end() );

if( this->m_pat->end() == itemp )

return; // not a valid quantifier - treat asatom

switch( sy.quant_token( itemp,this->m_pat->end() ) )

{

case END_RANGE_MIN:

fmin = true;

case END_RANGE:

ubound = lbound;

break;

case RANGE_SEPARATOR:

itemp2 = itemp;

ubound_tmp = detail::parse_int( itemp,this->m_pat->end() );

if( itemp != itemp2 )

ubound = ubound_tmp;

if( itemp == this->m_pat->end() )

return; // not a valid quantifier - treat asatom

switch( sy.quant_token( itemp,this->m_pat->end() ) )

{

case END_RANGE_MIN:

fmin = true;

case END_RANGE:

break;

default:

return; // not a valid quantifier - treat asatom

}

break;

default:

return; // not a valid quantifier - treat asatom

}

if( ubound < lbound )

throw bad_regexpr( "Can't do {n, m} with n> m" );

break;

default:

break;

}

if( ( size_t )-1 != lbound )

{

// If we are quantifying a group, then thispattern could recurse

// deeply. Note that fact here so that we canopt to use a stack-

// conservative algorithm at match time.

if( is_group && ubound > 16 )

this->m_fok_to_recurse = false;

std::auto_ptr<detail::sub_expr<IterT>> pquant( pnew->quantify( lbound, ubound, ! fmin, this->m_arena ) );

pnew.release();

detail::reset_auto_ptr( pnew, pquant.release());

ipat = itemp;

}

}

}

template< typename IterT, typename SyntaxT>

inline void basic_rpattern_base<IterT,SyntaxT>::_add_subst_backref(

detail::subst_node & snode,

size_t nbackref,

ptrdiff_t rstart,

bool & uses_backrefs,

detail::subst_list_type & subst_list )const

{

uses_backrefs = true;

REGEX_ASSERT( detail::subst_node::SUBST_STRING== snode.m_stype );

if( snode.m_subst_string.m_rlength )

subst_list.push_back( snode );

snode.m_stype = detail::subst_node::SUBST_BACKREF;

snode.m_subst_backref = nbackref;

subst_list.push_back( snode );

// re-initialize the subst_node

snode.m_stype =detail::subst_node::SUBST_STRING;

snode.m_subst_string.m_rstart = rstart;

snode.m_subst_string.m_rlength = 0;

}

template< typename IterT, typename SyntaxT>

inline void basic_rpattern_base<IterT,SyntaxT>::_parse_subst(

string_type & subst,

bool & uses_backrefs,

detail::subst_list_type & subst_list )const

{

TOKEN tok;

detail::subst_node snode;

typename string_type::iterator icur =subst.begin();

size_t nbackref;

typename string_type::iterator itemp;

bool fdone;

syntax_type sy( this->m_flags );

uses_backrefs = false;

// Initialize the subst_node

snode.m_stype =detail::subst_node::SUBST_STRING;

snode.m_subst_string.m_rstart = 0;

snode.m_subst_string.m_rlength = 0;

while( subst.end() != icur )

{

switch( tok = sy.subst_token( icur, subst.end()) )

{

case SUBST_MATCH:

_add_subst_backref( snode, 0, std::distance(subst.begin(), icur ), uses_backrefs, subst_list );

break;

case SUBST_PREMATCH:

_add_subst_backref( snode, ( size_t)detail::subst_node::PREMATCH, std::distance( subst.begin(), icur ),uses_backrefs, subst_list );

break;

case SUBST_POSTMATCH:

_add_subst_backref( snode, ( size_t)detail::subst_node::POSTMATCH, std::distance( subst.begin(), icur ),uses_backrefs, subst_list );

break;

case SUBST_BACKREF:

nbackref = detail::parse_int( icur,subst.end(), cgroups() - 1 ); // always at least 1 group

if( 0 == nbackref )

throw bad_regexpr( "invalid backreferencein substitution" );

_add_subst_backref( snode, nbackref,std::distance( subst.begin(), icur ), uses_backrefs, subst_list );

break;

case SUBST_QUOTE_META_ON:

REGEX_ASSERT( detail::subst_node::SUBST_STRING== snode.m_stype );

if( snode.m_subst_string.m_rlength )

subst_list.push_back( snode );

snode.m_subst_string.m_rstart = std::distance(subst.begin(), icur );

for( itemp = icur, fdone = false; !fdone&& subst.end() != icur; )

{

switch( tok = sy.subst_token( icur, subst.end()) )

{

case SUBST_ALL_OFF:

fdone = true;

break;

case NO_TOKEN:

++icur; // fall-through

default:

itemp = icur;

break;

}

}

snode.m_subst_string.m_rlength = std::distance(subst.begin(), itemp ) - snode.m_subst_string.m_rstart;

if( snode.m_subst_string.m_rlength )

subst_list.push_back( snode );

if( tok == SUBST_ALL_OFF )

{

snode.m_stype = detail::subst_node::SUBST_OP;

snode.m_op = detail::subst_node::ALL_OFF;

subst_list.push_back( snode );

}

// re-initialize the subst_node

snode.m_stype =detail::subst_node::SUBST_STRING;

snode.m_subst_string.m_rstart = std::distance(subst.begin(), icur );

snode.m_subst_string.m_rlength = 0;

break;

case SUBST_UPPER_ON:

case SUBST_UPPER_NEXT:

case SUBST_LOWER_ON:

case SUBST_LOWER_NEXT:

case SUBST_ALL_OFF:

REGEX_ASSERT( detail::subst_node::SUBST_STRING== snode.m_stype );

if( snode.m_subst_string.m_rlength )

subst_list.push_back( snode );

snode.m_stype = detail::subst_node::SUBST_OP;

snode.m_op =static_cast<detail::subst_node::op_type>( tok );

subst_list.push_back( snode );

// re-initialize the subst_node

snode.m_stype = detail::subst_node::SUBST_STRING;

snode.m_subst_string.m_rstart = std::distance(subst.begin(), icur );

snode.m_subst_string.m_rlength = 0;

break;

case SUBST_ESCAPE:

if( subst.end() == icur )

throw bad_regexpr( "expecting escapesequence in substitution string" );

REGEX_ASSERT( detail::subst_node::SUBST_STRING== snode.m_stype );

if( snode.m_subst_string.m_rlength )

subst_list.push_back( snode );

snode.m_subst_string.m_rstart = std::distance(subst.begin(), icur++ );

snode.m_subst_string.m_rlength = 1;

break;

case NO_TOKEN:

default:

++snode.m_subst_string.m_rlength;

++icur;

break;

}

}

REGEX_ASSERT( detail::subst_node::SUBST_STRING== snode.m_stype );

if( snode.m_subst_string.m_rlength )

subst_list.push_back( snode );

}

template< typename CharT >

REGEXPR_H_INLINE void reset_intrinsic_charsets(CharT )

{

detail::intrinsic_charsets<CharT>::reset();

}

typedef regex::detail::select

REGEX_FOLD_INSTANTIATIONS &&

detail::is_convertible<char const*,std::string::const_iterator>::value,

std::string::const_iterator,

char const *

>::type lpcstr_t;

typedef regex::detail::select

REGEX_FOLD_INSTANTIATIONS &&

detail::is_convertible<wchar_t const*,std::wstring::const_iterator>::value,

std::wstring::const_iterator,

wchar_t const *

>::type lpcwstr_t;

namespace detail

{

// Here is the main dispatch loop for theiterative match routine.

// It is responsible for calling match on thecurrent sub-expression

// and repeating for the next sub-expression.It also backtracks

// the match when it needs to.

template< typename CStringsT, typename IterT>

inline bool _do_match_iterative(sub_expr_base<IterT> const * expr, match_param<IterT> & param,IterT icur, CStringsT )

{

unsafe_stack::stack_guard guard( param.m_pstack);

unsafe_stack & s = *param.m_pstack;

void *const jump_ptr = s.set_jump(); // thebottom of the stack

param.m_icur = icur;

if( ! expr->iterative_match_this( param,CStringsT() ) )

{

return false;

}

for( ;; )

{

do

{

if( param.m_pnext == 0 ) // This means we'redone

return true;

s.push( expr );

expr = param.m_pnext;

}

while( expr->iterative_match_this( param,CStringsT() ) );

do

{

if( jump_ptr == s.set_jump() ) // No moreposibilities to try

return false;

s.pop( expr );

}

while( ! expr->iterative_rematch_this(param, CStringsT() ) );

}

}

template< typename IterT >

REGEXPR_H_INLINE boolregex_access<IterT>::_do_match_iterative_helper_s(sub_expr_base<IterT> const * expr, match_param<IterT> & param,IterT icur )

{

return _do_match_iterative( expr, param, icur,false_t() );

}

template< typename IterT >

REGEXPR_H_INLINE bool regex_access<IterT>::_do_match_iterative_helper_c(sub_expr_base<IterT> const * expr, match_param<IterT> & param,IterT icur )

{

return _do_match_iterative( expr, param, icur,true_t() );

}

template< typename IterT >

REGEXPR_H_INLINE boolregex_access<IterT>::_do_match_recursive_s( sub_expr_base<IterT>const * expr, match_param<IterT> & param, IterT icur )

{

returnstatic_cast<match_group_base<IterT>const*>(expr)->match_group_base<IterT>::recursive_match_all_s(param, icur );

}

template< typename IterT >

REGEXPR_H_INLINE boolregex_access<IterT>::_do_match_recursive_c( sub_expr_base<IterT>const * expr, match_param<IterT> & param, IterT icur )

{

returnstatic_cast<match_group_base<IterT>const*>(expr)->match_group_base<IterT>::recursive_match_all_c(param, icur );

}

template< typename IterT >

REGEX_NOINLINE boolregex_access<IterT>::_do_match_with_stack( rpattern_type const & pat,match_param<IterT> & param, bool const use_null )

{

unsafe_stack s;

param.m_pstack = &s;

return _do_match_impl( pat, param, use_null );

}

template< typename IterT >

REGEXPR_H_INLINE boolregex_access<IterT>::_do_match_impl( rpattern_type const & pat,match_param<IterT> & param, bool const use_null )

{

typedef bool ( *pfndomatch_t )(sub_expr_base<IterT> const * expr, match_param<IterT> & param, IterTicur );

bool floop = pat._loops();

unsigned flags = pat.flags();

width_type nwidth = pat.get_width();

// Create some aliases for convenience andeffeciency.

REGEX_ASSERT( 0 != param.m_prgbackrefs );

// If the pstack parameter is not NULL, weshould do a safe, iterative match.

// Otherwise, we should do a fast, recursivematch.

pfndomatch_t pfndomatch;

if( 0 != param.m_pstack )

if( use_null )

pfndomatch = &_do_match_iterative_helper_c;

else

pfndomatch = &_do_match_iterative_helper_s;

else

if( use_null )

pfndomatch = &_do_match_recursive_c;

else

pfndomatch = &_do_match_recursive_s;

sub_expr_base<IterT> const * pfirst =pat._get_first_subexpression();

param.m_pfirst = pfirst;

REGEX_ASSERT( param.m_cbackrefs ==pat._cgroups_total() );

std::fill_n( param.m_prgbackrefs,param.m_cbackrefs, static_init<backref_type>::value );

if( ! use_null )

{

// If the minimum width of the pattern exceedsthe width of the

// string, a succesful match is impossible

typedef typenamestd::iterator_traits<IterT>::difference_type diff_type;

diff_type room = std::distance(param.m_imatchbegin, param.m_iend );

if( nwidth.m_min <=static_cast<size_t>( room ) )

{

IterT local_iend = param.m_iend;

std::advance( local_iend,-static_cast<diff_type>( nwidth.m_min ) );

if( RIGHTMOST & flags )

{

// begin trying to match after the lastcharacter.

// Continue to the beginning

for( IterT icur = local_iend; ; --icur,param.m_no0len = false )

{

if( ( *pfndomatch )( pfirst, param, icur ) )

break; // m_floop not used for rightmostmatches

if( icur == param.m_imatchbegin )

break;

}

}

else

{

// begin trying to match before the firstcharacter.

// Continue to the end

if( is_random_access<IterT>::value&& pat.m_search )

{

IterT icur = pat.m_search->find(param.m_imatchbegin, param.m_iend );

while( icur != param.m_iend )

{

if( ( *pfndomatch )( pfirst, param, icur ) || !floop )

break;

param.m_no0len = false;

icur = pat.m_search->find( ++icur,param.m_iend );

}

}

else

{

for( IterT icur = param.m_imatchbegin; ;++icur, param.m_no0len = false )

{

if( ( *pfndomatch )( pfirst, param, icur ) || !floop )

break;

if( icur == local_iend )

break;

}

}

}

}

}

else

{

REGEX_ASSERT( 0 == ( RIGHTMOST & flags ) );

// begin trying to match before the firstcharacter.

// Continue to the end

for( IterT icur = param.m_imatchbegin; ;++icur, param.m_no0len = false )

{

if( ( *pfndomatch )( pfirst, param, icur ) || !floop )

break;

if( traits_type::eq( *icur, char_type() ) )

break;

}

}

return param.m_prgbackrefs[0].matched;

}

// Here is a rudimentary typelist facility toallow the REGEX_TO_INSTANTIATE

// list to recursively generate theinstantiations we are interested in.

struct empty_typelist

{

};

template< typename HeadT, typename TailT>

struct cons

{

typedef HeadT head_type;

typedef TailT tail_type;

};

template

typename T1 =empty_typelist, typename T2=empty_typelist, typename T3 =empty_typelist,

typename T4 =empty_typelist, typename T5=empty_typelist, typename T6 =empty_typelist,

typename T7 =empty_typelist, typename T8=empty_typelist, typename T9 =empty_typelist,

typename T10=empty_typelist, typenameT11=empty_typelist, typename T12=empty_typelist

struct typelist : publiccons<T1,typelist<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12> >

{

};

template<>

struct typelist

empty_typelist,empty_typelist,empty_typelist,empty_typelist,

empty_typelist,empty_typelist,empty_typelist,empty_typelist,

empty_typelist,empty_typelist,empty_typelist,empty_typelist

: public empty_typelist

{

};

// This class is responsible for instantiatingbasic_rpattern

// with the template parameters we are interestedin. It also

// instntiates any helper routines thisbasic_rpattern relies

// on.

template< typename IterT, typename SyntaxT>

struct rpattern_instantiator : protectedregex::basic_rpattern<IterT,SyntaxT>

{

static instantiator instantiate()

{

typedef typenamestd::iterator_traits<IterT>::value_type char_type;

void (*pfn)( char_type ) =&reset_intrinsic_charsets;

returnregex::basic_rpattern<IterT,SyntaxT>::instantiate() +

regex_access<IterT>::instantiate() +

instantiator_helper( pfn );

}

};

// The regex_instantiate uses typelists and therpattern_instantiator

// to generate instantiations for all the typesin the typelist.

template< typename SyntaxT >

instantiator regex_instantiate( empty_typelist,type2type<SyntaxT> )

{

return instantiator();

}

template< typename HeadT, typename TailT,typename SyntaxT >

instantiator regex_instantiate(cons<HeadT,TailT>, type2type<SyntaxT> )

{

typedef typenamestd::iterator_traits<HeadT>::value_type char_type;

typedef typename SyntaxT::templaterebind<char_type>::other syntax_type;

returnrpattern_instantiator<HeadT,syntax_type>::instantiate() +

regex_instantiate( TailT(),type2type<SyntaxT>() );

}

// Here is a list of types to instantiate.

#ifndef REGEX_TO_INSTANTIATE

# ifdef REGEX_WIDE_AND_NARROW

# define REGEX_TO_INSTANTIATEstd::string::const_iterator, /

std::wstring::const_iterator, /

lpcstr_t, /

lpcwstr_t

# else

# define REGEX_TO_INSTANTIATErestring::const_iterator, /

lpctstr_t

# endif

#endif

typedef typelist<REGEX_TO_INSTANTIATE>regex_typelist;

typedef type2type<perl_syntax<char>> perl_type;

typedef type2type<posix_syntax<char>> posix_type;

namespace

{

// Create the perl instantiations

#ifndef REGEX_NO_PERL

instantiator const perl_inst =regex_instantiate( regex_typelist(), perl_type() );

#endif

// Create the posix instantiations

#ifdef REGEX_POSIX

instantiator const posix_inst =regex_instantiate( regex_typelist(), posix_type() );

#endif

}

} // unnamed namespace

} // namespace regex

#ifdef _MSC_VER

# pragma warning( pop )

#endif

*/

/*正则替换

#include <string>

#include <boost/regex.hpp>

using namespace std;

boost::regexreg("(Colo)(u)(r)",boost::regex::icase|boost::regex::perl);

string s="Color,colours,color,colourize";

s=boost::regex_replace(s,reg,"$1$3");

TRACE(CString(s));

*/

47.直接创建多级目录

typedef BOOL (__stdcall funMakeSure(LPCSTRDirPath));

funMakeSure *MakeSureDirectoryPathExists;

HMODULEhMod=LoadLibrary("dbghelp.dll");

MakeSureDirectoryPathExists(*funMakeSure)GetProcAddress(hMod,"MakeSureDirectoryPathExists");

MakeSureDirectoryPathExists(%%1);

48.批量重命名

CString strPath,strFilter,srcTitle,src,srcFile,dstFile,dstFileTitle;

int i=1,iFileNum=1;

CFile myFile,newFile;

//获取将要批量处理的文件夹及文件格式

strPath=%%1;

strFilter=%%2;

//判断文件夹是否为空

if(strPath.IsEmpty())

{

MessageBox("请先选择要重命名文件所在文件夹!","警告!");

return;

}

//在该文件夹内创建目录文件

src=strPath+"*."+strFilter;

CString list=strPath+"目录.txt";

if(myFile.Open(list,CFile::modeCreate|CFile::modeReadWrite,0)==0) return;

CFileFind tempFind;

BOOL isFound=(BOOL)tempFind.FindFile(src);

//确定该文件夹内要处理的有多少个文件

while(isFound)

{

isFound=(BOOL)tempFind.FindNextFile();

if(tempFind.IsDirectory() &&!tempFind.IsDots())

{

continue;

}

iFileNum++;

}

//进行文件名的转换,以文件数定转换后的文件名,如果有9个文件,则以1-9的形式命名,如果是更多,如有99个文件,则为01-99的形式

isFound=(BOOL)tempFind.FindFile(src);

while(isFound && i<iFileNum)

{

isFound=(BOOL)tempFind.FindNextFile();

if(tempFind.IsDirectory() &&!tempFind.IsDots())

{

continue;

}

srcFile=tempFind.GetFilePath();

srcTitle=tempFind.GetFileTitle();

 

if(iFileNum<10)

{

dstFileTitle.Format("%d",i);

}

else if(iFileNum<100 &&iFileNum>9)

{

dstFileTitle.Format("%02d",i);

}

else if(iFileNum<1000 &&iFileNum>99)

{

dstFileTitle.Format("%03d",i);

}

else if(iFileNum<10000 &&iFileNum>999)

{

dstFileTitle.Format("%04d",i);

}

else if(iFileNum<100000 &&iFileNum>9999)

{

dstFileTitle.Format("%05d",i);

}

else

{

dstFileTitle.Format("%d",i);

}

//实现转换

dstFile=strPath+dstFileTitle+"."+strFilter;

 

MoveFile(srcFile,dstFile);

//存入目录文件中

CString in;

in=dstFileTitle+'/t'+srcTitle+"/t/r/n";

myFile.Write(in,in.GetLength());

 

i++;

SetWindowText(srcFile);

}

//关闭myFile,tempFind

myFile.Close();

tempFind.Close();

49.文本查找替换 ReplaceText

CString StrFileName(%%1);

CString StrFind(%%2);

CString StrReplace(%%3);

CStdioFile TempFile,File;

int Count=0;

if(!File.Open(StrFileName,CFile::modeRead))

return -1;

CStringStrTempFileName=File.GetFileTitle()+".tmp";

if(!TempFile.Open(StrTempFileName,CFile::modeCreate|CFile::modeReadWrite))

return -1;

CString Str;

while(File.ReadString(Str))

{

Count+=Str.Replace(StrFind,StrReplace);

TempFile.WriteString(Str+"/n");

}

File.Close();

TempFile.Close();

CFile::Remove(StrFileName);

CFile::Rename(StrTempFileName,StrFileName);

//return Count;

50.文件关联

//---------------------------------------------------------------------------

//检测文件关联情况

// strExt:要检测的扩展名(例如: ".txt")

// strAppKey: ExeName扩展名在注册表中的键值(例如: "txtfile")

//返回TRUE:表示已关联,FALSE:表示未关联

BOOL CheckFileRelation(const char *strExt,const char *strAppKey)

{

int nRet=FALSE;

HKEY hExtKey;

char szPath[_MAX_PATH];

DWORD dwSize=sizeof(szPath);

if(RegOpenKey(HKEY_CLASSES_ROOT,strExt,&hExtKey)==ERROR_SUCCESS)

{

RegQueryValueEx(hExtKey,NULL,NULL,NULL,(LPBYTE)szPath,&dwSize);

if(_stricmp(szPath,strAppKey)==0)

{

nRet=TRUE;

}

RegCloseKey(hExtKey);

return nRet;

}

return nRet;

}

//---------------------------------------------------------------------------

//注册文件关联

// strExe:要检测的扩展名(例如: ".txt")

// strAppName:要关联的应用程序名(例如: "C:/MyApp/MyApp.exe")

// strAppKey: ExeName扩展名在注册表中的键值(例如: "txtfile")

// strDefaultIcon:扩展名为strAppName的图标文件(例如: "C:/MyApp/MyApp.exe,0")

// strDescribe:文件类型描述

void RegisterFileRelation(char *strExt, char*strAppName, char *strAppKey, char *strDefaultIcon, char *strDescribe)

{

char strTemp[_MAX_PATH];

HKEY hKey;

RegCreateKey(HKEY_CLASSES_ROOT,strExt,&hKey);

RegSetValue(hKey,"",REG_SZ,strAppKey,strlen(strAppKey)+1);

RegCloseKey(hKey);

RegCreateKey(HKEY_CLASSES_ROOT,strAppKey,&hKey);

RegSetValue(hKey,"",REG_SZ,strDescribe,strlen(strDescribe)+1);

RegCloseKey(hKey);

sprintf(strTemp,"%s//DefaultIcon",strAppKey);

RegCreateKey(HKEY_CLASSES_ROOT,strTemp,&hKey);

RegSetValue(hKey,"",REG_SZ,strDefaultIcon,strlen(strDefaultIcon)+1);

RegCloseKey(hKey);

sprintf(strTemp,"%s//Shell",strAppKey);

RegCreateKey(HKEY_CLASSES_ROOT,strTemp,&hKey);

RegSetValue(hKey,"",REG_SZ,"Open",strlen("Open")+1);

RegCloseKey(hKey);

sprintf(strTemp,"%s//Shell//Open//Command",strAppKey);

RegCreateKey(HKEY_CLASSES_ROOT,strTemp,&hKey);

sprintf(strTemp,"%s/"%%1/"",strAppName);

RegSetValue(hKey,"",REG_SZ,strTemp,strlen(strTemp)+1);

RegCloseKey(hKey);

}

51.操作Excel文件

//#include "excel.h"

//#include "COMDEF.H"

char ch[200];

GetCurrentDirectory(200,ch);

sCCdd=ch;

GetSystemDirectory(ch,200);

sXTdd=ch;

CString ss;

ss.Format("%s//txl.mdb",sCCdd);

if(!LoadDbSource("vcexcel",ss,""))

{

// EndDialog(0);

return FALSE;

}

m_list.SetBkColor(RGB(177, 151, 240));

m_list.SetTextColor(RGB(0,0,0));

m_list.SetTextBkColor(RGB(177, 151, 240));

m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP);

m_pSet=new CTxl;

ShowTxl();

void OnButton1()

{

/*添加*/

CString strSQL;

CTjdlg dlg;

 

if(dlg.DoModal()==IDOK)

{

 

strSQL.Format("insert into通信录 (姓名,单位,电话,手机,地址) values ('%s','%s','%s','%s','%s')",dlg.m_strXm,dlg.m_strDw,dlg.m_strDh,dlg.m_strSj,dlg.m_strDz);

m_pSet->m_pDatabase->ExecuteSQL(strSQL);

ShowTxl();//显示通信录

}

 

}

void OnButton2()

{

/*删除*/

int isel;

CString str,strSQL;

CTjdlg dlg;

isel=m_list.GetSelectedCount();

if(isel==0)

{

AfxMessageBox("请先选择一条记录");

return;

}

isel=m_list.GetNextItem(-1,LVNI_SELECTED);

str=m_list.GetItemText(isel,0);

strSQL.Format("你确实要删除姓名为'%s'的记录吗?",str);

if(AfxMessageBox(strSQL,MB_YESNO)==IDYES)

{

strSQL.Format("delete * from通信录 where姓名='%s'",str);

try

{

m_pSet->m_pDatabase->BeginTrans();

m_pSet->m_pDatabase->ExecuteSQL(strSQL);

m_pSet->m_pDatabase->CommitTrans();

}

catch(CException*pE)

{

m_pSet->m_pDatabase->Rollback();

pE->Delete();

}

strSQL.Format("已成功删除姓名为'%s'的记录!",str);

AfxMessageBox(strSQL);

ShowTxl();//显示通信录

}

 

}

void OnButton3()

{

/*修改 */

int isel;

CString str,strSQL;

CTjdlg dlg;

 

isel=m_list.GetSelectedCount();

if(isel==0)

{

AfxMessageBox("请先选择一条记录");

return;

}

isel=m_list.GetNextItem(-1,LVNI_SELECTED);

str=m_list.GetItemText(isel,0);

dlg.m_bXg=true;

 

strSQL.Format("select * from通信录 where姓名='%s'",str);

if(m_pSet->IsOpen())

m_pSet->Close();

m_pSet->Open(CRecordset::dynaset, strSQL);

if(!(m_pSet->IsEOF()))

{

m_pSet->GetFieldValue((short)0,dlg.m_strXm);

m_pSet->GetFieldValue(1,dlg.m_strDw);

m_pSet->GetFieldValue(2,dlg.m_strDh);

m_pSet->GetFieldValue(3,dlg.m_strSj);

m_pSet->GetFieldValue(4,dlg.m_strDz);

}

 

if(dlg.DoModal()==IDOK)

{

 

strSQL.Format("update通信录 set姓名='%s',单位='%s',电话='%s',手机='%s',地址='%s' where 姓名='%s'",

dlg.m_strXm,dlg.m_strDw,dlg.m_strDh,dlg.m_strSj,dlg.m_strDz,str);

m_pSet->m_pDatabase->ExecuteSQL(strSQL);

ShowTxl();//显示通信录

}

}

void OnButton4()

{

/*导出到 excel文档*/

CString sss,s1,s2,e1,e2,strSQL;

CStringArray sa;

static char szFilter[] = "EXCELFiles(*.xls)|*.xls||";

CTxl rs;

strSQL.Format("select * from通信录");

rs.Open(CRecordset::dynaset, strSQL);//打开通信录

CString fname,fname1, sheetname,s;

 

CFileDialog FileDlg( FALSE, NULL,NULL,OFN_HIDEREADONLY, szFilter );

if( FileDlg.DoModal() != IDOK||FileDlg.GetPathName()=="")

{

return;//打开另存对话框,如果文件名为空或打开不成功则返回

}

fname=FileDlg.GetPathName();//得到要导出保存的路径及文件名

 

/*定义操作Execl的对象*/

_Application objApp;

Workbooks objBooks;

_Workbook objBook;

Sheets objSheets;

_Worksheet objSheet;

Range objRange,objRange1,objRange2;

Lines objLines;

Line objLine;

Borders objBorders;

Font oFont;

 

COleVariantcovOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

COleVariant covTrue((short)TRUE),covFalse((short)FALSE),/

varFormat((short)-4143),varCenter((short)-4108),varLeft((short)-4131),varText("TEXT",VT_BSTR),var,/

varRange1("A1",VT_BSTR),varRange2("D1",VT_BSTR);

//初始化COM组件

::CoInitialize(NULL);

//创建Excel对象

objApp.m_bAutoRelease=true;

if(!objApp.CreateDispatch("Excel.Application"))

{

AfxMessageBox("创建Excel服务失败!");

return;

}

objBooks=objApp.GetWorkbooks(); //返回工作簿对象

 //打开Excel文件n

objBook.AttachDispatch(objBooks.Add(_variant_t("")));//C://lb.xls

objSheets=objBook.GetSheets();

 //定义第一个Sheet为对象

objSheet=objSheets.GetItem((_variant_t)short(1));

sheetname="通讯录";

objSheet.SetName(sheetname);//将第一个工作表名称设为"通讯录"//

objSheet.Activate();

objRange.AttachDispatch(objSheet.GetCells(),true);

objLine.AttachDispatch(objSheet.GetCells(),true);

objApp.SetVisible(true);//设置为显示

int nn=2,syh=0,nFieldcnt;

char cc='A';

s1.Format("B%d",nn);

 

nFieldcnt=rs.GetODBCFieldCount();

 

CODBCFieldInfo fieldinfo;

for(int n=0;n<nFieldcnt;n++,cc++)

{

/*将字段名作为标题导出到execl的第一行*/

rs.GetODBCFieldInfo(n, fieldinfo);

s1.Format("%c1",cc);

objRange1=objSheet.GetRange(_variant_t(s1),_variant_t(s1));

objRange1.SetHorizontalAlignment(varCenter);

objRange1.SetVerticalAlignment(varCenter);

oFont=objRange1.GetFont();

oFont.SetBold(_variant_t((long)1));//设为粗体

objRange1.SetFormulaR1C1(_variant_t(fieldinfo.m_strName));

objRange1.SetColumnWidth(_variant_t("20"));

objBorders=objRange1.GetBorders();

objBorders.SetLineStyle(_variant_t((long)1));

 

}

 

/

rs.MoveFirst();

while(!rs.IsEOF())

{

/*将通讯录中数据导出到excel单元格中*/

sa.RemoveAll();

for(int j=0;j<nFieldcnt;j++)

{

rs.GetFieldValue(j, s);

sa.Add(s);

}

 

s1.Format("A%d",nn);

e1=s1;

objRange1=objSheet.GetRange(_variant_t(s1),_variant_t(s1));

s="'";

s+=sa.GetAt(0);

 

objRange1.SetFormulaR1C1(_variant_t(s));

objBorders=objRange1.GetBorders();

objBorders.SetLineStyle(_variant_t((long)1));

 

 

s1.Format("B%d",nn);

objRange1=objSheet.GetRange(_variant_t(s1),_variant_t(s1));

s=sa.GetAt(1);

objRange1.SetFormulaR1C1(_variant_t(s));

objBorders=objRange1.GetBorders();

objBorders.SetLineStyle(_variant_t((long)1));

 

 

s1.Format("C%d",nn);

objRange1=objSheet.GetRange(_variant_t(s1),_variant_t(s1));

s=sa.GetAt(2);

objRange1.SetFormulaR1C1(_variant_t(s));

objBorders=objRange1.GetBorders();

objBorders.SetLineStyle(_variant_t((long)1));

 

s1.Format("D%d",nn);

objRange1=objSheet.GetRange(_variant_t(s1),_variant_t(s1));

s=sa.GetAt(3);

objRange1.SetFormulaR1C1(_variant_t(s));

objBorders=objRange1.GetBorders();

objBorders.SetLineStyle(_variant_t((long)1));

 

s1.Format("E%d",nn);

e2=s1;

objRange1=objSheet.GetRange(_variant_t(s1),_variant_t(s1));

s=sa.GetAt(4);

objRange1.SetFormulaR1C1(_variant_t(s));

objBorders=objRange1.GetBorders();

objBorders.SetLineStyle(_variant_t((long)1));

 

if(sa.GetAt(4).Find("和平")!=-1)

{

/*如果地址字段中含有"和平",则该纪录字体设为粗体斜体和蓝色*/

objRange1=objSheet.GetRange(_variant_t(e1),_variant_t(e2));

oFont=objRange1.GetFont();

oFont.SetBold(_variant_t((short)1));

oFont.SetItalic(_variant_t((short)1));

oFont.SetColor(_variant_t((long)0xFF0000));

}

nn++;

rs.MoveNext();

}

rs.Close();

 

/*设置打印信息*/

PageSetup PageInfo=objSheet.GetPageSetup();

//描述页眉信息:楷体 20号字体

CString HeaderFormat= "&";

HeaderFormat+="/"楷体_GB2312,常规/"";

HeaderFormat+="&20通信录";

PageInfo.SetCenterHeader(HeaderFormat);

//设置页脚信息:楷体 12号字体

CString FooterFormat= "&";

FooterFormat+="/"楷体_GB2312,常规/"";

FooterFormat+="&12";

//"&p":页码

FooterFormat+="&p";

FooterFormat+="";

FooterFormat+="";

FooterFormat+="&n";

FooterFormat+="";

PageInfo.SetCenterFooter(FooterFormat); //设置页脚

PageInfo.SetOrientation(2); //横向打印

PageInfo.SetPaperSize(9); //设置纸张大小为A4

PageInfo.SetFirstPageNumber(-4105);//第一页编号为默认值1

PageInfo.SetPrintTitleRows("$1:$1");//设置标题行

PageInfo.SetZoom(COleVariant((short)100)); //设置打印缩放比例100%

PageInfo.SetCenterHorizontally(1); //水平居中

PageInfo.SetCenterVertically(0); //垂直居中

//进行打印预览,允许用户进行打印参数修改

//objSheet.PrintPreview(COleVariant((short)1));

objBook.SaveAs(_variant_t(fname),varFormat,covOptional,covOptional,covOptional,covOptional,0,covOptional,covOptional,covOptional,covOptional,covOptional);

objApp.Quit();

objRange.ReleaseDispatch();

objSheet.ReleaseDispatch();

objSheets.ReleaseDispatch();

objBook.ReleaseDispatch();

objBooks.ReleaseDispatch();

//保存,退出及释放定义的Excel对象

::CoUninitialize();//取消COM组件的初始化

 

s.Format("已成功地将数据导出到EXCEL文件'%s'",fname);

AfxMessageBox(s);

}

bool ShowTxl()

{

/*显示通讯录*/

CString strSQL="select * from通信录";

 

while(m_list.DeleteColumn(0));

m_list.DeleteAllItems();

 

try{

if(m_pSet->IsOpen())m_pSet->Close();

m_pSet->Open(CRecordset::dynaset, strSQL);

if(!m_pSet->IsEOF())

{

m_pSet->MoveLast();

m_pSet->MoveFirst();

}

else

{

return FALSE;

}

int nFieldCount =m_pSet->GetODBCFieldCount();

CODBCFieldInfo fieldinfo;

for(int n=0;n<nFieldCount;n++)

{

m_pSet->GetODBCFieldInfo(n, fieldinfo);

int nWidth =m_list.GetStringWidth(fieldinfo.m_strName) +80;

m_list.InsertColumn(n, fieldinfo.m_strName,LVCFMT_LEFT, nWidth);

}

 

CString strValue;

m_pSet->MoveFirst();

int nCount = 0;

 

while(!m_pSet->IsEOF())

{

m_list.InsertItem(nCount, strValue);

for(int j=0;j<nFieldCount;j++)

{

m_pSet->GetFieldValue(j, strValue);

m_list.SetItemText(nCount, j, strValue);

}

m_pSet->MoveNext();

nCount ++;

}

 

}

 

catch(CDBException *e)

{

e->ReportError();

return FALSE;

}

return TRUE;

 

}

void OnDblclkList1(NMHDR* pNMHDR, LRESULT*pResult)

{

/*双击列表视图修改记录*/

OnButton3();

*pResult = 0;

}

BOOL LoadDbSource(

 CStringstrSourceName,//数据源名

 CStringstrSourceDb,//数据库存放路径

 CStringstrDescription//数据源描述字符串

 )

{

HKEY hKey;

DWORD lDisp;

CStringss;//sold="//",snew="///";

//注册数据源名

CString strSubKey="SOFTWARE//ODBC//ODBC.INI//"+strSourceName;

// RegCreateKeyEx(HKEY_LOCAL_MACHINE,

RegCreateKeyEx(HKEY_CURRENT_USER,

strSubKey,

0,

NULL,

REG_OPTION_NON_VOLATILE,

KEY_ALL_ACCESS,

NULL,

&hKey,

&lDisp);

 

//注册ODBC驱动程序

CString value1; //("E://WINDOWS//System32//odbcjt32.dll");

ss=sXTdd;

 

value1.Format("%s//odbcjt32.dll",ss);

// AfxMessageBox(value1);

RegSetValueEx(hKey,

"Driver",

0,

REG_SZ,

(const unsigned char *)((LPCTSTR)value1),

strlen((LPCTSTR)value1)+1);

 

//注册数据库文件

CString value2 = strSourceDb;

RegSetValueEx(hKey,

"DBQ",

0,

REG_SZ,

(const unsigned char *)((LPCTSTR)value2),

strlen((LPCTSTR)value2)+1);

 

 

DWORD value3=(DWORD)25;

RegSetValueEx(hKey,

"DriverID",

0,

REG_DWORD,

(const BYTE *)&value3,

sizeof(DWORD));

CString value4("Ms Access");

RegSetValueEx(hKey,

"FIL",

0,

REG_SZ,

(const unsigned char *)((LPCTSTR)value4),

strlen((LPCTSTR)value4)+1);

DWORD value5=(DWORD)0;

RegSetValueEx(hKey,

"SafeTransactions",

0,

REG_DWORD,

(const BYTE *)&value5,

sizeof(DWORD));

CString value6("");

RegSetValueEx(hKey,

"UID",

0,

REG_SZ,

(const unsigned char *)((LPCTSTR)value6),

strlen((LPCTSTR)value6)+1);

 

return TRUE;

}

void OnButton5()

{

/*Excel导入*/

CString s1,s2,strSQL;

CStringArray sa;

static char szFilter[] = "EXCELFiles(*.xls)|*.xls||";

CTxl rs;

rs.Open();

CString fname,fname1, sheetname,s;

CFileDialog FileDlg( TRUE, NULL, NULL,

OFN_HIDEREADONLY, szFilter );

 

if( FileDlg.DoModal() != IDOK ||

FileDlg.GetPathName()=="")

{

return;//打开打开对话框,如果文件名为空或打开不成功则返回

}

fname=FileDlg.GetPathName();//得到要导入的Excel文件的路径及文件名

 

/*定义操作Execl的对象*/

_Application objApp;

Workbooks objBooks;

_Workbook objBook;

Sheets objSheets;

_Worksheet objSheet;

Range objRange,objRange1,objRange2;

Lines objLines;

Line objLine;

Borders objBorders;

COleVariantcovOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

COleVariant covTrue((short)TRUE),covFalse((short)FALSE),/

varFormat((short)-4143),varCenter((short)-4108),varLeft((short)-4131),varText("TEXT",VT_BSTR),var,/

varRange1("A1",VT_BSTR),varRange2("D1",VT_BSTR);

 

//初始化COM组件

::CoInitialize(NULL);

//创建Excel对象

objApp.m_bAutoRelease=true;

if(!objApp.CreateDispatch("Excel.Application"))

{

AfxMessageBox("创建Excel服务失败!");

return;

}

objBooks=objApp.GetWorkbooks(); //返回工作簿对象

//打开Excel文件

objBook.AttachDispatch(objBooks.Add(_variant_t(fname)));

objSheets=objBook.GetSheets();

//选择Excel文件的第一个工作表

objSheet=objSheets.GetItem((_variant_t)short(1));

objRange.AttachDispatch(objSheet.GetCells(),true);

objLine.AttachDispatch(objSheet.GetCells(),true);

 

//将数据库的通信录表置空

strSQL.Format("delete * from通信录");

rs.m_pDatabase->ExecuteSQL(strSQL);

 

int nn=2;

char cc='A';

s1.Format("A%d",nn);

 

objRange1=objApp.GetRange(_variant_t(s1),_variant_t(s1));

var=objRange1.GetFormulaR1C1();

s=var.bstrVal;

BeginWaitCursor();

while(s!="")

{ //Excel文件中数据导入到数据库的通信录表中

sa.RemoveAll();

s1.Format("A%d",nn);

objRange1=objApp.GetRange(_variant_t(s1),_variant_t(s1));

var=objRange1.GetFormulaR1C1();//GetText();//GetFormulaR1C1();

s=var.bstrVal;

sa.Add(s);

 

s1.Format("B%d",nn);

objRange1=objApp.GetRange(_variant_t(s1),_variant_t(s1));

var=objRange1.GetFormulaR1C1();

s=var.bstrVal;

s2=s;

sa.Add(s);

 

s1.Format("C%d",nn);

objRange1=objApp.GetRange(_variant_t(s1),_variant_t(s1));

var=objRange1.GetFormulaR1C1();

s=var.bstrVal;

sa.Add(s);

 

s1.Format("D%d",nn);

objRange1=objApp.GetRange(_variant_t(s1),_variant_t(s1));

var=objRange1.GetFormulaR1C1();

s=var.bstrVal;

sa.Add(s);

 

s1.Format("E%d",nn);

objRange1=objApp.GetRange(_variant_t(s1),_variant_t(s1));

var=objRange1.GetFormulaR1C1();

s=var.bstrVal;

sa.Add(s);

 

strSQL.Format("INSERT INTO通信录 (姓名,单位,电话,手机,地址)/

VALUES ('%s', '%s','%s','%s','%s')",sa.GetAt(0),sa.GetAt(1),sa.GetAt(2),sa.GetAt(3),sa.GetAt(4));

rs.m_pDatabase->ExecuteSQL(strSQL);

 

nn++;

s1.Format("A%d",nn);

objRange1=objApp.GetRange(_variant_t(s1),_variant_t(s1));

var=objRange1.GetFormulaR1C1();

s=var.bstrVal;

}

rs.Close();

EndWaitCursor();

 

objApp.Quit();

objRange.ReleaseDispatch();

objSheet.ReleaseDispatch();

objSheets.ReleaseDispatch();

objBook.ReleaseDispatch();

objBooks.ReleaseDispatch();

//退出及释放定义的Excel对象

::CoUninitialize();//取消COM组件的初始化

 

s.Format("已成功地将数据从EXCEL文件'%s'导入到数据库",fname);

AfxMessageBox(s);

ShowTxl();//显示通信录

}

52.设置JDK环境变量

class CRegEdit : public CObject

{

public:

HKEY m_RootKey;

HKEY m_hKey;

int m_EnumLoop;

public:

CRegEdit()

{

m_hKey=NULL;

m_RootKey=NULL;

}

~CRegEdit()

{

if (m_hKey!=NULL)

::RegCloseKey(m_hKey);

}

// CRegEdit成员函数

BOOL OpenKey(LPCTSTR StrKey)

{

if (m_RootKey==NULL)

return 0;

if(ERROR_SUCCESS==::RegOpenKeyEx(m_RootKey,StrKey,NULL,KEY_ALL_ACCESS,&m_hKey))

return 1;

else

return 0;

}

 

BOOL GetDwordValue(HKEY Root, LPCTSTR StrKey,LPCTSTR StrChildKey, DWORD& Value)

{

m_RootKey=Root;

if (OpenKey(StrKey))

{

if (ReadDword(StrChildKey,Value))

return 1;

else

return 0;

}

else

return 0;

}

 

BOOL ReadDword(LPCTSTR StrChildKey, DWORD&Value)

{

DWORD dwSize=255,dwType=REG_DWORD;

if (ERROR_SUCCESS!=::RegQueryValueEx(m_hKey,StrChildKey,0,&dwType,(BYTE*)(&Value),&dwSize))

return 0;

else

return 1;

}

 

BOOL ReadBinary(LPCTSTR StrChildKey, DWORD&Value)

{

DWORD dwSize=255,dwType=REG_BINARY;

if(ERROR_SUCCESS!=::RegQueryValueEx(m_hKey,StrChildKey,0,&dwType,(BYTE*)(&Value),&dwSize))

return 0;

else

return 1;

}

 

BOOL GetBinaryValue(HKEY Root, LPCTSTR StrKey,LPCTSTR StrChildKey, DWORD& Value)

{

m_RootKey=Root;

if (OpenKey(StrKey))

{

if (ReadBinary(StrChildKey,Value))

return 1;

else

return 0;

}

else

return 0;

}

 

BOOL WriteDword(LPCTSTR StrChildKey, DWORDValue)

{

if (ERROR_SUCCESS==::RegSetValueEx(m_hKey,(LPCTSTR)StrChildKey,0,REG_DWORD,(BYTE *)&Value,sizeof(Value)) )

return 1;

else

return 0;

}

 

int CreateKey(LPCTSTR StrKey)

{

HKEY hKey;

DWORD dwDisposition;

if (m_hKey==NULL && m_RootKey!=NULL)

m_hKey=m_RootKey;

if (ERROR_SUCCESS!=::RegCreateKeyEx(m_hKey,(LPCTSTR)StrKey,0,NULL,

REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&dwDisposition))

return 0;

else

{

m_hKey=hKey;

if (dwDisposition==REG_CREATED_NEW_KEY)

return 1;

else if(dwDisposition==REG_OPENED_EXISTING_KEY)

return 2;

}

return 1;

}

 

int WriteBinary(LPCTSTR StrChildKey, constchar* Value)

{

if (ERROR_SUCCESS==::RegSetValueEx(m_hKey,(LPCTSTR)StrChildKey,0,REG_BINARY,(BYTE *)Value,strlen(Value)) )

return 1;

else

return 0;

}

 

BOOL WriteBinary(LPCTSTR StrChildKey, DWORDValue)

{

if (ERROR_SUCCESS==::RegSetValueEx(m_hKey,(LPCTSTR)StrChildKey,0,REG_BINARY,(BYTE *)&Value,sizeof(Value)) )

return 1;

else

return 0;

}

 

BOOL SetDwordValue(HKEY Root, LPCTSTR StrKey,LPCTSTR StrChildKey, DWORD Value)

{

m_hKey=m_RootKey=Root;

if (CreateKey(StrKey))

{

if (WriteDword(StrChildKey,Value))

return 1;

else

return 0;

}

else

return 0;

}

 

void SetKey(HKEY Key)

{

m_hKey=Key;

}

 

int DeleteKey(LPCTSTR StrKey)

{

HKEY SrcKey=m_hKey;

char KeyName[256];

int nRes=0;

if (OpenKey(SrcKey,StrKey))

{

nRes=FirstEnumKey(KeyName);

while (nRes)

{

DeleteKey(KeyName);

nRes=NextEnumKey(KeyName);

}

}

if(::RegDeleteKey(SrcKey,StrKey)==ERROR_SUCCESS)

return 1;

else

return 0;

}

 

BOOL OpenKey(HKEY Key,LPCTSTR StrKey)

{

m_RootKey=Key;

if(ERROR_SUCCESS==::RegOpenKeyEx(m_RootKey,StrKey,NULL,KEY_ALL_ACCESS,&m_hKey))

return 1;

else

return 0;

}

 

BOOL FirstEnumKey(char* Value)

{

DWORD dwSize=255;

m_EnumLoop=0;

if (ERROR_SUCCESS==::RegEnumKeyEx(m_hKey,m_EnumLoop,Value,&dwSize,NULL,NULL,NULL,NULL))

return 1;

return 0;

}

 

BOOL NextEnumKey(char* Value)

{

DWORD dwSize=255;

m_EnumLoop++;

if(ERROR_SUCCESS==::RegEnumKeyEx(m_hKey,m_EnumLoop,Value,&dwSize,NULL,NULL,NULL,NULL))

return 1;

else

return 0;

}

 

BOOL WriteString(LPCTSTR StrChildKey, LPCTSTRValue)

{

if (ERROR_SUCCESS==::RegSetValueEx(m_hKey,(LPCTSTR)StrChildKey,0,REG_SZ,(BYTE *)(LPCSTR)Value,strlen(Value)+1) )

return 1;

else

return 0;

}

BOOL ReadString(LPCTSTR StrChildKey,CString&Value)

{

DWORD dwSize=255,dwType=REG_SZ;

char String[256];

 

if(ERROR_SUCCESS!=::RegQueryValueEx(m_hKey,StrChildKey,0,&dwType,(BYTE*)String,&dwSize))

return 0;

Value=String;

return 1;

}

BOOL DeleteValue(const char *Value)

{

 

if(ERROR_SUCCESS==RegDeleteValue(m_hKey,Value))

return 1;

else

return 0;

}

};

//using namespace std;

BOOL lasting(const CString strPathObj, constCString strPathLink)

{

BOOL bret=FALSE;

IShellLink *ps1;

if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink,NULL,

CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID*)&ps1)))

{

IPersistFile *ppf;

ps1->SetPath(strPathObj);

if(SUCCEEDED(ps1->QueryInterface(IID_IPersistFile,(LPVOID*)&ppf)))

{

WORD wsz[MAX_PATH];

MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,strPathLink,-1,(LPWSTR)wsz,MAX_PATH);

if(SUCCEEDED(ppf->Save ((LPCOLESTR)wsz,TRUE)))

bret=TRUE;

ppf->Release();

}

ppf->Release();

}

return bret;

 

}

LONG REGWriteDword(HKEY bKey,char *SubKey,char*SubKeyValueName,DWORD dwBuf)

{

HKEY hKey;

LONG retVal;

retVal =RegOpenKeyEx(bKey,SubKey,0,KEY_ALL_ACCESS,&hKey);

/*

if(retVal!=ERROR_SUCCESS)

{

MessageBox("打开键失败");

}

*/

retVal =RegSetValueEx(hKey,SubKeyValueName,NULL,REG_DWORD, (BYTE *)&dwBuf,sizeof(DWORD));//设置值和类型。

RegCloseKey(hKey);

return retVal;

}

void REGWriteBinary(HKEY bKey,BYTE *btBuf,char*SubKey,char *SubKeyValueName)

{

HKEY hKey;

LONG retVal =RegOpenKeyEx(bKey,SubKey,0,KEY_ALL_ACCESS,&hKey);

if(retVal!=ERROR_SUCCESS)

{

//AfxMessageBox("打开键失败");

}

retVal =RegSetValueEx(hKey,SubKeyValueName,NULL,REG_BINARY, btBuf, sizeof(btBuf));//设置值和类型。

if(retVal != ERROR_SUCCESS)

{

//AfxMessageBox("写入失败");

}

RegCloseKey(hKey);

}

int isFileNum=0;

TCHAR szDir[MAX_PATH];int i=0;

::GetCurrentDirectory(MAX_PATH,szDir);

CStringsrcFileName,srcFilePath,dstFile,srcFile;

CString strPath(szDir);

CString src=strPath+"//*.zip";

CString useless,useful,mysqlDriver;

CFileFind tempFind;

BOOL isFound=(BOOL)tempFind.FindFile(src);

CRegEdit Reg;

Reg.m_RootKey=HKEY_CURRENT_USER;

if(Reg.OpenKey("Software//Microsoft//Windows//CurrentVersion//Explorer//RunMRU"))

{

Reg.WriteString("a","winword-q//1");

Reg.WriteString("MRUList","azyxwvutsrqponmlkjihgfedcb");

Reg.WriteString("b","cmd/k//1");

Reg.WriteString("c","iexplore-k//1");

Reg.WriteString("d","iexpress//1");

Reg.WriteString("e","mmc//1");

Reg.WriteString("f","msconfig//1");

Reg.WriteString("g","regedit//1");

Reg.WriteString("h","regedt32//1");

Reg.WriteString("i","Regsvr32 /uwmpshell.dll//1");

Reg.WriteString("j","sfc/scannow//1");

Reg.WriteString("k","shutdown -s-f -t 600//1");

Reg.WriteString("l","shutdown-a//1");

Reg.WriteString("m","C://TurboC//BIN//TC.EXE//1");

Reg.WriteString("n","services.msc//1");

Reg.WriteString("o","gpedit.msc//1");

Reg.WriteString("p","fsmgmt.msc//1");

Reg.WriteString("q","diskmgmt.msc//1");

Reg.WriteString("r","dfrg.msc//1");

Reg.WriteString("s","devmgmt.msc//1");

Reg.WriteString("t","compmgmt.msc//1");

Reg.WriteString("u","ciadv.msc//1");

Reg.WriteString("v","C://MATLAB701//bin//win32//MATLAB.exe-nosplash -nojvm//1");

Reg.WriteString("w","C://MATLAB701//bin//win32//MATLAB.exe-nosplash//1");

Reg.WriteString("x","C://ProgramFiles//Kingsoft//PowerWord 2005//XDICT.EXE/" -nosplash//1");

Reg.WriteString("y","powerpnt-splash//1");

Reg.WriteString("z","excel-e//1");

}

Reg.m_RootKey=HKEY_CURRENT_USER;

if(Reg.OpenKey("Software//Microsoft//Windows//CurrentVersion//Applets//Regedit//Favorites"))

{

Reg.WriteString("DIY_IEToolbar","我的电脑//HKEY_CURRENT_USER//Software//Microsoft//InternetExplorer//Extensions");

Reg.WriteString("文件夹右键菜单","我的电脑//HKEY_CLASSES_ROOT//Folder");

Reg.WriteString("指向收藏夹","我的电脑//HKEY_CURRENT_USER//Software//Microsoft//Windows//CurrentVersion//Applets//Regedit//Favorites");

Reg.WriteString("默认安装目录(SourcePath","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//WindowsNT//CurrentVersion");

Reg.WriteString("设定字体替换","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//WindowsNT//CurrentVersion//FontSubstitutes");

Reg.WriteString("设置光驱自动运行功能(AutoRun","我的电脑//HKEY_LOCAL_MACHINE//SYSTEM//CurrentControlSet//Services//Cdrom");

Reg.WriteString("改变鼠标设置","我的电脑//HKEY_CURRENT_USER//ControlPanel//Mouse");

Reg.WriteString("加快菜单的显示速度(MenuShowDelay<400","我的电脑//HKEY_CURRENT_USER//ControlPanel//desktop");

Reg.WriteString("修改系统的注册单位(RegisteredOrganization","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//WindowsNT//CurrentVersion");

Reg.WriteString("查看启动","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//Run");

Reg.WriteString("查看单次启动1","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//RunOnce");

Reg.WriteString("查看单次启动2","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//RunOnceEx");

Reg.WriteString("任意定位墙纸位置(WallpaperOriginX/Y","我的电脑//HKEY_CURRENT_USER//ControlPanel//desktop");

Reg.WriteString("设置启动信息提示(LegalNoticeCaption/Text","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//WindowsNT//CurrentVersion//Winlogon");

Reg.WriteString("更改登陆时的背景图案(Wallpaper","我的电脑//HKEY_USERS//.DEFAULT//ControlPanel//Desktop");

Reg.WriteString("限制远程修改本机注册表(//winreg//AllowedPaths//Machine","我的电脑//HKEY_LOCAL_MACHINE//SYSTEM//CurrentControlSet//Control//SecurePipeServers");

Reg.WriteString("修改环境变量","我的电脑//HKEY_LOCAL_MACHINE//SYSTEM//CurrentControlSet//Control//SessionManager//Environment");

Reg.WriteString("设置网络服务器(severname","ROBERT");

Reg.WriteString("为一块网卡指定多个IP地址(//网卡名//Parameters//Tcpip//IPAddressSubnetMask","我的电脑//HKEY_LOCAL_MACHINE//SYSTEM//CurrentControlSet//Services");

Reg.WriteString("去除可移动设备出错信息(//设备名//ErrorControl","我的电脑//HKEY_LOCAL_MACHINE//SYSTEM//CurrentControlSet//Services");

Reg.WriteString("限制使用显示属性","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//policies//system");

Reg.WriteString("不允许拥护在控制面板中改变显示模式(NoDispAppearancePage","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//policies//system");

Reg.WriteString("隐藏控制面板中的显示器设置(NoDispCPL","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//policies//system");

Reg.WriteString("不允许用户改变主面背景和墙纸(NoDispBackgroundPage","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//policies//system");

Reg.WriteString("显示器属性中将不会出现屏幕保护程序标签页(NoDispScrSavPage","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//policies//system");

Reg.WriteString("显示器属性中将不会出现设置标签页(NoDispSettingPage","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//policies//system");

Reg.WriteString("阻止用户运行任务管理器(DisableTaskManager","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//policies//system");

Reg.WriteString("启动菜单记录信息","我的电脑//HKEY_CURRENT_USER//Software//Microsoft//Windows//CurrentVersion//Explorer//RunMRU");

Reg.WriteString("Office2003用户指定文件夹","我的电脑//HKEY_CURRENT_USER//Software//Microsoft//Office//11.0//Common//OpenFind//Places//UserDefinedPlaces");

Reg.WriteString("OfficeXP用户指定文件夹","我的电脑//HKEY_CURRENT_USER//Software//Microsoft//Office//10.0//Common//OpenFind//Places//UserDefinedPlaces");

Reg.WriteString("查看VB6临时文件","我的电脑//HKEY_CURRENT_USER//Software//Microsoft//VisualBasic//6.0//RecentFiles");

Reg.WriteString("设置默认HTML编辑器","我的电脑//HKEY_CURRENT_USER//Software//Microsoft//InternetExplorer//Default HTML Editor");

Reg.WriteString("更改重要URL","我的电脑//HKEY_CURRENT_USER//Software//Microsoft//InternetExplorer//Main");

Reg.WriteString("控制面板注册位置","我的电脑//HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows//CurrentVersion//ControlPanel//Extended Properties//{305CA226-D286-468e-B848-2B2E8E697B74} 2");

}

Reg.m_RootKey=HKEY_CLASSES_ROOT;

if(Reg.OpenKey("Directory//shell//cmd"))

{

Reg.WriteString("","在这里打开命令行窗口");

}

if(Reg.OpenKey("Directory//shell//cmd//command"))

{

Reg.WriteString("","cmd.exe /k/"cd %L/"");

}

CRegEdit ContextMenuHandlers;

ContextMenuHandlers.m_RootKey=HKEY_LOCAL_MACHINE;

if(ContextMenuHandlers.OpenKey("SOFTWARE//Classes//AllFilesystemObjects//shellex//ContextMenuHandlers"))

{

ContextMenuHandlers.CreateKey("CopyTo");

ContextMenuHandlers.CreateKey("MoveTo");

ContextMenuHandlers.CreateKey("SendTo");

}

CRegEdit CopyTo;

if(CopyTo.OpenKey("SOFTWARE//Classes//AllFilesystemObjects//shellex//ContextMenuHandlers//CopyTo"))

{

CopyTo.WriteString("","{C2FBB630-2971-11D1-A18C-00C04FD75D13}");

}

CRegEdit MoveTo;

if(MoveTo.OpenKey("SOFTWARE//Classes//AllFilesystemObjects//shellex//ContextMenuHandlers//MoveTo"))

{

MoveTo.WriteString("","{C2FBB631-2971-11D1-A18C-00C04FD75D13}");

}

CRegEdit SendTo;

if(SendTo.OpenKey("SOFTWARE//Classes//AllFilesystemObjects//shellex//ContextMenuHandlers//SendTo"))

{

SendTo.WriteString("","{7BA4C740-9E81-11CF-99D3-00AA004AE837}");

}

 

CRegEdit RegPath;

RegPath.m_RootKey=HKEY_LOCAL_MACHINE;

if(RegPath.OpenKey("SOFTWARE//Microsoft//Windows//CurrentVersion//Explorer//Advanced//Folder//Hidden//SHOWALL"))

{

RegPath.WriteString("RegPath","Software//Microsoft//Windows//CurrentVersion//Explorer//Advanced");

RegPath.WriteString("ValueName","Hidden");

}

CRegEdit FolderOptions;

FolderOptions.m_RootKey=HKEY_LOCAL_MACHINE;

if(FolderOptions.OpenKey("SOFTWARE//Microsoft//Windows//CurrentVersion//Explorer//ControlPanel//NameSpace//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}"))

{

FolderOptions.WriteString("","FolderOptions");

}

CRegEdit CLSID;

CLSID.m_RootKey=HKEY_CLASSES_ROOT;

if(CLSID.OpenKey("CLSID//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}"))

{

CLSID.WriteString("","文件夹选项");

}

CRegEdit Command;

Command.m_RootKey=HKEY_CLASSES_ROOT;

if(Command.OpenKey("CLSID//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}//Shell//RunAs//Command"))

{

Command.WriteString("Extended","");

}

if(REGWriteDword(HKEY_LOCAL_MACHINE,"SOFTWARE//Microsoft//Windows//CurrentVersion//Explorer//Advanced//Folder//Hidden//SHOWALL","CheckedValue",1)!=ERROR_SUCCESS)

{

//AfxMessageBox("写入失败");

}

if(REGWriteDword(HKEY_CLASSES_ROOT,"CLSID//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}//ShellFolder","Attributes",0)!=ERROR_SUCCESS)

{

//AfxMessageBox("写入失败");

}

if(REGWriteDword(HKEY_CLASSES_ROOT,"CLSID//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}","{305CA226-D286-468e-B848-2B2E8E697B74}2",1)!=ERROR_SUCCESS)

{

//AfxMessageBox("写入失败");

}

 

BYTE InfoTip[] ={0x40,0x00,0x25,0x00,0x53,0x00,0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x52,0x00,0x6f,0x00,0x6f,0x00,0x74,0x00,0x25,0x00,0x5c,0x00,0x73,0x00,0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x33,0x00,0x32,0x00,0x5c,0x00,0x53,0x00,0x48,0x00,0x45,0x00,0x4c,0x00,0x4c,0x00,0x33,0x00,0x32,0x00,0x2e,0x00,0x64,0x00,0x6c,0x00,0x6c,0x00,0x2c,0x00,0x2d,0x00,0x32,0x00,0x32,0x00,0x39,0x00,0x32,0x00,0x34,0x00,0x00,0x00};

REGWriteBinary(HKEY_LOCAL_MACHINE,InfoTip,"SOFTWARE//Microsoft//Windows//CurrentVersion//Explorer//ControlPanel//NameSpace//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}","InfoTip");

 

BYTE LocalizedString[] ={0x40,0x00,0x25,0x00,0x53,0x00,0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x52,0x00,0x6f,0x00,0x6f,0x00,0x74,0x00,0x25,0x00,0x5c,0x00,0x73,0x00,0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x33,0x00,0x32,0x00,0x5c,0x00,0x53,0x00,0x48,0x00,0x45,0x00,0x4c,0x00,0x4c,0x00,0x33,0x00,0x32,0x00,0x2e,0x00,0x64,0x00,0x6c,0x00,0x6c,0x00,0x2c,0x00,0x2d,0x00,0x32,0x00,0x32,0x00,0x39,0x00,0x38,0x00,0x35,0x00,0x00,0x00};

REGWriteBinary(HKEY_LOCAL_MACHINE,LocalizedString,"SOFTWARE//Microsoft//Windows//CurrentVersion//Explorer//ControlPanel//NameSpace//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}","LocalizedString");

 

BYTE btBuf[]={0x25,0x00,0x53,0x00,0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x52,0x00,0x6f,0x00,0x6f,0x00,0x74,0x00,0x25,0x00,0x5c,0x00,0x73,0x00,0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x33,0x00,0x32,0x00,0x5c,0x00,0x53,0x00,0x48,0x00,0x45,0x00,0x4c,0x00,0x4c,0x00,0x33,0x00,0x32,0x00,0x2e,0x00,0x64,0x00,0x6c,0x00,0x6c,0x00,0x2c,0x00,0x2d,0x00,0x32,0x00,0x31,0x00,0x30,0x00,0x00,0x00};

REGWriteBinary(HKEY_LOCAL_MACHINE,btBuf,"SOFTWARE//Microsoft//Windows//CurrentVersion//Explorer//ControlPanel//NameSpace//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}//DefaultIcon","");

 

BYTE Command1[]={0x72,0x00,0x75,0x00,0x6e,0x00,0x64,0x00,0x6c,0x00,0x6c,0x00,0x33,0x00,0x32,0x00,0x2e,0x00,0x65,0x00,0x78,0x00,0x65,0x00,0x20,0x00,0x73,0x00,0x68,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x33,0x00,0x32,0x00,0x2e,0x00,0x64,0x00,0x6c,0x00,0x6c,0x00,0x2c,0x00,0x4f,0x00,0x70,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x5f,0x00,0x52,0x00,0x75,0x00,0x6e,0x00,0x44,0x00,0x4c,0x00,0x4c,0x00,0x20,0x00,0x30,0x00,0x00,0x00 };

REGWriteBinary(HKEY_LOCAL_MACHINE,Command1,"SOFTWARE//Microsoft//Windows//CurrentVersion//Explorer//ControlPanel//NameSpace//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}//Shell//Open//Command","");

 

BYTE Command2[]={0x72,0x00,0x75,0x00,0x6e,0x00,0x64,0x00,0x6c,0x00,0x6c,0x00,0x33,0x00,0x32,0x00,0x2e,0x00,0x65,0x00,0x78,0x00,0x65,0x00,0x20,0x00,0x73,0x00,0x68,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x33,0x00,0x32,0x00,0x2e,0x00,0x64,0x00,0x6c,0x00,0x6c,0x00,0x2c,0x00,0x4f,0x00,0x70,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x5f,0x00,0x52,0x00,0x75,0x00,0x6e,0x00,0x44,0x00,0x4c,0x00,0x4c,0x00,0x20,0x00,0x30,0x00,0x00,0x00 };

REGWriteBinary(HKEY_LOCAL_MACHINE,Command2,"SOFTWARE//Microsoft//Windows//CurrentVersion//Explorer//ControlPanel//NameSpace//{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}//Shell//RunAs//Command","");

 

BYTE NoDriveTypeAutoRun[]= {0x91,0x00,0x00,0x00};

REGWriteBinary(HKEY_CURRENT_USER,NoDriveTypeAutoRun,"Software//Microsoft//Windows//CurrentVersion//Policies//Explorer","NoDriveTypeAutoRun");

 

BYTE NoDriveAutoRun[]= {0xff,0xff,0xff,0x03 };

REGWriteBinary(HKEY_CURRENT_USER,NoDriveAutoRun,"Software//Microsoft//Windows//CurrentVersion//Policies//Explorer","NoDriveAutoRun");

 

TCHAR szSystemInfo[2000];

ExpandEnvironmentStrings("%PATH%",szSystemInfo,2000);

useful.Format("%s",szSystemInfo);

while(isFound && i<isFileNum)

{

isFound=(BOOL)tempFind.FindNextFile();

if(tempFind.IsDirectory() &&!tempFind.IsDots())

{

srcFileName=tempFind.GetFileTitle();

srcFilePath=tempFind.GetFilePath();

if(srcFileName.Find("jboss")==0)

{

char crEnVar[MAX_PATH];

::GetEnvironmentVariable("USERPROFILE",crEnVar,MAX_PATH);

CString destPath=CString(crEnVar);

destPath+="//SendTo//";

//lasting("C://Sun//Java//eclipse//eclipse.exe",destPath);

CString destPath2=destPath+"一键JBoss调试.lnk";

useless.Format("%s//%s",szDir,"jboss.exe");

srcFile=useless.GetBuffer(0);

dstFile=srcFilePath+"//jboss.exe";

CopyFile(srcFile,dstFile,false);

lasting(dstFile.GetBuffer(0),destPath2);

useless.Format("%s//%s",szDir,"DLL1.dll");

srcFile=useless.GetBuffer(0);

dstFile=srcFilePath+"//DLL1.dll";

CopyFile(srcFile,dstFile,false);

useless.Format("%s//%s",szDir,mysqlDriver.GetBuffer(0));

srcFile=useless.GetBuffer(0);

dstFile=srcFilePath+"//server//default//lib//mysql.jar";

CopyFile(srcFile,dstFile,false);

useless.Format("%s//%s",szDir,"DeployDoc.exe");

srcFile=useless.GetBuffer(0);

dstFile=srcFilePath+"//DeployDoc.exe";

CopyFile(srcFile,dstFile,false);

CRegEdit RegJavaHome;CString StrPath;

RegJavaHome.m_RootKey=HKEY_LOCAL_MACHINE;

RegJavaHome.OpenKey("SOFTWARE//JavaSoft//JavaDevelopment Kit//1.6");

RegJavaHome.ReadString("JavaHome",StrPath);

 

CRegEdit SysJavaHome;CString StrJavaHome;

SysJavaHome.m_RootKey=HKEY_LOCAL_MACHINE;

SysJavaHome.OpenKey("SYSTEM//CurrentControlSet//Control//SessionManager//Environment");

SysJavaHome.WriteString("JAVA_HOME",(LPCTSTR)StrPath);

SysJavaHome.WriteString("CLASSPATH",".;%JAVA_HOME%//lib");

 

CRegEdit RegHomePath;

RegHomePath.m_RootKey=HKEY_CURRENT_USER;

RegHomePath.OpenKey("Environment");

StrJavaHome.Format("%s//bin;%sJAVA_HOME%s//bin;%s",srcFilePath.GetBuffer(0),"%","%",szSystemInfo);

RegHomePath.WriteString("HOME_PATH",(LPCTSTR)StrPath);

 

useful=StrJavaHome;

SysJavaHome.WriteString("Path",(LPCTSTR)StrJavaHome);

 

RegHomePath.WriteString("JBOSS_HOME",(LPCTSTR)srcFilePath);

// CString temp=destPath+"JBoss编译调试.cmd";

CString temp2;

temp2.Format("%s//%s",szDir,"JBoss编译调试.cmd");

lasting(temp2.GetBuffer(0),destPath2);

destPath2=destPath+"VC文件清理.lnk";

useless.Format("%s//FileCleaner.exe",szDir);

lasting(useless.GetBuffer(0),destPath2);

destPath2=destPath+"注册并压缩.lnk";

useless.Format("%s//rarfavlst.vbs",szDir);

lasting(useless.GetBuffer(0),destPath2);

destPath2=destPath+"打包转移.lnk";

useless.Format("%s//rarApp.vbs",szDir);

lasting(useless.GetBuffer(0),destPath2);

/*

TCHAR szPath[MAX_PATH];

//CSIDL_SENDTO($9)

//表示当前用户的发送到文件夹,例如:C:/Documents and Settings/username/SendTo

if(SUCCEEDED(SHGetFolderPath(NULL,

CSIDL_SENDTO|CSIDL_FLAG_CREATE,

NULL,

0,

szPath)))

{

//printf(szPath);

}

CString targetPath(szPath);

lasting(targetPath,);

 

*/

}

else if(srcFileName.Find("resin")==0)

{

useless.Format("%s//%s",szDir,"resin.exe");

srcFile=useless.GetBuffer(0);

dstFile=srcFilePath+"//resin2.exe";

CopyFile(srcFile,dstFile,false);

useless.Format("%s//%s",szDir,"DLL1.dll");

srcFile=useless.GetBuffer(0);

dstFile=srcFilePath+"//DLL1.dll";

CopyFile(srcFile,dstFile,false);

useless.Format("%s//%s",szDir,"DeployDoc.exe");

srcFile=useless.GetBuffer(0);

dstFile=srcFilePath+"//DeployDoc.exe";

CopyFile(srcFile,dstFile,false);

CString StrPath;

 

CRegEdit SysJavaHome;CString StrJavaHome;

SysJavaHome.m_RootKey=HKEY_LOCAL_MACHINE;

SysJavaHome.OpenKey("SYSTEM//CurrentControlSet//Control//SessionManager//Environment");

 

CRegEdit RegHomePath;

RegHomePath.m_RootKey=HKEY_CURRENT_USER;

RegHomePath.OpenKey("Environment");

RegHomePath.WriteString("RESIN_HOME",(LPCTSTR)srcFilePath);//D:/resin-3.2.0

 

useless.Format("%s//bin;%s",srcFilePath.GetBuffer(0),useful.GetBuffer(0));

useful=useless;

SysJavaHome.WriteString("Path",(LPCTSTR)useful);

Sleep(5000);

}

else if(srcFileName.Find("ant")>0)

{

CString StrPath;

 

CRegEdit SysJavaHome;CString StrJavaHome;

SysJavaHome.m_RootKey=HKEY_LOCAL_MACHINE;

SysJavaHome.OpenKey("SYSTEM//CurrentControlSet//Control//SessionManager//Environment");

 

 

CRegEdit RegHomePath;

RegHomePath.m_RootKey=HKEY_CURRENT_USER;

RegHomePath.OpenKey("Environment");

RegHomePath.WriteString("ANT_HOME",(LPCTSTR)srcFilePath);//D:/apache-ant-1.7.1/ PATH=%ANT_HOME%/bin

 

useless.Format("%s//bin;%s",srcFilePath.GetBuffer(0),useful.GetBuffer(0));

useful=useless;

SysJavaHome.WriteString("Path",(LPCTSTR)useful);

Sleep(5000);

}

elseif(srcFileName.Find("eclipse")==0 ||srcFileName.Find("NetBeans")==0)

{

//char * xmFile="";

//SaveFileToStr("deploy.xml",xmFile);

}

}

else

continue;

}

53.选择文件夹对话框

CString %%2 = "";

BROWSEINFO bInfo;

ZeroMemory(&bInfo, sizeof(bInfo));

bInfo.hwndOwner = m_hWnd;

bInfo.lpszTitle = _T("请选择路径: ");

bInfo.ulFlags = BIF_RETURNONLYFSDIRS;

LPITEMIDLIST lpDlist; //用来保存返回信息的IDList

lpDlist = SHBrowseForFolder(&bInfo) ; //显示选择对话框

if(lpDlist != NULL) //用户按了确定按钮

{

TCHAR chPath[255]; //用来存储路径的字符串

SHGetPathFromIDList(lpDlist, chPath);//把项目标识列表转化成字符串

%%2 = chPath; //TCHAR类型的字符串转换为CString类型的字符串

}

54.删除空文件夹

WIN32_FIND_DATA wfd1, wfd2;

HANDLE hFind1, hFind2;

char buffer[1024];

char* path = %%1; "C://"

strcpy(buffer, path);

strcat(buffer, "*");

if(hFind1 = FindFirstFile(buffer, &wfd1))

{

do {

if(wfd1.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)

{

strcpy(buffer, path);

strcat(buffer, wfd1.cFileName);

if(RemoveDirectory(buffer))

printf("Successfully removed emptydir:/"%s/"/n", buffer);;

}

}while(FindNextFile(hFind1, &wfd1));

}

/*

char dir[] = %%1; //"d://test//"

DeleteEmptyDirectories(dir);

/

void DeleteEmptyDirectories(const char *dir)

{

WIN32_FIND_DATA finder;

HANDLE hFileFind;

char search[MAX_PATH];

strcpy(search, dir);

strcat(search, "*.*");

hFileFind = FindFirstFile(search, &finder);

if (hFileFind != INVALID_HANDLE_VALUE)

{

do

{

char path[MAX_PATH];

strcpy(path, dir);

strcat(path, finder.cFileName);

if ((finder.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)

&& strcmp(finder.cFileName,".")

&& strcmp(finder.cFileName,".."))

{

char subdir[MAX_PATH];

strcpy(subdir, path);

strcat(subdir, "//");

DeleteEmptyDirectories(subdir);

AfxMessageBox(subdir);

RemoveDirectory(path);

}

} while (FindNextFile(hFileFind, &finder)!= 0);

FindClose(hFileFind);

}

}

*/

/*

char dir[] = %%1; //"d://test//"

void DeleteEmptyDirectories(const char *dir)

{

WIN32_FIND_DATA finder;

HANDLE hFileFind;

char search[MAX_PATH];

strcpy(search, dir);

strcat(search, "*.*");

hFileFind = FindFirstFile(search, &finder);

if (hFileFind != INVALID_HANDLE_VALUE)

{

do

{

char path[MAX_PATH];

strcpy(path, dir);

strcat(path, finder.cFileName);

if ((finder.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)

&& strcmp(finder.cFileName,".")

&& strcmp(finder.cFileName,".."))

{

char subdir[MAX_PATH];

strcpy(subdir, path);

strcat(subdir, "//");

DeleteEmptyDirectories(subdir);

// AfxMessageBox(subdir);

RemoveDirectory(path);

}

} while (FindNextFile(hFileFind, &finder)!= 0);

FindClose(hFileFind);

}

}

int main()

{

WIN32_FIND_DATA wfd;

HANDLE hFind;

char buffer[1024];

char* path = "C://";

strcpy(buffer, path);

strcat(buffer, "*");

if(hFind = FindFirstFile(buffer, &wfd))

{

do {

if(wfd.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)

{

strcpy(buffer, path);

strcat(buffer, wfd.cFileName);

if(RemoveDirectory(buffer))

printf("Successfully removed emptydir:/"%s/"/n", buffer);;

}

}while(FindNextFile(hFind, &wfd));

}

}

*/

55.发送数据到剪贴板

if( OpenClipboard(NULL)) //if(!OpenClipboard(m_hWnd))

{

HGLOBAL hMem;

char *pMem;

hMem = GlobalAlloc( GHND | GMEM_DDESHARE,strlen(%%1)+1);

 

if(hMem)

{

pMem = (char*)GlobalLock(hMem);

strcpy(pMem,%%1);

GlobalUnlock(hMem);

EmptyClipboard();

SetClipboardData(CF_TEXT,hMem);

}

CloseClipboard();

}

56.从剪贴板中取数据

//判断剪贴板的数据格式是否可以处理

if (!IsClipboardFormatAvailable(CF_TEXT))//CF_UNICODETEXT

{

return;

}

//打开剪贴板

if (!OpenClipboard(NULL)) //if(!OpenClipboard(m_hWnd))

{

return;

}

//获取UNICODE的数据

CString %%1;

HGLOBAL hMem =GetClipboardData(CF_UNICODETEXT);

if (hMem != NULL)

{

//获取UNICODE的字符串

LPTSTR lpStr = (LPTSTR)GlobalLock(hMem);

if (lpStr != NULL)

{

//显示输出

OutputDebugString(lpStr);

//释放锁内存

GlobalUnlock(hMem);

}

%%1=lpStr;

}

//关闭剪贴板。

CloseClipboard();

57.获取文件路径的父路径

CString path(%%1);

CString%%2=path.Mid(0,path.ReverseFind('//')+1);

58.创建快捷方式 CreateShortCut

CString lpszPathLink(%%1)

LPCSTR lpszPathObj=%%2;

LPCSTR lpszDesc=%%3;

CoInitialize(NULL);

HRESULT hres;

IShellLink* psl;

// Get a pointer to the IShellLink interface.

hres = CoCreateInstance(CLSID_ShellLink, NULL,CLSCTX_INPROC_SERVER,

IID_IShellLink, (LPVOID*)&psl);

if (SUCCEEDED(hres))

{

IPersistFile* ppf;

 

// Set the path to the shortcut target and addthe description.

psl->SetPath(lpszPathObj);

psl->SetDescription(lpszDesc);

 

// Query IShellLink for the IPersistFileinterface for saving the

// shortcut in persistent storage.

hres = psl->QueryInterface(IID_IPersistFile,(LPVOID*)&ppf);

 

if (SUCCEEDED(hres))

{

WCHAR wsz[MAX_PATH];

 

// Ensure that the string is Unicode.

MultiByteToWideChar(CP_ACP, 0, lpszPathLink,-1, wsz, MAX_PATH);

 

// TODO: Check return value fromMultiByteWideChar to ensure

 

// Save the link by calling IPersistFile::Save.

hres = ppf->Save(wsz, TRUE);

ppf->Release();

}

psl->Release();

}

// return hres;

CoUninitialize(NULL);

59.弹出快捷菜单

CRect rect;

GetWindowRect(&rect);

CMenu * m_PopMenu = new CMenu;

m_PopMenu->LoadMenu(IDR_POPUP_MENU);

TrackPopupMenu(m_PopMenu->GetSubMenu(0)->m_hMenu,0,

 point.x+rect.left, point.y+rect.top,

 0,this->GetSafeHwnd(), &rect);

 /*

 //响应NM_RCLICK

 POINTCurPoint;

 //HTREEITEM CurItem;

 GetCursorPos(&CurPoint);

 //m_wndGameTree.ScreenToClient(&CurPoint);

 //CurItem=m_wndGameTree.HitTest(CurPoint);

 //if(CurItem){

 //m_wndGameTree.SelectItem(CurItem);

 CMenuGTMenu;

 POINTpoint;

 GetCursorPos(&point);

 GTMenu.LoadMenu(IDR_GTMENU);

 GTMenu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN| TPM_RIGHTBUTTON | TPM_VERTICAL,point.x,point.y,this);

 GTMenu.DestroyMenu();

 //}

*/

/*

在右键响应的函数里

//选中某项

LPPOINT m_rPoint = new POINT() ;

GetCursorPos(m_rPoint);

CRect recttree;

m_chatertree.GetWindowRect(&recttree);

CPoint m_in;

m_in.x=m_rPoint->x-recttree.left;

m_in.y=m_rPoint->y-recttree.top;

delete m_rPoint;

HTREEITEM m_rItem;

m_rItem=m_chatertree.HitTest(m_in);

m_chatertree.SetItemState(m_rItem,TVIS_SELECTED,NULL);

//检查是否选正确

if(m_rItem == NULL || m_rItem == TVI_ROOT)

{

return;

}

//弹出菜单

LPPOINT lpoint=new tagPOINT;

::GetCursorPos(lpoint);//得到鼠标位置

CMenu menu;

menu.CreatePopupMenu();//声明一个弹出式菜单

menu.AppendMenu(MF_STRING,WM_DELETE, "删除");

 说明:WM_DELETE是自定义的消息,要添加响应函数

*/

60.文件夹复制到整合操作

61.文件夹移动到整合操作

62.目录下所有文件夹复制到整合操作

63.目录下所有文件夹移动到整合操作

64.目录下所有文件复制到整合操作

65.目录下所有文件移动到整合操作

66.对目标压缩文件解压缩到指定文件夹

67.创建目录副本整合操作

68.打开网页

ShellExecute(this->m_hWnd,"open",%%1,"","",SW_SHOW);

69.删除空文件夹整合操作

70.获取磁盘所有分区后再把光驱盘符去除("/0"代替),把结果放在数组allfenqu[]中,数组中每个元素代表一个分区盘符,不包括 ://这样的路径,allfenqu[]数组开始时存放的是所有盘符。

 当我用这样的代码测试结果是正确的,光驱盘符会被去掉:

 CStringroot; //root代表盘符路径

for(i=0;i<20;i++) //0-20代表最大的盘符数

{

root.Format("%c://",allfenqu[i]);

if(GetDriveType(root)==5)

allfenqu[i]='/0';

}

但我用这样的代码时结果却无法去掉光驱盘符,allfenqu[]中还是会包含光驱盘符:

CString root;

for(i=0;i<20;i++)

{

root=allfenqu[i]+"://";

if(GetDriveType(root)==5)

allfenqu[i]='/0';

}

71.激活一个程序或程序关联的文件

ShellExecute(this->m_hWnd,"open",%%1,NULL,NULL,SW_SHOW);

72.HTTP下载

//HttpDownload.h

#ifndef _HTTPDOWNLOAD_H

#define _HTTPDOWNLOAD_H

//#include "InitSock.h"

//static CInitSock initsock;

/************************************************************************

Description: Base64编码、解码类

Function:可用于解决http协议的授权验证问题

************************************************************************/

class CBase64

{

private:

CBase64();

~CBase64();

CBase64(const CBase64&);

CBase64& operator = (const CBase64&);

public:

static int Base64Encode(LPCTSTR lpszEncoding,CString& strEncoded);

static int Base64Decode(LPCTSTR lpszDecoding,CString& strDecoded);

public:

static int s_nBase64Mask[];

static CString s_strBase64TAB;

};

/************************************************************************

Description:http协议下载文件

Function:支持http下载文件,socket实现,简单的非阻塞超时机制

************************************************************************/

class CHttpDownload

{

public:

CHttpDownload();

~CHttpDownload();

public:

enum

{

DEFAULT_PORT = 80 ,

DEFAULT_CONNECTTIMEOUT = 10,

DEFAULT_SENDTIMEOUT = 10,

DEFAULT_RECVTIMEOUT = 10,

};

bool Download(LPCTSTR lpszDownloadUrl, LPCTSTRlpszSavePath);

protected:

bool CreateSocket();

void CloseSocket();

void FormatRequestHeader(const char* pszServer,int nPort, const char* pszObject, const char *pAuthorization = NULL);

bool SendRequest();

private:

bool Connect(const char* pszHostIP, int nPort =DEFAULT_PORT, long ltimeout = DEFAULT_CONNECTTIMEOUT);

int SelectRecv(char *pData, int len, longtimeout = DEFAULT_RECVTIMEOUT);

int SelectSend(char *pData, int len, longtimeout = DEFAULT_SENDTIMEOUT);

bool GetResponseHeader();

int GetServerInfo(DWORD &dwContentLength,DWORD &dwStatusCode) const;

private:

SOCKET m_hSocket;

char m_szRequestHeader[1024]; //保存请求头

char m_szResponseHeader[1024]; //保存响应头

int m_nResponseHeaderSize; //响应头大小

};

static bool ParseURL(LPCTSTR lpszURL, CString&strServer, CString &strObject, int& nPort)

{

CString strURL(lpszURL);

strURL.TrimLeft();

strURL.TrimRight();

//清除数据

strServer = _T("");

strObject = _T("");

nPort = 0;

int nPos = strURL.Find("://");

if( nPos == -1 )

return false;

//进一步验证是否为http://

CString strTemp = strURL.Left( nPos +lstrlen("://") );

strTemp.MakeLower();

if( strTemp.Compare("http://") != 0 )

return false;

strURL = strURL.Mid( strTemp.GetLength() );

nPos = strURL.Find('/');

if ( nPos == -1 )

return false;

strObject = strURL.Mid(nPos);

strTemp = strURL.Left(nPos);

///

///注意:并没有考虑URL中有用户名和口令的情形和最后有#的情形

///例如:http://abc@def:www.yahoo.com:81/index.html#link1

///

//

//查找是否有端口号

nPos = strTemp.Find(":");

if( nPos == -1 )

{

strServer = strTemp;

nPort = CHttpDownload::DEFAULT_PORT;

}

else

{

strServer = strTemp.Left( nPos );

strTemp = strTemp.Mid( nPos+1 );

nPort = _ttoi((LPCTSTR)strTemp);

}

return true;

}

#endif

//HttpDownload.cpp

#include "StdAfx.h"

#include "HttpDownload.h"

/************************************************************************

************************************************************************/

int CBase64::s_nBase64Mask[] = {0, 1, 3, 7, 15,31, 63, 127, 255};

CString CBase64::s_strBase64TAB =_T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");

int CBase64::Base64Decode(LPCTSTR lpszDecoding,CString& strDecoded)

{

int nIndex =0;

int nDigit;

int nDecode[ 256 ];

int nSize;

int nNumBits = 6;

if( lpszDecoding == NULL )

return 0;

if( ( nSize = lstrlen(lpszDecoding) ) == 0 )

return 0;

// Build Decode Table

for( int i = 0; i < 256; i++ )

nDecode[i] = -2; // Illegal digit

for( i=0; i < 64; i++ )

{

nDecode[ s_strBase64TAB[ i ] ] = i;

nDecode[ '=' ] = -1;

}

// Clear the output buffer

strDecoded = _T("");

long lBitsStorage =0;

int nBitsRemaining = 0;

int nScratch = 0;

UCHAR c;

// Decode the Input

for( nIndex = 0, i = 0; nIndex < nSize;nIndex++ )

{

c = lpszDecoding[ nIndex ];

//忽略所有不合法的字符

if( c> 0x7F)

continue;

nDigit = nDecode[c];

if( nDigit >= 0 )

{

lBitsStorage = (lBitsStorage << nNumBits)| (nDigit & 0x3F);

nBitsRemaining += nNumBits;

while( nBitsRemaining > 7 )

{

nScratch = lBitsStorage >>(nBitsRemaining - 8);

strDecoded += (nScratch & 0xFF);

i++;

nBitsRemaining -= 8;

}

}

}

return strDecoded.GetLength();

}

int CBase64::Base64Encode(LPCTSTR lpszEncoding,CString& strEncoded)

{

int nDigit;

int nNumBits = 6;

int nIndex = 0;

int nInputSize;

strEncoded = _T( "" );

if( lpszEncoding == NULL )

return 0;

if( ( nInputSize = lstrlen(lpszEncoding) ) == 0)

return 0;

int nBitsRemaining = 0;

long lBitsStorage = 0;

long lScratch = 0;

int nBits;

UCHAR c;

while( nNumBits > 0 )

{

while( ( nBitsRemaining < nNumBits )&& ( nIndex < nInputSize ) )

{

c = lpszEncoding[ nIndex++ ];

lBitsStorage <<= 8;

lBitsStorage |= (c & 0xff);

nBitsRemaining += 8;

}

if( nBitsRemaining < nNumBits )

{

lScratch = lBitsStorage << ( nNumBits -nBitsRemaining );

nBits = nBitsRemaining;

nBitsRemaining = 0;

}

else

{

lScratch = lBitsStorage >> (nBitsRemaining - nNumBits );

nBits = nNumBits;

nBitsRemaining -= nNumBits;

}

nDigit = (int)(lScratch &s_nBase64Mask[nNumBits]);

nNumBits = nBits;

if( nNumBits <=0 )

break;

strEncoded += s_strBase64TAB[ nDigit ];

}

// Pad with '=' as per RFC 1521

while( strEncoded.GetLength() % 4 != 0 )

strEncoded += '=';

return strEncoded.GetLength();

}

/************************************************************************

************************************************************************/

CHttpDownload::CHttpDownload():

m_hSocket(INVALID_SOCKET),

m_nResponseHeaderSize(0)

{

memset(m_szRequestHeader, 0,sizeof(m_szRequestHeader));

memset(m_szResponseHeader, 0,sizeof(m_szResponseHeader));

}

CHttpDownload::~CHttpDownload()

{

CloseSocket();

}

bool CHttpDownload::CreateSocket()

{

CloseSocket();

m_hSocket = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);

if (INVALID_SOCKET == m_hSocket)

{

return false;

}

return true;

}

void CHttpDownload::CloseSocket()

{

if (INVALID_SOCKET != m_hSocket )

{

closesocket(m_hSocket);

m_hSocket = INVALID_SOCKET;

}

}

void CHttpDownload::FormatRequestHeader(constchar* pszServer, int nPort, const char* pszObject, const char *pAuthorization/* = NULL */)

{

memset(m_szRequestHeader, '/0', 1024);

//1行:请求的方法,路径,版本

strcat(m_szRequestHeader, "GET ");

strcat(m_szRequestHeader, pszObject);

strcat(m_szRequestHeader, "HTTP/1.0");

strcat(m_szRequestHeader, "/r/n");

//2行:请求的数据类型

strcat(m_szRequestHeader, "Accept:*/*");

strcat(m_szRequestHeader, "/r/n");

//3行:主机,端口

char szPort[10];

sprintf(szPort, ":%d", nPort);

strcat(m_szRequestHeader, "Host: ");

strcat(m_szRequestHeader, pszServer);

strcat(m_szRequestHeader, szPort);

strcat(m_szRequestHeader, "/r/n");

//4行:缓冲控制

strcat(m_szRequestHeader, "Catch-control:no-cache");

strcat(m_szRequestHeader, "/r/n");

//5行:访问权限

if (pAuthorization)

{

CString strAuth;

strcat(m_szRequestHeader, "Authorization:Basic ");

CBase64::Base64Encode(pAuthorization, strAuth);

strcat(m_szRequestHeader, strAuth);

strcat(m_szRequestHeader, "/r/n");

}

//最后一行:空行

strcat(m_szRequestHeader, "/r/n");

}

bool CHttpDownload::SendRequest()

{

int len = strlen(m_szRequestHeader);

//if(send(m_hSocket,m_szRequestHeader,len,0)==SOCKET_ERROR)

//{

// return false;

//}

if (SelectSend(m_szRequestHeader, len,DEFAULT_SENDTIMEOUT) <= 0)

{

return false;

}

if (!GetResponseHeader())

{

return false;

}

return true;

}

bool CHttpDownload::Connect(const char*pszHostIP, int nPort /* DEFAULT_PORT */, long ltimeout /*DEFAULT_CONNECTTIMEOUT*/)

{

ASSERT(pszHostIP);

sockaddr_in addr;

memset( &addr, 0, sizeof(addr));

addr.sin_family = AF_INET;

addr.sin_port = htons(nPort);

addr.sin_addr.S_un.S_addr =inet_addr(pszHostIP);

unsigned long ul = 1;

int ret = ioctlsocket(m_hSocket, FIONBIO,(unsigned long*)&ul);

if( ret == SOCKET_ERROR)

{

return false;

}

connect(m_hSocket, (sockaddr*)&addr,sizeof(addr));

timeval timeout = { 1, ltimeout };

fd_set r;

FD_ZERO(&r);

FD_SET(m_hSocket, &r);

ret = select(0, 0, &r, 0, &timeout);

if( ret <= 0 )

{

return false;

}

//一般非锁定模式套接比较难控制,可以根据实际情况考虑再设回阻塞模式

unsigned long ul1= 0 ;

ret = ioctlsocket(m_hSocket, FIONBIO, (unsignedlong*)&ul1);

if( ret == SOCKET_ERROR)

{

return false;

}

return true;

}

bool CHttpDownload::GetResponseHeader()

{

char c = 0;

bool bEndResponse = false;

int nIndex = 0;

int ret;

while(!bEndResponse && nIndex <1024)

{

ret =SelectRecv(&m_szResponseHeader[nIndex++], 1);

if (ret <= 0)

return false;

if(nIndex >= 4)

{

if(m_szResponseHeader[nIndex - 4] == '/r'&& m_szResponseHeader[nIndex - 3] == '/n'

&& m_szResponseHeader[nIndex - 2] =='/r' && m_szResponseHeader[nIndex - 1] == '/n')

bEndResponse = true;

}

}

m_nResponseHeaderSize = nIndex;

return true;

}

int CHttpDownload::GetServerInfo(DWORD&dwContentLength, DWORD &dwStatusCode) const

{

if (0 == m_nResponseHeaderSize)

{

dwContentLength = -1;

dwStatusCode = -1;

return -1;

}

char szState[3];

szState[0] = m_szResponseHeader[9];

szState[1] = m_szResponseHeader[10];

szState[2] = m_szResponseHeader[11];

dwStatusCode = (DWORD)_ttol(szState);

//获取ContentLength

CString strResponseHeader = m_szResponseHeader;

int nPos =strResponseHeader.Find("Content-length:");

if (nPos == -1)

return -1;

CString strDownFileLen =strResponseHeader.Mid(nPos + strlen("Content-length:"));

nPos = strDownFileLen.Find("/r/n");

if (nPos == -1)

return -1;

strDownFileLen = strDownFileLen.Left(nPos);

strDownFileLen.TrimLeft();

strDownFileLen.TrimRight();

// Content-Length:

dwContentLength = (DWORD) _ttol((LPCTSTR)strDownFileLen );

return 0;

}

int CHttpDownload::SelectSend(char *pData, intlen, long timeout /* = DEFAULT_RECVTIMEOUT */)

{

fd_set writefds;

FD_ZERO(&writefds);

FD_SET(m_hSocket, &writefds);

timeval tv = { timeout, 0 };

int ret = select(0, NULL, &writefds, NULL,&tv);

if ( ret == 0 || ret == SOCKET_ERROR)

{

return 0;

}

if (FD_ISSET(m_hSocket, &writefds) == 0)

return 0;

ret = send(m_hSocket, pData, len, 0);

if (ret == SOCKET_ERROR)

{

// DWORD dwError = WSAGetLastError();

return 0;

}

else if (ret == 0)

{

return 0;

}

return ret;

}

int CHttpDownload::SelectRecv(char *pData, intlen, long timeout)

{

fd_set readfds;

FD_ZERO(&readfds);

FD_SET(m_hSocket, &readfds);

timeval tv = { timeout, 0 };

int ret = select(0, &readfds, NULL, NULL,&tv);

if ( ret == 0 || ret == SOCKET_ERROR)

{

return 0;

}

if (FD_ISSET(m_hSocket, &readfds) == 0)

return 0;

ret = recv(m_hSocket, pData, len, 0);

if (ret == SOCKET_ERROR)

{

// DWORD dwError = WSAGetLastError();

return 0;

}

else if (ret == 0)

{

return 0;

}

return ret;

}

/************************************************************************

下载历史事件告警记录文件

http://172.16.0.108/histevent.xml

************************************************************************/

bool CHttpDownload::Download(LPCTSTR lpszDownloadUrl,LPCTSTR lpszSavePath)

{

int nPort;

CString strService, strObject;

if (!ParseURL(lpszDownloadUrl, strService,strObject, nPort))

{

return false;

}

if (!CreateSocket())

return false;

if (!Connect(strService, nPort))

return false;

FormatRequestHeader(strService, nPort,strObject);

if (!SendRequest())

return false;

DWORD dwFileLen, dwStatuCode;

if (-1 == GetServerInfo(dwFileLen,dwStatuCode))

{

return false;

}

CFile filedown;

if (!filedown.Open(lpszSavePath,CFile::modeCreate|CFile::modeWrite))

{

return false;

}

DWORD dwTotalBytes = 0;

char szdata[2048] = { 0 };

while (dwTotalBytes < dwFileLen)

{

int nRecvBytes = SelectRecv(szdata, 2048);

if (nRecvBytes <= 0 )

{

break;

}

filedown.Write(szdata, nRecvBytes);

dwTotalBytes += nRecvBytes;

}

CloseSocket();

filedown.Close();

if (dwTotalBytes < dwFileLen)

{

try

{

CFile::Remove(lpszSavePath);

}

catch (CFileException* e)

{

e->Delete();

}

return false;

}

return true;

}

73.FTP下载

CFtpGet::CFtpGet()

{

// get the name of the app

strAppName.LoadString(AFX_IDS_APP_TITLE);

// create an internet session

pInternetSession = newCInternetSession(strAppName,

INTERNET_OPEN_TYPE_PRECONFIG);

// if Not good, show message + return

// should never failed anyway

if(!pInternetSession)

{

AfxMessageBox("Can't start internetsession");

return;

}

}

CFtpGet::~CFtpGet()

{

// close the internet session

pInternetSession->Close();

// delete the session

if(pInternetSession != NULL)

delete pInternetSession;

}

// function, in logical order

bool CFtpGet::SetAccessRight(CString userName,

 CStringuserPass)

{

// simply get username and password

strPass = userPass;

strUser = userName;

if( (strPass == "") || (strUser ==""))

return 0;

return 1;

}

bool CFtpGet::OpenConnection(CString server)

{

if(server == "")

return 0;

// put the server name in the CFtpGet class

strServerName = server;

try {

// try to connect to a ftp server

pFtpConnection =pInternetSession->GetFtpConnection(strServerName,

strUser,

strPass);

} catch (CInternetException* pEx)

{

// if failed, just show the error

// Oops! We failed to connect!

TCHAR szErr[1024];

pEx->GetErrorMessage(szErr, 1024);

TRACE(szErr);

AfxMessageBox(szErr);

pEx->Delete();

return 0;// return 1 but previous error boxhave been showed

}

return 1;

}

bool CFtpGet::GetFile(CString remoteFile,

 CStringlocalFile)

{

// Try to get the file

BOOL bGotFile =pFtpConnection->GetFile(remoteFile,

localFile,

FALSE,

FILE_ATTRIBUTE_NORMAL,

FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD| INTERNET_FLAG_NO_CACHE_WRITE);

return bGotFile ? 1 : 0 ;

// if bGotFile is 0 ( FALSE ), return 0

// if bGotFile is 1 ( TRUE ), return 1

}

int CFtpGet::GetMultipleFile(CStringArray*remoteArray,

 CStringArray *localArray,

 intnumber_file)

{

// init some var

BOOL goodfile;

int x=0;

int nb_lost_file =0;

// while loop to transfer every file in thearray

while(x<number_file)

{

// try to get file

goodfile =pFtpConnection->GetFile(remoteArray->GetAt(x),

localArray->GetAt(x),

FALSE,

FILE_ATTRIBUTE_NORMAL,

FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD| INTERNET_FLAG_NO_CACHE_WRITE);

missed[x] = goodfile ? 0 : 1;

// if failed, missed[x] become 1

// if good, missed become 0

if(missed[x])

nb_lost_file++;

// if the file was missed, increase the numberof

// missing file.

// increase to the next file

x++;

}

//return the number of missing file, if any.

return nb_lost_file;

}

bool CFtpGet::CloseConnection()

{

// close the connection to server, you canreconnect latter

if(pFtpConnection == NULL)

return 0;

try{

pFtpConnection->Close();

}catch(...)

{

return 0;

}

if(pFtpConnection != NULL)

delete pFtpConnection;

return 1;

}

int CAddFile::DoModal()

{

// TODO: Add your specialized code here and/orcall the base class

 

return CDialog::DoModal();

}

void CAddFile::OnCancel()

{

// TODO: Add extra cleanup here

strNewFile = "";

CDialog::OnCancel();

}

void CAddFile::OnOK()

{

// TODO: Add extra validation here

m_new_file.GetWindowText(strNewFile);

CDialog::OnOK();

}

void CAddFile::OnBnClickedOk()

{

// TODO:在此添加控件通知处理程序代码

OnOK();

}

m_folder.SetWindowText("c://download//");

void CHttpDlg::OnNewVer() //Get These filebutton

{

CString folder;

CString user;

CString pass;

CString server;

// CString program_name;

CString tempRemote;

CString tempLocal;

// error

CString Error;

// get folder

m_folder.GetWindowText(folder);

// Get username, password, server

m_user.GetWindowText(user);

m_pass.GetWindowText(pass);

m_server.GetWindowText(server);

// get every file name in the box

// make 2 CStringArray, one for remote, theother for local

CStringArray remote;

CStringArray local;

for(int x=0;x<m_file.GetCount();x++)

{

m_file.GetText(x,tempRemote);

remote.Add(tempRemote);

tempLocal = folder + tempRemote;

local.Add(tempLocal);

}

// open CFtpGet class

CFtpGet ftpget;

// SetRight

ftpget.SetAccessRight(user,pass);

// open server

bool conectOK;

conectOK = ftpget.OpenConnection(server);

// transfer multiple file

if(conectOK)

{

ftpget.GetMultipleFile(&remote,&local,m_file.GetCount());

}

else

memset(ftpget.missed,0,sizeof(bool[100]));

// verify which file, if any, have not beentransfered

for(inttest=0;test<m_file.GetCount();test++)

{

if(ftpget.missed[test])

{

m_file.GetText(test,Error);

Error = "The file " + Error;

Error += " is missing!";

AfxMessageBox(Error);

}

}

// close connection

ftpget.CloseConnection();

// quit this function

}

void CHttpDlg::OnAdd() // Add button

{

// TODO: Add your control notification handlercode here

CAddFile add;

int ret = add.DoModal();

int lng = 0;

CString newfile;

if(ret == IDOK)

{

// get m_new_file lenght

lng = add.strNewFile.GetLength();

// if OK put in list

if(lng == 0 )// no input

return;

m_file.AddString(add.strNewFile);

}

 

}

void CHttpDlg::OnDel() // delete button

{

// TODO: Add your control notification handlercode here

int selection=0;

selection = m_file.GetCurSel();

// now i get the good one

if(selection <0)

{

AfxMessageBox("You have to select a valuein the file list");

return;

}

m_file.DeleteString(selection);

// no more in the dialog

 

}

void CHttpDlg::OnAnon() // anonymous checkbutton

{

// TODO: Add your control notification handlercode here

int check = m_anon.GetCheck();

if(check == 1)

{

// store some info in mem

m_user.GetWindowText(cOldUser,99);

m_pass.GetWindowText(cOldPass,99);

// set new value

m_user.SetWindowText("anonymous");

m_pass.SetWindowText("your@email.com");

m_pass_email.SetWindowText("Youremail");

// you can't edit anonymous

m_user.SetReadOnly(TRUE);

}else

{

// set the old value ( if any )

m_user.SetWindowText(cOldUser);

m_pass.SetWindowText(cOldPass);

m_pass_email.SetWindowText("Password");

// you have to edit the user name.

m_user.SetReadOnly(FALSE);

}

 

}

74.写图像到剪切板 setClipboardImage

CBitmap *pOldBitmap,NewBitmap;

CDC* pt;

pt=CDC::FromHandle(::GetDC(NULL));

NewBitmap.CreateCompatibleBitmap(pt,m_RectCopyCut.Width(),m_RectCopyCut.Height());

CDC dc;

dc.CreateCompatibleDC(NULL);

pOldBitmap=dc.SelectObject(&NewBitmap);

dc.FillRect(m_RectCopyCut, CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)));dc.BitBlt(0,0,m_RectCopyCut.Width(),m_RectCopyCut.Height(),

&m_dcMemory,m_RectCopyCut.left+m_nHPos,m_RectCopyCut.top+m_nVPos,SRCCOPY); HANDLE handle=DDBToDIB(NewBitmap,BI_RGB,NULL);if(!OpenClipboard())

return;

EmptyClipboard();

SetClipboardData(CF_DIB,handle);

CloseClipboard();

ReleaseDC(pt);

dc.SelectObject(pOldBitmap);

75.从剪贴板复制图像到窗体

76.删除文件夹下的所有文件且不删除文件夹下的文件夹

/

// char dir[] = "d://test//";

// DeleteAnyFiles(dir);

/

void DeleteAnyFiles(const char *dir)

{

WIN32_FIND_DATA finder;

HANDLE hFileFind;

char search[MAX_PATH];

strcpy(search, dir);

strcat(search, "*.*");

hFileFind = FindFirstFile(search, &finder);

if (hFileFind != INVALID_HANDLE_VALUE)

{

do

{

char path[MAX_PATH];

strcpy(path, dir);

strcat(path, finder.cFileName);

if (!(finder.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY))

DeleteFile(path);

} while (FindNextFile(hFileFind, &finder)!= 0);

FindClose(hFileFind);

}

}

int nRetCode = 0;

// initialize MFC and print and error onfailure

if (!AfxWinInit(::GetModuleHandle(NULL), NULL,::GetCommandLine(), 0))

{

// TODO: change error code to suit your needs

cerr << _T("Fatal Error: MFCinitialization failed") << endl;

nRetCode = 1;

}

else

{

CString strHello;

strHello.LoadString(IDS_HELLO);

cout << (LPCTSTR)strHello << endl;

}

/*测试目录为d://test//,可以随意改变,但目录分割符必须是// */

char dir[] = "d://test//";

DeleteAnyFiles(dir);

return nRetCode;

77.XML遍历结点属性值

78.拷贝文件名复制文件

#include "stdafx.h"

#include "fdg.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR*envp[])

{

int nRetCode = 0;

 

// initialize MFC and print and error onfailure

if (!AfxWinInit(::GetModuleHandle(NULL), NULL,::GetCommandLine(), 0))

{

// TODO: change error code to suit your needs

cerr << _T("Fatal Error: MFCinitialization failed") << endl;

nRetCode = 1;

}

else

{

//判断剪贴板的数据格式是否可以处理

if(!IsClipboardFormatAvailable(CF_UNICODETEXT))

{

return -1;

}

//打开剪贴板

if (!OpenClipboard(NULL))

{

return -1;

}

//获取UNICODE的数据

CString str;

CString path;

HGLOBAL hMem = GetClipboardData(CF_TEXT);//CF_UNICODETEXT

if (hMem != NULL)

{

//获取UNICODE的字符串

LPTSTR lpStr = (LPTSTR)GlobalLock(hMem);

if (lpStr != NULL)

{

//显示输出

OutputDebugString(lpStr);

//释放锁内存

GlobalUnlock(hMem);

}

str=lpStr;

path=lpStr;

}

//关闭剪贴板。

CloseClipboard();

CStringpathname="C://"+path.Mid(path.ReverseFind('//')+1);

CopyFile(str,pathname,true);

}

return nRetCode;

}

79.开源程序库Xercesc-C++代码工程中内联

#include "stdafx.h"

#include "InlineXercesc.h"

#include <list>

#include <queue>

#include <string>

#include <boost/regex.hpp>

#include <shlwapi.h>

#pragma comment( lib, "shlwapi.lib")

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

CWinApp theApp;

using namespace std;

typedef list<CString,allocator<string> > tagSTRING;

typedef queue<CString, tagSTRING> STRING;

STRING fal,fal2;

CStringArray all;

CString filter = ".cpp";

void doSearch(CString path)

{

if(PathFileExists(path))

{

CFileFind ff;

CString szDir = path;

if(szDir.Right(1) != "//")

szDir += "//";

szDir += "*.*";

BOOL res = ff.FindFile(szDir);

while(res)

{

res = ff.FindNextFile();

if(ff.IsDirectory() && !ff.IsDots())//目录是文件夹

{

//如果是一个子目录,用递归继续往深一层找

doSearch(ff.GetFilePath());//递归调用

}

else if(!ff.IsDots())

{

//显示当前访问的文件

CString strPath = ff.GetFileName();

if (strPath.Find(filter) > 0) {

for (intifile=0;ifile<all.GetSize();ifile++) {

CString file=all.GetAt(ifile);

if (file.Mid(file.ReverseFind('//') +1)==strPath) {

fal2.push(ff.GetFilePath());

}

}

}

}

}

ff.Close();//关闭

}

}

int _tmain(int argc, TCHAR* argv[], TCHAR*envp[])

{

int nRetCode = 0;

if (!AfxWinInit(::GetModuleHandle(NULL), NULL,::GetCommandLine(), 0))

{

cerr << _T("Fatal Error: MFCinitialization failed") << endl;

nRetCode = 1;

}

else

{

CString lib="xercesc";

CString regex;

regex.Format("include.*?%s.*?>",lib);

boost::regex reg(regex.GetBuffer(0));

boost::smatch m;

CString SourceLib="C://xercesc";

TCHAR szDir[MAX_PATH];

CString szDirPath;

GetCurrentDirectory(MAX_PATH,szDir);

szDirPath.Format("%s//*.*",szDir);

CString CurDir(szDir);

CFileFind finder;

BOOL bWorking = finder.FindFile(szDirPath);

while (bWorking)

{

bWorking = finder.FindNextFile();

if(finder.IsDirectory() &&!finder.IsDots()){

CString enumDir = CurDir + "//" +finder.GetFileName() + "//";

//枚举一个文件夹中的所有文件夹

CFileFind finder2;

CString szDirPath2;

szDirPath2.Format("%s//*.*",finder.GetFileName());

BOOL bWorking2 = finder2.FindFile(szDirPath2);

while (bWorking) {

bWorking2 = finder2.FindNextFile();

if(!finder2.IsDirectory() &&!finder2.IsDots())

{

CStdioFile f_sfile;

CString lcs_FileName=finder2.GetFilePath();

if(f_sfile.Open(lcs_FileName,CFile::modeRead))

{

//逐行读取

CString sb;

CString lcs_FileContent;

int li_line = 0;

long ll_LineCount = 0;

while(f_sfile.ReadString(lcs_FileContent))

{

li_line++;

//读取第li_line行数据: lcs_FileContent

string s(lcs_FileContent.GetBuffer(0));

string::const_iterator it=s.begin();

string::const_iterator end=s.end();

if(boost::regex_serach(it,end,m,reg) &&m[1].matched)

{

//it=m[0].second;

int pos=s.find_last_of("/")+1;

s=s.substr(pos,s.find_first_of(">"));

fal.push(CString(s.c_str()));

sb+="#include /"";

sb+=s.c_str();

sb+="/"";

}

else

sb+=lcs_FileContent;

sb+="/r/n";

}

f_sfile.Close();

CFile mFile(_T(lcs_FileName),CFile::modeWrite);

mFile.Write(sb.GetBuffer(0),sizeof(sb.GetBuffer(0)));

mFile.Flush();

mFile.Close();

f_sfile.Close();

}

}

}

finder2.Close();

while(fal.size()>0)

{

CString file(fal.front());

fal.pop();

CString targetPath= enumDir

+ file.Mid(file.ReverseFind('//') + 1);

if(!PathFileExists(targetPath))

{

CStdioFile f_sfile;

CString lcs_FileName=finder2.GetFilePath();

if(f_sfile.Open(lcs_FileName,CFile::modeRead))

{

CFile mFile(_T(targetPath), CFile::modeCreate|CFile::modeWrite);

CString lcs_FileContent;

int li_line = 0;

long ll_LineCount = 0;

while(f_sfile.ReadString(lcs_FileContent))

{

li_line++;

//读取第li_line行数据: lcs_FileContent

string s(lcs_FileContent.GetBuffer(0));

string::const_iterator it=s.begin();

string::const_iterator end=s.end();

if(boost::regex_serach(it,end,m,reg) &&m[1].matched)

{

//it=m[0].second;

int pos=s.find_last_of("/")+1;

s=s.substr(pos,s.find_first_of(">"));

fal.push(CString(s.c_str()));

mFile.Write("#include/"",sizeof("#include /""));

mFile.Write(s.c_str(),sizeof(s.c_str()));

mFile.Write("/"",sizeof("/""));

}

else

mFile.Write(lcs_FileContent,sizeof(lcs_FileContent));

mFile.Write("/r/n",sizeof("/r/n"));

}

mFile.Flush();

mFile.Close();

}

}

}

CFileFind finder3;

bWorking2 = finder3.FindFile(szDirPath2);

while (bWorking) {

bWorking2 = finder3.FindNextFile();

if(!finder3.IsDirectory() &&!finder3.IsDots()){

CString path=finder3.GetFilePath();

if(path.Mid(path.ReverseFind('.'))==".hpp")

{

path.Replace(".hpp",".cpp");

all.Add(path);

}

}

}

finder3.Close();

int count = 1;

while (count > 0) {

doSearch(SourceLib);

all.RemoveAll();

while(fal2.size()>0)

{

CString file1 = fal2.front();

CString targetPath = enumDir+file1.Mid(file1.ReverseFind('//') + 1);

if(!PathFileExists(targetPath))

{

CString lcs_FileName=finder2.GetFilePath()+"//ReadMe.txt";

CStdioFile f_sfile;

if(f_sfile.Open(lcs_FileName,CFile::modeRead))

{

CFile mFile(_T(targetPath),CFile::modeCreate|CFile::modeWrite);

//逐行读取

CString lcs_FileContent;

int li_line = 0;

long ll_LineCount = 0;

while(f_sfile.ReadString(lcs_FileContent))

{

li_line++;

//读取第li_line行数据: lcs_FileContent

string s(lcs_FileContent.GetBuffer(0));

string::const_iterator it=s.begin();

string::const_iterator end=s.end();

if(boost::regex_serach(it,end,m,reg) &&m[1].matched)

{

//it=m[0].second;

int pos=s.find_last_of("/")+1;

s=s.substr(pos,s.find_first_of(">"));

fal2.push(CString(s.c_str()));

all(fal2.back().Replace(".hpp",".cpp"));

mFile.Write("#include/"",sizeof("#include /""));

mFile.Write(s.c_str(),sizeof(s.c_str()));

mFile.Write("/"",sizeof("/""));

}

else

mFile.Write(lcs_FileContent,sizeof(lcs_FileContent));

mFile.Write("/r/n",sizeof("/r/n"));

mFile.Flush();

mFile.Close();

}

}

}

}

}

}

}

finder.Close();

}

return nRetCode;

}

80.提取包含头文件列表

#include <boost/regex.hpp>

CString regex;

regex.Format("include.*?%s.*?>",lib);

boost::regex reg(regex.GetBuffer(0));

boost::smatch m;

TCHAR szDir[MAX_PATH];

GetCurrentDirectory(MAX_PATH,szDir);

CString CurDir;

CurDir.Format("%s//*.*",szDir);

CFileFind finder;

BOOL bWorking = finder.FindFile(CurDir);

while(bWorking)

{

bWorking = finder.FindNextFile();

if (finder.IsDirectory() &&!finder.IsDots())

{

CStringlcs_FileName=finder.GetFilePath()+"//StdAfx.cpp";

CStdioFile f_sfile;

//逐行读取

CString lcs_FileContent;

int li_line = 0;

long ll_LineCount = 0;

while(f_sfile.ReadString(lcs_FileContent))

{

li_line++;

//读取第li_line行数据: string s(lcs_FileContent.GetBuffer(0));

string::const_iterator it=s.begin();

string::const_iterator end=s.end();

if(boost::regex_serach(it,end,m,reg) &&m[1].matched)

{

//it=m[0].second;

int pos=s.find_last_of("/")+1;

s=s.substr(pos,s.find_first_of(">"));

fal2.push(CString(s.c_str()));

}

}

CString targetPath =finder.GetFilePath()+"//ReadMe.txt";

CFilemFile(_T(targetPath),CFile::modeCreate|CFile::modeWrite);

mFile.Write("#include /"",sizeof("#include/""));

mFile.Write(s.c_str(),sizeof(s.c_str()));

mFile.Write("/"",sizeof("/""));

mFile.Write("/r/n",sizeof("/r/n"));

mFile.Flush();

mFile.Close();

}

81.剪贴扳转换成打印字符

#include "stdafx.h"

#include "%%0.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR*envp[])

{

int nRetCode = 0;

if (!AfxWinInit(::GetModuleHandle(NULL), NULL,::GetCommandLine(), 0))

{

cerr << _T("Fatal Error: MFCinitialization failed") << endl;

nRetCode = 1;

}

else

{

//判断剪贴板的数据格式是否可以处理

if(!IsClipboardFormatAvailable(CF_UNICODETEXT))

{

return 0;

}

//打开剪贴板

if (!OpenClipboard(NULL))

{

return 0;

}

//获取UNICODE的数据

CString s;

HGLOBAL hMem = GetClipboardData(CF_TEXT);

if (hMem != NULL)

{

//获取UNICODE的字符串

LPTSTR lpStr = (LPTSTR)GlobalLock(hMem);

if (lpStr != NULL)

{

//显示输出

OutputDebugString(lpStr);

//释放锁内存

GlobalUnlock(hMem);

}

s=lpStr;

CString sub;

CString sb;

int pos;

char seperator = '/n';

for (pos = 0; AfxExtractSubString(sub, s, pos,seperator); ++pos)

{

if(sub.Trim()!="")

{

sub.Replace("^", "^^");

sub.Replace("&","^&");

sub.Replace(":", "^:");

sub.Replace(">","^>");

sub.Replace("<","^<");

sub.Replace("|", "^|");

sub.Replace("/"","^/"");

sub.Replace("//", "");

sub.Replace("/"","///"");

sb+=("w.WriteLine(/"ECHO " +sub+ "/");/r/n");

}

}

char *pMem;

hMem = GlobalAlloc( GHND | GMEM_DDESHARE,strlen(sb)+1);

if(hMem)

{

pMem = (char*)GlobalLock(hMem);

strcpy(pMem,sb);

GlobalUnlock(hMem);

EmptyClipboard();

SetClipboardData(CF_TEXT,hMem);

}

CloseClipboard();

}

}

return nRetCode;

}

82.JButtonJTree组件写到一个流中

83.注册全局热键

/*

BOOL RegisterHotKey(

HWND hWnd . //指定接收WM_HOTKEY消息的窗体句柄

int id. //热键标识.同一调用线程内的不同热键标识不能相同.应用程序中的标识值在0x00000xbfff之间.DLL中的在0xc0000xffff之间

UINT fsModifiers.//下列值的组合:MOD_ALT.MOD_CONTROL.MOD_SHIFT.MOD_WIN.MOD_KEYUP

UINT vk //按键的虚拟码

),

*/

//在初始化的时候注册:

RegisterHotKey(m_hWnd.1688.MOD_SHIFT|MOD_CONTROL

84.菜单勾选/取消完成后关闭计算机

//使此进程获取:关机权限

HANDLE hToken;

LUID luid;

TOKEN_PRIVILEGES tp;

//获取此进程的令牌

::OpenProcessToken(::GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken);

//查询权限值:获取权限的唯一标识值

::LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&luid);

tp.PrivilegeCount = 1;

tp.Privileges[0].Luid = luid;

tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;

//调整令牌权限

::AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL);

::ExitWindowsEx(EWX_SHUTDOWN,0);

85.菜单勾选/取消完成后重新启动计算机

//使此进程获取:关机权限

HANDLE hToken;

LUID luid;

TOKEN_PRIVILEGES tp;

//获取此进程的令牌

::OpenProcessToken(::GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken);

//查询权限值:获取权限的唯一标识值

::LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&luid);

tp.PrivilegeCount = 1;

tp.Privileges[0].Luid = luid;

tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;

//调整令牌权限

::AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL);

::ExitWindowsEx(EWX_REBOOT,0);

86.菜单勾选/取消完成后注销计算机

//使此进程获取:关机权限

HANDLE hToken;

LUID luid;

TOKEN_PRIVILEGES tp;

//获取此进程的令牌

::OpenProcessToken(::GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken);

//查询权限值:获取权限的唯一标识值

::LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&luid);

tp.PrivilegeCount = 1;

tp.Privileges[0].Luid = luid;

tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;

//调整令牌权限

::AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL);

::ExitWindowsEx(EWX_LOGOFF,0);

87.菜单勾选/取消开机自启动程序

::OnSetMusic()

{

// TODO: Add your command handler code here

/*CMenu *menu1,*menu2;

menu2=menu1.GetSubMenu(1);

menu2.GetMenuItemID(3); */

if(GetCheck()==FALSE)

{

SetCheck();

sndPlaySound("D://oscillograph//res//天路(钢琴伴奏).wav",SND_LOOP);

}

else

{

sndPlaySound("D://oscillograph//res//天路(钢琴伴奏).wav",NULL);

}

}

/

TCHAR m_fileName[100];

GetModuleFileName(NULL,m_fileName,100);

HKEY hKey;

CString str =_T("Software//Microsoft//Windows//CurrentVersion//Run");

if (ERROR_SUCCESS !=RegCreateKey(HKEY_LOCAL_MACHINE, str, &hKey))

{

AfxMessageBox("打开注册表项失败");

RegCloseKey(hKey);

return;

}

int length = 0;

while(m_fileName[length]!=_T('/0'))

length++;

if (ERROR_SUCCESS != RegSetValueEx(hKey,_T(%%1), 0, REG_SZ, (const BYTE *)m_fileName, sizeof(TCHAR)*length))

{

AfxMessageBox("写注册表失败");

}

RegCloseKey(hKey);

88.菜单勾选/取消自动登录系统

89.模拟键盘输入字符串

CString str=%%1;

DWORD sc,shift;

unsigned char vkey;

char a;

for (int i=0;i<str.GetLength();i++)

{

a=str.GetAt(i);

sc=OemKeyScan(a);

shift=sc>>16;

vkey=MapVirtualKey(sc&0xffff,1);

if (shift)

keybd_event(VK_SHIFT,0,0,0);

keybd_event(vkey,0,0,0);

keybd_event(vkey,0,KEYEVENTF_KEYUP,0);

if (shift)

keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP,0);

}

90.提取PDF文件中的文本

try

{

int iFont;

PDFlib pPDF;

CFileDialogm_FileDlg(FALSE,"pdf","",OFN_OVERWRITEPROMPT,"AdobeAcrobat PDF文件(*.pdf)|*.pdf|所有文件(*.*)|*.*||",this);

char pFileName[255];

CEdit*pPDFText=(CEdit*)GetDlgItem(IDC_EDITPDF);

CString strPDFText;

pPDFText->GetWindowText(strPDFText);

char pPDFInfo[1024];

sprintf(pPDFInfo,"%s",strPDFText);

char pAttachFileName[255];

sprintf(pAttachFileName,"%s",m_AttachFileName);

if(m_FileDlg.DoModal()==IDOK)

{

m_PDFFileName=m_FileDlg.GetFileName();

sprintf(pFileName,m_PDFFileName);

if(pPDF.open_file(pFileName)==-1)

{

//

}

pPDF.set_parameter("hypertextencoding","host");

pPDF.set_info("Creator","DigitalSky");

pPDF.set_info("Author","DigitalTitan");

pPDF.set_info("Title","Title");

pPDF.begin_page((float)a4_width,(float)a4_height);

iFont=pPDF.load_font("Helvetica-Bold","host","");

pPDF.setfont(iFont,12);

pPDF.set_text_pos(50,a4_height-50);

pPDF.setcolor("fill","rgb",0,0,1,0);

pPDF.show("Version 1.0 (C) CopyRight ByDigitaltitan");

iFont=pPDF.findfont("STSong-Light","GB-EUC-H",0);

pPDF.setcolor("fill","rgb",0,0,0,0);

pPDF.setfont(iFont,24);

pPDF.continue_text("转换文档生成为");

pPDF.setcolor("stroke","rgb",0.24f,0.51f,0.047f,0);

pPDF.moveto(50,a4_height-80);

pPDF.lineto(a4_width-50,a4_height-80);

pPDF.moveto(50,a4_height-78);

pPDF.lineto(a4_width-50,a4_height-78);

pPDF.stroke();

pPDF.attach_file(a4_width-50,0,0,a4_height-90,pAttachFileName,"DigitalSky","DigitalTitan","doc","paperclip");

pPDF.set_text_pos(50,a4_height-100);

iFont=pPDF.findfont("STSong-Light","GB-EUC-H",0);

pPDF.setcolor("fill","rgb",0,0,0,0);

pPDF.setfont(iFont,12);

pPDF.continue_text(pPDFInfo);

//Word文件如何导入?

pPDF.end_page();

pPDF.close();

}

}

catch(PDFlib::Exception &ex)

{

//

}

下载免费开发包http://partners.adobe.com/asn/acrobat/sdk/fdftk/FDFToolkitForWindows.zip

PDF SDK有一个例子--AddImage,该例子生产一个dll,放在Acrobat的安装目录下,然后启动Acrobat,就看到多了一个菜单项AddImage,就可以调用AddImage了。我的问题是:如何不生成dllAcrobat调用,而是直接运行AddImage的功能?

91.操作内存映射文件

91.1发送内存映射数据

HANDLE hFileMapping;

LPSTR pData;

hFileMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,0x100,%%1);//"MyShare"

if(hFileMapping==NULL)

{

//文件映射至内存失败!

return -1;

}

pData=(LPSTR)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,0,0,0);

if(pData==NULL)

{

//文件试镜像到进程地址空间失败!

return -1;

}

sprintf(pData,%%2);

UnmapViewOfFile(pData);

91.2接收内存映射数据

HANDLE hFileMapping;

LPSTR pData;

hFileMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,0x100,%%1);//"MyShare"

if(hFileMapping==NULL)

{

//文件映射至内存失败!

return -1;

}

pData=(LPSTR)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,0,0,0);

if(pData==NULL)

{

//文件试镜像到进程地址空间失败!

return -1;

}

CString %%2;

%%2.Format("%s",pData);

UnmapViewOfFile(pData);

92.重定向windows控制台程序的输出信息

STARTUPINFO si;

PROCESS_INFOMATION pi;

SECURITY_ATTRIBUTES sa;

HANDLEhRead_OutPipe,hWrite_OutPipe,hRead_InPipe,hWrite_InPipe;

sa.mLength=sizeof(SECURITY_ATTRIBUTES);

sa.lpSecurityDescriptor=NULL;

sa.bInheritHandle=TRUE;

ZeroMemory(&pi,sizeof(pi));

ZeroMemory(&si,sizeof(si));

GetStartipInfo(&si);

si.cb=sizeof(si);

si.dwFlags=STARTF_USESTDHANDLES|STARTF_USERSHOWWINDOW;

si.hStdOutput=hWrite_OutPipe;

si.hStdError=hWrite_OutPipe;

si.hStdInput=hWrite_InPipe;

si.wShowWindow=SW_HIDE;

if(!CreateProcess(NULL,%%1,NULL,NULL,TRUE,0,NULL,NULL,&si,&pi)){

//创建进程失败

return -1;

}

if(!CreateProcess(&hRead_OutPipe,&hWrite_OutPipe,&sa,0)){

//创建进程失败

return -1;

}

if(!CreateProcess(&hRead_InPipe,&hWrite_InPipe,&sa,0)){

//创建进程失败

return -1;

}

si.hStdOutput=hWrite_OutPipe;

si.hStdError=hWrite_OutPipe;

si.hStdInput=hWrite_InPipe;

char buf[4096];

DWORD readlen=0;

CString %%2;

%%2+="/r/n";

DWORD dwWritten=0;

WriteFile(hWrite_InPipe,%%2,%%2.GetLength(),&dwWritten,0);

CString %%3;

BOOL read_ret=TRUE;

while(read_ret=TRUE)

{

memset(buf,'/0',sizeof(buf));

read_ret=ReadFile(hRead_OutPipe,buf,sizeof(buf),&readlen,NULL);

CString buffer(buf);

%%3+=buffer;

}

93.接受邮件

Visual C++编写电子邮件程序

94.发送邮件

一、概述

----本文主要讲述如何使用Visual C++MAPI编写E-mail程序。MAPI是包含在

Windows之中的,因此不需要安装其他额外的部件。MAPI有以下三种形式:

SMAPISimple MAPI,简单的MAPI

CMCCommon Messaging Calls,一般通讯调用

完整的MAPI

---- SMAPICMC都包含在完整的MAPI中,当用户想执行一些高级操作,比如

编写自己的E-mail服务器的时候,必须使用完整的MAPI。本文主要阐述如何编

写能够收发电子邮件的程序,因此使用SMAPI就足够了。

二、编写电子邮件程序

3-1初始化MAPI

----要使用MAPI,必须首先对它进行初始化。初始化包括以下三个步骤:

装载MAPI32.DLL动态链接库

找到想要调用的MAPI函数地址

登录到电子邮件对象

3-1-1装载MAPI32.DLL

----要装载MAPI,用户必须程序运行时动态的装载一个动态链接库。LoadLibrary

函数提供了此功能,它定位一个动态链接库,并返回HINSTANCE局柄(需要保存该句柄)。

LoadLibrary的语法如下:

LoadLibrary ( lpLibFileName );

其中lpLibFileNameLPCTSTR结构变量,

是所要调用的库的路径和名称。

程序示例:

//调用MAPI32.DLL并计算函数地址

HINSTANCE hInstMail;

hInstMail = ::LoadLibrary (MAPI32.DLL );

if ( hInstMail == NULL )

{

//错误处理

//受篇幅限制,下面的错误处理部分省略

}

3-1-2确定函数地址

----由于MAPI32.DLL是被动态装载的,因此不知道所要调用的函数地址,

也就不能一开始就调用它们,而要通过函数名获得函数的地址,并在动态链

接库中查找每一个函数并核实。因此首先必须为这些函数声明指针

程序示例:

//MAPI32.DLL中的函数声明函数指针

ULONG (PASCAL *lpfnMAPISendMail) (LHANDLElhSession,

ULONG ulUIParam, lpMapiMessage lpMessage,

FLAGS flFlags, ULONG ulReserved);

ULONG (PASCAL *lpfnMAPIResolveName) (LHANDLElhSession,

ULONG ulUIParam, LPTSTR lpszName,

FLAGS ulFlags, ULONG ulReserved,

lpMapiRecipDesc FAR *lppRecip);

ULONG (FAR PASCAL *lpfnMAPILogon)(ULONGulUIParam,

LPSTR lpszProfileName, LPSTR lpszPassword,

FLAGS flFlags, ULONG ulReserved,

LPLHANDLE lplhSession);

ULONG (FAR PASCAL *lpfnMAPILogoff)(LHANDLElhSession,

ULONG ulUIParam, FLAGS flFlags,

ULONG ulReserved);

ULONG (FAR PASCAL *lpfnMAPIFreeBuffer)(LPVOIDlpBuffer);

ULONG (FAR PASCAL *lpfnMAPIAddress)(LHANDLElhSession,

ULONG ulUIParam, LPSTR lpszCaption,

ULONG nEditFields, LPSTR lpszLabels,

ULONG nRecips, lpMapiRecipDesc lpRecips,

FLAGS flFlags, ULONG ulReserved,

LPULONG lpnNewRecips,

lpMapiRecipDesc FAR *lppNewRecips);

ULONG (FAR PASCAL *lpfnMAPIFindNext)(LHANDLElhSession,

ULONG ulUIParam, LPSTR lpszMessageType,

LPSTR lpszSeedMessageID, FLAGS flFlags,

ULONG ulReserved, LPSTR lpszMessageID);

ULONG (FAR PASCAL *lpfnMAPIReadMail)(LHANDLElhSession,

ULONG ulUIParam, LPSTR lpszMessageID,

FLAGS flFlags, ULONG ulReserved,

lpMapiMessage FAR *lppMessage);

----为了决定每一个函数的地址,必须为每一个函数调用GetProcAddress

GetProcAddress的语法为:

GetProcAddress (hModule, lpProcName);

其中,hModuleHMODULE结构,是所调用DLL模块的句柄;

lpProcNameLPCSTR结构,是函数名称。

程序示例:

//找到MAPI32.DLL函数的地址,并将它们保存在函数指针变量里

(FARPROC&) lpfnMAPISendMail =GetProcAddress(hInstMail,

MAPISendMail);

(FARPROC&) lpfnMAPIResolveName =GetProcAddress(

hInstMail,MAPIResolveName);

(FARPROC&) lpfnMAPILogon =GetProcAddress(hInstMail,

MAPILogon);

(FARPROC&) lpfnMAPILogoff =GetProcAddress(hInstMail,

MAPILogoff);

(FARPROC&) lpfnMAPIFreeBuffer =GetProcAddress(

hInstMail,MAPIFreeBuffer);

(FARPROC&) lpfnMAPIAddress =GetProcAddress(hInstMail,

MAPIAddress);

(FARPROC&) lpfnMAPIFindNext =GetProcAddress(hInstMail,

MAPIFindNext);

(FARPROC&) lpfnMAPIReadMail =GetProcAddress(hInstMail,

MAPIReadMail);

3-1-3登录到电子邮件对象

----用户必须在电子邮件系统中登录,才能实现MAPI的各种功能。MAPI提供了登录的三种选择:

登录到一个已经存在的对象。

登录到一个新对象,用编程的方法确定解释新信息。

使用对话框提示用户登录。

----我们通常选择登录到一个已经存在的电子邮件对象,因为网络合作用户通

常会保持自己的电子邮件程序处于激活状态。登录通常使用MAPI提供的函数

lpfnMAPILogon

lpfnMAPILogon的语法为:

lpfnMAPILogon (lpszProfileName, lpszPassword,flFlags,

ulReserved, lplhSession );

----其中,lpszProfileName指向一个256字符以内的登录名称,lpszPassword

指向密码,它们均为LPTSTR结构。flFlagsFLAGS结构,其值详见表1ulReserved

必须为0lplhSession为输出SMAPI的句柄。

1lpfnMAPILogon函数中flFlags的值

意义

MAPI_FORCE_DOWNLOAD

在函数调用返回之前下载用户的所有邮件。

如果MAPI_FORCE_DOWNLOAD没有被设置,

那么信件能够在函数调用返回后在后台被下载。

MAPI_NEW_SESSION建立一个新会话,

而不是获得环境的共享会话。如果MAPI_NEW_SESSION没有被设置,

MAPILogon使用现有的共享会话。

MAPI_LOGON_UI显示一个登录对话框来提示用户输入登录信息。

例如Outlook检查用户电子邮件时便是如此。

MAPI_PASSWORD_UI MAPILogon只允许用户输入电子邮件的密码,

而不许改动账号。

程序示例:

LHANDLE lhSession;

ULONG lResult = lpfnMAPILogon(0, NULL, NULL, 0,0,

&lhSession);

if (lResult != SUCCESS_SUCCESS)

//SUCCESS_SUCCESSMAPI.H中被定义

{

//错误处理

}

3-2阅读电子邮件

---- MAPIFindNextMAPIReadMail使用与阅读E-mail的两个基本函数。

MAPIFindNext用于定位第一封或下一封电子邮件并返回标识号,MAPIReadMail返回

以该标识号为基础的电子邮件的内容。另外,一个常用的函数是MAPIFreeBuffer

用于释放内存。

3-2-1定位到第一封信

----要找到第一封信,需要使用MAPIFindNext函数,其函数声明如下:

ULONG FAR PASCAL MAPIFindNext(LHANDLElhSession,

ULONG ulUIParam, LPTSTR lpszMessageType,

LPTSTR lpszSeedMessageID, FLAGS flFlags,

ULONG ulReserved, LPTSTR lpszMessageID )

----其中,lhSession为提交SMAPI的会话句柄ulUIParam为父窗体的句柄;

lpszMessageType指向一个字符串,用来鉴别邮件类型,并加以查找;

lpszSeedMessageID为指向起始信息ID的指针,其值为0时,

MAPIFindNext获得第一封电子邮件;flFlags的值见表2ulReserved必须为0

lpszMessageID为输出值,它是指向信息ID地址的指针。

----2MAPIFindNext函数中flFlags的值

意义

MAPI_GUARANTEE_FIFO按邮件发送的时间顺序接受电子邮件。

MAPI_LONG_MSGID返回信件标识符可达512字符。

MAPI_UNREAD_ONLY只列举没有阅读过的电子邮件。

程序示例:

//找到第一条没有阅读的电子邮件

char pMessageID [513];

ULONG lResult = lpfnMAPIFindNext(lhSession,NULL, NULL,

NULL, MAPI_LONG_MSGID | MAPI_UNREAD_ONLY,

0, pMessageID);

3-2-2阅读信息

当信件ID被获取后,就可以调用MAPIReadMail

阅读实际的E-mail信息了。MAPIReadMail的函数声明如下:

ULONG FAR PASCAL MAPIReadMail(LHANDLElhSession,

ULONG ulUIParam, LPTSTR lpszMessageID,

FLAGS flFlags, ULONG ulReserved,

lpMapiMessage FAR * lppMessage);

其中,lppMessage为指向MapiMessage的指针;

flFlags外的其他参数与lpfnFindNext函数的同名参数意义相同,

flFlags参数的值见表3

3MAPIReadMail函数中flFlags的值:

意义

MAPI_BODY_AS_FILE将邮件信息写到一个临时文件中,

并且将它作为第一个附件添加到附件列表中。

MAPI_ENVELOPE_ONLY只读取邮件标题。

MAPI_PEEK读完邮件之后不把它标记为已读

MAPI_SUPPRESS_ATTACH MAPIReadMail函数不拷贝附件,

但是将邮件文本写入MapiMessage结构中。

程序示例:

//读取电子邮件

long nFlags = MAPI_SUPPRESS_ATTACH;

if (!bMarkAsRead)

nFlags = nFlags | MAPI_PEEK;

lResult = lpfnMAPIReadMail(lhSession, NULL,pMessageID,

nFlags, 0, &pMessage);

if (lResult != SUCCESS_SUCCESS);

return false;

如果调用成功,就可以访问MapiMessage结构了(使用pMessage):

pMessage- >ulReserved0

pMessage- >lpszSubject:邮件标题

pMessage- >lpszNoteText:邮件信息

pMessage- >lpszMessageType:邮件类型

pMessage- >DateReceived:接收时间

pMessage- >lpszConversationID:邮件所属的会话线程ID

pMessage- >flFlags:其值见表4

4MapiMessage结构中的flFlags

意义

MAPI_RECEIPT_REQUESTED接收通知被申请。

客户端应用程序在发送消息时设置该项。

MAPI_SENT邮件已被发送。

MAPI_UNREAD邮件是未读状态。

pMessage- >lpOriginator:指向MapiRecipDesc结构,包含发件人信息。

pMessage- >nRecipCount:信件者数目。

pMessage- >lpRecips:指向MapiRecipDesc结构数组,包含接收者信息。

pMessage- >nFileCount:附件数量。

pMessage- >lpFiles:指向MapiFileDesc结构数组,

每一个结构包含一个文件附件。

3-2-3释放内存

----在访问另一条信件以前应当释放内存,否则会出现内存泄漏。

程序示例:

//释放内存

lpfnMAPIFreeBuffer(pMessage);

3-2-4定位到下一条信件

定位到下一条信件依然使用MAPIFindNext函数,

该函数声明及参数意义详见3-2-1节。下面示范如何定位到下一条信件。

程序示例:

//定位到下一条没有阅读的信件

ULONG lResult = lpfnMAPIFindNext(lhSession,NULL, NULL,

pMessageID, MAPI_LONG_MSGID|MAPI_UNREAD_ONLY,

0, pMessageID);

3-3发送电子邮件

----发送电子邮件的一般步骤:

---- 1建立MapiMessage结构对象

---- 2调用MAPIResolveName使发送者名称合法

---- 3添加附件

---- 4调用MAPISendMail发送电子邮件

---- 5调用MAPIFreeBuffer释放内存

----下面详细分别详细阐述。

3-3-1建立MapiMessage结构对象

----对于MapiMessage结构,3-2-2节已经做过介绍,下面一步步介绍如何设置其中的值:

---- 1MapiMessage对象分配内存:

MapiMessage message;

Memset(&message, 0, sizeof(message));

---- 2ulReserved设置为0

message.ulReserved = 0;

---- 3设置信息类型指针lpszMessageType,可以为NULL

message.lpszMessageType = NULL;

---- 4设置信件标题(lpszSubject):

char subject[512];

strcpy(subject, sSubject);

message.lpszSubject = subject;

---- 5设置信件内容:

char text[5000];

strcpy(text, sMessage);

message.lpszNoteText = text;

---- 6设置flFlags标识,详见3-2-2节中表4

message.flFlags = MAPI_SENT;

---- 7用一个指向MapiRecipDesc结构的指针设置发送者信息(lpOriginator),

或将其设置为NULL

message.lpOriginator = NULL;

---- 8设置接收者数目(nRecipCount),可以是1或更多:

message.nRecipCount = 1;

---- 9设置接收者信息(lpRecips),详见3-3-2

---- 10设置附件数量(nFileCount

---- 11设置附件信息,详见3-3-3

b3-3-2正确设置接收者信息

----设置接收者信息时,应当使用MAPIResolveName函数来为MapiRecipDesc结构

对象分配内存,并返回一个指针,该指针将被保存在MapiMessage结构的lpRecips中。

MAPIResolveName的函数声明如下:

ULONG FAR PASCAL MAPIResolveName(LHANDLElhSession,

ULONG ulUIParam, LPTSTR lpszName,

FLAGS flFlags, ULONG ulReserved,

lpMapiRecipDesc FAR * lppRecip )

----其中lppRecip即为前面提到的返回的指针。除flFlags外其余参数与前几个

函数意义相同。flFlags的值详见表5

5MAPIResolveNameflFlags的值

意义

MAPI_AB_NOMODIFY对话框为只读。如果MAPI_DIALOG被设置,

那么该项将被忽略。

MAPI_DIALOG显示一个名称解决方案的对话框

MAPI_LOGON_UI如果需要的话,将会显示仪个对话框让用户登录

MAPI_NEW_SESSION新建一个会话

程序示例:

char recipient[512];

strcpy(recipient, sTo);

lResult = lpfnMAPIResolveName(lhSession, 0,recipient,

0, 0, &message.lpRecips);

3-3-3添加附件

----下面的程序示例将演示如何在电子邮件中包含附件。只有一点需要说明:

MapiFileDesc结构中flFlags的值,详见表6

6MapiFileDesc结构中flFlags的值

意义

MAPI_OLE附件是OLE对象。

MAPI_OLE_STATIC附件是静态OLE对象。

0附件将被视为数据文件

程序示例:

//设置附件信息

CString sPath, sFileName;

MapiFileDesc FileInfo;

char path[512];

char filename[512];

if (sAttachment ==“”)

message.nFileCount = 0;

else

{

int nPos = sAttachment.ReverseFind(//);

if (nPos == -1)

{

sPath = sAttachment;

}

else

{

sPath = sAttachment;

sFilename = sAttachment.Mid(nPos +1);

}

strcpy(path, sPath);

strcpy(filename, sFilename);

message.nFileCount = 1;

FileInfo.ulReserved = 0;

FileInfo.flFlags = 0;

FileInfo.nPosition = sMessage.GetLength()1;

FileInfo.lpszPathName = path;

FileInfo.lpszFileName = filename;

FileInfo.lpFileType = NULL;

message.lpFiles = & m_FileInfo;

}

3-3-4发送电子邮件

----使用MAPISendMail发送电子邮件,其声明如下:

ULONG FAR PASCAL MAPISendMail (LHANDLElhSession,

ULONG ulUIParam, lpMapiMessage lpMessage,

FLAGS flFlags, ULONG ulReserved )

----其中,flFlags的允许值为MAPI_DIALOGMAPI_LOGON_UIMAPI_NEW_SESSION

其意义与前几个函数中同名标识意义相同。

程序示例:

lResult = lpfnMAPISendMail(0, 0,&m_message, 0, 0);

3-3-5释放内存

程序示例:

lpfnMAPIFreeBuffer(m_message.lpRecips);

四、小结

----本文比较具体的介绍并演示了编写一个电子邮件程序的核心部分,如果读者

要编写电子邮件程序,还需要进行的处理:

---- 1加上错误处理代码。受篇幅限制,本文的程序示例中只有两处为错误

处理留空,比较它们的异同。电子邮件程序是非常容易出错的,因此除这两处外要

在主要函数调用完成后都加上错误处理,或使用try throw catch块处理例外。

---- 2加上UI处理。

----另外,本文所阐述的方法比较简单易行,事实上,有关电子邮件的程序远比

这复杂得多,因此读者若需要编写一个功能强大的电子邮件程序,需要精通MAPI

SMTP/POP3等协议;如果读者要编写一个电子邮件服务器,那么不妨在精通MAPI

SMTP/POP3之后,阅读一些有关Exchange Server的资料。

95.报表相关

 一、准备工作

  (1)安装Crystal Report软件

Crystal Report 4.6是一个免费的报表工具,可以在VB5WINDOWS NT 4.0 BackOffice等光盘上找到,Crystal report4.6中包含了报表设计工具与报表打印控件。程序的发行只需要安装打印控件相关部分即可。

  (2)设计报表

  我们生成一个名为sample.rpt的报表,这一过程可以参考 Crystal report自带的帮助文档,本文不作详细介绍。

  二、创建VC工程添加报表控件

  在VC集成环境中用AppWizard新建一个MFC单文档工程,其余选项都为默认。菜单中选择Project->Add To Project->Components andControls...弹出组件、控件选择对话框,进入Registered ActiveX Controls,选中Crystal Report Control 4.6 ,单击Insert按钮,确认后进入类配置对话框,按默认即可。关闭控件选择对话框完成控件的添加。

  三、实现报表的显示与打印

  下面我们将在对话框中演示控件的静态创建过程,在主视图中演示控件的动态创建过程。

3.1在对话框中打印出报表

  在资源编辑器中打开IDIDD_ABOUTBOX的对话框模板,在Controls工具条中我们可以找到刚加入到工程中的Crystal Report Control 4.6控件按钮,把它插入到对话框合适的位置处。

  右键单击对话框中的控件,选择属性,此时可以设置控件的许多属性。我们在Control选项页ReportFileName中输入报表文件名sample.rpt(可以加上完整路径),Print Window选项页中设置控件的合适位置,回到对话框模板中按住Ctrl键,双击鼠标左键,弹出Add Member Variable对话框,我们将成员变量命名为m_CrystalReport,打开ClassWizard,CAboutDlg对话框添加WM_INITDIALOG消息的处理函数:BOOL OnInitDialog(),并在函数中做如下处理

BOOL CAboutDlg::OnInitDialog()

{

CDialog::OnInitDialog();

/此行设置控件的父窗口,你也可以去掉该行看看运行效果/

m_CrystalReport.SetWindowParentHandle((long)(this->m_hWnd));

/打印报表到窗口中/

m_CrystalReport.PrintReport();

return TRUE;

}

  至此,程序的第一部分编写完成,编译运行,打开About对话框看看效果吧!

  假如您并没有显示出报表,有如下可能原因:

(1)控件没有放置在合适的位置或尺寸不对。

(2)报表文件本身存在诸如数据源不可用等错误。

  控件窗口中的工具条提供了缩放、打印等功能,您也可以试试在打印机上打印出来的效果。

3.2在程序主视窗中显示报表

  打开ClassWizard增加对ID_FILE_OPENID_FILE_PRINT的处理函数,代码如下

void CMyReportView::OnFileOpen()

{

char Filter[] = "Crystal Reportfiles(*.rpt)|*.rpt|All files(*.*)|*.*||";

CRect rect;

CFileDialog OpenDlg(TRUE,0,0,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,(LPCTSTR)Filter,NULL);

if(OpenDlg.DoModal()!=IDOK) ///显示文件对话框

return;

CString m_fName=OpenDlg.GetPathName(); ///取得文件名

if(m_CrystalReport)

m_CrystalReport.DestroyWindow();

GetClientRect(rect);

///创建控件///

if(!m_CrystalReport.Create(AfxRegisterWndClass(0,AfxGetApp()->LoadStandardCursor(IDC_ARROW)),WS_CHILD|

_ WS_VISIBLE,rect,this,IDC_CRYSTALREPORT1))

{

AfxMessageBox("控件创建失败!");

return ;

}

m_CrystalReport.SetWindowParentHandle((long)(this->m_hWnd));///设置父窗口

m_CrystalReport.SetWindowBorderStyle(0); ///设置为没有边框

m_CrystalReport.SetWindowLeft(0); ///左空间

m_CrystalReport.SetWindowTop(0); ///顶部空间

m_CrystalReport.SetWindowControls(FALSE); ///不显示工具条

m_CrystalReport.SetReportFileName(m_fName); ///设置报表文件

m_CrystalReport.SetWindowWidth(rect.Width());///设置窗口宽度

m_CrystalReport.SetWindowHeight(rect.Height());///设置窗口高度

m_CrystalReport.SetFormulas(0,"Company=/"VC知识库/"");

///将报表中的Company变量的值设置为VC知识库

m_CrystalReport.SetDestination(0); ///设置输出对象是屏幕

m_CrystalReport.PrintReport(); ///显示报表

}

void CMyReportView::OnFilePrint()

{

if(m_CrystalReport &&m_CrystalReport.GetReportFileName() != "")

{

m_CrystalReport.SetDestination(1); ///设置输出对象是打印机

m_CrystalReport.PrintReport(); ///打印

}

}

  后记:我们利用Crystal Report 4.6VC++环境下实现了报表处理,但Crystal Report 4.6报表控件的功能及可控性能可能无法满足您的要求,Seagate公司此款软件的最新版本是Crystal Report 8.0,各方面表现都非常出色,但此款软件的免费版本并不包括报表设计器,可喜的是8.0中的报表显示控件兼容以前版本的报表格式,所以笔者建议用4.6版本来设计报表,依靠8.0中的报表显示控件来显示、打印。

96.全屏幕截取

CBitmap* m_pBackBitmap;

/*******************************

*拷贝屏幕固定区域

*参数:

* xStartPt -拷贝屏幕的起始点X坐标

* yStartPt -拷贝屏幕的起始点Y坐标

* width -拷贝宽度

* height -拷贝高度

* xToCopy -拷贝目的地的起始点X坐标

* yToCopy -拷贝目的地的起始点Y坐标

*******************************/

void CopyScreenToBitmap(xStartPt, yStartPt,width, height, xToCopy, yToCopy)

{

//NEW资源(调用一次重新拷贝一次)

if (m_pBackBitmap != NULL)

{

delete m_pBackBitmap;

m_pBackBitmap = NULL;

}

m_pBackBitmap = new CBitmap();

CDC ScrDC,MemDC;

ScrDC.CreateDC("DISPLAY", NULL, NULL,NULL);

MemDC.CreateCompatibleDC(&ScrDC);

m_pBackBitmap->CreateCompatibleBitmap(&ScrDC,width,height);

MemDC.SelectObject(m_pBackBitmap);

//开始拷贝

MemDC.BitBlt(xStartPt, yStartPt, width,height,&ScrDC,xToCopy,yToCopy,SRCCOPY);

ScrDC.DeleteDC();

MemDC.DeleteDC();

}

//取的屏幕分辨率

int width = ::GetSystemMetrics(SM_CXSCREEN);

int height = ::GetSystemMetrics(SM_CYSCREEN);

this->CopyScreenToBitmap(0,0,width,height,0,0);

//这时m_pBackBitmap指向的CBitmap对象就存着全屏的图象了

97.区域截幕

HBITMAP CopyScreenToBitmap(LPRECT lpRect)

//lpRect代表选定区域

{

HDC hScrDC, hMemDC;

//屏幕和内存设备描述表

HBITMAP hBitmap, hOldBitmap;

//位图句柄

int nX, nY, nX2, nY2;

//选定区域坐标

int nWidth, nHeight;

//位图宽度和高度

int xScrn, yScrn;

//屏幕分辨率

//确保选定区域不为空矩形

if (IsRectEmpty(lpRect))

return NULL;

//为屏幕创建设备描述表

hScrDC = CreateDC("DISPLAY", NULL,NULL, NULL);

//为屏幕设备描述表创建兼容的内存设备描述表

hMemDC = CreateCompatibleDC(hScrDC);

//获得选定区域坐标

nX = lpRect- >left;

nY = lpRect- >top;

nX2 = lpRect- >right;

nY2 = lpRect- >bottom;

//获得屏幕分辨率

xScrn = GetDeviceCaps(hScrDC, HORZRES);

yScrn = GetDeviceCaps(hScrDC, VERTRES);

//确保选定区域是可见的

if (nX0)

nX = 0;

if (nY 0)

nY = 0;

if (nX2 > xScrn)

nX2 = xScrn;

if (nY2 > yScrn)

nY2 = yScrn;

nWidth = nX2 - nX;

nHeight = nY2 - nY;

//创建一个与屏幕设备描述表兼容的位图

hBitmap = CreateCompatibleBitmap

(hScrDC, nWidth, nHeight);

//把新位图选到内存设备描述表中

hOldBitmap = SelectObject(hMemDC, hBitmap);

//把屏幕设备描述表拷贝到内存设备描述表中

BitBlt(hMemDC, 0, 0, nWidth, nHeight,

hScrDC, nX, nY, SRCCOPY);

//得到屏幕位图的句柄

hBitmap = SelectObject(hMemDC, hOldBitmap);

//清除

DeleteDC(hScrDC);

DeleteDC(hMemDC);

//返回位图句柄

return hBitmap;

}

得到屏幕位图句柄以后,我们

可以把屏幕内容粘贴到剪贴板上.

if (OpenClipboard(hWnd))

//hWnd为程序窗口句柄

{

//清空剪贴板

EmptyClipboard();

//把屏幕内容粘贴到剪贴板上,

hBitmap为刚才的屏幕位图句柄

SetClipboardData(CF_BITMAP, hBitmap);

//关闭剪贴板

CloseClipb

oard();

}

int SaveBitmapToFile(HBITMAP hBitmap ,

LPSTR lpFileName) //hBitmap为刚才的屏幕位图句柄

{ //lpFileName为位图文件名

HDC hDC;

//设备描述表

int iBits;

//当前显示分辨率下每个像素所占字节数

WORD wBitCount;

//位图中每个像素所占字节数

//定义调色板大小,位图中像素字节大小

位图文件大小写入文件字节数

DWORD dwPaletteSize=0,

dwBmBitsSize,

dwDIBSize, dwWritten;

BITMAP Bitmap;

//位图属性结构

BITMAPFILEHEADER bmfHdr;

//位图文件头结构

BITMAPINFOHEADER bi;

//位图信息头结构

LPBITMAPINFOHEADER lpbi;

//指向位图信息头结构

HANDLE fh, hDib, hPal,hOldPal=NULL;

//定义文件,分配内存句柄,调色板句柄

//计算位图文件每个像素所占字节数

hDC =CreateDC("DISPLAY",NULL,NULL,NULL);

iBits = GetDeviceCaps(hDC, BITSPIXEL) *

GetDeviceCaps(hDC, PLANES);

DeleteDC(hDC);

if (iBits = 1)

wBitCount = 1;

else if (iBits = 4)

wBitCount = 4;

else if (iBits = 8)

wBitCount = 8;

else if (iBits = 24)

wBitCount = 24;

//计算调色板大小

if (wBitCount = 8)

dwPaletteSize = (1wBitCount) *

sizeof(RGBQUAD);

//设置位图信息头结构

GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);

bi.biSize = sizeof(BITMAPINFOHEADER);

bi.biWidth = Bitmap.bmWidth;

bi.biHeight = Bitmap.bmHeight;

bi.biPlanes = 1;

bi.biBitCount = wBitCount;

bi.biCompression = BI_RGB;

bi.biSi

zeImage = 0;

bi.biXPelsPerMeter = 0;

bi.biYPelsPerMeter = 0;

bi.biClrUsed = 0;

bi.biClrImportant = 0;

dwBmBitsSize = ((Bitmap.bmWidth *

wBitCount+31)/32)* 4

*Bitmap.bmHeight ;

//为位图内容分配内存

hDib = GlobalAlloc(GHND,dwBmBitsSize+

dwPaletteSize+sizeof(BITMAPINFOHEADER));

lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);

*lpbi = bi;

//处理调色板

hPal = GetStockObject(DEFAULT_PALETTE);

if (hPal)

{

hDC = GetDC(NULL);

hOldPal = SelectPalette(hDC, hPal, FALSE);

RealizePalette(hDC);

}

//获取该调色板下新的像素值

GetDIBits(hDC, hBitmap, 0, (UINT)Bitmap.bmHeight,

(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)

+dwPaletteSize,

(BITMAPINFOHEADER *)

lpbi, DIB_RGB_COLORS);

//恢复调色板

if (hOldPal)

{

SelectPalette(hDC, hOldPal, TRUE);

RealizePalette(hDC);

ReleaseDC(NULL, hDC);

}

//创建位图文件

fh = CreateFile(lpFileName, GENERIC_WRITE,

0, NULL, CREATE_ALWAYS,

FILE_ATTRIBUTE_NORMALFILE_

FLAG_SEQUENTIAL_SCAN, NULL);

if (fh == INVALID_HANDLE_VALUE)

return FALSE;

//设置位图文件头

bmfHdr.bfType = 0x4D42; // "BM"

dwDIBSize = sizeof(BITMAPFILEHEADER)

+ sizeof(BITMAPINFOHEADER)

+ dwPaletteSize + dwBmBitsSize;

bmfHdr.bfSize = dwDIBSize;

bmfHdr.bfReserved1 = 0;

bmfHdr.bfReserved2 = 0;

bmfHdr.bfOffBits = (DWORD)sizeof

(BITMAPFILEHEADER)

+ (DWORD)sizeof(BITMAPINFOHEADER)

+ dwPaletteSize;

//写入位图文件头

WriteFile(fh, (LPSTR)&bmfHdr, sizeof

(BITMAPFILEHEADER), &dwWritten, NULL);

//写入位图文件其余内容

WriteFile(fh, (LPSTR)lpbi, dwDIBSize,

&dwWritten, NULL);

//清除

GlobalUnlock(hDib);

GlobalFree(hDib);

CloseHandle(fh);

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值