@@ -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 |"); | |||
} |