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