Skip to content

Commit 776fca8

Browse files
committed
Merge branch 'ci/sync_gh_tflite-micro' into 'master'
Sync esp-tflite-micro from github - 839441 See merge request app-frameworks/esp-tflite-micro!158
2 parents 9128d06 + 7cb2507 commit 776fca8

File tree

3 files changed

+196
-0
lines changed

3 files changed

+196
-0
lines changed

tensorflow/lite/micro/hexdump.cc

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2024 The TensorFlow Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "tensorflow/lite/micro/hexdump.h"
16+
17+
#include <algorithm>
18+
#include <cctype>
19+
20+
#include "tensorflow/lite/micro/debug_log.h"
21+
#include "tensorflow/lite/micro/static_vector.h"
22+
23+
namespace {
24+
25+
tflite::Span<char> output(const tflite::Span<char>& buf, const char* format,
26+
...) {
27+
// Writes formatted output, printf-style, to either a buffer or DebugLog.
28+
// Writes to DebugLog if the buffer data pointer is null. Does not exceed
29+
// the size of the buffer. Returns the unused remainder of the buffer, or a
30+
// buffer with a null data pointer in the case of printing to DebugLog.
31+
32+
tflite::Span<char> result{nullptr, 0};
33+
34+
va_list args;
35+
va_start(args, format);
36+
37+
if (buf.data() == nullptr) {
38+
DebugLog(format, args);
39+
result = {nullptr, 0};
40+
} else {
41+
size_t len = DebugVsnprintf(buf.data(), buf.size(), format, args);
42+
// Returns the number of characters that would have been written if
43+
// there were enough room, so cap it at the size of the buffer in order to
44+
// know how much was actually written.
45+
size_t consumed = std::min(len, buf.size());
46+
result = {buf.data() + consumed, buf.size() - consumed};
47+
}
48+
49+
va_end(args);
50+
return result;
51+
}
52+
53+
} // end anonymous namespace
54+
55+
tflite::Span<char> tflite::hexdump(const tflite::Span<const std::byte> region,
56+
const tflite::Span<char> out) {
57+
tflite::Span<char> buffer{out};
58+
std::size_t byte_nr = 0;
59+
constexpr int per_line = 16;
60+
const int lines = (region.size() + per_line - 1) / per_line; // round up
61+
62+
for (int line = 0; line < lines; ++line) {
63+
tflite::StaticVector<char, per_line> ascii;
64+
65+
// print address
66+
buffer = output(buffer, "%08X:", line);
67+
68+
for (int pos = 0; pos < per_line; ++pos) {
69+
if (byte_nr < region.size()) {
70+
// print byte
71+
int as_int = static_cast<int>(region[byte_nr++]);
72+
buffer = output(buffer, " %02X", as_int);
73+
74+
// buffer an ascii printable value
75+
char c{'.'};
76+
if (std::isprint(as_int)) {
77+
c = static_cast<char>(as_int);
78+
}
79+
ascii.push_back(c);
80+
} else {
81+
buffer = output(buffer, " ");
82+
}
83+
84+
// print extra space in middle of the line
85+
if (pos == per_line / 2 - 1) {
86+
buffer = output(buffer, " ");
87+
}
88+
}
89+
90+
// print the ascii value
91+
buffer = output(buffer, " ");
92+
for (const auto& c : ascii) {
93+
buffer = output(buffer, "%c", c);
94+
}
95+
buffer = output(buffer, "%c", '\n');
96+
}
97+
98+
return {out.data(), out.size() - buffer.size()};
99+
}
100+
101+
void tflite::hexdump(const tflite::Span<const std::byte> region) {
102+
hexdump(region, {nullptr, 0});
103+
}

tensorflow/lite/micro/hexdump.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2024 The TensorFlow Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef TENSORFLOW_LITE_MICRO_HEXDUMP_H_
16+
#define TENSORFLOW_LITE_MICRO_HEXDUMP_H_
17+
18+
#include <cstddef>
19+
20+
#include "tensorflow/lite/micro/span.h"
21+
22+
namespace tflite {
23+
24+
// Displays the contents of a memory region, formatted in hexadecimal and ASCII
25+
// in a style matching Python's hexdump module, using DebugLog().
26+
void hexdump(Span<const std::byte> region);
27+
28+
// Writes the contents of a memory region, formatted in hexadecimal and ASCII
29+
// in a style matching Python's hexdump module, to a buffer. Returns the portion
30+
// of the buffer written.
31+
Span<char> hexdump(Span<const std::byte> region, Span<char> buffer);
32+
33+
} // end namespace tflite
34+
35+
#endif // TENSORFLOW_LITE_MICRO_HEXDUMP_H_

tensorflow/lite/micro/hexdump_test.cc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2024 The TensorFlow Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "tensorflow/lite/micro/hexdump.h"
16+
17+
#include <array>
18+
19+
#include "tensorflow/lite/micro/span.h"
20+
#include "tensorflow/lite/micro/testing/micro_test.h"
21+
22+
constexpr tflite::Span<const char> input{
23+
"This is an input string for testing."};
24+
25+
const tflite::Span<const std::byte> region{
26+
reinterpret_cast<const std::byte*>(input.data()), input.size()};
27+
28+
// clang-format off
29+
constexpr tflite::Span<const char> expected{
30+
"00000000: 54 68 69 73 20 69 73 20 61 6E 20 69 6E 70 75 74 This is an input\n"
31+
"00000001: 20 73 74 72 69 6E 67 20 66 6F 72 20 74 65 73 74 string for test\n"
32+
"00000002: 69 6E 67 2E 00 ing..\n"};
33+
// clang-format on
34+
35+
// String literals have null terminators, but don't expect a null terminator
36+
// in the hexdump output.
37+
constexpr tflite::Span<const char> expected_no_null{expected.data(),
38+
expected.size() - 1};
39+
40+
TF_LITE_MICRO_TESTS_BEGIN
41+
42+
TF_LITE_MICRO_TEST(TestOutputToBuffer) {
43+
// Allocate a buffer with an arbitrary amount of extra room so the test has
44+
// the possibility of failing if hexdump mishandles the extra space.
45+
std::array<char, expected.size() + 10> buffer;
46+
47+
tflite::Span<char> output = tflite::hexdump(region, buffer);
48+
TF_LITE_MICRO_EXPECT(output == expected_no_null);
49+
}
50+
51+
TF_LITE_MICRO_TEST(TestOutputToDebugLog) {
52+
// There's no easy way to verify DebugLog output; however, test it anyhow to
53+
// catch an outright crash, and so the output appears in the log should
54+
// someone wish to examine it.
55+
tflite::hexdump(region);
56+
}
57+
58+
TF_LITE_MICRO_TESTS_END

0 commit comments

Comments
 (0)