1 | // ================================================================= // |
---|
2 | // // |
---|
3 | // File : awt_hexdump.hxx // |
---|
4 | // Purpose : // |
---|
5 | // // |
---|
6 | // Coded by Ralf Westram (coder@reallysoft.de) in September 2011 // |
---|
7 | // Institute of Microbiology (Technical University Munich) // |
---|
8 | // http://www.arb-home.de/ // |
---|
9 | // // |
---|
10 | // ================================================================= // |
---|
11 | |
---|
12 | #ifndef AWT_HEXDUMP_HXX |
---|
13 | #define AWT_HEXDUMP_HXX |
---|
14 | |
---|
15 | #ifndef AWT_HXX |
---|
16 | #include "awt.hxx" |
---|
17 | #endif |
---|
18 | |
---|
19 | #ifndef AW_ROOT_HXX |
---|
20 | #include <aw_root.hxx> |
---|
21 | #endif |
---|
22 | #ifndef ARB_STRBUF_H |
---|
23 | #include <arb_strbuf.h> |
---|
24 | #endif |
---|
25 | #ifndef _GLIBCXX_CCTYPE |
---|
26 | #include <cctype> |
---|
27 | #endif |
---|
28 | |
---|
29 | // ------------------- |
---|
30 | // hex dumper |
---|
31 | |
---|
32 | CONSTEXPR_INLINE char nibble2hex(unsigned char c) { return "0123456789ABCDEF"[c&0x0f]; } |
---|
33 | inline void dump_hexbyte(GBS_strstruct& buf, unsigned char c) { buf.put(nibble2hex(c>>4)); buf.put(nibble2hex(c)); } |
---|
34 | |
---|
35 | class MemDump { |
---|
36 | bool show_offset; // prefix every line with position info ? |
---|
37 | bool hex; // dump hex ? |
---|
38 | bool ascii; // dump ascii ? |
---|
39 | |
---|
40 | size_t width; // > 0 -> wrap lines every XXX positions |
---|
41 | size_t separate; // > 0 -> separate by one additional space after every XXX bytes |
---|
42 | bool space; // true -> space hex bytes |
---|
43 | |
---|
44 | bool is_separate_position(size_t pos) const { return separate && pos && !(pos%separate); } |
---|
45 | |
---|
46 | void dump_sep(GBS_strstruct& buf) const { buf.cat(" | "); } |
---|
47 | void dump_offset(GBS_strstruct& buf, size_t off) const { |
---|
48 | if (show_offset) { |
---|
49 | dump_hexbyte(buf, off>>8); |
---|
50 | dump_hexbyte(buf, off&0xff); |
---|
51 | if (hex||ascii) dump_sep(buf); |
---|
52 | } |
---|
53 | } |
---|
54 | void dump_hex(GBS_strstruct& buf, const char *mem, size_t off, size_t count, bool padded) const { |
---|
55 | size_t i; |
---|
56 | for (i = 0; i<count; ++i) { |
---|
57 | if (is_separate_position(i)) buf.put(' '); |
---|
58 | dump_hexbyte(buf, mem[off+i]); |
---|
59 | if (space) buf.put(' '); |
---|
60 | } |
---|
61 | if (padded) { |
---|
62 | for (; i<width; ++i) { |
---|
63 | buf.nput(' ', 2+space+is_separate_position(i)); |
---|
64 | } |
---|
65 | } |
---|
66 | buf.cut_tail(space); |
---|
67 | } |
---|
68 | void dump_ascii(GBS_strstruct& buf, const char *mem, size_t off, size_t count) const { |
---|
69 | for (size_t i = 0; i<count; ++i) { |
---|
70 | if (is_separate_position(i)) buf.put(' '); |
---|
71 | buf.put(isprint(mem[off+i]) ? mem[off+i] : '.'); |
---|
72 | } |
---|
73 | } |
---|
74 | void dump_line(GBS_strstruct& buf, const char *mem, size_t off, size_t count) const { |
---|
75 | dump_offset(buf, off); |
---|
76 | if (hex) { |
---|
77 | dump_hex(buf, mem, off, count, ascii); |
---|
78 | if (ascii) dump_sep(buf); |
---|
79 | } |
---|
80 | if (ascii) dump_ascii(buf, mem, off, count); |
---|
81 | buf.put('\n'); |
---|
82 | } |
---|
83 | void dump_wrapped(GBS_strstruct& buf, const char *mem, size_t size) const { |
---|
84 | awt_assert(wrapped()); |
---|
85 | size_t off = 0; |
---|
86 | while (size) { |
---|
87 | size_t count = size<width ? size : width; |
---|
88 | dump_line(buf, mem, off, count); |
---|
89 | size -= count; |
---|
90 | off += count; |
---|
91 | } |
---|
92 | } |
---|
93 | |
---|
94 | public: |
---|
95 | |
---|
96 | MemDump(bool show_offset_, bool hex_, bool ascii_, size_t width_ = 0, size_t separate_ = 0, bool space_ = true) |
---|
97 | : show_offset(show_offset_), |
---|
98 | hex(hex_), |
---|
99 | ascii(ascii_), |
---|
100 | width(width_), |
---|
101 | separate(separate_), |
---|
102 | space(space_) |
---|
103 | {} |
---|
104 | |
---|
105 | bool wrapped() const { return width; } |
---|
106 | |
---|
107 | size_t mem_needed_for_dump(size_t bytes) const { |
---|
108 | size_t sections = show_offset+hex+ascii; |
---|
109 | |
---|
110 | if (!sections) return 1; |
---|
111 | |
---|
112 | size_t perByte = hex*3+ascii; |
---|
113 | size_t extraPerLine = (sections-1)*3+1; |
---|
114 | size_t lines = width ? bytes/width+1 : 1; |
---|
115 | |
---|
116 | return bytes*perByte + lines*extraPerLine + 50; |
---|
117 | } |
---|
118 | |
---|
119 | void dump_to(GBS_strstruct& buf, const char *mem, size_t size) const { |
---|
120 | if (size) { |
---|
121 | if (wrapped()) dump_wrapped(buf, mem, size); |
---|
122 | else { // one-line dump |
---|
123 | MemDump mod(*this); |
---|
124 | mod.width = size; |
---|
125 | mod.dump_wrapped(buf, mem, size); |
---|
126 | } |
---|
127 | } |
---|
128 | } |
---|
129 | }; |
---|
130 | |
---|
131 | |
---|
132 | |
---|
133 | #else |
---|
134 | #error awt_hexdump.hxx included twice |
---|
135 | #endif // AWT_HEXDUMP_HXX |
---|