Skip to content

Commit f8dba97

Browse files
authored
Merge pull request #577 from souvik1914581/sr_vpdToolDumpInventory_finalPR
Implement vpd-tool dump inventory in table format
2 parents 720f4d0 + 19c718c commit f8dba97

File tree

4 files changed

+254
-6
lines changed

4 files changed

+254
-6
lines changed

vpd-tool/include/tool_types.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ using WriteVpdParams = std::variant<IpzData, KwData>;
5858
// Return type of ObjectMapper GetObject API
5959
using MapperGetObject = std::map<std::string,std::vector<std::string>>;
6060

61+
// Table row data
62+
using TableRowData = std::vector<std::string>;
63+
64+
// Type used to populate table data
65+
using TableInputData = std::vector<TableRowData>;
66+
67+
// A table column name-size pair
68+
using TableColumnNameSizePair = std::pair<std::string, std::size_t>;
69+
6170
enum UserOption
6271
{
6372
Exit,

vpd-tool/include/tool_utils.hpp

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,5 +494,190 @@ inline std::vector<std::string> GetSubTreePaths(
494494
}
495495
return l_objectPaths;
496496
}
497+
498+
/**
499+
* @brief A class to print data in tabular format
500+
*
501+
* This class implements methods to print data in a two dimensional tabular
502+
* format. All entries in the table must be in string format.
503+
*
504+
*/
505+
class Table
506+
{
507+
class Column : public types::TableColumnNameSizePair
508+
{
509+
public:
510+
/**
511+
* @brief API to get the name of the Column
512+
*
513+
* @return Name of the Column.
514+
*/
515+
const std::string& Name() const
516+
{
517+
return this->first;
518+
}
519+
520+
/**
521+
* @brief API to get the width of the Column
522+
*
523+
* @return Width of the Column.
524+
*/
525+
std::size_t Width() const
526+
{
527+
return this->second;
528+
}
529+
};
530+
531+
// Current width of the table
532+
std::size_t m_currentWidth;
533+
534+
// Character to be used as fill character between entries
535+
char m_fillCharacter;
536+
537+
// Separator character to be used between columns
538+
char m_separator;
539+
540+
// Array of columns
541+
std::vector<Column> m_columns;
542+
543+
/**
544+
* @brief API to Print Header
545+
*
546+
* Header line prints the names of the Column headers separated by the
547+
* specified separator character and spaced accordingly.
548+
*
549+
* @throw std::out_of_range, std::length_error, std::bad_alloc
550+
*/
551+
void PrintHeader() const
552+
{
553+
for (const auto& l_column : m_columns)
554+
{
555+
PrintEntry(l_column.Name(), l_column.Width());
556+
}
557+
std::cout << m_separator << std::endl;
558+
}
559+
560+
/**
561+
* @brief API to Print Horizontal Line
562+
*
563+
* A horizontal line is a sequence of '*'s.
564+
*
565+
* @throw std::out_of_range, std::length_error, std::bad_alloc
566+
*/
567+
void PrintHorizontalLine() const
568+
{
569+
std::cout << std::string(m_currentWidth, '*') << std::endl;
570+
}
571+
572+
/**
573+
* @brief API to print an entry in the table
574+
*
575+
* An entry is a separator character followed by the text to print.
576+
* The text is centre-aligned.
577+
*
578+
* @param[in] i_text - text to print
579+
* @param[in] i_columnWidth - width of the column
580+
*
581+
* @throw std::out_of_range, std::length_error, std::bad_alloc
582+
*/
583+
void PrintEntry(const std::string& i_text, std::size_t i_columnWidth) const
584+
{
585+
const std::size_t l_textLength{i_text.length()};
586+
587+
constexpr std::size_t l_minFillChars{3};
588+
const std::size_t l_numFillChars =
589+
((l_textLength >= i_columnWidth ? l_minFillChars
590+
: i_columnWidth - l_textLength)) -
591+
1; // -1 for the separator character
592+
593+
const unsigned l_oddFill = l_numFillChars % 2;
594+
595+
std::cout << m_separator
596+
<< std::string((l_numFillChars / 2) + l_oddFill,
597+
m_fillCharacter)
598+
<< i_text << std::string(l_numFillChars / 2, m_fillCharacter);
599+
}
600+
601+
public:
602+
/**
603+
* @brief Table Constructor
604+
*
605+
* Parameterized constructor for a Table object
606+
*
607+
*/
608+
constexpr explicit Table(const char i_fillCharacter = ' ',
609+
const char i_separator = '|') noexcept :
610+
m_currentWidth{0}, m_fillCharacter{i_fillCharacter},
611+
m_separator{i_separator}
612+
{}
613+
614+
// deleted methods
615+
Table(const Table&) = delete;
616+
Table operator=(const Table&) = delete;
617+
Table(const Table&&) = delete;
618+
Table operator=(const Table&&) = delete;
619+
620+
~Table() = default;
621+
622+
/**
623+
* @brief API to add column to Table
624+
*
625+
* @param[in] i_name - Name of the column.
626+
*
627+
* @param[in] i_width - Width to allocate for the column.
628+
*
629+
* @return On success returns 0, otherwise returns -1.
630+
*/
631+
int AddColumn(const std::string& i_name, std::size_t i_width)
632+
{
633+
if (i_width < i_name.length())
634+
return constants::FAILURE;
635+
m_columns.emplace_back(types::TableColumnNameSizePair(i_name, i_width));
636+
m_currentWidth += i_width;
637+
return constants::SUCCESS;
638+
}
639+
640+
/**
641+
* @brief API to print the Table to console.
642+
*
643+
* This API prints the table data to console.
644+
*
645+
* @param[in] i_tableData - The data to be printed.
646+
*
647+
* @return On success returns 0, otherwise returns -1.
648+
*
649+
* @throw std::out_of_range, std::length_error, std::bad_alloc
650+
*/
651+
int Print(const types::TableInputData& i_tableData) const
652+
{
653+
PrintHorizontalLine();
654+
PrintHeader();
655+
PrintHorizontalLine();
656+
657+
// print the table data
658+
for (const auto& l_row : i_tableData)
659+
{
660+
unsigned l_columnNumber{0};
661+
662+
// number of columns in input data is greater than the number of
663+
// columns specified in Table
664+
if (l_row.size() > m_columns.size())
665+
{
666+
return constants::FAILURE;
667+
}
668+
669+
for (const auto& l_entry : l_row)
670+
{
671+
PrintEntry(l_entry, m_columns[l_columnNumber].Width());
672+
673+
++l_columnNumber;
674+
}
675+
std::cout << m_separator << std::endl;
676+
}
677+
PrintHorizontalLine();
678+
return constants::SUCCESS;
679+
}
680+
};
681+
497682
} // namespace utils
498683
} // namespace vpd

vpd-tool/include/vpd_tool.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,12 @@ class VpdTool
236236
int cleanSystemVpd() const noexcept;
237237

238238
/**
239-
* @brief Dump all the inventory objects in JSON or Table format to console.
239+
* @brief Dump all the inventory objects in JSON or table format to console.
240240
*
241-
* This API dumps specific properties of all the objects in Phosphor
242-
* Inventory Manager DBus tree to console in JSON or Table format to
243-
* console. For each object, the following properties are dumped to console:
241+
* This API dumps specific properties of all the inventory objects to
242+
* console in JSON or table format to console. The inventory object paths
243+
* are extracted from PIM. For each object, the following properties are
244+
* dumped to console:
244245
* - Present property, Pretty Name, Location Code, Sub Model
245246
* - SN, PN, CC, FN, DR keywords under VINI record.
246247
* If the "Present" property of a FRU is false, the FRU is not dumped to
@@ -249,7 +250,7 @@ class VpdTool
249250
* console.
250251
*
251252
* @param[in] i_dumpTable - Flag which specifies if the inventory should be
252-
* dumped in Table format or not.
253+
* dumped in table format or not.
253254
*
254255
* @return On success returns 0, otherwise returns -1.
255256
*/

vpd-tool/src/vpd_tool.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,60 @@ int VpdTool::dumpInventory(bool i_dumpTable) const noexcept
715715

716716
if (i_dumpTable)
717717
{
718-
// TODO: Dump inventory in table format
718+
// create Table object
719+
utils::Table l_inventoryTable{};
720+
721+
// columns to be populated in the Inventory table
722+
const std::vector<types::TableColumnNameSizePair>
723+
l_tableColumns = {
724+
{"FRU", 100}, {"CC", 6}, {"DR", 20},
725+
{"LocationCode", 32}, {"PN", 8}, {"PrettyName", 80},
726+
{"SubModel", 10}, {"SN", 15}, {"type", 60}};
727+
728+
types::TableInputData l_tableData;
729+
730+
// First prepare the Table Columns
731+
for (const auto& l_column : l_tableColumns)
732+
{
733+
if (constants::FAILURE ==
734+
l_inventoryTable.AddColumn(l_column.first,
735+
l_column.second))
736+
{
737+
// TODO: Enable logging when verbose is enabled.
738+
std::cerr << "Failed to add column " << l_column.first
739+
<< " in Inventory Table." << std::endl;
740+
}
741+
}
742+
743+
// iterate through the json array
744+
for (const auto& l_fruEntry : l_resultInJson[0].items())
745+
{
746+
std::vector<std::string> l_row;
747+
for (const auto& l_column : l_tableColumns)
748+
{
749+
const auto& l_fruJson = l_fruEntry.value();
750+
751+
if (l_column.first == "FRU")
752+
{
753+
l_row.push_back(l_fruEntry.key());
754+
}
755+
else
756+
{
757+
if (l_fruJson.contains(l_column.first))
758+
{
759+
l_row.push_back(l_fruJson[l_column.first]);
760+
}
761+
else
762+
{
763+
l_row.push_back("");
764+
}
765+
}
766+
}
767+
768+
l_tableData.push_back(l_row);
769+
}
770+
771+
l_rc = l_inventoryTable.Print(l_tableData);
719772
}
720773
else
721774
{

0 commit comments

Comments
 (0)