diff --git a/tensorflow/lite/micro/BUILD b/tensorflow/lite/micro/BUILD index 97d6897b9c8..d92b93dac0a 100644 --- a/tensorflow/lite/micro/BUILD +++ b/tensorflow/lite/micro/BUILD @@ -381,6 +381,20 @@ cc_library( ], ) +cc_library( + name = "hexdump", + srcs = [ + "hexdump.cc", + ], + hdrs = [ + "hexdump.h", + ], + deps = [ + ":span", + ":static_vector" + ], +) + cc_library( name = "recording_allocators", srcs = [ @@ -556,6 +570,17 @@ cc_test( ], ) +cc_test( + name = "hexdump_test", + srcs = [ + "hexdump_test.cc", + ], + deps = [ + ":hexdump", + ], + size = "small", +) + cc_test( name = "memory_helpers_test", srcs = [ diff --git a/tensorflow/lite/micro/hexdump.cc b/tensorflow/lite/micro/hexdump.cc new file mode 100644 index 00000000000..0d72e293b47 --- /dev/null +++ b/tensorflow/lite/micro/hexdump.cc @@ -0,0 +1,66 @@ +/* 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 +#include +#include + +#include "tensorflow/lite/micro/static_vector.h" + +void tflite::hexdump(tflite::Span region, std::ostream& out) { + auto initial_flags = out.flags(); + out << std::hex << std::uppercase << std::setfill('0'); + + std::size_t byte = 0; + constexpr int per_line = 16; + const int lines = (region.size() + per_line - 1) / per_line; // rounded up + for (int line = 0; line < lines; ++line) { + tflite::StaticVector ascii; + + // print address + out << std::setw(8) << line << ":"; + + for (int pos = 0; pos < per_line; ++pos) { + if (byte < region.size()) { + // print byte + int as_int = static_cast(region[byte++]); + out << ' ' << std::setw(2) << as_int; + + // buffer an ascii printable value + char c{'.'}; + if (std::isprint(as_int)) { + c = static_cast(as_int); + } + ascii.push_back(c); + } else { + out << " "; + } + + // extra space in the middle + if (pos == per_line / 2 - 1) { + out << " "; + } + } + + out << " "; + for (const auto& c : ascii) { + out << c; + } + out << '\n'; + } + + out.flags(initial_flags); +} diff --git a/tensorflow/lite/micro/hexdump.h b/tensorflow/lite/micro/hexdump.h new file mode 100644 index 00000000000..5c535c35ad1 --- /dev/null +++ b/tensorflow/lite/micro/hexdump.h @@ -0,0 +1,32 @@ +/* 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. */ + +// A hexdump with an output style matching Python's hexdump module. + +#ifndef TENSORFLOW_LITE_MICRO_HEXDUMP_H_ +#define TENSORFLOW_LITE_MICRO_HEXDUMP_H_ + +#include +#include +#include + +#include "tensorflow/lite/micro/span.h" + +namespace tflite { + +void hexdump(Span region, std::ostream& = std::cout); + +} // end namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_HEXDUMP_H_ diff --git a/tensorflow/lite/micro/hexdump_test.cc b/tensorflow/lite/micro/hexdump_test.cc new file mode 100644 index 00000000000..49647c6aeb9 --- /dev/null +++ b/tensorflow/lite/micro/hexdump_test.cc @@ -0,0 +1,9 @@ +#include "tensorflow/lite/micro/hexdump.h" + +#include + +int main(int argc, char* argv[]) { + const std::string s{"This is a really long test string."}; + tflite::hexdump({reinterpret_cast(s.data()), s.size()}); + return 0; +}