| @@ -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" | |||
| @@ -0,0 +1,56 @@ | |||
| #pragma once | |||
| #include <iostream> | |||
| 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<typename T_char, typename T_traits> | |||
| inline basic_ostream<T_char, T_traits>& operator<< ( | |||
| basic_ostream<T_char, T_traits>& os, | |||
| const cppcore::hexdump& d); | |||
| } | |||
| #include "hexdump.inl" | |||
| @@ -0,0 +1,89 @@ | |||
| #pragma once | |||
| #include <iomanip> | |||
| #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<const uint8_t*>(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<char>(p[i]) | |||
| : '.'); | |||
| os << " " << hex << setw(2) << setfill('0') << static_cast<int>(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<typename T_char, typename T_traits> | |||
| inline basic_ostream<T_char, T_traits>& operator<< ( | |||
| basic_ostream<T_char, T_traits>& os, | |||
| const cppcore::hexdump& d) | |||
| { | |||
| d.print(os); | |||
| return os; | |||
| } | |||
| } | |||
| @@ -0,0 +1,19 @@ | |||
| #include <gtest/gtest.h> | |||
| #include <cppcore/misc/hexdump.h> | |||
| 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 |"); | |||
| } | |||