-
Notifications
You must be signed in to change notification settings - Fork 97
Expand file tree
/
Copy pathmisc.h
More file actions
172 lines (140 loc) · 6.19 KB
/
misc.h
File metadata and controls
172 lines (140 loc) · 6.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#pragma once
// system headers
#include <algorithm>
#include <climits>
#include <cstring>
#include <filesystem>
#include <fnmatch.h>
#include <sstream>
#include <string>
#include <unistd.h>
#include <vector>
namespace linuxdeploy {
namespace util {
namespace misc {
static inline bool ltrim(std::string& s, char to_trim = ' ') {
// TODO: find more efficient way to check whether elements have been removed
size_t initialLength = s.length();
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [to_trim](int ch) {
return ch != to_trim;
}));
return s.length() < initialLength;
}
static inline bool rtrim(std::string& s, char to_trim = ' ') {
// TODO: find more efficient way to check whether elements have been removed
auto initialLength = s.length();
s.erase(std::find_if(s.rbegin(), s.rend(), [to_trim](int ch) {
return ch != to_trim;
}).base(), s.end());
return s.length() < initialLength;
}
static inline bool trim(std::string& s, char to_trim = ' ') {
// returns true if either modifies s
auto ltrim_result = ltrim(s, to_trim);
return rtrim(s, to_trim) && ltrim_result;
}
static std::vector<std::string> split(const std::string& s, char delim = ' ') {
std::vector<std::string> result;
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
result.push_back(item);
}
return result;
}
static std::vector<std::string> splitLines(const std::string& s) {
return split(s, '\n');
}
static std::string join(const std::vector<std::string> &strings, const std::string &delimiter) {
std::string result;
for (size_t i = 0; i < strings.size(); i++) {
result += strings[i];
if (i != strings.size() - 1) {
result += delimiter;
}
}
return result;
}
static inline std::string strLower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
return s;
}
static bool stringStartsWith(const std::string& string, const std::string& prefix) {
// sanity check
if (string.size() < prefix.size())
return false;
return strncmp(string.c_str(), prefix.c_str(), prefix.size()) == 0;
}
static bool stringEndsWith(const std::string& string, const std::string& suffix) {
// sanity check
if (string.size() < suffix.size())
return false;
return strcmp(string.c_str() + (string.size() - suffix.size()), suffix.c_str()) == 0;
}
static bool stringContains(const std::string& string, const std::string& part) {
return string.find(part) != std::string::npos;
}
static std::string getOwnExecutablePath() {
// FIXME: reading /proc/self/exe line is Linux specific
std::vector<char> buf(PATH_MAX, '\0');
if (readlink("/proc/self/exe", buf.data(), buf.size()) < 0) {
return "";
}
return buf.data();
}
// very simple but for our purposes good enough which like algorithm to find binaries in $PATH
static std::filesystem::path which(const std::string& name) {
namespace fs = std::filesystem;
// check if name is an absolute path and a valid binary to run
const fs::path name_path(name);
if (name_path.is_absolute()
&& fs::exists(name_path)
&& (fs::status(name_path).permissions() & fs::perms::owner_exec) != fs::perms::none) {
return name_path;
}
const auto* path = getenv("PATH");
if (path == nullptr)
return "";
for (const auto& binDir : split(path, ':')) {
if (!fs::is_directory(binDir)) {
continue;
}
for (fs::directory_iterator it(binDir); it != fs::directory_iterator{}; ++it) {
const auto binary = it->path();
if (binary.filename() == name) {
// TODO: check if file is executable (skip otherwise)
return binary;
}
}
}
return {};
}
// returns a string vector splitted from envVar
static std::vector<std::string> splitEnv(const char *envVar, char delimiter) {
std::vector<std::string> result;
const auto ret = getenv(envVar);
if (ret) {
result = split(ret, delimiter);
}
return result;
}
static bool isInExcludelist(const std::filesystem::path& fileName, const std::vector<std::string> &excludeList) {
for (const auto& excludePattern : excludeList) {
// simple string match is faster than using fnmatch
if (excludePattern == fileName)
return true;
auto fnmatchResult = fnmatch(excludePattern.c_str(), fileName.string().c_str(), FNM_PATHNAME);
switch (fnmatchResult) {
case 0:
return true;
case FNM_NOMATCH:
break;
default:
return false;
}
}
return false;
}
}
}
}