Move HexDump to include/perfetto/ext/base/utils.h

It's going to have a usecase outside of tests.

Bug: 205763418
Change-Id: I1686ff72c1c235ff64675e057a9a01ef501326e2
diff --git a/src/base/utils.cc b/src/base/utils.cc
index b5d3d3c..363a0d6 100644
--- a/src/base/utils.cc
+++ b/src/base/utils.cc
@@ -266,5 +266,28 @@
 #endif
 }
 
+std::string HexDump(const void* data_void, size_t len, size_t bytes_per_line) {
+  const char* data = reinterpret_cast<const char*>(data_void);
+  std::string res;
+  static const size_t kPadding = bytes_per_line * 3 + 12;
+  std::unique_ptr<char[]> line(new char[bytes_per_line * 4 + 128]);
+  for (size_t i = 0; i < len; i += bytes_per_line) {
+    char* wptr = line.get();
+    wptr += sprintf(wptr, "%08zX: ", i);
+    for (size_t j = i; j < i + bytes_per_line && j < len; j++)
+      wptr += sprintf(wptr, "%02X ", static_cast<unsigned>(data[j]) & 0xFF);
+    for (size_t j = static_cast<size_t>(wptr - line.get()); j < kPadding; ++j)
+      *(wptr++) = ' ';
+    for (size_t j = i; j < i + bytes_per_line && j < len; j++) {
+      char c = data[j];
+      *(wptr++) = (c >= 32 && c < 127) ? c : '.';
+    }
+    *(wptr++) = '\n';
+    *(wptr++) = '\0';
+    res.append(line.get());
+  }
+  return res;
+}
+
 }  // namespace base
 }  // namespace perfetto