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         regex_grep_example_4.cpp
15   *   VERSION      see <boost/version.hpp>
16   *   DESCRIPTION: regex_grep example 4: searches a cpp file for class definitions,
17   *                using a C++ Builder closure as a callback.
18   */
19 
20 #ifdef __BORLANDC__
21 
22 #include <string>
23 #include <map>
24 #include <boost/regex.hpp>
25 #include <functional>
26 
27 // purpose:
28 // takes the contents of a file in the form of a string
29 // and searches for all the C++ class definitions, storing
30 // their locations in a map of strings/int's
31 
32 typedef std::map<std::string, int, std::less<std::string> > map_type;
33 
34 const char* re =
35    // possibly leading whitespace:
36    "^[[:space:]]*"
37    // possible template declaration:
38    "(template[[:space:]]*<[^;:{]+>[[:space:]]*)?"
39    // class or struct:
40    "(class|struct)[[:space:]]*"
41    // leading declspec macros etc:
42    "("
43       "\\<\\w+\\>"
44       "("
45          "[[:blank:]]*\\([^)]*\\)"
46       ")?"
47       "[[:space:]]*"
48    ")*"
49    // the class name
50    "(\\<\\w*\\>)[[:space:]]*"
51    // template specialisation parameters
52    "(<[^;:{]+>)?[[:space:]]*"
53    // terminate in { or :
54    "(\\{|:[^;\\{()]*\\{)";
55 
56 
57 class class_index
58 {
59    boost::regex expression;
60    map_type index;
61    std::string::const_iterator base;
62    typedef boost::match_results<std::string::const_iterator> arg_type;
63 
64    bool grep_callback(const boost::match_results<std::string::const_iterator>& what);
65 public:
get_map()66    map_type& get_map() { return index; }
67    typedef bool (__closure* grep_callback_type)(const arg_type&);
68    void IndexClasses(const std::string& file);
class_index()69    class_index()
70       : index(),
71         expression(re)
72         {}
73 };
74 
grep_callback(const boost::match_results<std::string::const_iterator> & what)75 bool class_index::grep_callback(const boost::match_results<std::string::const_iterator>& what)
76 {
77    // what[0] contains the whole string
78    // what[5] contains the class name.
79    // what[6] contains the template specialisation if any.
80    // add class name and position to map:
81    index[std::string(what[5].first, what[5].second) + std::string(what[6].first, what[6].second)] =
82                what[5].first - base;
83    return true;
84 }
85 
IndexClasses(const std::string & file)86 void class_index::IndexClasses(const std::string& file)
87 {
88    std::string::const_iterator start, end;
89    start = file.begin();
90    end = file.end();
91    base = start;
92    class_index::grep_callback_type cl = &(this->grep_callback);
93    boost::regex_grep(cl,
94             start,
95             end,
96             expression);
97 }
98 
99 
100 #include <fstream>
101 #include <iostream>
102 
103 using namespace std;
104 
load_file(std::string & s,std::istream & is)105 void load_file(std::string& s, std::istream& is)
106 {
107    s.erase();
108    if(is.bad()) return;
109    s.reserve(is.rdbuf()->in_avail());
110    char c;
111    while(is.get(c))
112    {
113       if(s.capacity() == s.size())
114          s.reserve(s.capacity() * 3);
115       s.append(1, c);
116    }
117 }
118 
main(int argc,const char ** argv)119 int main(int argc, const char** argv)
120 {
121    std::string text;
122    for(int i = 1; i < argc; ++i)
123    {
124       cout << "Processing file " << argv[i] << endl;
125       std::ifstream fs(argv[i]);
126       load_file(text, fs);
127       fs.close();
128       class_index i;
129       i.IndexClasses(text);
130       cout << i.get_map().size() << " matches found" << endl;
131       map_type::iterator c, d;
132       c = i.get_map().begin();
133       d = i.get_map().end();
134       while(c != d)
135       {
136          cout << "class \"" << (*c).first << "\" found at index: " << (*c).second << endl;
137          ++c;
138       }
139    }
140    return 0;
141 }
142 
143 #else  // __BORLANDC__
144 
main()145 int main()
146 {
147    return 0;
148 }
149 
150 
151 #endif
152 
153 
154 
155 
156