Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/regex/src/cregex.cpp @ 13

Last change on this file since 13 was 12, checked in by landauf, 17 years ago

added boost

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