]>
git.saurik.com Git - wxWidgets.git/blob - src/common/regex.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/regex.cpp
3 // Purpose: regular expression matching
4 // Author: Karsten Ballüder and Vadim Zeitlin
8 // Copyright: (c) 2000 Karsten Ballüder <ballueder@gmx.net>
9 // 2001 Vadim Zeitlin <vadim@wxwindows.org>
10 // Licence: wxWindows licence
11 ///////////////////////////////////////////////////////////////////////////////
13 // ============================================================================
15 // ============================================================================
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
22 #pragma implementation "regex.h"
25 // For compilers that support precompilation, includes "wx.h".
26 #include "wx/wxprec.h"
35 #include "wx/object.h"
36 #include "wx/string.h"
45 // ----------------------------------------------------------------------------
47 // ----------------------------------------------------------------------------
49 // the real implementation of wxRegEx
57 // return TRUE if Compile() had been called successfully
58 bool IsValid() const { return m_isCompiled
; }
61 bool Compile(const wxString
& expr
, int flags
);
62 bool Matches(const wxString
& str
, int flags
) const;
63 bool GetMatch(size_t *start
, size_t *len
, size_t index
) const;
64 int Replace(wxString
*pattern
, const wxString
& replacement
) const;
67 // return the string containing the error message for the given err code
68 wxString
GetErrorMsg(int errorcode
) const;
70 // free the RE if compiled
84 // the subexpressions data
85 regmatch_t
*m_Matches
;
88 // TRUE if m_RegEx is valid
92 // ============================================================================
94 // ============================================================================
96 // ----------------------------------------------------------------------------
98 // ----------------------------------------------------------------------------
100 wxRegExImpl::wxRegExImpl()
102 m_isCompiled
= FALSE
;
106 wxRegExImpl::~wxRegExImpl()
113 wxString
wxRegExImpl::GetErrorMsg(int errorcode
) const
117 // first get the string length needed
118 int len
= regerror(errorcode
, &m_RegEx
, NULL
, 0);
123 (void)regerror(errorcode
, &m_RegEx
, msg
.GetWriteBuf(len
), len
);
127 else // regerror() returned 0
129 msg
= _("unknown error");
135 bool wxRegExImpl::Compile(const wxString
& expr
, int flags
)
139 // translate our flags to regcomp() ones
140 wxASSERT_MSG( !(flags
&
141 ~(wxRE_BASIC
| wxRE_ICASE
| wxRE_NOSUB
| wxRE_NEWLINE
)),
142 _T("unrecognized flags in wxRegEx::Compile") );
145 if ( !(flags
& wxRE_BASIC
) )
146 flagsRE
|= REG_EXTENDED
;
147 if ( flags
& wxRE_ICASE
)
148 flagsRE
|= REG_ICASE
;
149 if ( flags
& wxRE_NOSUB
)
150 flagsRE
|= REG_NOSUB
;
151 if ( flags
& wxRE_NEWLINE
)
152 flagsRE
|= REG_NEWLINE
;
155 int errorcode
= regcomp(&m_RegEx
, expr
, flagsRE
);
158 wxLogError(_("Invalid regular expression '%s': %s"),
159 expr
.c_str(), GetErrorMsg(errorcode
).c_str());
161 m_isCompiled
= FALSE
;
165 // don't allocate the matches array now, but do it later if necessary
166 if ( flags
& wxRE_NOSUB
)
168 // we don't need it at all
174 m_nMatches
= WX_REGEX_MAXMATCHES
;
183 bool wxRegExImpl::Matches(const wxString
& str
, int flags
) const
185 wxCHECK_MSG( IsValid(), FALSE
, _T("must successfully Compile() first") );
187 // translate our flags to regexec() ones
188 wxASSERT_MSG( !(flags
& ~(wxRE_NOTBOL
| wxRE_NOTEOL
)),
189 _T("unrecognized flags in wxRegEx::Matches") );
192 if ( flags
& wxRE_NOTBOL
)
193 flagsRE
|= REG_NOTBOL
;
194 if ( flags
& wxRE_NOTEOL
)
195 flagsRE
|= REG_NOTEOL
;
197 // allocate matches array if needed
198 wxRegExImpl
*self
= wxConstCast(this, wxRegExImpl
);
199 if ( !m_Matches
&& m_nMatches
)
201 self
->m_Matches
= new regmatch_t
[m_nMatches
];
205 int rc
= regexec(&self
->m_RegEx
, str
, m_nMatches
, m_Matches
, flagsRE
);
210 // matched successfully
215 wxLogError(_("Failed to match '%s' in regular expression: %s"),
216 str
.c_str(), GetErrorMsg(rc
).c_str());
225 bool wxRegExImpl::GetMatch(size_t *start
, size_t *len
, size_t index
) const
227 wxCHECK_MSG( IsValid(), FALSE
, _T("must successfully Compile() first") );
228 wxCHECK_MSG( m_Matches
, FALSE
, _T("can't use with wxRE_NOSUB") );
229 wxCHECK_MSG( index
< m_nMatches
, FALSE
, _T("invalid match index") );
231 const regmatch_t
& match
= m_Matches
[index
];
232 if ( match
.rm_so
== -1 )
236 *start
= match
.rm_so
;
238 *len
= match
.rm_eo
- match
.rm_so
;
243 int wxRegExImpl::Replace(wxString
*pattern
, const wxString
& replacement
) const
245 wxCHECK_MSG( pattern
, -1, _T("NULL pattern in wxRegEx::Replace") );
247 wxCHECK_MSG( IsValid(), FALSE
, _T("must successfully Compile() first") );
253 for ( size_t idx
= 0;
254 m_Matches
[idx
].rm_so
!= -1 && idx
< m_nMatches
;
257 // copy non-matching bits:
258 newstring
<< pattern
->Mid(lastpos
, m_Matches
[idx
].rm_so
- lastpos
);
260 newstring
<< replacement
;
261 // remember how far we got:
262 lastpos
= m_Matches
[idx
].rm_eo
;
266 *pattern
= newstring
;
270 // ----------------------------------------------------------------------------
271 // wxRegEx: all methods are mostly forwarded to wxRegExImpl
272 // ----------------------------------------------------------------------------
285 bool wxRegEx::Compile(const wxString
& expr
, int flags
)
289 m_impl
= new wxRegExImpl
;
292 if ( !m_impl
->Compile(expr
, flags
) )
294 // error message already given in wxRegExImpl::Compile
304 bool wxRegEx::Matches(const wxString
& str
, int flags
) const
306 wxCHECK_MSG( IsValid(), FALSE
, _T("must successfully Compile() first") );
308 return m_impl
->Matches(str
, flags
);
311 bool wxRegEx::GetMatch(size_t *start
, size_t *len
, size_t index
) const
313 wxCHECK_MSG( IsValid(), -1, _T("must successfully Compile() first") );
315 return m_impl
->GetMatch(start
, len
, index
);
318 wxString
wxRegEx::GetMatch(const wxString
& text
, size_t index
) const
321 if ( !GetMatch(&start
, &len
, index
) )
322 return wxEmptyString
;
324 return text
.Mid(start
, len
);
327 int wxRegEx::Replace(wxString
*pattern
, const wxString
& replacement
) const
329 wxCHECK_MSG( IsValid(), -1, _T("must successfully Compile() first") );
331 return m_impl
->Replace(pattern
, replacement
);
334 #endif // wxUSE_REGEX