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