3
* Copyright (c) 1998-2002
6
* Permission to use, copy, modify, distribute and sell this software
7
* and its documentation for any purpose is hereby granted without fee,
8
* provided that the above copyright notice appear in all copies and
9
* that both that copyright notice and this permission notice appear
10
* in supporting documentation. Dr John Maddock makes no representations
11
* about the suitability of this software for any purpose.
12
* It is provided "as is" without express or implied warranty.
17
* LOCATION: see http://www.boost.org for most recent version.
19
* VERSION: see <boost/version.hpp>
20
* DESCRIPTION: Implements high level class boost::RexEx
24
#define BOOST_REGEX_SOURCE
26
#include <boost/cregex.hpp>
27
#include <boost/regex.hpp>
28
#if !defined(BOOST_NO_STD_STRING)
31
#include <boost/regex/v3/fileiter.hpp>
37
#if __BORLANDC__ < 0x530
39
// we need to instantiate the vector classes we use
40
// since declaring a reference to type doesn't seem to
42
std::vector<std::size_t> inst1;
43
std::vector<std::string> inst2;
49
template <class iterator>
50
std::string to_string(iterator i, iterator j)
62
inline std::string to_string(const char* i, const char* j)
64
return std::string(i, j);
81
#ifndef BOOST_REGEX_NO_FILEITER
82
match_results<mapfile::iterator, regex::allocator_type> fm;
87
#ifndef BOOST_REGEX_NO_FILEITER
88
mapfile::iterator fbase;
90
std::map<int, std::string, std::less<int> > strings;
91
std::map<int, std::ptrdiff_t, std::less<int> > positions;
94
RegExData() : e(), m(),
95
#ifndef BOOST_REGEX_NO_FILEITER
98
t(type_copy), pbase(0), line(0),
99
#ifndef BOOST_REGEX_NO_FILEITER
102
strings(), positions() {}
105
void RegExData::update()
108
strings.erase(strings.begin(), strings.end());
109
positions.erase(positions.begin(), positions.end());
112
for(unsigned int i = 0; i < m.size(); ++i)
114
if(m[i].matched) strings[i] = std::string(m[i].first, m[i].second);
115
positions[i] = m[i].matched ? m[i].first - pbase : -1;
119
#ifndef BOOST_REGEX_NO_FILEITER
122
for(unsigned int i = 0; i < fm.size(); ++i)
124
if(fm[i].matched) strings[i] = to_string(fm[i].first, fm[i].second);
125
positions[i] = fm[i].matched ? fm[i].first - fbase : -1;
133
void RegExData::clean()
136
#ifndef BOOST_REGEX_NO_FILEITER
137
fbase = mapfile::iterator();
138
fm = match_results<mapfile::iterator, regex::allocator_type>();
147
pdata = new re_detail::RegExData();
150
RegEx::RegEx(const RegEx& o)
153
pdata = new re_detail::RegExData(*(o.pdata));
162
RegEx::RegEx(const char* c, bool icase)
165
pdata = new re_detail::RegExData();
166
SetExpression(c, icase);
169
RegEx::RegEx(const std::string& s, bool icase)
172
pdata = new re_detail::RegExData();
173
SetExpression(s.c_str(), icase);
176
RegEx& RegEx::operator=(const RegEx& o)
183
RegEx& RegEx::operator=(const char* p)
186
SetExpression(p, false);
190
unsigned int RegEx::SetExpression(const char* p, bool icase)
193
boost::uint_fast32_t f = icase ? regbase::normal | regbase::use_except | regbase::icase : regbase::normal | regbase::use_except;
194
return pdata->e.set_expression(p, f);
197
unsigned int RegEx::error_code()const
199
return pdata->e.error_code();
203
std::string RegEx::Expression()const
206
return pdata->e.expression();
210
// now matching operators:
212
bool RegEx::Match(const char* p, unsigned int flags)
215
pdata->t = re_detail::RegExData::type_pc;
220
if(regex_match(p, end, pdata->m, pdata->e, flags))
228
bool RegEx::Search(const char* p, unsigned int flags)
231
pdata->t = re_detail::RegExData::type_pc;
236
if(regex_search(p, end, pdata->m, pdata->e, flags))
248
pred1(GrepCallback c, RegEx* i) : cb(c), pe(i) {}
249
bool operator()(const cmatch& m)
256
unsigned int RegEx::Grep(GrepCallback cb, const char* p, unsigned int flags)
259
pdata->t = re_detail::RegExData::type_pc;
264
unsigned int result = regex_grep(re_detail::pred1(cb, this), p, end, pdata->e, flags);
272
std::vector<std::string>& v;
274
pred2(std::vector<std::string>& o, RegEx* e) : v(o), pe(e) {}
275
bool operator()(const cmatch& m)
278
v.push_back(std::string(m[0].first, m[0].second));
282
pred2& operator=(const pred2&);
286
unsigned int RegEx::Grep(std::vector<std::string>& v, const char* p, unsigned int flags)
289
pdata->t = re_detail::RegExData::type_pc;
294
unsigned int result = regex_grep(re_detail::pred2(v, this), p, end, pdata->e, flags);
302
std::vector<std::size_t>& v;
305
pred3(std::vector<std::size_t>& o, const char* pb, RegEx* p) : v(o), base(pb), pe(p) {}
306
bool operator()(const cmatch& m)
309
v.push_back(static_cast<std::size_t>(m[0].first - base));
313
pred3& operator=(const pred3&);
316
unsigned int RegEx::Grep(std::vector<std::size_t>& v, const char* p, unsigned int flags)
319
pdata->t = re_detail::RegExData::type_pc;
324
unsigned int result = regex_grep(re_detail::pred3(v, p, this), p, end, pdata->e, flags);
329
#ifndef BOOST_REGEX_NO_FILEITER
337
pred4(GrepFileCallback c, RegEx* i, const char* f) : cb(c), pe(i), file(f), ok(true) {}
338
bool operator()(const match_results<mapfile::iterator, regex::allocator_type>& m)
340
pe->pdata->t = RegExData::type_pf;
349
void BuildFileList(std::list<std::string>* pl, const char* files, bool recurse)
352
file_iterator start(files);
356
// go through sub directories:
358
std::strcpy(buf, start.root());
361
std::strcpy(buf, ".");
362
std::strcat(buf, directory_iterator::separator());
363
std::strcat(buf, "*");
367
std::strcat(buf, directory_iterator::separator());
368
std::strcat(buf, "*");
370
directory_iterator dstart(buf);
371
directory_iterator dend;
373
// now get the file mask bit of "files":
374
const char* ptr = files;
376
while((ptr != files) && (*ptr != *directory_iterator::separator()) && (*ptr != '/'))--ptr;
377
if(ptr != files) ++ptr;
379
while(dstart != dend)
381
std::sprintf(buf, "%s%s%s", dstart.path(), directory_iterator::separator(), ptr);
382
BuildFileList(pl, buf, recurse);
388
pl->push_back(*start);
394
unsigned int RegEx::GrepFiles(GrepFileCallback cb, const char* files, bool recurse, unsigned int flags)
397
unsigned int result = 0;
398
std::list<std::string> file_list;
399
BuildFileList(&file_list, files, recurse);
400
std::list<std::string>::iterator start, end;
401
start = file_list.begin();
402
end = file_list.end();
406
mapfile map((*start).c_str());
407
pdata->t = re_detail::RegExData::type_pf;
408
pdata->fbase = map.begin();
409
re_detail::pred4 pred(cb, this, (*start).c_str());
410
int r = regex_grep(pred, map.begin(), map.end(), pdata->e, flags);
422
unsigned int RegEx::FindFiles(FindFilesCallback cb, const char* files, bool recurse, unsigned int flags)
425
unsigned int result = 0;
426
std::list<std::string> file_list;
427
BuildFileList(&file_list, files, recurse);
428
std::list<std::string>::iterator start, end;
429
start = file_list.begin();
430
end = file_list.end();
434
mapfile map((*start).c_str());
435
pdata->t = re_detail::RegExData::type_pf;
436
pdata->fbase = map.begin();
438
if(regex_search(map.begin(), map.end(), pdata->fm, pdata->e, flags))
441
if(false == cb((*start).c_str()))
453
std::string RegEx::Merge(const std::string& in, const std::string& fmt,
454
bool copy, unsigned int flags)
457
re_detail::string_out_iterator<std::string> i(result);
458
if(!copy) flags |= format_no_copy;
459
regex_merge(i, in.begin(), in.end(), pdata->e, fmt.c_str(), flags);
463
std::string RegEx::Merge(const char* in, const char* fmt,
464
bool copy, unsigned int flags)
467
if(!copy) flags |= format_no_copy;
468
re_detail::string_out_iterator<std::string> i(result);
469
regex_merge(i, in, in + std::strlen(in), pdata->e, fmt, flags);
473
std::size_t RegEx::Split(std::vector<std::string>& v,
478
return regex_split(std::back_inserter(v), s, pdata->e, flags, max_count);
484
// now operators for returning what matched in more detail:
486
std::size_t RegEx::Position(int i)const
491
case re_detail::RegExData::type_pc:
492
return pdata->m[i].matched ? pdata->m[i].first - pdata->pbase : RegEx::npos;
493
#ifndef BOOST_REGEX_NO_FILEITER
494
case re_detail::RegExData::type_pf:
495
return pdata->fm[i].matched ? pdata->fm[i].first - pdata->fbase : RegEx::npos;
497
case re_detail::RegExData::type_copy:
499
std::map<int, std::ptrdiff_t, std::less<int> >::iterator pos = pdata->positions.find(i);
500
if(pos == pdata->positions.end())
502
return (*pos).second;
508
unsigned int RegEx::Line()const
513
case re_detail::RegExData::type_pc:
514
return pdata->m[0].matched ? pdata->m.line() : RegEx::npos;
515
#ifndef BOOST_REGEX_NO_FILEITER
516
case re_detail::RegExData::type_pf:
517
return pdata->fm[0].matched ? pdata->fm.line() : RegEx::npos;
519
case re_detail::RegExData::type_copy:
527
unsigned int RegEx::Marks()const
530
return pdata->e.mark_count();
534
std::size_t RegEx::Length(int i)const
539
case re_detail::RegExData::type_pc:
540
return pdata->m[i].matched ? pdata->m[i].second - pdata->m[i].first : RegEx::npos;
541
#ifndef BOOST_REGEX_NO_FILEITER
542
case re_detail::RegExData::type_pf:
543
return pdata->fm[i].matched ? pdata->fm[i].second - pdata->fm[i].first : RegEx::npos;
545
case re_detail::RegExData::type_copy:
547
std::map<int, std::string, std::less<int> >::iterator pos = pdata->strings.find(i);
548
if(pos == pdata->strings.end())
550
return (*pos).second.size();
556
bool RegEx::Matched(int i)const
561
case re_detail::RegExData::type_pc:
562
return pdata->m[i].matched;
563
#ifndef BOOST_REGEX_NO_FILEITER
564
case re_detail::RegExData::type_pf:
565
return pdata->fm[i].matched;
567
case re_detail::RegExData::type_copy:
569
std::map<int, std::string, std::less<int> >::iterator pos = pdata->strings.find(i);
570
if(pos == pdata->strings.end())
579
std::string RegEx::What(int i)const
585
case re_detail::RegExData::type_pc:
586
if(pdata->m[i].matched)
587
result.assign(pdata->m[i].first, pdata->m[i].second);
589
case re_detail::RegExData::type_pf:
590
if(pdata->m[i].matched)
591
result.assign(to_string(pdata->m[i].first, pdata->m[i].second));
593
case re_detail::RegExData::type_copy:
595
std::map<int, std::string, std::less<int> >::iterator pos = pdata->strings.find(i);
596
if(pos != pdata->strings.end())
597
result = (*pos).second;
604
const unsigned int RegEx::npos = ~0u;
609
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) && (__BORLANDC__ <= 0x551) && !defined(_RWSTD_COMPILE_INSTANTIATE)
611
// this is an ugly hack to work around an ugly problem:
612
// by default this file will produce unresolved externals during
613
// linking unless _RWSTD_COMPILE_INSTANTIATE is defined (Borland bug).
614
// However if _RWSTD_COMPILE_INSTANTIATE is defined then we get separate
615
// copies of basic_string's static data in the RTL and this DLL, this messes
616
// with basic_string's memory management and results in run-time crashes,
617
// Oh sweet joy of Catch 22....
620
template<> template<>
622
basic_string<char>::replace<const char*>(char* f1, char* f2, const char* i1, const char* i2)
624
unsigned insert_pos = f1 - begin();
625
unsigned remove_len = f2 - f1;
626
unsigned insert_len = i2 - i1;
627
unsigned org_size = size();
628
if(insert_len > remove_len)
630
append(insert_len-remove_len, ' ');
631
std::copy_backward(begin() + insert_pos + remove_len, begin() + org_size, end());
632
std::copy(i1, i2, begin() + insert_pos);
636
std::copy(begin() + insert_pos + remove_len, begin() + org_size, begin() + insert_pos + insert_len);
637
std::copy(i1, i2, begin() + insert_pos);
638
erase(size() + insert_len - remove_len);