From cc7d1870ff8b75a5480adc86402aecc3d8d82cde Mon Sep 17 00:00:00 2001 From: bergmann Date: Wed, 17 Jul 2019 20:53:06 +0200 Subject: [PATCH] * Implemented hexdump --- include/cppcore/misc.h | 1 + include/cppcore/misc/hexdump.h | 56 ++++++++++++++++++ include/cppcore/misc/hexdump.inl | 89 +++++++++++++++++++++++++++++ test/cppcore/misc/hexdump_tests.cpp | 19 ++++++ 4 files changed, 165 insertions(+) create mode 100644 include/cppcore/misc/hexdump.h create mode 100644 include/cppcore/misc/hexdump.inl create mode 100644 test/cppcore/misc/hexdump_tests.cpp diff --git a/include/cppcore/misc.h b/include/cppcore/misc.h index 27c62de..db5d054 100644 --- a/include/cppcore/misc.h +++ b/include/cppcore/misc.h @@ -2,6 +2,7 @@ #include "misc/exception.h" #include "misc/flags.h" +#include "misc/hexdump.h" #include "misc/indent.h" #include "misc/stream.h" #include "misc/type_helper.h" diff --git a/include/cppcore/misc/hexdump.h b/include/cppcore/misc/hexdump.h new file mode 100644 index 0000000..d200c19 --- /dev/null +++ b/include/cppcore/misc/hexdump.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +namespace cppcore +{ + + /** + * @brief Helper class to print hexdumps. + */ + struct hexdump + { + const void * data; //!< Data to dump. + size_t len; //!< Number of bytes stored in data. + size_t offset; //!< Offset to start numbering at (this will not affect the passed data pointer). + size_t split; //!< Add extra colum after specified number of bytes. + size_t newline; //!< Add new line after specified number of bytes. + + /** + * Constructor. + * + * @param[in] p_data Data to dump. + * @param[in] p_len Number of bytes stored in @data. + * @param[in] p_offset Offset to start numbering at (this will not affect the passed data pointer). + * @param[in] p_split Add extra colum after specified number of bytes. + * @param[in] p_newline Add new line after specified number of bytes. + */ + inline hexdump( + const void * p_data, + size_t p_len, + size_t p_offset = 0, + size_t p_split = 8, + size_t p_newline = 16); + + /** + * @pbrief Print the hexdump to the passed stream. + */ + inline void print(std::ostream& os) const; + }; + +} + +namespace std +{ + + /** + * @brief Write the helper class to stream using the << operator. + */ + template + inline basic_ostream& operator<< ( + basic_ostream& os, + const cppcore::hexdump& d); + +} + +#include "hexdump.inl" diff --git a/include/cppcore/misc/hexdump.inl b/include/cppcore/misc/hexdump.inl new file mode 100644 index 0000000..23afc77 --- /dev/null +++ b/include/cppcore/misc/hexdump.inl @@ -0,0 +1,89 @@ +#pragma once + +#include + +#include "hexdump.h" + +namespace cppcore +{ + + /* hexdump */ + + hexdump::hexdump( + const void * p_data, + size_t p_len, + size_t p_offset, + size_t p_split, + size_t p_newline) + : data (p_data) + , len (p_len) + , offset (p_offset) + , split (p_split) + , newline (p_newline) + { } + + void hexdump::print(std::ostream& os) const + { + using namespace ::std; + + const uint8_t * p = static_cast(data); + size_t i = 0; + size_t l = 0; + std::string s; + + while (i < len) + { + if (i % newline == 0) + { + os << hex << setw(8) << setfill('0') << (offset + i); + } + + if (l % split == 0) + { + os.put(' '); + s.push_back('|'); + } + + s.push_back(std::isprint(p[i]) + ? static_cast(p[i]) + : '.'); + + os << " " << hex << setw(2) << setfill('0') << static_cast(p[i]); + ++l; + ++i; + + if (i % newline == 0) + { + os << " " << s << "|" << endl; + s.clear(); + l = 0; + } + } + + if (l > 0) + { + auto rest = (newline - l); + auto fill = (rest / split); + os << std::string(3 * rest + fill, ' ') + << " " << s << std::string(rest + fill, ' ') << "|"; + } + } + +} + +namespace std +{ + + /** + * @brief Write the helper class to stream using the << operator. + */ + template + inline basic_ostream& operator<< ( + basic_ostream& os, + const cppcore::hexdump& d) + { + d.print(os); + return os; + } + +} diff --git a/test/cppcore/misc/hexdump_tests.cpp b/test/cppcore/misc/hexdump_tests.cpp new file mode 100644 index 0000000..22efad0 --- /dev/null +++ b/test/cppcore/misc/hexdump_tests.cpp @@ -0,0 +1,19 @@ +#include +#include + +using namespace ::cppcore; +using namespace ::testing; + +TEST(hexdump_tests, simple) +{ + std::string s("ahgiupiPTIBPHgGHIbt974ht hPVIb pg ZTPGTiBGBKGSGSQT20Z4TNVK AQHZQ"); + std::ostringstream ss; + ss << hexdump(s.data(), s.size(), 123, 4); + EXPECT_EQ( + ss.str(), + "0000007b 61 68 67 69 75 70 69 50 54 49 42 50 48 67 47 48 |ahgi|upiP|TIBP|HgGH|\n" + "0000008b 49 62 74 39 37 34 68 74 20 68 50 56 49 62 20 70 |Ibt9|74ht| hPV|Ib p|\n" + "0000009b 67 20 5a 54 50 47 54 69 42 47 42 4b 47 53 47 53 |g ZT|PGTi|BGBK|GSGS|\n" + "000000ab 51 54 32 30 5a 34 54 4e 56 4b 20 20 41 51 48 5a |QT20|Z4TN|VK |AQHZ|\n" + "000000bb 51 |Q |"); +}