]> git.lyx.org Git - lyx.git/blob - boost/libs/regex/src/cregex.cpp
bdfd751ff77b32e15e67ae7390039f62770adf1b
[lyx.git] / boost / libs / regex / src / cregex.cpp
1 /*
2  *
3  * Copyright (c) 1998-2002
4  * Dr John Maddock
5  *
6  * Use, modification and distribution are subject to the 
7  * Boost Software License, Version 1.0. (See accompanying file 
8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  */
11
12  /*
13   *   LOCATION:    see http://www.boost.org for most recent version.
14   *   FILE:        cregex.cpp
15   *   VERSION:     see <boost/version.hpp>
16   *   DESCRIPTION: Implements high level class boost::RexEx
17   */
18
19
20 #define BOOST_REGEX_SOURCE
21
22 #include <boost/cregex.hpp>
23 #include <boost/regex.hpp>
24 #if !defined(BOOST_NO_STD_STRING)
25 #include <map>
26 #include <list>
27 #ifdef BOOST_REGEX_V3
28 #include <boost/regex/v3/fileiter.hpp>
29 typedef unsigned match_flag_type;
30 #else
31 #include <boost/regex/v4/fileiter.hpp>
32 typedef boost::match_flag_type match_flag_type;
33 #endif
34 #include <cstdio>
35
36 namespace boost{
37
38 #ifdef __BORLANDC__
39 #if __BORLANDC__ < 0x530
40 //
41 // we need to instantiate the vector classes we use
42 // since declaring a reference to type doesn't seem to
43 // do the job...
44 std::vector<std::size_t> inst1;
45 std::vector<std::string> inst2;
46 #endif
47 #endif
48
49 namespace{
50
51 template <class iterator>
52 std::string to_string(iterator i, iterator j)
53 {
54    BOOST_RE_GUARD_STACK
55    std::string s;
56    while(i != j)
57    {
58       s.append(1, *i);
59       ++i;
60    }
61    return s;
62 }
63
64 inline std::string to_string(const char* i, const char* j)
65 {
66    return std::string(i, j);
67 }
68
69 }
70 namespace re_detail{
71
72 class RegExData
73 {
74 public:
75    enum type
76    {
77       type_pc,
78       type_pf,
79       type_copy
80    };
81    regex e;
82    cmatch m;
83 #ifndef BOOST_REGEX_NO_FILEITER
84    match_results<mapfile::iterator> fm;
85 #endif
86    type t;
87    const char* pbase;
88 #ifndef BOOST_REGEX_NO_FILEITER
89    mapfile::iterator fbase;
90 #endif
91    std::map<int, std::string, std::less<int> > strings;
92    std::map<int, std::ptrdiff_t, std::less<int> > positions;
93    void update();
94    void clean();
95    RegExData() : e(), m(),
96 #ifndef BOOST_REGEX_NO_FILEITER
97    fm(),
98 #endif
99    t(type_copy), pbase(0),
100 #ifndef BOOST_REGEX_NO_FILEITER
101    fbase(),
102 #endif
103    strings(), positions() {}
104 };
105
106 void RegExData::update()
107 {
108    BOOST_RE_GUARD_STACK
109    strings.erase(strings.begin(), strings.end());
110    positions.erase(positions.begin(), positions.end());
111    if(t == type_pc)
112    {
113       for(unsigned int i = 0; i < m.size(); ++i)
114       {
115          if(m[i].matched) strings[i] = std::string(m[i].first, m[i].second);
116          positions[i] = m[i].matched ? m[i].first - pbase : -1;
117       }
118    }
119 #ifndef BOOST_REGEX_NO_FILEITER
120    else
121    {
122       for(unsigned int i = 0; i < fm.size(); ++i)
123       {
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;
126       }
127    }
128 #endif
129    t = type_copy;
130 }
131
132 void RegExData::clean()
133 {
134    BOOST_RE_GUARD_STACK
135 #ifndef BOOST_REGEX_NO_FILEITER
136    fbase = mapfile::iterator();
137    fm = match_results<mapfile::iterator>();
138 #endif
139 }
140
141 } // namespace
142
143 RegEx::RegEx()
144 {
145    BOOST_RE_GUARD_STACK
146    pdata = new re_detail::RegExData();
147 }
148
149 RegEx::RegEx(const RegEx& o)
150 {
151    BOOST_RE_GUARD_STACK
152    pdata = new re_detail::RegExData(*(o.pdata));
153 }
154
155 RegEx::~RegEx()
156 {
157    BOOST_RE_GUARD_STACK
158    delete pdata;
159 }
160
161 RegEx::RegEx(const char* c, bool icase)
162 {
163    BOOST_RE_GUARD_STACK
164    pdata = new re_detail::RegExData();
165    SetExpression(c, icase);
166 }
167
168 RegEx::RegEx(const std::string& s, bool icase)
169 {
170    BOOST_RE_GUARD_STACK
171    pdata = new re_detail::RegExData();
172    SetExpression(s.c_str(), icase);
173 }
174
175 RegEx& RegEx::operator=(const RegEx& o)
176 {
177    BOOST_RE_GUARD_STACK
178    *pdata = *(o.pdata);
179    return *this;
180 }
181
182 RegEx& RegEx::operator=(const char* p)
183 {
184    BOOST_RE_GUARD_STACK
185    SetExpression(p, false);
186    return *this;
187 }
188
189 unsigned int RegEx::SetExpression(const char* p, bool icase)
190 {
191    BOOST_RE_GUARD_STACK
192    boost::uint_fast32_t f = icase ? regex::normal | regex::use_except | regex::icase : regex::normal | regex::use_except;
193    return pdata->e.set_expression(p, f);
194 }
195
196 unsigned int RegEx::error_code()const
197 {
198    return pdata->e.error_code();
199 }
200
201
202 std::string RegEx::Expression()const
203 {
204    BOOST_RE_GUARD_STACK
205    return pdata->e.expression();
206 }
207
208 //
209 // now matching operators:
210 //
211 bool RegEx::Match(const char* p, match_flag_type flags)
212 {
213    BOOST_RE_GUARD_STACK
214    pdata->t = re_detail::RegExData::type_pc;
215    pdata->pbase = p;
216    const char* end = p;
217    while(*end)++end;
218
219    if(regex_match(p, end, pdata->m, pdata->e, flags))
220    {
221       pdata->update();
222       return true;
223    }
224    return false;
225 }
226
227 bool RegEx::Search(const char* p, match_flag_type flags)
228 {
229    BOOST_RE_GUARD_STACK
230    pdata->t = re_detail::RegExData::type_pc;
231    pdata->pbase = p;
232    const char* end = p;
233    while(*end)++end;
234
235    if(regex_search(p, end, pdata->m, pdata->e, flags))
236    {
237       pdata->update();
238       return true;
239    }
240    return false;
241 }
242 namespace re_detail{
243 struct pred1
244 {
245    GrepCallback cb;
246    RegEx* pe;
247    pred1(GrepCallback c, RegEx* i) : cb(c), pe(i) {}
248    bool operator()(const cmatch& m)
249    {
250       pe->pdata->m = m;
251       return cb(*pe);
252    }
253 };
254 }
255 unsigned int RegEx::Grep(GrepCallback cb, const char* p, match_flag_type flags)
256 {
257    BOOST_RE_GUARD_STACK
258    pdata->t = re_detail::RegExData::type_pc;
259    pdata->pbase = p;
260    const char* end = p;
261    while(*end)++end;
262
263    unsigned int result = regex_grep(re_detail::pred1(cb, this), p, end, pdata->e, flags);
264    if(result)
265       pdata->update();
266    return result;
267 }
268 namespace re_detail{
269 struct pred2
270 {
271    std::vector<std::string>& v;
272    RegEx* pe;
273    pred2(std::vector<std::string>& o, RegEx* e) : v(o), pe(e) {}
274    bool operator()(const cmatch& m)
275    {
276       pe->pdata->m = m;
277       v.push_back(std::string(m[0].first, m[0].second));
278       return true;
279    }
280 private:
281    pred2& operator=(const pred2&);
282 };
283 }
284
285 unsigned int RegEx::Grep(std::vector<std::string>& v, const char* p, match_flag_type flags)
286 {
287    BOOST_RE_GUARD_STACK
288    pdata->t = re_detail::RegExData::type_pc;
289    pdata->pbase = p;
290    const char* end = p;
291    while(*end)++end;
292
293    unsigned int result = regex_grep(re_detail::pred2(v, this), p, end, pdata->e, flags);
294    if(result)
295       pdata->update();
296    return result;
297 }
298 namespace re_detail{
299 struct pred3
300 {
301    std::vector<std::size_t>& v;
302    const char* base;
303    RegEx* pe;
304    pred3(std::vector<std::size_t>& o, const char* pb, RegEx* p) : v(o), base(pb), pe(p) {}
305    bool operator()(const cmatch& m)
306    {
307       pe->pdata->m = m;
308       v.push_back(static_cast<std::size_t>(m[0].first - base));
309       return true;
310    }
311 private:
312    pred3& operator=(const pred3&);
313 };
314 }
315 unsigned int RegEx::Grep(std::vector<std::size_t>& v, const char* p, match_flag_type flags)
316 {
317    BOOST_RE_GUARD_STACK
318    pdata->t = re_detail::RegExData::type_pc;
319    pdata->pbase = p;
320    const char* end = p;
321    while(*end)++end;
322
323    unsigned int result = regex_grep(re_detail::pred3(v, p, this), p, end, pdata->e, flags);
324    if(result)
325       pdata->update();
326    return result;
327 }
328 #ifndef BOOST_REGEX_NO_FILEITER
329 namespace re_detail{
330 struct pred4
331 {
332    GrepFileCallback cb;
333    RegEx* pe;
334    const char* file;
335    bool ok;
336    pred4(GrepFileCallback c, RegEx* i, const char* f) : cb(c), pe(i), file(f), ok(true) {}
337    bool operator()(const match_results<mapfile::iterator>& m)
338    {
339       pe->pdata->t = RegExData::type_pf;
340       pe->pdata->fm = m;
341       pe->pdata->update();
342       ok = cb(file, *pe);
343       return ok;
344    }
345 };
346 }
347 namespace{
348 void BuildFileList(std::list<std::string>* pl, const char* files, bool recurse)
349 {
350    BOOST_RE_GUARD_STACK
351    file_iterator start(files);
352    file_iterator end;
353    if(recurse)
354    {
355       // go through sub directories:
356       char buf[MAX_PATH];
357       std::strcpy(buf, start.root());
358       if(*buf == 0)
359       {
360          std::strcpy(buf, ".");
361          std::strcat(buf, directory_iterator::separator());
362          std::strcat(buf, "*");
363       }
364       else
365       {
366          std::strcat(buf, directory_iterator::separator());
367          std::strcat(buf, "*");
368       }
369       directory_iterator dstart(buf);
370       directory_iterator dend;
371
372       // now get the file mask bit of "files":
373       const char* ptr = files;
374       while(*ptr) ++ptr;
375       while((ptr != files) && (*ptr != *directory_iterator::separator()) && (*ptr != '/'))--ptr;
376       if(ptr != files) ++ptr;
377
378       while(dstart != dend)
379       {
380          std::sprintf(buf, "%s%s%s", dstart.path(), directory_iterator::separator(), ptr);
381          BuildFileList(pl, buf, recurse);
382          ++dstart;
383       }
384    }
385    while(start != end)
386    {
387       pl->push_back(*start);
388       ++start;
389    }
390 }
391 }
392
393 unsigned int RegEx::GrepFiles(GrepFileCallback cb, const char* files, bool recurse, match_flag_type flags)
394 {
395    BOOST_RE_GUARD_STACK
396    unsigned int result = 0;
397    std::list<std::string> file_list;
398    BuildFileList(&file_list, files, recurse);
399    std::list<std::string>::iterator start, end;
400    start = file_list.begin();
401    end = file_list.end();
402
403    while(start != end)
404    {
405       mapfile map((*start).c_str());
406       pdata->t = re_detail::RegExData::type_pf;
407       pdata->fbase = map.begin();
408       re_detail::pred4 pred(cb, this, (*start).c_str());
409       int r = regex_grep(pred, map.begin(), map.end(), pdata->e, flags);
410       result += r;
411       ++start;
412       pdata->clean();
413       if(pred.ok == false)
414          return result;
415    }
416
417    return result;
418 }
419
420
421 unsigned int RegEx::FindFiles(FindFilesCallback cb, const char* files, bool recurse, match_flag_type flags)
422 {
423    BOOST_RE_GUARD_STACK
424    unsigned int result = 0;
425    std::list<std::string> file_list;
426    BuildFileList(&file_list, files, recurse);
427    std::list<std::string>::iterator start, end;
428    start = file_list.begin();
429    end = file_list.end();
430
431    while(start != end)
432    {
433       mapfile map((*start).c_str());
434       pdata->t = re_detail::RegExData::type_pf;
435       pdata->fbase = map.begin();
436
437       if(regex_search(map.begin(), map.end(), pdata->fm, pdata->e, flags))
438       {
439          ++result;
440          if(false == cb((*start).c_str()))
441             return result;
442       }
443       //pdata->update();
444       ++start;
445       //pdata->clean();
446    }
447
448    return result;
449 }
450 #endif
451
452 #ifdef BOOST_REGEX_V3
453 #define regex_replace regex_merge
454 #endif
455
456 std::string RegEx::Merge(const std::string& in, const std::string& fmt,
457                     bool copy, match_flag_type flags)
458 {
459    std::string result;
460    re_detail::string_out_iterator<std::string> i(result);
461    if(!copy) flags |= format_no_copy;
462    regex_replace(i, in.begin(), in.end(), pdata->e, fmt.c_str(), flags);
463    return result;
464 }
465
466 std::string RegEx::Merge(const char* in, const char* fmt,
467                     bool copy, match_flag_type flags)
468 {
469    std::string result;
470    if(!copy) flags |= format_no_copy;
471    re_detail::string_out_iterator<std::string> i(result);
472    regex_replace(i, in, in + std::strlen(in), pdata->e, fmt, flags);
473    return result;
474 }
475
476 std::size_t RegEx::Split(std::vector<std::string>& v, 
477                       std::string& s,
478                       match_flag_type flags,
479                       unsigned max_count)
480 {
481    return regex_split(std::back_inserter(v), s, pdata->e, flags, max_count);
482 }
483
484
485
486 //
487 // now operators for returning what matched in more detail:
488 //
489 std::size_t RegEx::Position(int i)const
490 {
491    BOOST_RE_GUARD_STACK
492    switch(pdata->t)
493    {
494    case re_detail::RegExData::type_pc:
495       return pdata->m[i].matched ? pdata->m[i].first - pdata->pbase : RegEx::npos;
496 #ifndef BOOST_REGEX_NO_FILEITER
497    case re_detail::RegExData::type_pf:
498       return pdata->fm[i].matched ? pdata->fm[i].first - pdata->fbase : RegEx::npos;
499 #endif
500    case re_detail::RegExData::type_copy:
501       {
502       std::map<int, std::ptrdiff_t, std::less<int> >::iterator pos = pdata->positions.find(i);
503       if(pos == pdata->positions.end())
504          return RegEx::npos;
505       return (*pos).second;
506       }
507    }
508    return RegEx::npos;
509 }
510
511 unsigned int RegEx::Marks()const
512 {
513    BOOST_RE_GUARD_STACK
514    return pdata->e.mark_count();
515 }
516
517
518 std::size_t RegEx::Length(int i)const
519 {
520    BOOST_RE_GUARD_STACK
521    switch(pdata->t)
522    {
523    case re_detail::RegExData::type_pc:
524       return pdata->m[i].matched ? pdata->m[i].second - pdata->m[i].first : RegEx::npos;
525 #ifndef BOOST_REGEX_NO_FILEITER
526    case re_detail::RegExData::type_pf:
527       return pdata->fm[i].matched ? pdata->fm[i].second - pdata->fm[i].first : RegEx::npos;
528 #endif
529    case re_detail::RegExData::type_copy:
530       {
531       std::map<int, std::string, std::less<int> >::iterator pos = pdata->strings.find(i);
532       if(pos == pdata->strings.end())
533          return RegEx::npos;
534       return (*pos).second.size();
535       }
536    }
537    return RegEx::npos;
538 }
539
540 bool RegEx::Matched(int i)const
541 {
542    BOOST_RE_GUARD_STACK
543    switch(pdata->t)
544    {
545    case re_detail::RegExData::type_pc:
546       return pdata->m[i].matched;
547 #ifndef BOOST_REGEX_NO_FILEITER
548    case re_detail::RegExData::type_pf:
549       return pdata->fm[i].matched;
550 #endif      
551    case re_detail::RegExData::type_copy:
552       {
553       std::map<int, std::string, std::less<int> >::iterator pos = pdata->strings.find(i);
554       if(pos == pdata->strings.end())
555          return false;
556       return true;
557       }
558    }
559    return false;
560 }
561
562
563 std::string RegEx::What(int i)const
564 {
565    BOOST_RE_GUARD_STACK
566    std::string result;
567    switch(pdata->t)
568    {
569    case re_detail::RegExData::type_pc:
570       if(pdata->m[i].matched) 
571          result.assign(pdata->m[i].first, pdata->m[i].second);
572       break;
573    case re_detail::RegExData::type_pf:
574       if(pdata->m[i].matched) 
575          result.assign(to_string(pdata->m[i].first, pdata->m[i].second));
576       break;
577    case re_detail::RegExData::type_copy:
578       {
579       std::map<int, std::string, std::less<int> >::iterator pos = pdata->strings.find(i);
580       if(pos != pdata->strings.end())
581          result = (*pos).second;
582       break;
583       }
584    }
585    return result;
586 }
587
588 const unsigned int RegEx::npos = ~0u;
589
590
591 } // namespace boost
592
593 #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) && (__BORLANDC__ <= 0x551) && !defined(_RWSTD_COMPILE_INSTANTIATE)
594 //
595 // this is an ugly hack to work around an ugly problem:
596 // by default this file will produce unresolved externals during
597 // linking unless _RWSTD_COMPILE_INSTANTIATE is defined (Borland bug).
598 // However if _RWSTD_COMPILE_INSTANTIATE is defined then we get separate
599 // copies of basic_string's static data in the RTL and this DLL, this messes
600 // with basic_string's memory management and results in run-time crashes,
601 // Oh sweet joy of Catch 22....
602 //
603 namespace std{
604 template<> template<>
605 basic_string<char>&
606 basic_string<char>::replace<const char*>(char* f1, char* f2, const char* i1, const char* i2)
607 {
608    unsigned insert_pos = f1 - begin();
609    unsigned remove_len = f2 - f1;
610    unsigned insert_len = i2 - i1;
611    unsigned org_size = size();
612    if(insert_len > remove_len)
613    {
614       append(insert_len-remove_len, ' ');
615       std::copy_backward(begin() + insert_pos + remove_len, begin() + org_size, end());
616       std::copy(i1, i2, begin() + insert_pos);
617    }
618    else
619    {
620       std::copy(begin() + insert_pos + remove_len, begin() + org_size, begin() + insert_pos + insert_len);
621       std::copy(i1, i2, begin() + insert_pos);
622       erase(size() + insert_len - remove_len);
623    }
624    return *this;
625 }
626 }
627 #endif
628
629 #endif
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644