C++で正規表現 (2)

PCRE(Perl Compatible Regular Expressions, http://www.pcre.org/)のラッパーも作ってみた。
PCREはC++ Builderに入っていたり、Cではメジャーなライブラリである。

PCRE用のCRegexの使い方は(1)と同じで、


CRegex Regex( "(abc)(def)ghi" );
int nResults = Regex.Match( "abcdefghijkl" );
という感じ。以下Regex.hのソース。

#include <vector>
#include <string>
struct real_pcre;

class CRegex
{
real_pcre *m_pcre;
int m_nOutVecSize;
int *m_pOutputVector;
int m_nResult;
std::vector m_Results;

public:
CRegex( const char *pszExpression, bool bIgnoreCase = false );
~CRegex();
void Reset( void );
int Match( const char *pszTarget );
std::string GetResult( int nIndex ) const;
bool GetPosition( int nIndex, int &nStart, int &nEnd ) const;
};

続いてRegex.cpp。

#include "Regex.h"
#include "pcre.h"

// コンストラクタ(bIgnoreCase == true: 大文字小文字無視)
CRegex::CRegex( const char *pszExpression, bool bIgnoreCase )
: m_pcre( NULL ), m_nOutVecSize( 0 ),
m_pOutputVector( NULL ), m_nResult( 0 )
{
const char *error;
int nErrorOffset;
m_pcre = pcre_compile( pszExpression, PCRE_DOTALL | PCRE_MULTILINE |
( bIgnoreCase ? PCRE_CASELESS : 0 ), &error, &nErrorOffset, NULL );
if ( m_pcre == NULL ) {
return;
}
int nCapture;
if ( pcre_fullinfo( m_pcre, NULL, PCRE_INFO_CAPTURECOUNT, &nCapture ) != 0 ) {
return;
}
// 全体 + 後方参照数で 1 + nCapture
// ワークエリアとして3倍必要
m_nOutVecSize = ( 1 + nCapture ) * 3;
m_pOutputVector = new int[m_nOutVecSize];
}

CRegex::~CRegex()
{
delete [] m_pOutputVector;
if ( m_pcre ) {
pcre_free( m_pcre );
}
}

// 検索結果のリセット
void CRegex::Reset()
{
m_nResult = 0;
m_Results.clear();
}

// 一致判定(pszTarget: 検索対象文字列)
int CRegex::Match( const char *pszTarget )
{
if ( m_pcre == NULL || m_pOutputVector == NULL ) {
return -1;
}
Reset();
m_nResult = pcre_exec( m_pcre, NULL, pszTarget, strlen(pszTarget),
0, 0, m_pOutputVector, m_nOutVecSize );
int i;
for ( i = 0; i < m_nResult; ++i ) {
int nStart = m_pOutputVector[ i * 2 ];
int nEnd = m_pOutputVector[ i * 2 + 1 ];
if ( nStart >= 0 && nEnd >= 0 ) {
m_Results.push_back( std::string( pszTarget + nStart, nEnd - nStart ) );
}
}
return m_nResult;
}

// 一致した先頭位置と終端位置を取得(終端-先頭=長さ)
bool CRegex::GetPosition( int nIndex, int &nStart, int &nEnd ) const
{
if ( nIndex < 0 || nIndex >= m_nResult ) {
return false;
}
nStart = m_pOutputVector[ nIndex * 2 ];
nEnd = m_pOutputVector[ nIndex * 2 + 1 ];
return true;
}

// 一致した文字列を取得
std::string CRegex::GetResult( int nIndex ) const
{
if ( nIndex < 0 || nIndex >= m_nResult ) {
return "";
}
return m_Results[ nIndex ];
}