1 // Copyright 2020 The Pigweed Authors
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
7 // https://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
20 #include "pw_bytes/span.h"
21 #include "pw_status/status.h"
25 // Size, in bytes, of the resulting string after converting an address to a
26 // UTF-8 encoded hex representation. This constant depends on the size
32 // Note: the +2 accounts for the "0x" prefix.
33 constexpr const size_t kHexAddrStringSize = sizeof(uintptr_t) * 2 + 2;
35 // It is strongly recommended NOT to directly depend on this dump format;
36 // pw_hex_dump does NOT guarantee stability for the output format, but strives
37 // to remain xxd compatible.
40 // Offs. 0 1 2 3 4 5 6 7 8 9 A B C D E F Text
41 // 0000: A4 CC 32 62 9B 46 38 1A 23 1A 2A 7A BC E2 40 A0 ..2b.F8.#.*z..@.
42 // 0010: FF 33 E5 2B 9E 9F 6B 3C BE 9B 89 3C 7E 4A 7A 48 .3.+..k<...<~JzH
45 // Example 1 (32-bit machine, group_every=4, prefix_mode=kAbsolute,
46 // bytes_per_line = 8):
48 // 0x20000000: A4CC3262 9B46381A ..2b.F8.
49 // 0x20000008: 231A2A7A BCE240A0 #.*z..@.
50 // 0x20000010: FF33E52B 9E9F6B3C .3.+..k<
51 // 0x20000018: BE9B893C 7E4A7A48 ...<~JzH
54 // Example 2 (group_every=1, bytes_per_line = 16):
55 // Offs. 0 1 2 3 4 5 6 7 8 9 A B C D E F
56 // 0000: A4 CC 32 62 9B 46 38 1A 23 1A 2A 7A BC E2 40 A0
57 // 0010: FF 33 E5 2B 9E 9F 6B 3C BE 9B 89 3C 7E 4A 7A 48
60 // Example 3 (group_every=0, prefix_mode=kNone, show_header=false,
62 // A4CC32629B46381A231A2A7ABCE240A0
63 // FF33E52B9E9F6B3CBE9B893C7E4A7A48
65 class FormattedHexDumper {
74 // Sets the number of source data bytes to print in each formatted line.
75 uint8_t bytes_per_line : 8;
77 // Inserts a space every N bytes for readability. Note that this is in
78 // number of bytes converted to characters. Set to zero to disable. I.e. a
79 // value of 2 results in:
80 // 0x00000000: 0102 0304 0506 0708
81 uint8_t group_every : 8;
83 // Show or hide ascii interpretation of binary data.
86 // Show descriptive column headers.
89 // Prefix each line of the dump with an offset or absolute address.
90 AddressMode prefix_mode : 2;
93 Flags flags = {.bytes_per_line = 16,
97 .prefix_mode = AddressMode::kOffset};
99 FormattedHexDumper() = default;
100 FormattedHexDumper(std::span<char> dest) { SetLineBuffer(dest); }
101 FormattedHexDumper(std::span<char> dest, Flags config_flags)
102 : flags(config_flags) {
106 // TODO(pwbug/218): Add iterator support.
108 // Set the destination buffer that the hex dumper will write to line-by-line.
111 // RESOURCE_EXHAUSTED - The buffer was set, but is too small to fit the
112 // current formatting configuration.
113 // INVALID_ARGUMENT - The destination buffer is invalid (nullptr or zero-
115 Status SetLineBuffer(std::span<char> dest);
117 // Begin dumping the provided data. Does NOT populate the line buffer with
118 // a string, simply resets the statefulness to track this buffer.
121 // OK - Ready to begin dump.
122 // INVALID_ARGUMENT - The source data starts at null, but has been set.
123 // FAILED_PRECONDITION - Line buffer too small to hold current formatting
125 Status BeginDump(ConstByteSpan data);
127 // Dumps a single line to the line buffer.
131 // std::array<char, 80> temp;
132 // FormattedHexDumper hex_dumper(temp);
133 // hex_dumper.BeginDump(my_data);
134 // while(hex_dumper.DumpLine().ok()) {
135 // LOG_INFO("%s", temp.data());
139 // OK - A line has been written to the line buffer.
140 // RESOURCE_EXHAUSTED - All the data has been dumped.
141 // FAILED_PRECONDITION - Destination line buffer is too small to fit current
142 // formatting configuration.
146 Status ValidateBufferSize();
147 Status PrintFormatHeader();
149 size_t current_offset_;
150 std::span<char> dest_;
151 ConstByteSpan source_data_;
154 // Dumps a uintptr_t to a character buffer as a hex address. This may be useful
155 // to print out an address in a generalized way when %z and %p aren't supported
156 // by a standard library implementation. The destination buffer MUST be large
157 // enough to hold kHexAddrStringSize + 1 (null terminator) bytes.
160 // 0x000000000022b698
165 // OK - Address has been written to the buffer.
166 // INVALID_ARGUMENT - The destination buffer is invalid (nullptr).
167 // RESOURCE_EXHAUSTED - The destination buffer is too small. No data written.
168 Status DumpAddr(std::span<char> dest, uintptr_t addr);
169 inline Status DumpAddr(std::span<char> dest, const void* ptr) {
170 uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
171 return DumpAddr(dest, addr);
174 } // namespace pw::dump