Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/regex/src/cregex.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

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