-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
433 additions
and
383 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
#ifndef SNAPSHOT_INTERNAL_FILE_UTILITY_H | ||
#define SNAPSHOT_INTERNAL_FILE_UTILITY_H | ||
|
||
#include <ctype.h> | ||
#include <dirent.h> | ||
#include <sys/stat.h> | ||
#include <sys/types.h> | ||
#include <unistd.h> | ||
#include <fstream> | ||
#include <string> | ||
#include <vector> | ||
|
||
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<int>(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<std::string> GetAllLines(const std::string& file_path) { | ||
std::vector<std::string> 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<long>(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<long>(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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
#ifndef SNAPSHOT_INTERNAL_STRING_UTILITY_H_ | ||
#define SNAPSHOT_INTERNAL_STRING_UTILITY_H_ | ||
|
||
#include <sstream> | ||
#include <string> | ||
#include <type_traits> | ||
#include <vector> | ||
|
||
namespace snapshot { | ||
|
||
class StringUtility { | ||
friend class StringUtilityTest; | ||
|
||
public: | ||
template <typename T> | ||
class HasStdToString { | ||
private: | ||
template <typename U> | ||
static auto check(int) -> decltype(std::to_string(std::declval<U>()), std::true_type()); | ||
|
||
template <typename U> | ||
static std::false_type check(...); | ||
|
||
public: | ||
enum { value = std::is_same<decltype(check<T>(0)), std::true_type>::value }; | ||
}; | ||
|
||
public: | ||
template <typename T, std::enable_if_t<HasStdToString<T>::value, bool> = true> | ||
static std::string ToString(const T& t) { | ||
return std::to_string(t); | ||
} | ||
|
||
template <typename T, std::enable_if_t<!HasStdToString<T>::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 <typename A, typename B> | ||
static std::string ToString(const std::pair<A, B>& v) { | ||
std::string res = "{"; | ||
res += ToString(v.first); | ||
res += ", "; | ||
res += ToString(v.second); | ||
res += "}"; | ||
return res; | ||
} | ||
|
||
template <typename T> | ||
static std::string ToString(const std::vector<T>& v) { | ||
if (v.empty()) { | ||
return "{}"; | ||
} | ||
|
||
std::vector<std::string> 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<std::string> Split(const std::string& s, const char delimiter) { | ||
std::vector<std::string> res; | ||
int len = static_cast<int>(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<std::string>& 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 <typename T> | ||
static std::vector<std::string> getStringVector(const std::vector<T>& vec) { | ||
std::vector<std::string> 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_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#ifndef SNAPSHOT_INTERNAL_SYSTEM_UTILITY_H_ | ||
#define SNAPSHOT_INTERNAL_SYSTEM_UTILITY_H_ | ||
|
||
#include <array> | ||
#include <memory> | ||
#include <string> | ||
|
||
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<char, 128> buffer; | ||
std::string result; | ||
std::unique_ptr<FILE, decltype(&pclose)> 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_ |
Oops, something went wrong.