blob: b4d164f6690b13d5cce4a8b23cc466a6fcb7d52d [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.
43 * @returns Hex representation of the byte as a character.
44 */
45constexpr 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 */
56inline 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 */
67template <typename T, typename... Types>
68inline 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 */
83template <typename T, typename... Types>
84inline 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 */
112inline 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 R6f142832025-04-11 04:17:49 -0500117
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 */
128inline 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 Royaf528982025-07-16 13:50:18 -0500141
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 */
155inline 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 */
193inline 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 Srivastava995e1c22025-08-28 03:13:00 -0500239/**
240 * @brief API to get current time stamp since Epoch.
241 *
242 * @return time stamp in seconds.
243 */
244inline 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 Srivastavafa5e4d32023-03-12 11:59:49 -0500256} // namespace commonUtility
257} // namespace vpd