From 49a490061e990b2e8b84d207de8965c5cc3d6a5e Mon Sep 17 00:00:00 2001 From: zvon Date: Thu, 3 Jan 2019 19:01:43 +0100 Subject: [PATCH] C++11 --- Makefile | 9 +++-- filesystem.cpp | 29 ++++++++++++++ filesystem.hpp | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ functions.cpp | 30 +++++++------- functions.hpp | 3 +- tv_rename.cpp | 36 +++++++++-------- 6 files changed, 175 insertions(+), 38 deletions(-) create mode 100644 filesystem.cpp create mode 100644 filesystem.hpp diff --git a/Makefile b/Makefile index 0c78f60..fcc72c8 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,16 @@ CC ?= clang CXX ?= clang++ -CFLAGS ?= -O2 -g -Wall -Wextra -std=c++17 +CFLAGS ?= -O2 -g -Wall -Wextra -std=c++11 default: tv_rename # using libc++ because libstdc++ has a bug in regex that causes seg fault with long lines -tv_rename: functions.o tv_rename.cpp - $(CXX) $(CFLAGS) -stdlib=libc++ -o tv_rename tv_rename.cpp functions.o -lcurl -lc++fs +tv_rename: functions.o filesystem.o tv_rename.cpp + $(CXX) $(CFLAGS) -stdlib=libc++ -o tv_rename tv_rename.cpp functions.o filesystem.o -lcurl + +filesystem.o: filesystem.cpp + $(CXX) $(CFLAGS) -stdlib=libc++ -c filesystem.cpp functions.o: functions.cpp $(CXX) $(CFLAGS) -stdlib=libc++ -c functions.cpp diff --git a/filesystem.cpp b/filesystem.cpp new file mode 100644 index 0000000..bc6ff04 --- /dev/null +++ b/filesystem.cpp @@ -0,0 +1,29 @@ +#include "filesystem.hpp" +#include +#include +#include + +bool FSLib::exists(const std::string &path) { + struct stat path_stat; + return stat( path.c_str(), &path_stat ) == 0; +} + +bool FSLib::isDirectory(const std::string &path) { + struct stat path_stat; + stat( path.c_str(), &path_stat ); + return S_ISDIR(path_stat.st_mode); +} + +std::string FSLib::canonical(const std::string &path) { + char *canonical_path = static_cast(malloc(PATH_MAX)); + if( realpath(path.c_str(), canonical_path) == nullptr ) + return ""; + std::string canonical_string{canonical_path}; + free(canonical_path); + return canonical_string; +} + +bool FSLib::rename(const std::string &file_a, const std::string &file_b) { + return ::rename( file_a.c_str(), file_b.c_str() ) == 0; +} + diff --git a/filesystem.hpp b/filesystem.hpp new file mode 100644 index 0000000..b6d9746 --- /dev/null +++ b/filesystem.hpp @@ -0,0 +1,106 @@ +#ifndef FSLIB_H +#define FSLIB_H + +#include +#include +#include + +namespace FSLib{ + bool exists(const std::string &path); + bool isDirectory(const std::string &path); + std::string canonical(const std::string &path); + bool rename(const std::string &file_a, const std::string &file_b); + + class Directory { + public: + Directory(const std::string &path_) : dir_path(path_) {} + Directory() = delete; + Directory(const Directory &d) = default; + Directory(Directory &&d) = default; + + class Iterator { + public: + Iterator( const Directory &d_ ) : d(opendir(d_.path())) { + current_entry = readdir(d); + } + + Iterator( const Directory &d_, const struct dirent *current_entry_) : d(opendir(d_.path())), current_entry(current_entry_) {} + + Iterator() = delete; + + Iterator(const Iterator &i) = default; + + Iterator(Iterator &&i) = default; + + ~Iterator() { + closedir(d); + } + + std::string operator*() { + return current_entry->d_name; + } + + Iterator &operator++() { + if( current_entry == nullptr ) + return *this; + current_entry = readdir(d); + if( current_entry != nullptr && (!strcmp(current_entry->d_name, ".") || !strcmp(current_entry->d_name, "..")) ) + operator++(); + return *this; + } + + Iterator operator++(int) { + Iterator ret(*this); + operator++(); + return ret; + } + + bool operator==(const Iterator &i_other) { + return i_other.current_entry == current_entry; + } + + bool operator!=(const Iterator &i_other) { + return i_other.current_entry != current_entry; + } + + private: + DIR *d; + const struct dirent *current_entry; + }; + + using iterator = Iterator; + using const_iterator = Iterator; + + iterator begin() { + return Iterator(dir_path); + } + + const_iterator begin() const { + return Iterator(dir_path); + } + + const_iterator cbegin() const { + return begin(); + } + + iterator end() { + return Iterator(dir_path, nullptr); + } + + const_iterator end() const { + return Iterator(dir_path, nullptr); + } + + const_iterator cend() const { + return end(); + } + + const char *path() const { + return dir_path.c_str(); + } + private: + std::string dir_path; + }; +} //end FSLib + +#endif diff --git a/functions.cpp b/functions.cpp index b5c28d2..f86a8a2 100644 --- a/functions.cpp +++ b/functions.cpp @@ -1,4 +1,5 @@ #include "functions.hpp" +#include "filesystem.hpp" #include #include #include @@ -34,34 +35,32 @@ std::string Curl::execute(const std::string &url) { return source; } -void findSeason(std::set &files, int season, const std::string &path) { - namespace fs = std::experimental::filesystem; +void findSeason(std::set &files, int season, const std::string &path) { std::smatch match; auto episode = std::regex("[sS][0]{0,2000}" + std::to_string(season) + "[eE][0-9]{1,2000}"); - for( auto& p: fs::directory_iterator(path) ) { - if(fs::is_directory(p)) { - findSeason(files, season, p.path()); + for( const auto& p: FSLib::Directory(path) ) { + if(FSLib::isDirectory(path + "/" + p)) { + findSeason(files, season, path + "/" + p); continue; } - std::string a = p.path().filename(); - if( std::regex_search(a, episode) ) { - files.insert(p.path()); + + if( std::regex_search(p, episode) ) { + files.insert(path + "/" + p); } } } void iterateFS(std::set &seasons, const std::string &path) { - namespace fs = std::experimental::filesystem; std::smatch match; auto episode = std::regex("[sS][0-9]{1,2000}[eE][0-9]{1,2000}"); - for( auto& p: fs::directory_iterator(path) ) { - if(fs::is_directory(p)) { - iterateFS(seasons, p.path()); + for( const auto& p: FSLib::Directory(path) ) { + if(FSLib::isDirectory(path + "/" + p)) { + iterateFS(seasons, path + "/" + p); continue; } - std::string a = p.path().filename(); - if( std::regex_search(a, match, episode) ) { - a = match[0]; + + if( std::regex_search(p, match, episode) ) { + std::string a = match[0]; a = std::regex_replace(a, std::regex("[eE][0-9]{1,2000}"), ""); a = a.substr(1); seasons.insert(std::stoi(a)); @@ -70,7 +69,6 @@ void iterateFS(std::set &seasons, const std::string &path) { } std::string getDefUrl( const std::string &show, const std::string &language, Curl &c ) { - using namespace std::string_literals; auto search = std::regex_replace(show, std::regex(" "), "+"); auto source_code = c.execute("https://www.thetvdb.com/search?q=" + search + "&l=" + language); auto series = std::regex(""); diff --git a/functions.hpp b/functions.hpp index 2e62621..b8fafa7 100644 --- a/functions.hpp +++ b/functions.hpp @@ -3,7 +3,6 @@ #include #include -#include #include class Curl { @@ -16,7 +15,7 @@ private: }; std::string getDefUrl( const std::string &show, const std::string &language, Curl &c ); -void findSeason(std::set &files, int season, const std::string &path); +void findSeason(std::set &files, int season, const std::string &path); void iterateFS(std::set &seasons, const std::string &path); void printHelp(); diff --git a/tv_rename.cpp b/tv_rename.cpp index df5ef97..d294dc3 100644 --- a/tv_rename.cpp +++ b/tv_rename.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include "filesystem.hpp" void singleSeason( const std::string &path, const std::string &show, int season, std::string url ); void multipleSeasons( const std::string &path, const std::string &show, const std::set seasons ); @@ -18,7 +18,6 @@ bool linux{false}; Curl c; int main(int argc, char** argv) { - namespace fs = std::filesystem; std::map languages{ {"en", "English"}, {"sv", "Svenska"}, {"no", "Norsk"}, {"da", "Dansk"}, {"fi", "Suomeksi"}, {"nl", "Nederlands"}, {"de", "Deutsch"}, {"it", "Italiano"}, {"es", "Español"}, {"fr", "Français"}, @@ -46,7 +45,7 @@ int main(int argc, char** argv) { } else if ( !(strcmp("-sp", argv[x]) && strcmp("--show-path", argv[x])) ) { path = std::string(argv[x+1]); x++; - if( !fs::exists(fs::absolute(path)) ) + if( !FSLib::isDirectory(path) ) change_dir = true; } else if ( !(strcmp("-t", argv[x]) && strcmp("--trust", argv[x])) ) { trust = true; @@ -73,13 +72,12 @@ int main(int argc, char** argv) { } while( change_dir ) { - auto abs = fs::absolute(path); - if( !fs::exists(abs) ) { + if( !FSLib::isDirectory(path) ) { std::cout << "This directory doesn't exist, please insert a correct path: " << std::endl; std::getline(std::cin, path); continue; } - std::cout << "Is this the right directory? " << fs::canonical(abs) << std::endl; + std::cout << "Is this the right directory? " << FSLib::canonical(path) << std::endl; std::string response; std::cin >> response; std::cin.ignore(1,'\n'); @@ -92,10 +90,8 @@ int main(int argc, char** argv) { } } - path = fs::absolute(path); - if( show.empty() ) { - show = std::regex_replace(fs::canonical(path).c_str(), std::regex(".*/"), ""); + show = std::regex_replace(FSLib::canonical(path).c_str(), std::regex(".*/"), ""); std::cout << "Is this the right show name? " << show << std::endl; std::string response; std::cin >> response; @@ -155,16 +151,24 @@ void singleSeason( const std::string &path, const std::string &show, int season, } if( episodes.empty() ) return; - std::set files; - std::set renamed_files; + std::set files; + std::set renamed_files; std::vector renamed_episodes; renamed_episodes.resize(episodes.size()); findSeason(files, season, path); if( files.empty() ) return; for( const auto &x : files ) { - std::string name = x.filename(); - std::string dir = x.parent_path(); + auto last = x.find_last_of("/"); + std::string name; + std::string dir; + if( last == static_cast(-1) ) { + name = x; + dir = "."; + } else { + name = x.substr(last+1); + dir = x.substr(0, last); + } unsigned long num; try { num = std::stoi(std::regex_replace(name, std::regex(".*[sS][0]{0,2000}" + std::to_string(season) + "[eE]([0-9]{1,2000}).*"), "$1")); @@ -185,9 +189,8 @@ void singleSeason( const std::string &path, const std::string &show, int season, } } auto orig = files.begin(); - namespace fs = std::experimental::filesystem; for(auto renamed = renamed_files.begin(); renamed != renamed_files.end(); ++renamed) { - std::cout << std::string((*orig).filename()) << " -> " << std::string((*renamed).filename()) << std::endl; + std::cout << *orig << " -> " << *renamed << std::endl; ++orig; } if( !trust ) { @@ -200,9 +203,8 @@ void singleSeason( const std::string &path, const std::string &show, int season, return; } orig = files.begin(); - namespace fs = std::experimental::filesystem; for(auto renamed = renamed_files.begin(); renamed != renamed_files.end(); ++renamed) { - fs::rename(*orig, *renamed); + FSLib::rename(*orig, *renamed); ++orig; } }