Skip to content

Instantly share code, notes, and snippets.

@yumetodo
Created April 9, 2017 15:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yumetodo/ac2e62583493b1e0ed8f609c686b6c70 to your computer and use it in GitHub Desktop.
Save yumetodo/ac2e62583493b1e0ed8f609c686b6c70 to your computer and use it in GitHub Desktop.
なんとなくhexdumpするために
#include <ostream>
#include <iomanip>
#include <utility>
#include <type_traits>
#include <cstdint>
#include <climits>
static_assert(CHAR_BIT == 8, "1byte != 8bit");
namespace detail{
template<typename T>
class hexdumper {
private:
const T* obj_;
public:
hexdumper() = delete;
hexdumper(const T& o) : obj_(&o) {}//promise not to modify target object
hexdumper(T&&) = delete;//reject rvale
hexdumper(const hexdumper&) = delete;
hexdumper(hexdumper&&) = default;//allow move ctor for factory function
hexdumper& operator=(const hexdumper&) = delete;
hexdumper& operator=(hexdumper&&) = delete;
void operator()(std::ostream& os) const {
constexpr std::size_t size = sizeof(T);
constexpr std::size_t col_num = 0x0F + 1;
using byte = char;
const byte* o = reinterpret_cast<const byte*>(this->obj_);
os
<< " Address | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 123456789ABCDEF" << std::endl
<< "---------+-------------------------------------------------+----------------" << std::endl;
for(std::size_t i = 0; i <= size / col_num; ++i){
const std::size_t line_first_pos = i * col_num;
os << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << line_first_pos << " | ";
std::size_t j = 0;
for(; j < col_num && j < size - line_first_pos; ++j){
os << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << std::uint16_t(std::uint8_t(o[line_first_pos + j])) << ' ';
}
for(; j < col_num; ++j) os << " ";
os << "| ";
for(std::size_t j = 0; j < col_num && j < size - line_first_pos; ++j){
const char c = (o[line_first_pos + j] && o[line_first_pos + j] <= 0xF4) ? o[line_first_pos + j] : u8"."[0];
const std::size_t char_width = (c < 0x7F) ? 1 : (c < 0xDF) ? 2 : (c < 0xEF) ? 3 : 4;
os << std::setfill('.') << std::setw(char_width) << c;
}
os << std::endl;
}
os << std::flush;
}
};
template<typename T>
std::ostream& operator<< (std::ostream& os, const hexdumper<T>& hexdumper) {
hexdumper(os);
return os;
}
}
template<typename T>
detail::hexdumper<std::remove_reference_t<T>> hexdump(T&& o){ return { std::forward<T>(o) }; }
@yumetodo
Copy link
Author

yumetodo commented Jul 3, 2017

使い方

#include "hexdumper.hpp"
#include <sstream>
#include <iostream>
int main()
{
    std::stringstream ss;
    ss
        << "P1" << std::endl
        << "1 1" << std::endl
        << "1" << std::endl;
    
    auto c = ss.get();
    std::cout << hexdump(c);
}

https://wandbox.org/permlink/IBqibdCTeem1i1PC

出力例

 Address | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 123456789ABCDEF
---------+-------------------------------------------------+----------------
00000000 | 50 00 00 00                                     | P...
#include <cstring>
#include <iostream>

#include "hexdumper.hpp"
class Hexa {
public:
    Hexa() : str_("arikitari") {}
    ~Hexa() = default;
    virtual void setStr(void){}
protected:
    char str_[0x10];
};

class Hexa2 : public Hexa {
public:
    Hexa2() : Hexa() {}
    ~Hexa2() = default;
    void setStr(void) noexcept override { std::strcpy(this->str_,"hexadrive"); }
    char* drawStr(void) noexcept { return this->str_; }
    const char* drawStr(void) const noexcept { return this->str_; }
};

int main(void)
{
    using std::endl;
    Hexa2 hexa = {};
    std::cout << "before memset" << endl << hexdump(hexa) << endl;
    Hexa2* pHexa = &hexa;
    std::memset(pHexa, 0, sizeof(Hexa2));
    std::cout << "after memset" << endl << hexdump(hexa) << endl;
    pHexa->setStr();    // ここでクラッシュする
    std::cout << pHexa->drawStr() << std::endl;
}

https://wandbox.org/permlink/0aoTnoyqgYaJd9Z6

出力例

before memset
 Address | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 123456789ABCDEF
---------+-------------------------------------------------+----------------
00000000 | 00 19 40 00 00 00 00 00 61 72 69 6B 69 74 61 72 | .�@.....arikitar
00000010 | 69 00 00 00 00 00 00 00                         | i.......

after memset
 Address | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 123456789ABCDEF
---------+-------------------------------------------------+----------------
00000000 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00000010 | 00 00 00 00 00 00 00 00                         | ........

Segmentation fault

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment