| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <lib/fostr/hex_dump.h> |
| #include <lib/fxl/files/path.h> |
| #include <lib/fxl/strings/concatenate.h> |
| #include <lib/fxl/strings/string_printf.h> |
| #include <lib/fxl/strings/utf_codecs.h> |
| #include <third_party/cobalt/util/crypto_util/base64.h> |
| |
| #include "garnet/bin/iquery/options.h" |
| #include "garnet/bin/iquery/utils.h" |
| |
| #include <iostream> |
| |
| using cobalt::crypto::Base64Encode; |
| |
| namespace iquery { |
| |
| namespace { |
| |
| constexpr size_t kMaxHexSize = 256; |
| std::string HexDump(fxl::StringView contents) { |
| std::ostringstream out; |
| if (contents.size() > kMaxHexSize) { |
| out << "\nFirst " << kMaxHexSize << " bytes of " << contents.size(); |
| } |
| out << fostr::HexDump(contents.data(), std::min(kMaxHexSize, contents.size()), |
| 0x0); |
| return out.str(); |
| } |
| |
| } // namespace |
| |
| ObjectNode::ObjectNode() = default; |
| ObjectNode::ObjectNode(std::string name) { object.name = std::move(name); } |
| |
| ObjectNode::ObjectNode(fuchsia::inspect::Object object) |
| : object(std::move(object)) {} |
| |
| ObjectNode::ObjectNode(ObjectNode&&) = default; |
| ObjectNode& ObjectNode::operator=(ObjectNode&&) = default; |
| |
| // TODO(donosoc): Cleanup artifacts like "//" or ending in '/' |
| std::string FormatPath(Options::PathFormatting path_format, |
| const std::string& path, const std::string& name) { |
| switch (path_format) { |
| case Options::PathFormatting::NONE: |
| return name; |
| case Options::PathFormatting::FULL: |
| return path; |
| case Options::PathFormatting::ABSOLUTE: |
| return files::AbsolutePath(path); |
| } |
| }; |
| |
| std::string FormatStringHexFallback(fxl::StringView val) { |
| if (IsStringPrintable(val)) { |
| return std::string(val.begin(), val.end()); |
| } else { |
| return fxl::StringPrintf("Binary: %s", HexDump(val).c_str()); |
| } |
| } |
| |
| std::string FormatStringBase64Fallback(fxl::StringView val) { |
| if (IsStringPrintable(val)) { |
| return std::string(val.begin(), val.end()); |
| } else { |
| std::string content; |
| Base64Encode((uint8_t*)val.data(), val.size(), &content); |
| return fxl::Concatenate({"b64:", content}); |
| } |
| } |
| |
| std::string FormatMetricValue(const fuchsia::inspect::Metric& metric) { |
| std::string out; |
| if (metric.value.is_int_value()) { |
| out = fxl::StringPrintf("%ld", metric.value.int_value()); |
| } else if (metric.value.is_uint_value()) { |
| out = fxl::StringPrintf("%lu", metric.value.uint_value()); |
| } else if (metric.value.is_double_value()) { |
| out = fxl::StringPrintf("%f", metric.value.double_value()); |
| } else { |
| // We already know which object we're outputting at this point. |
| FXL_LOG(WARNING) << "Unknown metric type"; |
| } |
| return out; |
| } |
| |
| bool IsStringPrintable(fxl::StringView input) { |
| if (!fxl::IsStringUTF8(input)) { |
| return false; |
| } |
| |
| // Ensure the string does not contain unprintable ASCII characters. |
| uint32_t code_point; |
| for (size_t index = 0; fxl::ReadUnicodeCharacter(input.data(), input.size(), |
| &index, &code_point) && |
| index != input.size(); |
| index++) { |
| // Skip any non-ASCII code points. |
| if (code_point & (~0x7F)) { |
| continue; |
| } |
| if (isprint(code_point) || code_point == '\t' || code_point == '\n' || |
| code_point == '\r') { |
| continue; |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| } // namespace iquery |