From 1095b44561698e37f95e4ab36232398762d98303 Mon Sep 17 00:00:00 2001 From: Dup4 Date: Tue, 28 Jun 2022 13:37:58 +0800 Subject: [PATCH] refactor: split files --- include/snapshot/internal/file_utility.h | 178 ++++++++++ include/snapshot/internal/string_utility.h | 160 +++++++++ include/snapshot/internal/system_utility.h | 40 +++ include/snapshot/internal/utility.h | 46 +++ include/snapshot/snapshot.h | 384 +-------------------- test/CMakeLists.txt | 8 +- test/{ => internal}/file_utility_test.cc | 0 test/{ => internal}/string_utility_test.cc | 0 test/{ => internal}/system_utility_test.cc | 0 test/{ => internal}/utility_test.cc | 0 10 files changed, 433 insertions(+), 383 deletions(-) create mode 100644 include/snapshot/internal/file_utility.h create mode 100644 include/snapshot/internal/string_utility.h create mode 100644 include/snapshot/internal/system_utility.h create mode 100644 include/snapshot/internal/utility.h rename test/{ => internal}/file_utility_test.cc (100%) rename test/{ => internal}/string_utility_test.cc (100%) rename test/{ => internal}/system_utility_test.cc (100%) rename test/{ => internal}/utility_test.cc (100%) diff --git a/include/snapshot/internal/file_utility.h b/include/snapshot/internal/file_utility.h new file mode 100644 index 0000000..49f6ddb --- /dev/null +++ b/include/snapshot/internal/file_utility.h @@ -0,0 +1,178 @@ +#ifndef SNAPSHOT_INTERNAL_FILE_UTILITY_H +#define SNAPSHOT_INTERNAL_FILE_UTILITY_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace snapshot { + +class FileUtility { +public: + // Create folder + // If the directory does not exist, it will be created recursively + static bool Mkdir(const std::string& path) { + // if the path exists in its entirety + // there is no need to create it + if (access(path.c_str(), F_OK) == 0) { + return true; + } + + if (path.length() == 0) { + return false; + } + + size_t len = path.length(); + size_t idx = 0; + int pos = -1; + + if (path[0] == '/') { + ++pos; + } + + auto __mkdir = [](const std::string& path) -> bool { + if (access(path.c_str(), F_OK) == 0) { + return true; + } + + auto ret = mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + + // if the path already exists + // don't consider creation failed + if (ret == 0 || errno == EEXIST) { + return true; + } + + return false; + }; + + while (true) { + size_t cur_pos = path.find('/', pos + 1); + pos = static_cast(cur_pos); + + if (cur_pos == std::string::npos) { + break; + } + + auto _path = path.substr(0, pos); + + if (!__mkdir(_path)) { + return false; + } + + idx = pos + 1; + } + + if (idx < len) { + if (!__mkdir(path)) { + return false; + } + } + + return true; + }; + + static int RemoveFile(const std::string& path) { + return removeFile(path.c_str()); + } + + static int RemoveDirectory(const std::string& path) { + return removeDirectory(path.c_str()); + } + + static std::vector GetAllLines(const std::string& file_path) { + std::vector res; + std::string tmp_s; + + std::ifstream read_file(file_path); + + while (!read_file.eof()) { + getline(read_file, tmp_s); + res.push_back(tmp_s); + } + + read_file.close(); + return res; + } + + static void RewriteFile(const std::string& file_path, const std::string& content) { + std::ofstream file; + file.open(file_path, std::ofstream::out | std::ofstream::trunc); + file.write(content.c_str(), static_cast(content.length())); + file.close(); + } + + static void AppendFile(const std::string& file_path, const std::string& content) { + std::ofstream file; + file.open(file_path, std::ofstream::out | std::ofstream::ate | std::ofstream::app); + file.write(content.c_str(), static_cast(content.length())); + file.close(); + } + +private: + static int removeFile(const char* path) { + if (access(path, F_OK) != 0) { + return 0; + } + + return remove(path); + } + + static int removeDirectory(const char* path) { + DIR* d = opendir(path); + size_t path_len = strlen(path); + int r = -1; + + if (d) { + struct dirent* p = nullptr; + + r = 0; + while (!r && (p = readdir(d))) { + int r2 = -1; + char* buf = nullptr; + size_t len = 0; + + /* Skip the names "." and ".." as we don't want to recurse on them. */ + if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) { + continue; + } + + len = path_len + strlen(p->d_name) + 2; + buf = (char*)malloc(len); + + if (buf) { + struct stat statbuf; + + snprintf(buf, len, "%s/%s", path, p->d_name); + if (!stat(buf, &statbuf)) { + if (S_ISDIR(statbuf.st_mode)) { + r2 = removeDirectory(buf); + } else { + r2 = unlink(buf); + } + } + free(buf); + } + + r = r2; + } + + closedir(d); + } + + if (!r) { + r = rmdir(path); + } + + return r; + } +}; + +} // namespace snapshot + +#endif // SNAPSHOT_INTERNAL_FILE_UTILITY_H diff --git a/include/snapshot/internal/string_utility.h b/include/snapshot/internal/string_utility.h new file mode 100644 index 0000000..5965095 --- /dev/null +++ b/include/snapshot/internal/string_utility.h @@ -0,0 +1,160 @@ +#ifndef SNAPSHOT_INTERNAL_STRING_UTILITY_H_ +#define SNAPSHOT_INTERNAL_STRING_UTILITY_H_ + +#include +#include +#include +#include + +namespace snapshot { + +class StringUtility { + friend class StringUtilityTest; + +public: + template + class HasStdToString { + private: + template + static auto check(int) -> decltype(std::to_string(std::declval()), std::true_type()); + + template + static std::false_type check(...); + + public: + enum { value = std::is_same(0)), std::true_type>::value }; + }; + +public: + template ::value, bool> = true> + static std::string ToString(const T& t) { + return std::to_string(t); + } + + template ::value, bool> = true> + static std::string ToString(const T& t) { + std::stringstream ss; + std::string s; + ss << t; + ss >> s; + return ss.str(); + } + + static std::string ToString(bool value) { + return value ? "true" : "false"; + } + + static std::string ToString(const char* s) { + if (hasEscapeCharacter(s)) { + return std::string("R\"(") + s + std::string(")\""); + } else { + return std::string("\"") + s + std::string("\""); + } + } + + static std::string ToString(const std::string& s) { + return std::string("std::string(") + ToString(s.c_str()) + std::string(")"); + } + + template + static std::string ToString(const std::pair& v) { + std::string res = "{"; + res += ToString(v.first); + res += ", "; + res += ToString(v.second); + res += "}"; + return res; + } + + template + static std::string ToString(const std::vector& v) { + if (v.empty()) { + return "{}"; + } + + std::vector string_vec = getStringVector(v); + char delimiter = ','; + + std::string res = "{\n"; + + for (const auto& s : string_vec) { + res += " "; + res += s; + res += delimiter; + res += "\n"; + } + + res += "}\n"; + + return res; + } + + static std::vector Split(const std::string& s, const char delimiter) { + std::vector res; + int len = static_cast(s.length()); + + std::string t = ""; + for (int i = 0; i <= len; i++) { + if (i == len || s[i] == delimiter) { + res.push_back(t); + t = ""; + } else { + t += s[i]; + } + } + + return res; + } + + static std::string Join(const std::vector& ss, const char delimiter) { + std::string res = ""; + for (size_t i = 0; i < ss.size(); i++) { + if (i) { + res += delimiter; + } + + res += ss[i]; + } + + return res; + } + +private: + template + static std::vector getStringVector(const std::vector& vec) { + std::vector res; + for (const auto& t : vec) { + res.push_back(ToString(t)); + } + + return res; + } + + static bool hasEscapeCharacter(const std::string& s) { + const char* escape_character_set = "\\\"\'\?\a\b\f\n\r\t\v\0"; + + const auto check = [&escape_character_set](char c) -> bool { + const auto* p = escape_character_set; + while (*p) { + if (c == *p) { + return true; + } + ++p; + } + + return false; + }; + + for (const auto& c : s) { + if (check(c)) { + return true; + } + } + + return false; + } +}; + +} // namespace snapshot + +#endif // SNAPSHOT_INTERNAL_STRING_UTILITY_H_ diff --git a/include/snapshot/internal/system_utility.h b/include/snapshot/internal/system_utility.h new file mode 100644 index 0000000..ec7fa2f --- /dev/null +++ b/include/snapshot/internal/system_utility.h @@ -0,0 +1,40 @@ +#ifndef SNAPSHOT_INTERNAL_SYSTEM_UTILITY_H_ +#define SNAPSHOT_INTERNAL_SYSTEM_UTILITY_H_ + +#include +#include +#include + +namespace snapshot { + +class SystemUtility { +public: + static std::string Exec(const std::string& cmd) { + return execSystemCommand(cmd.c_str()); + } + + static std::string Diff(const std::string& before_file_path, const std::string& after_file_path) { + return Exec(std::string("git diff ") + before_file_path + " " + after_file_path); + } + +private: + static std::string execSystemCommand(const char* cmd) { + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(cmd, "r"), pclose); + + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + + return result; + } +}; + +} // namespace snapshot + +#endif // SNAPSHOT_INTERNAL_SYSTEM_UTILITY_H_ diff --git a/include/snapshot/internal/utility.h b/include/snapshot/internal/utility.h new file mode 100644 index 0000000..5f41619 --- /dev/null +++ b/include/snapshot/internal/utility.h @@ -0,0 +1,46 @@ +#ifndef SNAPSHOT_INTERNAL_UTILITY_H_ +#define SNAPSHOT_INTERNAL_UTILITY_H_ + +#include + +namespace snapshot { + +class Utility { +public: + template + static bool All(const std::vector& vec, const F&& func) { + for (const auto& t : vec) { + if (!func(t)) { + return false; + } + } + + return true; + } + + template + static bool Any(const std::vector& vec, const F&& func) { + for (const auto& t : vec) { + if (func(t)) { + return true; + } + } + + return false; + } + + template + static int Count(const T& vec, const F&& func) { + int res = 0; + + for (const auto& t : vec) { + res += func(t); + } + + return res; + } +}; + +} // namespace snapshot + +#endif // SNAPSHOT_INTERNAL_UTILITY_H_ diff --git a/include/snapshot/snapshot.h b/include/snapshot/snapshot.h index bba1132..91ffc09 100644 --- a/include/snapshot/snapshot.h +++ b/include/snapshot/snapshot.h @@ -1,14 +1,7 @@ #ifndef SNAPSHOT_SNAPSHOT_H #define SNAPSHOT_SNAPSHOT_H -#include -#include #include -#include -#include -#include -#include -#include #include #include #include @@ -20,379 +13,12 @@ #include #include -namespace snapshot { - -class Utility { -public: - template - static bool All(const std::vector& vec, const F&& func) { - for (const auto& t : vec) { - if (!func(t)) { - return false; - } - } - - return true; - } - - template - static bool Any(const std::vector& vec, const F&& func) { - for (const auto& t : vec) { - if (func(t)) { - return true; - } - } - - return false; - } - - template - static int Count(const T& vec, const F&& func) { - int res = 0; - - for (const auto& t : vec) { - res += func(t); - } - - return res; - } -}; - -class StringUtility { - friend class StringUtilityTest; - -public: - template - class HasStdToString { - private: - template - static auto check(int) -> decltype(std::to_string(std::declval()), std::true_type()); - - template - static std::false_type check(...); - - public: - enum { value = std::is_same(0)), std::true_type>::value }; - }; - -public: - template ::value, bool> = true> - static std::string ToString(const T& t) { - return std::to_string(t); - } - - template ::value, bool> = true> - static std::string ToString(const T& t) { - std::stringstream ss; - std::string s; - ss << t; - ss >> s; - return ss.str(); - } - - static std::string ToString(bool value) { - return value ? "true" : "false"; - } - - static std::string ToString(const char* s) { - if (hasEscapeCharacter(s)) { - return std::string("R\"(") + s + std::string(")\""); - } else { - return std::string("\"") + s + std::string("\""); - } - } - - static std::string ToString(const std::string& s) { - return std::string("std::string(") + ToString(s.c_str()) + std::string(")"); - } - - template - static std::string ToString(const std::pair& v) { - std::string res = "{"; - res += ToString(v.first); - res += ", "; - res += ToString(v.second); - res += "}"; - return res; - } - - template - static std::string ToString(const std::vector& v) { - if (v.empty()) { - return "{}"; - } - - std::vector string_vec = getStringVector(v); - char delimiter = ','; - - std::string res = "{\n"; - - for (const auto& s : string_vec) { - res += " "; - res += s; - res += delimiter; - res += "\n"; - } - - res += "}\n"; - - return res; - } - - static std::vector Split(const std::string& s, const char delimiter) { - std::vector res; - int len = static_cast(s.length()); - - std::string t = ""; - for (int i = 0; i <= len; i++) { - if (i == len || s[i] == delimiter) { - res.push_back(t); - t = ""; - } else { - t += s[i]; - } - } - - return res; - } - - static std::string Join(const std::vector& ss, const char delimiter) { - std::string res = ""; - for (size_t i = 0; i < ss.size(); i++) { - if (i) { - res += delimiter; - } - - res += ss[i]; - } - - return res; - } - -private: - template - static std::vector getStringVector(const std::vector& vec) { - std::vector res; - for (const auto& t : vec) { - res.push_back(ToString(t)); - } - - return res; - } - - static bool hasEscapeCharacter(const std::string& s) { - const char* escape_character_set = "\\\"\'\?\a\b\f\n\r\t\v\0"; - - const auto check = [&escape_character_set](char c) -> bool { - const auto* p = escape_character_set; - while (*p) { - if (c == *p) { - return true; - } - ++p; - } - - return false; - }; - - for (const auto& c : s) { - if (check(c)) { - return true; - } - } +#include "./internal/file_utility.h" +#include "./internal/string_utility.h" +#include "./internal/system_utility.h" +#include "./internal/utility.h" - return false; - } -}; - -class FileUtility { -public: - // Create folder - // If the directory does not exist, it will be created recursively - static bool Mkdir(const std::string& path) { - // if the path exists in its entirety - // there is no need to create it - if (access(path.c_str(), F_OK) == 0) { - return true; - } - - if (path.length() == 0) { - return false; - } - - size_t len = path.length(); - size_t idx = 0; - int pos = -1; - - if (path[0] == '/') { - ++pos; - } - - auto __mkdir = [](const std::string& path) -> bool { - if (access(path.c_str(), F_OK) == 0) { - return true; - } - - auto ret = mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - - // if the path already exists - // don't consider creation failed - if (ret == 0 || errno == EEXIST) { - return true; - } - - return false; - }; - - while (true) { - size_t cur_pos = path.find('/', pos + 1); - pos = static_cast(cur_pos); - - if (cur_pos == std::string::npos) { - break; - } - - auto _path = path.substr(0, pos); - - if (!__mkdir(_path)) { - return false; - } - - idx = pos + 1; - } - - if (idx < len) { - if (!__mkdir(path)) { - return false; - } - } - - return true; - }; - - static int RemoveFile(const std::string& path) { - return removeFile(path.c_str()); - } - - static int RemoveDirectory(const std::string& path) { - return removeDirectory(path.c_str()); - } - - static std::vector GetAllLines(const std::string& file_path) { - std::vector res; - std::string tmp_s; - - std::ifstream read_file(file_path); - - while (!read_file.eof()) { - getline(read_file, tmp_s); - res.push_back(tmp_s); - } - - read_file.close(); - return res; - } - - static void RewriteFile(const std::string& file_path, const std::string& content) { - std::ofstream file; - file.open(file_path, std::ofstream::out | std::ofstream::trunc); - file.write(content.c_str(), static_cast(content.length())); - file.close(); - } - - static void AppendFile(const std::string& file_path, const std::string& content) { - std::ofstream file; - file.open(file_path, std::ofstream::out | std::ofstream::ate | std::ofstream::app); - file.write(content.c_str(), static_cast(content.length())); - file.close(); - } - -private: - static int removeFile(const char* path) { - if (access(path, F_OK) != 0) { - return 0; - } - - return remove(path); - } - - static int removeDirectory(const char* path) { - DIR* d = opendir(path); - size_t path_len = strlen(path); - int r = -1; - - if (d) { - struct dirent* p = nullptr; - - r = 0; - while (!r && (p = readdir(d))) { - int r2 = -1; - char* buf = nullptr; - size_t len = 0; - - /* Skip the names "." and ".." as we don't want to recurse on them. */ - if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) { - continue; - } - - len = path_len + strlen(p->d_name) + 2; - buf = (char*)malloc(len); - - if (buf) { - struct stat statbuf; - - snprintf(buf, len, "%s/%s", path, p->d_name); - if (!stat(buf, &statbuf)) { - if (S_ISDIR(statbuf.st_mode)) { - r2 = removeDirectory(buf); - } else { - r2 = unlink(buf); - } - } - free(buf); - } - - r = r2; - } - - closedir(d); - } - - if (!r) { - r = rmdir(path); - } - - return r; - } -}; - -class SystemUtility { -public: - static std::string Exec(const std::string& cmd) { - return execSystemCommand(cmd.c_str()); - } - - static std::string Diff(const std::string& before_file_path, const std::string& after_file_path) { - return Exec(std::string("git diff ") + before_file_path + " " + after_file_path); - } - -private: - static std::string execSystemCommand(const char* cmd) { - std::array buffer; - std::string result; - std::unique_ptr pipe(popen(cmd, "r"), pclose); - - if (!pipe) { - throw std::runtime_error("popen() failed!"); - } - - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - - return result; - } -}; +namespace snapshot { class Snapshot { friend class SnapshotTest; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f639318..4ad03b1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -28,11 +28,11 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") add_executable( unit_test - ${PROJECT_SOURCE_DIR}/test/file_utility_test.cc ${PROJECT_SOURCE_DIR}/test/snapshot_test.cc - ${PROJECT_SOURCE_DIR}/test/string_utility_test.cc - ${PROJECT_SOURCE_DIR}/test/system_utility_test.cc - ${PROJECT_SOURCE_DIR}/test/utility_test.cc + ${PROJECT_SOURCE_DIR}/test/internal/file_utility_test.cc + ${PROJECT_SOURCE_DIR}/test/internal/string_utility_test.cc + ${PROJECT_SOURCE_DIR}/test/internal/system_utility_test.cc + ${PROJECT_SOURCE_DIR}/test/internal/utility_test.cc ) target_link_libraries( diff --git a/test/file_utility_test.cc b/test/internal/file_utility_test.cc similarity index 100% rename from test/file_utility_test.cc rename to test/internal/file_utility_test.cc diff --git a/test/string_utility_test.cc b/test/internal/string_utility_test.cc similarity index 100% rename from test/string_utility_test.cc rename to test/internal/string_utility_test.cc diff --git a/test/system_utility_test.cc b/test/internal/system_utility_test.cc similarity index 100% rename from test/system_utility_test.cc rename to test/internal/system_utility_test.cc diff --git a/test/utility_test.cc b/test/internal/utility_test.cc similarity index 100% rename from test/utility_test.cc rename to test/internal/utility_test.cc