Sunny Srivastava | fa5e4d3 | 2023-03-12 11:59:49 -0500 | [diff] [blame] | 1 | #pragma once |
| 2 | |
| 3 | #include "constants.hpp" |
| 4 | #include "logger.hpp" |
| 5 | |
| 6 | #include <algorithm> |
Sunny Srivastava | 995e1c2 | 2025-08-28 03:13:00 -0500 | [diff] [blame] | 7 | #include <chrono> |
Sunny Srivastava | fa5e4d3 | 2023-03-12 11:59:49 -0500 | [diff] [blame] | 8 | #include <cstdio> |
| 9 | #include <cstdlib> |
| 10 | #include <vector> |
| 11 | |
| 12 | /** |
| 13 | * @brief Namespace to host common utility methods. |
| 14 | * |
| 15 | * A method qualifies as a common utility function if, |
| 16 | * A)It is being used by the utility namespace at the same level as well as |
| 17 | * other files directly. |
| 18 | * B) The utility should be a leaf node and should not be dependent on any other |
| 19 | * utility. |
| 20 | * ******************* |
| 21 | * | Commmon Utility | - - - - - - - |
| 22 | * ******************* | |
| 23 | * /\ | |
| 24 | * / \ | |
| 25 | * **************** **************** | |
| 26 | * | json utility | | dbus utility | | |
| 27 | * **************** **************** | |
| 28 | * \ / | |
| 29 | * \ / | |
| 30 | * ************************ | |
| 31 | * | Vpd specific Utility | - - - - - - - |
| 32 | * ************************ |
| 33 | */ |
| 34 | |
| 35 | namespace vpd |
| 36 | { |
| 37 | |
| 38 | namespace commonUtility |
| 39 | { |
| 40 | /** @brief Return the hex representation of the incoming byte. |
| 41 | * |
| 42 | * @param [in] i_aByte - The input byte. |
| 43 | * @returns Hex representation of the byte as a character. |
| 44 | */ |
| 45 | constexpr auto toHex(size_t i_aByte) |
| 46 | { |
| 47 | constexpr auto l_map = "0123456789abcdef"; |
| 48 | return l_map[i_aByte]; |
| 49 | } |
| 50 | |
| 51 | /** |
| 52 | * @brief API to return null at the end of variadic template args. |
| 53 | * |
| 54 | * @return empty string. |
| 55 | */ |
| 56 | inline std::string getCommand() |
| 57 | { |
| 58 | return ""; |
| 59 | } |
| 60 | |
| 61 | /** |
| 62 | * @brief API to arrange create command. |
| 63 | * |
| 64 | * @param[in] arguments to create the command |
| 65 | * @return Command string |
| 66 | */ |
| 67 | template <typename T, typename... Types> |
| 68 | inline std::string getCommand(T i_arg1, Types... i_args) |
| 69 | { |
| 70 | std::string l_cmd = " " + i_arg1 + getCommand(i_args...); |
| 71 | |
| 72 | return l_cmd; |
| 73 | } |
| 74 | |
| 75 | /** |
| 76 | * @brief API to create shell command and execute. |
| 77 | * |
| 78 | * @throw std::runtime_error. |
| 79 | * |
| 80 | * @param[in] arguments for command |
| 81 | * @returns output of that command |
| 82 | */ |
| 83 | template <typename T, typename... Types> |
| 84 | inline std::vector<std::string> executeCmd(T&& i_path, Types... i_args) |
| 85 | { |
| 86 | std::vector<std::string> l_cmdOutput; |
| 87 | std::array<char, constants::CMD_BUFFER_LENGTH> l_buffer; |
| 88 | |
| 89 | std::string l_cmd = i_path + getCommand(i_args...); |
| 90 | |
| 91 | std::unique_ptr<FILE, decltype(&pclose)> l_cmdPipe( |
| 92 | popen(l_cmd.c_str(), "r"), pclose); |
| 93 | |
| 94 | if (!l_cmdPipe) |
| 95 | { |
| 96 | logging::logMessage( |
| 97 | "popen failed with error " + std::string(strerror(errno))); |
| 98 | throw std::runtime_error("popen failed!"); |
| 99 | } |
| 100 | while (fgets(l_buffer.data(), l_buffer.size(), l_cmdPipe.get()) != nullptr) |
| 101 | { |
| 102 | l_cmdOutput.emplace_back(l_buffer.data()); |
| 103 | } |
| 104 | |
| 105 | return l_cmdOutput; |
| 106 | } |
| 107 | |
| 108 | /** @brief Converts string to lower case. |
| 109 | * |
| 110 | * @param [in] i_string - Input string. |
| 111 | */ |
| 112 | inline void toLower(std::string& i_string) |
| 113 | { |
| 114 | std::transform(i_string.begin(), i_string.end(), i_string.begin(), |
| 115 | [](unsigned char l_char) { return std::tolower(l_char); }); |
| 116 | } |
Anupama B R | 6f14283 | 2025-04-11 04:17:49 -0500 | [diff] [blame] | 117 | |
| 118 | /** |
| 119 | * @brief An API to get hex representation of the incoming bytes. |
| 120 | * |
| 121 | * The API returns the hex represented value of the given input in string format |
| 122 | * with 0x prefix. |
| 123 | * |
| 124 | * @param[in] i_keywordValue - Vector of input byte. |
| 125 | * |
| 126 | * @return - Returns the converted string value. |
| 127 | */ |
| 128 | inline std::string convertByteVectorToHex( |
| 129 | const types::BinaryVector& i_keywordValue) |
| 130 | { |
| 131 | std::ostringstream l_oss; |
| 132 | l_oss << "0x"; |
| 133 | for (const auto& l_byte : i_keywordValue) |
| 134 | { |
| 135 | l_oss << std::setfill('0') << std::setw(2) << std::hex |
| 136 | << static_cast<int>(l_byte); |
| 137 | } |
| 138 | |
| 139 | return l_oss.str(); |
| 140 | } |
Souvik Roy | af52898 | 2025-07-16 13:50:18 -0500 | [diff] [blame] | 141 | |
| 142 | /** |
| 143 | * @brief An API to convert binary value into ascii/hex representation. |
| 144 | * |
| 145 | * If given data contains printable characters, ASCII formated string value of |
| 146 | * the input data will be returned. Otherwise if the data has any non-printable |
| 147 | * value, returns the hex represented value of the given data in string format. |
| 148 | * |
| 149 | * @param[in] i_keywordValue - Data in binary format. |
| 150 | * |
| 151 | * @throw - Throws std::bad_alloc or std::terminate in case of error. |
| 152 | * |
| 153 | * @return - Returns the converted string value. |
| 154 | */ |
| 155 | inline std::string getPrintableValue(const types::BinaryVector& i_keywordValue) |
| 156 | { |
| 157 | bool l_allPrintable = |
| 158 | std::all_of(i_keywordValue.begin(), i_keywordValue.end(), |
| 159 | [](const auto& l_byte) { return std::isprint(l_byte); }); |
| 160 | |
| 161 | std::ostringstream l_oss; |
| 162 | if (l_allPrintable) |
| 163 | { |
| 164 | l_oss << std::string(i_keywordValue.begin(), i_keywordValue.end()); |
| 165 | } |
| 166 | else |
| 167 | { |
| 168 | l_oss << "0x"; |
| 169 | for (const auto& l_byte : i_keywordValue) |
| 170 | { |
| 171 | l_oss << std::setfill('0') << std::setw(2) << std::hex |
| 172 | << static_cast<int>(l_byte); |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | return l_oss.str(); |
| 177 | } |
| 178 | |
| 179 | /** |
| 180 | * @brief API to get data in binary format. |
| 181 | * |
| 182 | * This API converts given string value present in hexadecimal or decimal format |
| 183 | * into array of binary data. |
| 184 | * |
| 185 | * @param[in] i_value - Input data. |
| 186 | * |
| 187 | * @return - Array of binary data on success, throws as exception in case |
| 188 | * of any error. |
| 189 | * |
| 190 | * @throw std::runtime_error, std::out_of_range, std::bad_alloc, |
| 191 | * std::invalid_argument |
| 192 | */ |
| 193 | inline types::BinaryVector convertToBinary(const std::string& i_value) |
| 194 | { |
| 195 | if (i_value.empty()) |
| 196 | { |
| 197 | throw std::runtime_error("Empty input provided"); |
| 198 | } |
| 199 | |
| 200 | types::BinaryVector l_binaryValue{}; |
| 201 | |
| 202 | if (i_value.substr(0, 2).compare("0x") == constants::STR_CMP_SUCCESS) |
| 203 | { |
| 204 | if (i_value.length() % 2 != 0) |
| 205 | { |
| 206 | throw std::runtime_error( |
| 207 | "Write option accepts 2 digit hex numbers. (Ex. 0x1 " |
| 208 | "should be given as 0x01)."); |
| 209 | } |
| 210 | |
| 211 | auto l_value = i_value.substr(2); |
| 212 | |
| 213 | if (l_value.empty()) |
| 214 | { |
| 215 | throw std::runtime_error( |
| 216 | "Provide a valid hexadecimal input. (Ex. 0x30313233)"); |
| 217 | } |
| 218 | |
| 219 | if (l_value.find_first_not_of("0123456789abcdefABCDEF") != |
| 220 | std::string::npos) |
| 221 | { |
| 222 | throw std::runtime_error("Provide a valid hexadecimal input."); |
| 223 | } |
| 224 | |
| 225 | for (size_t l_pos = 0; l_pos < l_value.length(); l_pos += 2) |
| 226 | { |
| 227 | uint8_t l_byte = static_cast<uint8_t>( |
| 228 | std::stoi(l_value.substr(l_pos, 2), nullptr, 16)); |
| 229 | l_binaryValue.push_back(l_byte); |
| 230 | } |
| 231 | } |
| 232 | else |
| 233 | { |
| 234 | l_binaryValue.assign(i_value.begin(), i_value.end()); |
| 235 | } |
| 236 | return l_binaryValue; |
| 237 | } |
| 238 | |
Sunny Srivastava | 995e1c2 | 2025-08-28 03:13:00 -0500 | [diff] [blame] | 239 | /** |
| 240 | * @brief API to get current time stamp since Epoch. |
| 241 | * |
| 242 | * @return time stamp in seconds. |
| 243 | */ |
| 244 | inline size_t getCurrentTimeSinceEpoch() noexcept |
| 245 | { |
| 246 | // Use high_resolution_clock for better precision |
| 247 | const auto l_now = std::chrono::high_resolution_clock::now(); |
| 248 | auto l_durationSinceEpoch = l_now.time_since_epoch(); |
| 249 | |
| 250 | auto l_timeStampSeconds = |
| 251 | std::chrono::duration_cast<std::chrono::seconds>(l_durationSinceEpoch) |
| 252 | .count(); |
| 253 | return static_cast<size_t>(l_timeStampSeconds); |
| 254 | } |
| 255 | |
Sunny Srivastava | fa5e4d3 | 2023-03-12 11:59:49 -0500 | [diff] [blame] | 256 | } // namespace commonUtility |
| 257 | } // namespace vpd |