Skip to content

Commit

Permalink
refactor: split files
Browse files Browse the repository at this point in the history
  • Loading branch information
Dup4 committed Jun 28, 2022
1 parent e6eb491 commit 1095b44
Show file tree
Hide file tree
Showing 10 changed files with 433 additions and 383 deletions.
178 changes: 178 additions & 0 deletions include/snapshot/internal/file_utility.h
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
160 changes: 160 additions & 0 deletions include/snapshot/internal/string_utility.h
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_
40 changes: 40 additions & 0 deletions include/snapshot/internal/system_utility.h
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_
Loading

0 comments on commit 1095b44

Please sign in to comment.