#![crate_name = "doc"]
use regex::Regex;
use std::fs::{File, OpenOptions};
use std::io::prelude::*;
use std::io::{BufRead, BufReader};
use crate::prelude::*;
pub fn find_class_substring(filename: &str, class_name: &str) -> Result<String> {
let mut owned_string = "".to_owned();
let mut lines = BufReader::new(OpenOptions::new().read(true).open(filename).unwrap())
.lines()
.map(|line| line.unwrap())
.collect::<Vec<String>>();
let mut bracket_count = 0;
let mut offset = 0;
let class_string = "class ".to_owned() + class_name;
for i in 0..lines.len() {
if lines[i].contains(&class_string) {
if lines[i].contains("{") {
bracket_count += 1;
}
loop {
offset += 1;
owned_string = owned_string + &lines[i + offset];
if lines[i + offset].contains("{") {
bracket_count += 1
}
if lines[i + offset].contains("}") {
bracket_count -= 1
}
if bracket_count == 0 {
break;
}
}
break;
}
}
Ok(owned_string)
}
pub fn filter_incorrects(name: &str) -> Result<bool> {
let re = Regex::new(r"\w+\(\s+?\w+?\s+?\)").unwrap();
match re.captures(name) {
Some(x) => Ok(false),
_ => Ok(true),
}
}
pub fn find_function_names(class_string: &str) -> Result<Vec<String>> {
let re = Regex::new(r"(?:static|const|constexpr)?\s*?\w+(?:\s+|\s*\*\*?\s*|\s+\*\*?\s*|\s*\*\*?|\s+\&?\s*|\s*\&?\s+)(?:const\s*
(?:\s+|\s+\*\*?\s*|\s*\*\*?|\s+\&?\s*|\s*\&?\s+))?\w+((\n)*)\(([^.{}:=;]*)\)\s?(?:const)?(?:;|\n|\s)").unwrap();
let mut result = Vec::new();
for cap in re.captures_iter(&class_string) {
let function_name = cap.get(0).unwrap().as_str().to_string();
if filter_incorrects(&function_name).unwrap() {
let func_n = remove_whitespace(&function_name);
if func_n.contains("static ") {
continue;
}
let func_n_trim = &func_n[0..func_n.find(";").unwrap_or(func_n.len())];
result.push(func_n_trim.to_owned());
}
}
Ok(result)
}
pub fn find_c_function_names(filename: &str) -> Result<Vec<String>> {
let re = Regex::new(r"\w+(\s*?(\*\*?|\&)?\s*?)\w+((\n)*)\(([^.{}:\-=;]*)(?:;|\n)").unwrap();
let mut lines = BufReader::new(OpenOptions::new().read(true).open(filename).unwrap())
.lines()
.map(|line| line.unwrap())
.collect::<Vec<String>>();
let mut edited_lines = Vec::new();
for line in lines.iter() {
if line.contains("//") {
let split_line: Vec<&str> = line.split("//").collect();
let edit = split_line[0].trim().to_owned();
edited_lines.push(edit);
} else if line.contains("/*") {
let split_line: Vec<&str> = line.split("/*").collect();
let edit = split_line[0].trim().to_owned();
edited_lines.push(edit);
} else {
let edit = line.to_owned();
edited_lines.push(edit);
}
}
let mut file_string: String = edited_lines.join("\n");
let mut result = Vec::new();
for cap in re.captures_iter(&file_string) {
let function_name = cap.get(0).unwrap().as_str().to_string();
let function_name_trimmed = remove_whitespace(&function_name);
if function_name_trimmed.contains("return")
|| function_name_trimmed.contains("PACKED")
|| function_name_trimmed.contains("#define")
{
continue;
}
result.push(function_name_trimmed);
}
Ok(result)
}
fn remove_whitespace(s: &str) -> String {
let words: Vec<_> = s.split_whitespace().collect();
words.join(" ")
}