1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*!
21  * \file util.h
22  * \brief Defines some common utility function..
23  */
24 #ifndef TVM_COMMON_UTIL_H_
25 #define TVM_COMMON_UTIL_H_
26 
27 #include <stdio.h>
28 #ifndef _WIN32
29 #include <sys/wait.h>
30 #include <sys/types.h>
31 #endif
32 #include <vector>
33 #include <string>
34 #include <sstream>
35 #include <algorithm>
36 #include <array>
37 #include <cctype>
38 #include <memory>
39 
40 namespace tvm {
41 namespace common {
42 /*!
43  * \brief TVMPOpen wrapper of popen between windows / unix.
44  * \param command executed command
45  * \param type "r" is for reading or "w" for writing.
46  * \return normal standard stream
47  */
TVMPOpen(const char * command,const char * type)48 inline FILE* TVMPOpen(const char* command, const char* type) {
49 #if defined(_WIN32)
50   return _popen(command, type);
51 #else
52   return popen(command, type);
53 #endif
54 }
55 
56 /*!
57  * \brief TVMPClose wrapper of pclose between windows / linux
58  * \param stream the stream needed to be close.
59  * \return exit status
60  */
TVMPClose(FILE * stream)61 inline int TVMPClose(FILE* stream) {
62 #if defined(_WIN32)
63   return _pclose(stream);
64 #else
65   return pclose(stream);
66 #endif
67 }
68 
69 /*!
70  * \brief TVMWifexited wrapper of WIFEXITED between windows / linux
71  * \param status The status field that was filled in by the wait or waitpid function
72  * \return the exit code of the child process
73  */
TVMWifexited(int status)74 inline int TVMWifexited(int status) {
75 #if defined(_WIN32)
76   return (status != 3);
77 #else
78   return WIFEXITED(status);
79 #endif
80 }
81 
82 /*!
83  * \brief TVMWexitstatus wrapper of WEXITSTATUS between windows / linux
84  * \param status The status field that was filled in by the wait or waitpid function.
85  * \return the child process exited normally or not
86  */
TVMWexitstatus(int status)87 inline int TVMWexitstatus(int status) {
88 #if defined(_WIN32)
89   return status;
90 #else
91   return WEXITSTATUS(status);
92 #endif
93 }
94 
95 
96 /*!
97  * \brief IsNumber check whether string is a number.
98  * \param str input string
99  * \return result of operation.
100  */
IsNumber(const std::string & str)101 inline bool IsNumber(const std::string& str) {
102   return !str.empty() && std::find_if(str.begin(),
103       str.end(), [](char c) { return !std::isdigit(c); }) == str.end();
104 }
105 
106 /*!
107  * \brief split Split the string based on delimiter
108  * \param str Input string
109  * \param delim The delimiter.
110  * \return vector of strings which are splitted.
111  */
Split(const std::string & str,char delim)112 inline std::vector<std::string> Split(const std::string& str, char delim) {
113   std::string item;
114   std::istringstream is(str);
115   std::vector<std::string> ret;
116   while (std::getline(is, item, delim)) {
117     ret.push_back(item);
118   }
119   return ret;
120 }
121 
122 /*!
123  * \brief EndsWith check whether the strings ends with
124  * \param value The full string
125  * \param end The end substring
126  * \return bool The result.
127  */
EndsWith(std::string const & value,std::string const & end)128 inline bool EndsWith(std::string const& value, std::string const& end) {
129   if (end.size() <= value.size()) {
130     return std::equal(end.rbegin(), end.rend(), value.rbegin());
131   }
132   return false;
133 }
134 
135 /*!
136  * \brief Execute the command
137  * \param cmd The command we want to execute
138  * \param err_msg The error message if we have
139  * \return executed output status
140  */
Execute(std::string cmd,std::string * err_msg)141 inline int Execute(std::string cmd, std::string* err_msg) {
142   std::array<char, 128> buffer;
143   std::string result;
144   cmd += " 2>&1";
145   FILE* fd = TVMPOpen(cmd.c_str(), "r");
146   while (fgets(buffer.data(), buffer.size(), fd) != nullptr) {
147     *err_msg += buffer.data();
148   }
149   int status = TVMPClose(fd);
150   if (TVMWifexited(status)) {
151     return TVMWexitstatus(status);
152   }
153   return 255;
154 }
155 
156 }  // namespace common
157 }  // namespace tvm
158 #endif  // TVM_COMMON_UTIL_H_
159