blob: fba81fe2aeb34c59ff0e999d3569a2dcaa1cd782 [file] [log] [blame]
// 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 <cstdio>
#include <sstream>
#include <lib/fxl/strings/string_printf.h>
#include "garnet/bin/iquery/formatters/text.h"
#include "garnet/bin/iquery/options.h"
namespace iquery {
namespace {
#define INDENT_SIZE 2
inline std::string Indent(int indent) {
return std::string(indent * INDENT_SIZE, ' ');
}
// This version exists so we can pass in the indentation.
std::string RecursiveFormatCat(const Options& options, const ObjectNode& root,
int indent) {
// In each step of the indentation we output the path formatting. This is not
// equivalent to what formatters as JSON do, which will introduce a path
// entry under each object.
// This is mainly because this formatter is intended for human examination and
// it's not intended for easier parsing.
std::ostringstream ss;
const auto& object = root.object;
for (const auto& property : *object.properties) {
ss << Indent(indent) << FormatStringHexFallback(property.key) << " = ";
if (property.value.is_str()) {
ss << FormatStringHexFallback(property.value.str()) << std::endl;
} else {
auto& val = property.value.bytes();
ss << FormatStringHexFallback({(char*)val.data(), val.size()})
<< std::endl;
}
}
for (const auto& metric : *object.metrics) {
ss << Indent(indent) << FormatStringHexFallback(metric.key) << " = "
<< FormatMetricValue(metric) << std::endl;
}
// We print recursively. The recursion nature of the cat called is already
// taken care of by now.
for (const auto& child : root.children) {
ss << Indent(indent)
<< FormatPath(options.path_format, child.basepath, child.object.name)
<< ":" << std::endl;
ss << RecursiveFormatCat(options, child, indent + 1);
}
return ss.str();
}
std::string FormatFind(const Options& options,
const std::vector<ObjectNode>& results) {
std::stringstream ss;
for (const auto& node : results) {
ss << FormatPath(options.path_format, node.basepath, node.object.name)
<< std::endl;
}
return ss.str();
}
std::string FormatLs(const Options& options,
const std::vector<ObjectNode>& results) {
std::stringstream ss;
for (const auto& node : results) {
ss << FormatPath(options.path_format, node.basepath, node.object.name)
<< std::endl;
}
return ss.str();
}
std::string FormatCat(const Options& options,
const std::vector<ObjectNode>& results) {
std::ostringstream ss;
for (const auto& root_node : results) {
ss << FormatPath(options.path_format, root_node.basepath,
root_node.object.name)
<< ":" << std::endl;
ss << RecursiveFormatCat(options, root_node, 1);
}
return ss.str();
}
} // namespace
std::string TextFormatter::Format(const Options& options,
const std::vector<ObjectNode>& results) {
switch (options.mode) {
case Options::Mode::CAT:
return FormatCat(options, results);
case Options::Mode::FIND:
return FormatFind(options, results);
case Options::Mode::LS:
return FormatLs(options, results);
case Options::Mode::UNSET: {
FXL_LOG(ERROR) << "Unset Mode";
return "";
}
}
}
} // namespace iquery