6bool FunctionBreakerC::is_define(
size_t line,
size_t pos) {
7 size_t line_size = file_content.size();
9 if (pos + 7 > line_size)
12 string token =
"#define";
14 for (
size_t j = 0; j < 7; j++) {
15 match &= file_content[line][pos + j] == token[j];
22void FunctionBreakerC::filter_mask_commentaries_and_defines(vector<vector<bool>>& mask) {
25 size_t number_lines = file_content.size();
26 bool is_open_block_comment =
false;
27 bool is_open_define =
false;
28 bool is_open_quotation_marks =
false;
29 bool is_open_line_comment =
false;
31 for (
size_t i = 0; i < number_lines; i++) {
32 auto& line = file_content[i];
33 auto& mask_line = mask[i];
34 size_t line_size = line.size();
37 for (
size_t j = 0; j < line_size; j++) {
41 if (line.back() !=
'\\') {
42 is_open_define =
false;
47 if (is_open_line_comment) {
48 for (
size_t j = 0; j < line_size; j++) {
52 if (line.back() !=
'\\') {
53 is_open_line_comment =
false;
58 for (
size_t j = 0; j < line_size; j++) {
59 if (is_open_block_comment) {
62 if (j + 1 < line_size && line[j] ==
'*' && line[j + 1] ==
'/') {
65 is_open_block_comment =
false;
70 if (is_open_quotation_marks) {
74 is_open_quotation_marks =
false;
75 }
else if (line[j] ==
'\\') {
76 if (j == line_size - 1) {
86 if (line[j] ==
'\'') {
87 assert(j + 1 < line_size &&
88 "source code does not compile, ' open but not closed");
91 if (line[j] ==
'\\') {
92 assert(j + 2 < line_size && line[j + 2] ==
'\'' &&
93 "source code does not compile, ' open but not closed");
97 assert(j + 1 < line_size && line[j + 1] ==
'\'' &&
98 "source code does not compile, ' open but not closed");
100 mask_line[j] =
false;
102 mask_line[j] =
false;
106 if (line[j] ==
'"') {
107 is_open_quotation_marks =
true;
108 mask_line[j] =
false;
112 if (line[j] ==
'/') {
113 if (j == line_size - 1) {
117 if (line[j + 1] ==
'/') {
118 for (
size_t k = j; k < line_size; k++) {
119 mask_line[k] =
false;
123 is_open_line_comment = line.back() ==
'\\';
127 if (line[j + 1] ==
'*') {
128 mask_line[j] =
false;
130 mask_line[j] =
false;
131 is_open_block_comment =
true;
136 if (is_define(i, j)) {
137 for (
size_t k = j; k < line_size; k++) {
138 mask_line[k] =
false;
142 is_open_define = line.back() ==
'\\';
148 assert(is_open_block_comment ==
false &&
149 "source code does not compile, open block comment");
150 assert(is_open_quotation_marks ==
false &&
151 "source code does not compile, open quotation marks");
155vector<vector<bool>> FunctionBreakerC::build_mask_valid_code() {
156 vector<vector<bool>> mask(file_content.size());
157 for (
size_t i = 0; i < file_content.size(); i++) {
158 mask[i] = vector<bool>(file_content[i].size(),
true);
160 filter_mask_commentaries_and_defines(mask);
164set<array<int, 5>> FunctionBreakerC::find_start_end_and_depth_of_brackets() {
165 set<array<int, 5>> start_ends;
166 int open_brackets = 0;
168 vector<pair<int, int>> not_processed_open_brackets;
169 auto process_open = [&](
int line_number,
int column) {
171 not_processed_open_brackets.push_back({line_number, column});
173 auto process_close = [&](
int line_number,
int column) {
175 if (open_brackets <= -1) {
178 auto [matched_line, matched_column] = not_processed_open_brackets.back();
179 not_processed_open_brackets.pop_back();
180 int depth_of_open = not_processed_open_brackets.size();
181 start_ends.insert({matched_line,
189 for (
size_t i = 0; i < file_content.size(); i++) {
190 auto& line = file_content[i];
191 for (
size_t j = 0; j < line.size(); j++) {
192 if (!mask_valid[i][j]) {
207set<array<int, 4>> FunctionBreakerC::find_start_end_of_brackets_of_given_depth() {
208 set<array<int, 4>> ret;
209 set<array<int, 5>> bracket_pairs = find_start_end_and_depth_of_brackets();
210 for (
auto [start_line, start_column, end_line, end_column, dep] : bracket_pairs) {
211 if (dep == C_RELEVANT_DEPTH) {
212 ret.insert({start_line, start_column, end_line, end_column});
218vector<string> FunctionBreakerC::build_function_content(
int start_number_line,
int start_column,
int end_number_line,
int end_column) {
219 vector<string> function_content;
221 if (start_number_line == end_number_line) {
223 for (
int j = start_column; j <= end_column; j++) {
224 line += file_content[start_number_line][j];
226 function_content.push_back(line);
227 return function_content;
230 string first_line = file_content[start_number_line];
231 int first_line_size = first_line.size();
232 string first_line_contribution =
"";
233 for (
int j = start_column; j < first_line_size; j++) {
234 first_line_contribution += first_line[j];
236 function_content.push_back(first_line_contribution);
238 for (
int i = start_number_line + 1; i < end_number_line; i++) {
239 function_content.push_back(file_content[i]);
242 string last_line = file_content[end_number_line];
243 string last_line_contribution =
"";
244 for (
int j = 0; j <= end_column; j++) {
245 last_line_contribution += last_line[j];
247 function_content.push_back(last_line_contribution);
249 return function_content;
252bool FunctionBreakerC::move_pointer_until_character_outside_parenteses(
int& line,
int& column) {
253 int quantity_open = 0;
254 bool has_parenteses =
false;
255 while (line != 0 || column != -1) {
258 column = file_content[line].size();
263 auto c = file_content[line][column];
264 if (!mask_valid[line][column]) {
270 has_parenteses =
true;
276 has_parenteses =
true;
286 assert(!(line == 0 && column == -1) &&
"code does not compile, bad formation of parenteses ()");
287 return has_parenteses;
291tuple<string, int, vector<string>> FunctionBreakerC::extract_header_related_information(
int start_line,
int start_column) {
292 int line = start_line;
293 int column = start_column - 1;
295 bool has_parenteses = move_pointer_until_character_outside_parenteses(line, column);
297 string file_name =
"";
298 while (column >= 0 && column < (
int)file_content[line].size()) {
299 char c = file_content[line][column];
306 reverse(file_name.begin(), file_name.end());
308 move_pointer_until_character_outside_parenteses(line, column);
310 while (column >= 0 && column < (
int)file_content[line].size() && !
Utils::is_special_char(file_content[line][column])) {
315 vector<string> header_content;
316 if (start_column == 0) {
317 header_content = build_function_content(line, column, start_line - 1, (
int)file_content[start_line - 1].size() - 1);
319 header_content = build_function_content(line, column, start_line, start_column - 1);
322 if (!ALLOW_STRUCTS && !has_parenteses) {
323 return {
"", -1, header_content};
325 return {file_name, line, header_content};
328bool FunctionBreakerC::is_body_function_empty(
int start_number_line,
int start_column,
int end_number_line,
int end_column) {
329 vector<string> function_content = build_function_content(start_number_line, start_column, end_number_line, end_column);
330 int count_not_empty_char = 0;
331 for (
auto line : function_content) {
332 for (
auto c : line) {
334 count_not_empty_char++;
338 bool is_empty = count_not_empty_char <= 2;
342void FunctionBreakerC::process_function(
int start_number_line,
346 const fs::path& relative_path) {
347 string first_line = file_content[start_number_line];
348 auto [function_name, line_declaration, header_content] = extract_header_related_information(start_number_line, start_column);
349 if (function_name.empty()) {
352 if (IGNORE_EMPTY_FUNCTIONS) {
353 if (is_body_function_empty(start_number_line, start_column, end_number_line, end_column)) {
357 vector<string> function_content = build_function_content(start_number_line, start_column, end_number_line, end_column);
359 create_source_file(start_number_line, end_number_line, relative_path, function_name, function_content);
361 create_info_file(line_declaration, start_number_line, end_number_line, relative_path, function_name);
364fs::path FunctionBreakerC::file_path_from_folder_path(
const fs::path& file_path,
const fs::path& folder_path) {
365 return fs::relative(file_path, folder_path);
368void FunctionBreakerC::file_breaker_c(
const fs::path& file_path,
const fs::path& folder_path) {
369 const fs::path& relative_path = file_path_from_folder_path(file_path, folder_path);
371 mask_valid = build_mask_valid_code();
373 set<array<int, 4>> start_end_of_functions = find_start_end_of_brackets_of_given_depth();
374 for (
auto [start_line, start_column, end_line, end_column] : start_end_of_functions) {
375 process_function(start_line, start_column, end_line, end_column, relative_path);
380 file_breaker_c(file_path, folder_path);
FunctionBreakerC(const fs::path &file_path, const fs::path &folder_path)
Constructs function breaker and processes file.
C/C++ function parsing and extraction.
void create_source_file(int start_number_line, int end_number_line, const fs::path &relative_path, const string &function_name, const vector< string > &function_content)
Creates source file for a function.
void create_info_file(int line_declaration, int start_number_line, int end_number_line, const fs::path &relative_path, const string &function_name)
Creates JSON metadata file for a function.
void create_header_file(const fs::path &relative_path, const string &function_name, const vector< string > &header_content)
Creates header file for a function.
bool is_special_char(char c)
Checks if a character is special (non-alphanumeric and not underscore)
bool is_empty_char(char c)
Checks if a character is considered empty/whitespace.
std::vector< std::string > read_file_generic(const fs::path &string_path)
Reads a file line by line into a vector of strings.