tflite-micro/tensorflow/lite/micro/hexdump.cc
Shlomi Regev 15b55b7afd
Revert back from C/C++17 to C/C++11 (#3095)
There are older toolchains that don't support C++17 and are still used in shipping products.
Rewrite hexdump.cc to not use C++17 features (std::byte and Class Template Argument Deduction). Also remove forcing of -std=libc for xtensa targets, which was added because stdlib isn't supported with -std=c++17.

BUG=410831256
2025-05-13 04:37:10 +00:00

105 lines
3.2 KiB
C++

// Copyright 2024 The TensorFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tensorflow/lite/micro/hexdump.h"
#include <algorithm>
#include <cctype>
#include <cstdarg>
#include <cstdint>
#include "tensorflow/lite/micro/micro_log.h"
namespace {
tflite::Span<char> output(const tflite::Span<char>& buf, const char* format,
...) {
// Writes formatted output, printf-style, to either a buffer or DebugLog.
// Writes to DebugLog if the buffer data pointer is null. Does not exceed
// the size of the buffer. Returns the unused remainder of the buffer, or a
// buffer with a null data pointer in the case of printing to DebugLog.
tflite::Span<char> result{nullptr, 0};
va_list args;
va_start(args, format);
if (buf.data() == nullptr) {
VMicroPrintf(format, args);
result = {nullptr, 0};
} else {
size_t len = MicroVsnprintf(buf.data(), buf.size(), format, args);
// Returns the number of characters that would have been written if
// there were enough room, so cap it at the size of the buffer in order to
// know how much was actually written.
size_t consumed = std::min(len, buf.size());
result = {buf.data() + consumed, buf.size() - consumed};
}
va_end(args);
return result;
}
} // end anonymous namespace
tflite::Span<char> tflite::hexdump(const tflite::Span<const uint8_t> region,
const tflite::Span<char> out) {
tflite::Span<char> buffer{out};
std::size_t byte_nr = 0;
constexpr int per_line = 16;
const int lines = (region.size() + per_line - 1) / per_line; // round up
for (int line = 0; line < lines; ++line) {
char ascii[per_line];
int ascii_nr = 0;
// print address
buffer = output(buffer, "%08X:", line);
for (int pos = 0; pos < per_line; ++pos) {
if (byte_nr < region.size()) {
// print byte
int as_int = static_cast<int>(region[byte_nr++]);
buffer = output(buffer, " %02X", as_int);
// buffer an ascii printable value
char c{'.'};
if (std::isprint(as_int)) {
c = static_cast<char>(as_int);
}
ascii[ascii_nr++] = c;
} else {
buffer = output(buffer, " ");
}
// print extra space in middle of the line
if (pos == per_line / 2 - 1) {
buffer = output(buffer, " ");
}
}
// print the ascii value
buffer = output(buffer, " ");
for (int ascii_index = 0; ascii_index < ascii_nr; ascii_index++) {
buffer = output(buffer, "%c", ascii[ascii_index]);
}
buffer = output(buffer, "%c", '\n');
}
return {out.data(), out.size() - buffer.size()};
}
void tflite::hexdump(const tflite::Span<const uint8_t> region) {
hexdump(region, {nullptr, 0});
}