-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcpp-primer-output-orgmode.cpp
More file actions
145 lines (136 loc) · 3.64 KB
/
cpp-primer-output-orgmode.cpp
File metadata and controls
145 lines (136 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <iostream>
#include <fstream>
#include <sstream>
#include <set>
#include <map>
#include <string>
#include <cstring>
using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::istringstream;
using std::set;
using std::map;
using std::string;
using std::to_string;
using std::getline;
using std::ispunct;
bool is_include_using_line(const string &line);
void handle_reference_files(const string &chapter_path, const map<string, bool> &m, ofstream &ofs)
{
string file_path;
for(const auto &p : m)
{
if(!p.second) continue;
file_path = chapter_path + "/" + p.first;
string line;
ifstream ifs(file_path);
ofs << "* " + p.first + "\n\n";
ofs << "#+begin_src c++\n";
while(ifs)
{
getline(ifs, line);
if(!line.size() || is_include_using_line(line)) continue;
ofs << " " << line << "\n";
}
ofs << "#+end_src\n\n";
}
}
map<string, bool> get_reference_names(const string &line, set<string> &rset)
{
map<string, bool> ms;
istringstream iss(line);
string name;
while(iss >> name)
{
if((name.find(".cpp") != string::npos)
|| (name.find(".h")) != string::npos)
{
if(ispunct(name[name.size() - 1]))
name.erase(name.size() - 1);
if(rset.find(name) == rset.end())
{
ms[name] = true;
rset.insert(name);
}
else
ms[name] = false;
}
}
return ms;
}
bool is_file_reference(const string &line)
{
return (line.find("//") != string::npos)
&& ((line.find(".h") != string::npos)
|| (line.find(".cpp") != string::npos))
&& ((line.find("see") != string::npos)
|| (line.find("See") != string::npos));
}
bool is_include_using_line(const string &line)
{
return (line.find("#include") != string::npos)
|| (line.find("using std") != string::npos);
}
map<string, bool> handle_cpp_file(const string &file_name, ifstream &ifs, ofstream &ofs, set<string> &rset)
{
string line;
ofs << "* Exercise " + file_name + "\n\n";
ofs << "#+begin_src c++\n";
map<string, bool> m;
while(ifs)
{
getline(ifs, line);
if(!line.size() || is_include_using_line(line)) continue;
// There is one single line like "See xxx.h and xxx.cpp"
if(is_file_reference(line)) m = get_reference_names(line, rset);
ofs << " " << line << "\n";
}
ofs << "#+end_src\n\n";
return m;
}
void handle_cpp_files(const string &project_root, unsigned chapter_no, ofstream &ofs)
{
set<string> reference_files;
string chapter_path = project_root + "/chapter-" + to_string(chapter_no);
unsigned file_no = 1;
string file_name = to_string(chapter_no) + "." + to_string(file_no);
string file_path = chapter_path + "/" + file_name + ".cpp";
ifstream ifs(file_path);
while(ifs)
{
auto m = handle_cpp_file(file_name, ifs, ofs, reference_files);
for(const auto &p : m)
if(!p.second) ofs << "[[" + p.first + "]]\n\n";
handle_reference_files(chapter_path, m, ofs);
++file_no;
file_name = to_string(chapter_no) + "." + to_string(file_no);
file_path = chapter_path + "/" + file_name + ".cpp";
ifs.close();
ifs.open(file_path);
}
}
int main()
{
string project_root;
cout << "Specify project root path: ";
cin >> project_root;
unsigned first, last;
cout << "Specify first chpater and last chapter number: " << endl;
cin >> first >> last;
string chapter_path;
string output_path;
ofstream ofs;
while(first <= last)
{
output_path = project_root
+ "/Cpp-Primer-5th-Exercises-Chapter-" + to_string(first)
+ ".org";
ofs.open(output_path, ofstream::app);
handle_cpp_files(project_root, first, ofs);
++first;
ofs.close();
}
}