1/*
2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <debug_hex_dump.h>
8
9#include <ctype.h>
10#include <stdio.h>
11
12
13namespace BKernel {
14
15
16// #pragma mark - HexDumpDataProvider
17
18
19HexDumpDataProvider::~HexDumpDataProvider()
20{
21}
22
23
24bool
25HexDumpDataProvider::GetAddressString(char* buffer, size_t bufferSize) const
26{
27	return false;
28}
29
30
31// #pragma mark - HexDumpBufferDataProvider
32
33
34HexDumpBufferDataProvider::HexDumpBufferDataProvider(const void* data,
35	size_t dataSize)
36	:
37	fData((const uint8*)data),
38	fDataSize(dataSize)
39{
40}
41
42
43bool
44HexDumpBufferDataProvider::HasMoreData() const
45{
46	return fDataSize > 0;
47}
48
49
50uint8
51HexDumpBufferDataProvider::NextByte()
52{
53	if (fDataSize == 0)
54		return '\0';
55
56	fDataSize--;
57	return *fData++;
58}
59
60
61bool
62HexDumpBufferDataProvider::GetAddressString(char* buffer,
63	size_t bufferSize) const
64{
65	snprintf(buffer, bufferSize, "%p", fData);
66	return true;
67}
68
69
70// #pragma mark -
71
72
73void
74print_hex_dump(HexDumpDataProvider& data, size_t maxBytes, uint32 flags)
75{
76	static const size_t kBytesPerBlock = 4;
77	static const size_t kBytesPerLine = 16;
78
79	size_t i = 0;
80	for (; i < maxBytes && data.HasMoreData();) {
81		if (i > 0)
82			kputs("\n");
83
84		// print address
85		uint8 buffer[kBytesPerLine];
86		if ((flags & HEX_DUMP_FLAG_OMIT_ADDRESS) == 0
87			&& data.GetAddressString((char*)buffer, sizeof(buffer))) {
88			kputs((char*)buffer);
89			kputs(": ");
90		}
91
92		// get the line data
93		size_t bytesInLine = 0;
94		for (; i < maxBytes && bytesInLine < kBytesPerLine
95				&& data.HasMoreData();
96			i++) {
97			buffer[bytesInLine++] = data.NextByte();
98		}
99
100		// print hex representation
101		for (size_t k = 0; k < bytesInLine; k++) {
102			if (k > 0 && k % kBytesPerBlock == 0)
103				kputs(" ");
104			kprintf("%02x", buffer[k]);
105		}
106
107		// pad to align the text representation, if line is incomplete
108		if (bytesInLine < kBytesPerLine) {
109			int missingBytes = int(kBytesPerLine - bytesInLine);
110			kprintf("%*s",
111				2 * missingBytes + int(missingBytes / kBytesPerBlock), "");
112		}
113
114		// print character representation
115		kputs("  ");
116		for (size_t k = 0; k < bytesInLine; k++)
117			kprintf("%c", isprint(buffer[k]) ? buffer[k] : '.');
118	}
119
120	if (i > 0)
121		kputs("\n");
122}
123
124
125void
126print_hex_dump(const void* data, size_t maxBytes, uint32 flags)
127{
128	HexDumpBufferDataProvider dataProvider(data, maxBytes);
129	print_hex_dump(dataProvider, maxBytes, flags);
130}
131
132
133}	// namespace BKernel
134