11 #include <unordered_map>
18 bool ICompare(const std::string& a, const std::string& b)
20 return a.length() == b.length() &&
21 std::equal(b.begin(), b.end(), a.begin(),
22 [](unsigned char a, unsigned char b)
23 { return std::tolower(a) == std::tolower(b); });
26 bool ICompare(const std::string& a, int a_offset, const std::string& b, int b_offset, int length)
28 return static_cast<int>(a.length()) - length >= a_offset &&
29 static_cast<int>(b.length()) - length >= b_offset &&
30 std::equal(b.begin() + b_offset, b.begin() + b_offset + length, a.begin() + a_offset,
31 [](unsigned char a, unsigned char b)
32 { return std::tolower(a) == std::tolower(b); });
35 bool IsManagedAssembly(const std::string& filename)
37 return ICompare(filename, filename.size()-4, ".dll", 0, 4) ||
38 ICompare(filename, filename.size()-4, ".exe", 0, 4);
41 bool IsNativeImage(const std::string& filename)
43 return ICompare(filename, filename.size()-7, ".ni", 0, 3);
46 std::string ReadSelfPath()
49 ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
52 return std::string(buff);
58 std::string ConcatPath(const std::string& path1, const std::string& path2)
60 std::string path(path1);
61 if (path.back() == PATH_SEPARATOR)
67 path += PATH_SEPARATOR;
74 void AppendPath(std::string& path1, const std::string& path2)
76 if (path1.back() == PATH_SEPARATOR)
82 path1 += PATH_SEPARATOR;
87 std::string AbsolutePath(const std::string& path)
91 char realPath[PATH_MAX];
92 if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
94 absPath.assign(realPath);
100 std::string Basename(const std::string& path)
102 auto pos = path.find_last_of(PATH_SEPARATOR);
103 if (pos != std::string::npos)
105 return path.substr(0, pos);
109 return std::string(".");
114 bool EndWithIgnoreCase(const std::string& str1, const std::string& str2, std::string& filename)
116 std::string::size_type len1 = str1.length();
117 std::string::size_type len2 = str2.length();
118 if (len2 > len1) return false;
121 bool result = std::all_of(str1.cend() - len2, str1.end(),
122 [&i, &str2] (char x) {
123 return std::tolower(x) == std::tolower(str2[i++]);
127 filename = str1.substr(0, len1 - len2);
132 bool FileNotExist(const std::string& path)
135 return stat(path.c_str(), &sb) != 0;
138 static bool ExtCheckAndGetFileNameIfExist(const std::string& dir, const std::string& ext, struct dirent* entry, std::string& filename)
140 std::string fname(entry->d_name);
141 if (fname.length() < ext.length() ||
142 fname.compare(fname.length() - ext.length(), ext.length(), ext) != 0)
146 std::string fullname = ConcatPath(dir, entry->d_name);
147 switch (entry->d_type)
152 if (FileNotExist(fullname))
165 std::string StripNIDLL(const std::string& path)
167 std::string npath(path);
168 if (path.size() < 5) return npath;
169 if (strncasecmp(path.c_str() + path.size() - 4, ".dll", 4))
171 npath = path.substr(0, path.size()-4);
172 }else if (strncasecmp(path.c_str() + path.size() - 4, ".exe", 4))
174 npath = path.substr(0, path.size()-4);
176 if (strncasecmp(npath.c_str() + npath.size() - 3, ".ni", 3))
178 return npath.substr(0, npath.size()-3);
183 std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter)
185 switch (strings.size())
192 std::ostringstream os;
193 std::copy(strings.begin(), strings.end()-1, std::ostream_iterator<std::string>(os, delimeter));
194 os << *strings.rbegin();
205 bool operator == (const AssemblyFile& lhs, const AssemblyFile& rhs)
207 return lhs.noext == rhs.noext && lhs.ext == rhs.ext;
213 struct hash<AssemblyFile>
215 std::size_t operator () (const AssemblyFile& f) const
217 const std::size_t h1 = std::hash<std::string>{}(f.noext);
218 const std::size_t h2 = std::hash<std::string>{}(f.ext);
220 return h1 ^ (h2 << 1);
225 void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList)
227 std::unordered_map<AssemblyFile, bool> addedAssemblies;
229 auto reader = [&addedAssemblies] (const char* path)
231 std::string _path(path);
233 std::string::size_type dotp = _path.rfind('.');
234 std::string ext = dotp != std::string::npos ? _path.substr(dotp) : "";
238 if (IsManagedAssembly(_path))
240 if (IsNativeImage(_path))
242 noext = _path.substr(0, _path.size()-7);
247 noext = _path.substr(0, _path.size()-4);
250 AssemblyFile f = {noext, ext};
251 addedAssemblies[f] = ni;
255 for (auto directory : directories)
257 ScanFilesInDir(directory.c_str(), reader, 1);
260 for (auto kv : addedAssemblies)
262 tpaList += kv.first.noext + (kv.second ? ".ni" : "") + kv.first.ext + ':';
265 if (tpaList.back() == ':')
269 void ScanFilesInDir(const char* directory, FileReader reader, unsigned int depth)
272 struct dirent* entry;
275 dir = opendir(directory);
279 //_ERR("Can not open directory : %s", directory);
283 std::vector<std::string> innerDirectories;
285 while ((entry = readdir(dir)) != nullptr)
288 std::string path = ConcatPath(directory, entry->d_name);
289 switch (entry->d_type)
298 if (stat(path.c_str(), &sb) == -1)
303 if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
312 reader(path.c_str());
314 else if (depth > 1 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
316 innerDirectories.push_back(path);
322 for (auto& d : innerDirectories)
324 ScanFilesInDir(d.c_str(), reader, depth-1);