ArKanjo 0.5.1
A tool for find code duplicated functions in codebases
parser.cpp
Go to the documentation of this file.
2#include <iomanip>
3#include <iostream>
4
5Comparation::Comparation(std::string _path1, std::string _path2, double _sim) {
6 if (_path1 > _path2)
7 std::swap(_path1, _path2);
8 path1 = _path1;
9 path2 = _path2;
10 similarity = _sim;
11}
12
13bool Comparation::operator<(const Comparation& com) const {
14 if (similarity != com.similarity) {
15 return similarity > com.similarity;
16 }
17 if (path1 == com.path1) {
18 return path2 < com.path2;
19 }
20 return path1 < com.path1;
21}
22
23bool Comparation::operator==(const Comparation& com) const {
24 return path1 == com.path1 && path2 == com.path2;
25}
26
27std::vector<std::string> Parser::parser_line(const std::string& line) {
28 std::string at = "";
29 std::vector<std::string> ret;
30 for (auto c : line) {
31 if (c <= 20 || c == ' ') { // an space on non-printable char
32 if (!at.empty())
33 ret.push_back(at);
34 at = "";
35 } else {
36 at += c;
37 }
38 }
39 if (!at.empty())
40 ret.push_back(at);
41
42 return ret;
43}
44
45void removeANSI_inplace(std::string& s) {
46 size_t write = 0;
47
48 for (size_t i = 0; i < s.size(); ++i) {
49 if (s[i] == '\033' && i + 1 < s.size() && s[i + 1] == '[') {
50 i += 2;
51 while (i < s.size() && (s[i] < '@' || s[i] > '~')) {
52 i++;
53 }
54 } else {
55 s[write++] = s[i];
56 }
57 }
58
59 s.resize(write);
60}
61
62double Parser::retrive_similarity(const std::string& s) {
63 try {
64 return std::stod(s);
65 } catch (...) {
66 return 0.0;
67 }
68}
69
70void Parser::parser_block_stream(const std::string& path, const std::vector<std::string>& tokens, std::set<Comparation>& comparations) {
71 if (tokens.size() < 2)
72 return;
73
74 const std::string& path_comp = tokens[0];
75
76 if (!fs::is_regular_file(path_comp))
77 return;
78
79 double similarity = retrive_similarity(tokens[1]);
80
81 if (similarity < similarity_cap)
82 return;
83
84 Comparation com(path, path_comp, similarity);
85 comparations.insert(com);
86}
87
88void Parser::exec_from_stream(FILE* pipe) {
89 std::string line;
90 char chunk[256];
91
92 std::string path;
93
94 while (fgets(chunk, sizeof(chunk), pipe)) {
95 line += chunk;
96
97 if (!line.empty() && line.back() == '\n') {
99
100 auto tokens = parser_line(line);
101 if (tokens.size() > 2) {
102 for (auto token : tokens) {
103 if (fs::is_regular_file(token)) {
104 path = token;
105 break;
106 }
107 }
108 line.clear();
109 continue;
110 }
111
112 parser_block_stream(path, tokens, comparations);
113
114 line.clear();
115 }
116 }
117 fout << comparations.size() << '\n';
118 for (const auto& com : comparations) {
119 fout << com.path1 << ' ' << com.path2 << ' ';
120 fout << std::fixed << std::setprecision(2) << com.similarity << '\n';
121 }
122}
123
124Parser::Parser(const fs::path& output_file, double similarity_cap)
125 : fout(output_file), similarity_cap(similarity_cap) {
126
127 if (!fout) {
128 throw std::runtime_error("Failed to open output file");
129 }
130}
131
133 if (fout.is_open())
134 fout.close();
135}
void exec_from_stream(FILE *pipe)
Main parsing execution method using stream.
Definition: parser.cpp:88
~Parser()
Definition: parser.cpp:132
Parser(const fs::path &output_file, double similarity_cap)
Constructs parser with configuration.
Definition: parser.cpp:124
void removeANSI_inplace(std::string &s)
Definition: parser.cpp:45
Code duplication results parser.
Structure representing a code comparison result.
Definition: parser.hpp:29
bool operator<(const Comparation &com) const
Comparison operator for sorting.
Definition: parser.cpp:13
double similarity
Similarity score between the files (0-100)
Definition: parser.hpp:32
Comparation()
Default constructor.
Definition: parser.hpp:37
std::string path1
Path to first code file being compared.
Definition: parser.hpp:30
std::string path2
Path to second code file being compared.
Definition: parser.hpp:31
bool operator==(const Comparation &com) const
Equality comparison operator.
Definition: parser.cpp:23