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