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