blob: ea924633d0da2ceafc2ce7742df27378364ef04b [file] [log] [blame]
// Copyright 2019 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.
#ifndef SRC_LIB_FIDL_CODEC_PRINTER_H_
#define SRC_LIB_FIDL_CODEC_PRINTER_H_
#include <lib/syslog/cpp/macros.h>
#include <zircon/features.h>
#include <zircon/rights.h>
#include <zircon/syscalls/debug.h>
#include <zircon/syscalls/exception.h>
#include <zircon/syscalls/hypervisor.h>
#include <zircon/syscalls/object.h>
#include <zircon/syscalls/pci.h>
#include <zircon/syscalls/port.h>
#include <zircon/syscalls/profile.h>
#include <zircon/syscalls/resource.h>
#include <zircon/types.h>
#include <cinttypes>
#include <cstdint>
#include <ostream>
namespace fidl_codec {
constexpr int kTabSize = 2;
constexpr uint64_t kOneBillion = 1'000'000'000L;
constexpr zx_handle_op_t kNoHandleDisposition = 0xffffffffu;
#define kSecondsPerMinute 60
#define kMinutesPerHour 60
#define kHoursPerDay 24
struct Colors {
Colors(const char* new_reset, const char* new_red, const char* new_green, const char* new_blue,
const char* new_white_on_magenta, const char* new_yellow_background)
: reset(new_reset),
red(new_red),
green(new_green),
blue(new_blue),
white_on_magenta(new_white_on_magenta),
yellow_background(new_yellow_background) {}
const char* const reset;
const char* const red;
const char* const green;
const char* const blue;
const char* const white_on_magenta;
const char* const yellow_background;
};
extern const Colors WithoutColors;
extern const Colors WithColors;
class PrettyPrinter {
public:
PrettyPrinter(std::ostream& os, const Colors& colors, bool pretty_print,
std::string_view line_header, int max_line_size, bool header_on_every_line,
int tabulations = 0);
std::ostream& os() const { return os_; }
const Colors& colors() const { return colors_; }
bool pretty_print() const { return pretty_print_; }
int max_line_size() const { return max_line_size_; }
bool header_on_every_line() const { return header_on_every_line_; }
void set_header_on_every_line(bool header_on_every_line) {
header_on_every_line_ = header_on_every_line;
}
size_t remaining_size() const { return remaining_size_; }
bool LineEmpty() const { return need_to_print_header_; }
virtual bool DumpMessages() const { return false; }
// Displays a handle. This allows the caller to also display some infered data we have inferered
// for this handle (if any).
// If handle.operation == kNoHandleDisposition, only the info part of zx_handle_disposition_t is
// used and printed.
// Else, the handle comes from the write of an "etc" function (zx_channel_write_etc or write part
// of a zx_channel_call_etc). In that case, the full disposition is used to print the handle.
virtual void DisplayHandle(const zx_handle_disposition_t& handle);
// Displays a bti perm.
void DisplayBtiPerm(uint32_t perm);
// Displays a cache policy.
void DisplayCachePolicy(uint32_t cache_policy);
// Displays channel options.
void DisplayChannelOption(uint32_t options);
// Displays a clock.
void DisplayClock(zx_clock_t clock);
// Display the value of the field mode of fuchsia.io/Directory.Open.
void DisplayDirectoryOpenMode(uint32_t mode);
// Displays a duration.
void DisplayDuration(zx_duration_t duration_ns);
// Displays an exception channel type.
void DisplayExceptionChannelType(uint32_t type);
// Displays an exception state.
void DisplayExceptionState(uint32_t state);
// Displays an feature kind.
void DisplayFeatureKind(uint32_t kind);
// Displays an guest trap.
void DisplayGuestTrap(uint32_t trap_id);
// Displays a gpaddr.
void DisplayGpAddr(zx_gpaddr_t addr);
// Displays a koid.
void DisplayKoid(uint64_t value);
// Displays a uint8_t value in padded hexadecimal format.
void DisplayHexa8(uint8_t value);
// Displays a uint16_t value in padded hexadecimal format.
void DisplayHexa16(uint16_t value);
// Displays a uint32_t value in padded hexadecimal format.
void DisplayHexa32(uint32_t value);
// Displays a uint64_t value in padded hexadecimal format.
void DisplayHexa64(uint64_t value);
// Displays an info maps type.
void DisplayInfoMapsType(zx_info_maps_type_t type);
// Display interrupt flags.
void DisplayInterruptFlags(uint32_t flags);
// Display and iommu type.
void DisplayIommuType(uint32_t type);
// Displays a ktrace control action.
void DisplayKtraceControlAction(uint32_t action);
// Displays an object info topic.
void DisplayObjectInfoTopic(uint32_t topic);
// Displays an object type.
void DisplayObjType(zx_obj_type_t obj_type);
// Displays a packet guest_vcpu type.
void DisplayPacketGuestVcpuType(uint8_t type);
// Displays a packet page request command.
void DisplayPacketPageRequestCommand(uint16_t command);
// Displays a paddr.
void DisplayPaddr(zx_paddr_t addr);
// Displays PCI bar type.
void DisplayPciBarType(uint32_t type);
// Displays a policy action.
void DisplayPolicyAction(uint32_t action);
// Displays a policy condition.
void DisplayPolicyCondition(uint32_t condition);
// Displays a policy topic.
void DisplayPolicyTopic(uint32_t topic);
// Displays profile info flags name.
void DisplayProfileInfoFlags(uint32_t flags);
// Displays prop type.
void DisplayPropType(uint32_t type);
// Displays port packet type.
void DisplayPortPacketType(uint32_t type);
// Displays rights.
void DisplayRights(uint32_t rights);
// Displays rsrc kind.
void DisplayRsrcKind(zx_rsrc_kind_t kind);
// Displays signals
void DisplaySignals(zx_signals_t signals);
// Displays a socket create option.
void DisplaySocketCreateOptions(uint32_t options);
// Display a socket read option.
void DisplaySocketReadOptions(uint32_t options);
// Display a socket disposition.
void DisplaySocketDisposition(uint32_t disposition);
// Displays status.
void DisplayStatus(zx_status_t status);
// Displays string.
void DisplayString(std::string_view string);
// Displays a system event type.
void DisplaySystemEventType(zx_system_event_type_t type);
// Displays a system powerctl.
void DisplaySystemPowerctl(uint32_t powerctl);
// Displays a thread state.
void DisplayThreadState(uint32_t state);
// Display a threda state topic.
void DisplayThreadStateTopic(zx_thread_state_topic_t topic);
// Displays a time.
void DisplayTime(zx_time_t time_ns);
// Displays a timer option.
void DisplayTimerOption(uint32_t option);
// Displays a uintptr.
#ifdef __MACH__
void DisplayUintptr(uintptr_t ptr);
#else
void DisplayUintptr(uint64_t ptr);
#endif
// Displays a vaddr.
void DisplayVaddr(zx_vaddr_t addr);
// Displays a vcpu.
void DisplayVcpu(uint32_t type);
// Display a vmo option.
void DisplayVmOption(zx_vm_option_t option);
// Displays a vmo creation option.
void DisplayVmoCreationOption(uint32_t options);
// Displays a vmo operation.
void DisplayVmoOp(uint32_t op);
// Displays a vmo option.
void DisplayVmoOption(uint32_t options);
// Displays a vmo type.
void DisplayVmoType(uint32_t type);
void IncrementTabulations();
void DecrementTabulations();
void NeedHeader();
void PrintHeader(char first_character);
PrettyPrinter& operator<<(char data) {
if (need_to_print_header_) {
PrintHeader(data);
}
os_ << data;
if (data == '\n') {
NeedHeader();
} else {
--remaining_size_;
}
return *this;
}
PrettyPrinter& operator<<(int32_t data) {
FX_DCHECK((os_.flags() & os_.basefield) == os_.dec);
*this << std::to_string(data);
return *this;
}
PrettyPrinter& operator<<(int64_t data) {
FX_DCHECK((os_.flags() & os_.basefield) == os_.dec);
*this << std::to_string(data);
return *this;
}
PrettyPrinter& operator<<(uint32_t data) {
if (((os_.flags() & os_.basefield) == os_.dec) || (data == 0)) {
*this << std::to_string(data);
} else {
os_ << data;
int data_size = 0;
while (data > 0) {
data /= 16;
data_size++;
}
remaining_size_ -= data_size;
}
return *this;
}
PrettyPrinter& operator<<(uint64_t data) {
if (((os_.flags() & os_.basefield) == os_.dec) || (data == 0)) {
*this << std::to_string(data);
} else {
os_ << data;
int data_size = 0;
while (data > 0) {
data /= 16;
data_size++;
}
remaining_size_ -= data_size;
}
return *this;
}
#ifdef __MACH__
// On MacOs, the type of size_t is unsigned long.
PrettyPrinter& operator<<(size_t data) {
FX_DCHECK((os_.flags() & os_.basefield) == os_.dec);
*this << std::to_string(data);
return *this;
}
#endif
PrettyPrinter& operator<<(double data) {
*this << std::to_string(data);
return *this;
}
PrettyPrinter& operator<<(std::string_view data);
// Used by the color functions.
PrettyPrinter& operator<<(PrettyPrinter& (*pf)(PrettyPrinter& printer)) {
if (need_to_print_header_) {
PrintHeader(' ');
}
return pf(*this);
}
// Used by std::hex, std::dec.
PrettyPrinter& operator<<(std::ios_base& (*pf)(std::ios_base&)) {
pf(os_);
return *this;
}
private:
std::ostream& os_;
const Colors& colors_;
const bool pretty_print_;
const std::string_view line_header_;
const int max_line_size_;
bool header_on_every_line_;
bool need_to_print_header_ = true;
int line_header_size_ = 0;
int tabulations_;
size_t remaining_size_ = 0;
};
inline PrettyPrinter& ResetColor(PrettyPrinter& printer) {
printer.os() << printer.colors().reset;
return printer;
}
inline PrettyPrinter& Red(PrettyPrinter& printer) {
printer.os() << printer.colors().red;
return printer;
}
inline PrettyPrinter& Green(PrettyPrinter& printer) {
printer.os() << printer.colors().green;
return printer;
}
inline PrettyPrinter& Blue(PrettyPrinter& printer) {
printer.os() << printer.colors().blue;
return printer;
}
inline PrettyPrinter& WhiteOnMagenta(PrettyPrinter& printer) {
printer.os() << printer.colors().white_on_magenta;
return printer;
}
inline PrettyPrinter& YellowBackground(PrettyPrinter& printer) {
printer.os() << printer.colors().yellow_background;
return printer;
}
// Scope which increments the indentation.
class Indent {
public:
explicit Indent(PrettyPrinter& printer) : printer_(printer) { printer.IncrementTabulations(); }
~Indent() { printer_.DecrementTabulations(); }
private:
PrettyPrinter& printer_;
};
// Scope which increments the indentation several times.
class MultiIndent {
public:
explicit MultiIndent(PrettyPrinter& printer, int count) : printer_(printer), count_(count) {
while (count > 0) {
printer.IncrementTabulations();
--count;
}
}
~MultiIndent() {
while (count_ > 0) {
printer_.DecrementTabulations();
--count_;
}
}
private:
PrettyPrinter& printer_;
int count_;
};
} // namespace fidl_codec
#endif // SRC_LIB_FIDL_CODEC_PRINTER_H_