| // 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 <zircon/system/public/zircon/rights.h> |
| #include <zircon/system/public/zircon/syscalls/exception.h> |
| #include <zircon/system/public/zircon/syscalls/object.h> |
| #include <zircon/system/public/zircon/syscalls/resource.h> |
| #include <zircon/system/public/zircon/types.h> |
| |
| #include <cinttypes> |
| #include <cstdint> |
| #include <ostream> |
| |
| #include "src/lib/fxl/logging.h" |
| #include "zircon/system/public/zircon/syscalls/debug.h" |
| |
| namespace fidl_codec { |
| |
| constexpr int kTabSize = 2; |
| |
| 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, 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_; } |
| int max_line_size() const { return max_line_size_; } |
| int remaining_size() const { return remaining_size_; } |
| |
| bool LineEmpty() const { return need_to_print_header_; } |
| |
| virtual bool DumpMessages() const { return false; } |
| virtual bool PrettyPrint() const { return false; } |
| |
| // Displays a handle. This allows the caller to also display some infered data we have inferered |
| // for this handle (if any). |
| virtual void DisplayHandle(const zx_handle_info_t& handle); |
| |
| 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) { |
| FXL_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) { |
| FXL_DCHECK((os_.flags() & os_.basefield) == os_.dec); |
| *this << std::to_string(data); |
| return *this; |
| } |
| #endif |
| |
| 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 std::string_view line_header_; |
| const int max_line_size_; |
| const bool header_on_every_line_ = false; |
| bool need_to_print_header_ = true; |
| int line_header_size_ = 0; |
| int tabulations_; |
| int 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_; |
| }; |
| |
| } // namespace fidl_codec |
| |
| #endif // SRC_LIB_FIDL_CODEC_PRINTER_H_ |