HIP: Heterogenous-computing Interface for Portability
Loading...
Searching...
No Matches
hipBin_util.h
1/*
2Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved.
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"), to deal
6in the Software without restriction, including without limitation the rights
7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20THE SOFTWARE.
21*/
22
23#ifndef SRC_HIPBIN_UTIL_H_
24#define SRC_HIPBIN_UTIL_H_
25
26// We haven't checked which filesystem to include yet
27#ifndef INCLUDE_STD_FILESYSTEM_EXPERIMENTAL
28// Check for feature test macro for <filesystem>
29#if defined(__cpp_lib_filesystem)
30#define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 0
31// Check for feature test macro for <experimental/filesystem>
32#elif defined(__cpp_lib_experimental_filesystem)
33#define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 1
34// We can't check if headers exist...
35// Let's assume experimental to be safe
36#elif !defined(__has_include)
37#define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 1
38// Check if the header "<filesystem>" exists
39#elif __has_include(<filesystem>)
40// If we're compiling on Visual Studio and are not compiling with C++17,
41// we need to use experimental
42#ifdef _MSC_VER
43// Check and include header that defines "_HAS_CXX17"
44#if __has_include(<yvals_core.h>)
45#include <yvals_core.h>
46
47// Check for enabled C++17 support
48#if defined(_HAS_CXX17) && _HAS_CXX17
49// We're using C++17, so let's use the normal version
50#define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 0
51#endif
52
53#endif
54
55// If the marco isn't defined yet, that means any of the other
56// VS specific checks failed, so we need to use experimental
57#ifndef INCLUDE_STD_FILESYSTEM_EXPERIMENTAL
58#define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 1
59#endif
60
61// Not on Visual Studio. Let's use the normal version
62#else // #ifdef _MSC_VER
63#define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 0
64#endif
65
66// Check if the header "<filesystem>" exists
67#elif __has_include(<experimental/filesystem>)
68#define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 1
69
70// Fail if neither header is available with a nice error message
71#else
72#error Could not find system header "<filesystem>" ||
73 "<experimental/filesystem>"
74#endif
75
76// We priously determined that we need the exprimental version
77#if INCLUDE_STD_FILESYSTEM_EXPERIMENTAL
78// Include it
79#include <experimental/filesystem>
80// We need the alias from std::experimental::filesystem to std::filesystem
81namespace fs = std::experimental::filesystem;
82// We have a decent compiler and can use the normal version
83#else
84// Include it
85#include <filesystem>
86namespace fs = std::filesystem;
87#endif
88
89#endif // #ifndef INCLUDE_STD_FILESYSTEM_EXPERIMENTAL
90
91#include <assert.h>
92#include <stdlib.h>
93#include <limits.h>
94#include <iostream>
95#include <sstream>
96#include <string>
97#include <map>
98#include <fstream>
99#include <regex>
100#include <algorithm>
101#include <vector>
102
103
104#if defined(_WIN32) || defined(_WIN64)
105#include <tchar.h>
106#include <windows.h>
107#include <io.h>
108#ifdef _UNICODE
109 typedef wchar_t TCHAR;
110 typedef std::wstring TSTR;
111 typedef std::wstring::size_type TSIZE;
112#define ENDLINE L"/\\"
113#else
114 typedef char TCHAR;
115 typedef std::string TSTR;
116 typedef std::string::size_type TSIZE;
117#define ENDLINE "/\\"
118#endif
119#else
120#include <unistd.h>
121#endif
122
123using std::cout;
124using std::endl;
125using std::vector;
126using std::string;
127using std::ifstream;
128using std::ofstream;
129using std::regex;
130using std::regex_match;
131using std::regex_search;
132using std::regex_replace;
133using std::map;
134using std::smatch;
135using std::stringstream;
136
137
139 string out;
140 int exitCode = 0;
141};
142
143
145 public:
146 static HipBinUtil* getInstance() {
147 if (!instance)
148 instance = new HipBinUtil;
149 return instance;
150 }
151 virtual ~HipBinUtil();
152 // Common helper functions
153 string getSelfPath() const;
154 vector<string> splitStr(string fullStr, char delimiter) const;
155 string replaceStr(const string& s, const string& toReplace,
156 const string& replaceWith) const;
157 string replaceRegex(const string& s, regex toReplace,
158 string replaceWith) const;
159 SystemCmdOut exec(const char* cmd, bool printConsole) const;
160 string getTempDir();
161 void deleteTempFiles();
162 string mktempFile(string name);
163 string trim(string str) const;
164 string readConfigMap(map<string, string> hipVersionMap,
165 string keyName, string defaultValue) const;
166 map<string, string> parseConfigFile(fs::path configPath) const;
167 bool substringPresent(string fullString, string subString) const;
168 bool stringRegexMatch(string fullString, string pattern) const;
169 bool checkCmd(const vector<string>& commands, const string& argument);
170
171 private:
172 HipBinUtil() {}
173 vector<string> tmpFiles_;
174 static HipBinUtil *instance;
175};
176
177HipBinUtil *HipBinUtil::instance = 0;
178
179// deleting temp files created
180HipBinUtil::~HipBinUtil() {
181 deleteTempFiles();
182}
183
184// create temp file with the template name
185string HipBinUtil::mktempFile(string name) {
186 string fileName;
187#if defined(_WIN32) || defined(_WIN64)
188 fileName = _mktemp(&name[0]);
189#else
190 fileName = mkdtemp(&name[0]);
191#endif
192 tmpFiles_.push_back(fileName);
193 return fileName;
194}
195
196// gets the path of the executable name
197string HipBinUtil::getSelfPath() const {
198 int MAX_PATH_CHAR = 1024;
199 int bufferSize = 0;
200 string path;
201 #if defined(_WIN32) || defined(_WIN64)
202 TCHAR buffer[MAX_PATH] = { 0 };
203 bufferSize = GetModuleFileName(NULL, buffer, MAX_PATH_CHAR);
204 TSIZE pos = TSTR(buffer).find_last_of(ENDLINE);
205 TSTR wide = TSTR(buffer).substr(0, pos);
206 path = string(wide.begin(), wide.end());
207 #else
208 char buff[MAX_PATH_CHAR];
209 ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff) - 1);
210 if (len > 0) {
211 buff[len] = '\0';
212 path = string(buff);
213 fs::path exePath(path);
214 path = exePath.parent_path().string();
215 } else {
216 std::cerr << "readlink: Error reading the exe path" << endl;
217 perror("readlink");
218 exit(-1);
219 }
220 #endif
221 return path;
222}
223
224
225// removes the empty spaces and end lines
226string HipBinUtil::trim(string str) const {
227 string strChomp = str;
228 strChomp.erase(str.find_last_not_of(" \n\r\t")+1);
229 return strChomp;
230}
231
232// matches the pattern in the string
233bool HipBinUtil::stringRegexMatch(string fullString, string pattern) const {
234 return regex_match(fullString, regex(pattern));
235}
236
237// subtring is present in string
238bool HipBinUtil::substringPresent(string fullString, string subString) const {
239 return fullString.find(subString) != string::npos;
240}
241
242// splits the string with the delimiter
243vector<string> HipBinUtil::splitStr(string fullStr, char delimiter) const {
244 vector <string> tokens;
245 stringstream check1(fullStr);
246 string intermediate;
247 while (getline(check1, intermediate, delimiter)) {
248 tokens.push_back(intermediate);
249 }
250 return tokens;
251}
252
253// replaces the toReplace string with replaceWith string. Returns the new string
254string HipBinUtil::replaceStr(const string& s, const string& toReplace,
255 const string& replaceWith) const {
256 string out = s;
257 std::size_t pos = out.find(toReplace);
258 if (pos == string::npos) return out;
259 return out.replace(pos, toReplace.length(), replaceWith);
260}
261
262// replaces the toReplace regex pattern with replaceWith string.
263// Returns the new string
264string HipBinUtil::replaceRegex(const string& s, regex toReplace,
265 string replaceWith) const {
266 string out = s;
267 while (regex_search(out, toReplace)) {
268 out = regex_replace(out, toReplace, replaceWith);
269 }
270 return out;
271}
272
273// reads the config file and stores it in a map for access
274map<string, string> HipBinUtil::parseConfigFile(fs::path configPath) const {
275 map<string, string> configMap;
276 ifstream isFile(configPath.string());
277 string line;
278 if (isFile.is_open()) {
279 while (std::getline(isFile, line)) {
280 std::istringstream is_line(line);
281 string key;
282 if (std::getline(is_line, key, '=')) {
283 string value;
284 if (std::getline(is_line, value)) {
285 configMap.insert({ key, value });
286 }
287 }
288 }
289 isFile.close();
290 }
291 return configMap;
292}
293
294// Delete all created temporary files
295void HipBinUtil::deleteTempFiles() {
296 // Deleting temp files vs the temp directory
297 for (unsigned int i = 0; i < tmpFiles_.size(); i++) {
298 try {
299 if (!fs::remove(tmpFiles_.at(i)))
300 std::cerr << "Error deleting temp name: "<< tmpFiles_.at(i) <<endl;
301 }
302 catch(...) {
303 std::cerr << "Error deleting temp name: "<< tmpFiles_.at(i) <<endl;
304 }
305 }
306}
307
308// Create a new temporary directory and return it
309string HipBinUtil::getTempDir() {
310 // mkdtemp is only applicable for unix and not windows.
311 // Using filesystem becasuse of windows limitation
312 string tmpdir = fs::temp_directory_path().string();
313 // tmpDirs_.push_back(tmpdir);
314 return tmpdir;
315}
316
317// executes the command, returns the status and return string
318SystemCmdOut HipBinUtil::exec(const char* cmd,
319 bool printConsole = false) const {
320 SystemCmdOut sysOut;
321 try {
322 char buffer[128];
323 string result = "";
324 #if defined(_WIN32) || defined(_WIN64)
325 FILE* pipe = _popen(cmd, "r");
326 #else
327 FILE* pipe = popen(cmd, "r");
328 #endif
329 if (!pipe) throw std::runtime_error("popen() failed!");
330 try {
331 while (fgets(buffer, sizeof buffer, pipe) != NULL) {
332 result += buffer;
333 }
334 } catch (...) {
335 std::cerr << "Error while executing the command: " << cmd << endl;
336 }
337 #if defined(_WIN32) || defined(_WIN64)
338 sysOut.exitCode = _pclose(pipe);
339 #else
340 int closeStatus = pclose(pipe);
341 sysOut.exitCode = WEXITSTATUS(closeStatus);
342 #endif
343 if (printConsole == true) {
344 cout << result << endl;
345 }
346 sysOut.out = result;
347 }
348 catch(...) {
349 sysOut.exitCode = -1;
350 }
351 return sysOut;
352}
353
354// returns the value of the key from the Map passed
355string HipBinUtil::readConfigMap(map<string, string> hipVersionMap,
356 string keyName, string defaultValue) const {
357 auto it = hipVersionMap.find(keyName);
358 if (it != hipVersionMap.end()) {
359 return it->second;
360 }
361 return defaultValue;
362}
363
364
365
366bool HipBinUtil::checkCmd(const vector<string>& commands,
367 const string& argument) {
368 bool found = false;
369 for (unsigned int i = 0; i < commands.size(); i++) {
370 if (argument.compare(commands.at(i)) == 0) {
371 found = true;
372 break;
373 }
374 }
375 return found;
376}
377
378
379
380#endif // SRC_HIPBIN_UTIL_H_
Definition: hipBin_util.h:144
Definition: hipBin_util.h:138