Browse Source

* Implemented hexdump

master
bergmann 4 years ago
parent
commit
cc7d1870ff
4 changed files with 165 additions and 0 deletions
  1. +1
    -0
      include/cppcore/misc.h
  2. +56
    -0
      include/cppcore/misc/hexdump.h
  3. +89
    -0
      include/cppcore/misc/hexdump.inl
  4. +19
    -0
      test/cppcore/misc/hexdump_tests.cpp

+ 1
- 0
include/cppcore/misc.h View File

@@ -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"


+ 56
- 0
include/cppcore/misc/hexdump.h View File

@@ -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"

+ 89
- 0
include/cppcore/misc/hexdump.inl View File

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

}

+ 19
- 0
test/cppcore/misc/hexdump_tests.cpp View File

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

Loading…
Cancel
Save