| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /*! |
| * \file utils.h |
| * \brief Defines some common utility function.. |
| */ |
| #ifndef TVM_SUPPORT_UTILS_H_ |
| #define TVM_SUPPORT_UTILS_H_ |
| |
| #include <stdio.h> |
| #ifndef _WIN32 |
| #include <sys/types.h> |
| #ifndef __hexagon__ |
| #include <sys/wait.h> |
| #endif // __hexagon__ |
| #endif // _WIN32 |
| |
| #include <tvm/ffi/string.h> |
| |
| #include <algorithm> |
| #include <array> |
| #include <cctype> |
| #include <cstdlib> |
| #include <memory> |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| namespace tvm { |
| namespace support { |
| /*! |
| * \brief TVMPOpen wrapper of popen between windows / unix. |
| * \param command executed command |
| * \param type "r" is for reading or "w" for writing. |
| * \return normal standard stream |
| */ |
| #ifndef __hexagon__ |
| inline FILE* TVMPOpen(const char* command, const char* type) { |
| #if defined(_WIN32) |
| return _popen(command, type); |
| #else |
| return popen(command, type); |
| #endif |
| } |
| #endif // __hexagon__ |
| |
| /*! |
| * \brief TVMPClose wrapper of pclose between windows / linux |
| * \param stream the stream needed to be close. |
| * \return exit status |
| */ |
| #ifndef __hexagon__ |
| inline int TVMPClose(FILE* stream) { |
| #if defined(_WIN32) |
| return _pclose(stream); |
| #else |
| return pclose(stream); |
| #endif |
| } |
| #endif // __hexagon__ |
| |
| /*! |
| * \brief TVMWifexited wrapper of WIFEXITED between windows / linux |
| * \param status The status field that was filled in by the wait or waitpid function |
| * \return the exit code of the child process |
| */ |
| #ifndef __hexagon__ |
| inline int TVMWifexited(int status) { |
| #if defined(_WIN32) |
| return (status != 3); |
| #else |
| return WIFEXITED(status); |
| #endif |
| } |
| #endif // __hexagon__ |
| |
| /*! |
| * \brief TVMWexitstatus wrapper of WEXITSTATUS between windows / linux |
| * \param status The status field that was filled in by the wait or waitpid function. |
| * \return the child process exited normally or not |
| */ |
| #ifndef __hexagon__ |
| inline int TVMWexitstatus(int status) { |
| #if defined(_WIN32) |
| return status; |
| #else |
| return WEXITSTATUS(status); |
| #endif |
| } |
| #endif // __hexagon__ |
| |
| /*! |
| * \brief IsNumber check whether string is a number. |
| * \param str input string |
| * \return result of operation. |
| */ |
| inline bool IsNumber(const std::string& str) { |
| return !str.empty() && |
| std::find_if(str.begin(), str.end(), [](char c) { return !std::isdigit(c); }) == str.end(); |
| } |
| |
| /*! |
| * \brief split Split the string based on delimiter |
| * \param str Input string |
| * \param delim The delimiter. |
| * \return vector of strings which are splitted. |
| */ |
| inline std::vector<std::string> Split(const std::string& str, char delim) { |
| std::string item; |
| std::istringstream is(str); |
| std::vector<std::string> ret; |
| while (std::getline(is, item, delim)) { |
| ret.push_back(item); |
| } |
| return ret; |
| } |
| |
| /*! |
| * \brief Check whether the string starts with a given prefix. |
| * \param str The given string. |
| * \param prefix The given prefix. |
| * \return Whether the prefix matched. |
| */ |
| inline bool StartsWith(const ffi::String& str, const char* prefix) { |
| const char* data = str.data(); |
| const char* data_end = data + str.size(); |
| for (; data != data_end; ++data, ++prefix) { |
| if (*prefix == '\0') return true; |
| if (*data != *prefix) return false; |
| } |
| // return true if the str is equal to the prefix |
| return *prefix == '\0'; |
| } |
| |
| /*! |
| * \brief EndsWith check whether the strings ends with |
| * \param value The full string |
| * \param end The end substring |
| * \return bool The result. |
| */ |
| inline bool EndsWith(std::string const& value, std::string const& end) { |
| if (end.size() <= value.size()) { |
| return std::equal(end.rbegin(), end.rend(), value.rbegin()); |
| } |
| return false; |
| } |
| |
| /*! |
| * \brief Execute the command |
| * \param cmd The command we want to execute |
| * \param err_msg The error message if we have |
| * \return executed output status |
| */ |
| #ifndef __hexagon__ |
| inline int Execute(std::string cmd, std::string* err_msg) { |
| std::array<char, 128> buffer; |
| std::string result; |
| cmd += " 2>&1"; |
| FILE* fd = TVMPOpen(cmd.c_str(), "r"); |
| while (fgets(buffer.data(), buffer.size(), fd) != nullptr) { |
| *err_msg += buffer.data(); |
| } |
| int status = TVMPClose(fd); |
| if (TVMWifexited(status)) { |
| return TVMWexitstatus(status); |
| } |
| return 255; |
| } |
| #endif // __hexagon__ |
| |
| /*! |
| * \brief hash an object and combines uint64_t key with previous keys |
| * |
| * This hash function is stable across platforms. |
| * |
| * \param key The left operand. |
| * \param value The right operand. |
| * \return the combined result. |
| */ |
| template <typename T, std::enable_if_t<std::is_convertible<T, uint64_t>::value, bool> = true> |
| inline uint64_t HashCombine(uint64_t key, const T& value) { |
| // XXX: do not use std::hash in this function. This hash must be stable |
| // across different platforms and std::hash is implementation dependent. |
| return key ^ (uint64_t(value) + 0x9e3779b9 + (key << 6) + (key >> 2)); |
| } |
| |
| /*! |
| * \brief Return whether a boolean flag is set as an environment variable. |
| * |
| * Returns true if the environment variable is set to a non-zero |
| * integer, or to a non-empty string that is not an integer. |
| * |
| * Returns false if the environment variable is unset, if the |
| * environment variable is set to the integer zero, or if the |
| * environment variable is an empty string. |
| */ |
| inline bool BoolEnvironmentVar(const char* varname) { |
| const char* var = std::getenv(varname); |
| if (!var) { |
| return false; |
| } |
| |
| int x = 0; |
| std::istringstream is(var); |
| if (is >> x) { |
| return x; |
| } |
| |
| return *var; |
| } |
| |
| } // namespace support |
| } // namespace tvm |
| #endif // TVM_SUPPORT_UTILS_H_ |