Skip to content

Instantly share code, notes, and snippets.

@john01dav
Created October 7, 2019 05:33
Show Gist options
  • Save john01dav/ab2beffeb6c9af22c25dc1985f16cb15 to your computer and use it in GitHub Desktop.
Save john01dav/ab2beffeb6c9af22c25dc1985f16cb15 to your computer and use it in GitHub Desktop.
Simple Program To Count Lines of Code Of Another Program
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <filesystem>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
class extension_checker{
public:
extension_checker(int argc, char *argv[]);
bool matches(const std::string &name) const noexcept;
private:
std::vector<std::string> m_extensions;
};
bool ends_with(const std::string &str, const std::string &suffix);
unsigned long count_lines_of_code(const std::filesystem::path &file);
int main(int argc, char *argv[]) {
if(argc < 3){
std::cerr << "Usage: " << argv[0] << " <directory> <file-extension-1> [file-extension-2] [file-extension-3] ..." << std::endl;
return -1;
}
extension_checker extensionchecker(argc-2, argv+2);
unsigned long loccount = 0;
std::filesystem::path directory(argv[1]);
for(auto &file : std::filesystem::recursive_directory_iterator(directory)){
if(std::filesystem::is_regular_file(file)){
const auto &fileName = file.path().filename();
std::cout << file << "\n";
if(extensionchecker.matches(fileName)){
unsigned long currentcount = count_lines_of_code(file);
std::cout << "Found " << currentcount << " lines of code in " << file << ".\n";
loccount += currentcount;
}else{
std::cout << "Skipping " << file << " because it does not match any of the provided extensions.\n";
}
}
}
std::cout << "Counted " << loccount << " total lines of code." << std::endl;
return 0;
}
extension_checker::extension_checker(int argc, char *argv[]) {
m_extensions.reserve(argc);
for(unsigned i=0;i<argc;++i){
m_extensions.emplace_back(argv[i]);
}
}
bool extension_checker::matches(const std::string &name) const noexcept {
for(auto &extension : m_extensions){
if(ends_with(name, extension)){
return true;
}
}
return false;
}
bool ends_with(const std::string &str, const std::string &suffix){
if(str.length() < suffix.length()){
return false;
}
auto strit = str.rbegin();
for(auto it=suffix.rbegin();it!=suffix.rend();++it){
if(*it != *(strit++)){
return false;
}
}
return true;
}
unsigned long count_lines_of_code(const std::filesystem::path &file){
//reading in binary mode because we want to count the number of \n characters, and text mode does annoying formatting that makes this much more difficult
std::ifstream fin;
fin.exceptions(std::ios::badbit | std::ios::failbit);
fin.open(file, std::ios::binary | std::ios::ate);
std::vector<char> data(fin.tellg(), 0);
fin.seekg(0);
fin.read(data.data(), data.size());
return std::count(data.begin(), data.end(), '\n');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment