// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #ifndef CEPH_FORMATTER_H #define CEPH_FORMATTER_H #include "include/int_types.h" #include "include/buffer_fwd.h" #include #include #include #include #include #include namespace ceph { struct FormatterAttrs { std::list< std::pair > attrs; FormatterAttrs(const char *attr, ...); }; class Formatter { public: static Formatter *create(const std::string& type, const std::string& default_type, const std::string& fallback); static Formatter *create(const std::string& type, const std::string& default_type) { return create(type, default_type, ""); } static Formatter *create(const std::string& type) { return create(type, "json-pretty", ""); } Formatter(); virtual ~Formatter(); virtual void enable_line_break() = 0; virtual void flush(std::ostream& os) = 0; void flush(bufferlist &bl); virtual void reset() = 0; virtual void set_status(int status, const char* status_name) = 0; virtual void output_header() = 0; virtual void output_footer() = 0; virtual void open_array_section(const char *name) = 0; virtual void open_array_section_in_ns(const char *name, const char *ns) = 0; virtual void open_object_section(const char *name) = 0; virtual void open_object_section_in_ns(const char *name, const char *ns) = 0; virtual void close_section() = 0; virtual void dump_unsigned(const char *name, uint64_t u) = 0; virtual void dump_int(const char *name, int64_t s) = 0; virtual void dump_float(const char *name, double d) = 0; virtual void dump_string(const char *name, const std::string& s) = 0; virtual void dump_bool(const char *name, bool b) { dump_format_unquoted(name, "%s", (b ? "true" : "false")); } template void dump_object(const char *name, const T& foo) { open_object_section(name); foo.dump(this); close_section(); } virtual std::ostream& dump_stream(const char *name) = 0; virtual void dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap) = 0; virtual void dump_format(const char *name, const char *fmt, ...); virtual void dump_format_ns(const char *name, const char *ns, const char *fmt, ...); virtual void dump_format_unquoted(const char *name, const char *fmt, ...); virtual int get_len() const = 0; virtual void write_raw_data(const char *data) = 0; /* with attrs */ virtual void open_array_section_with_attrs(const char *name, const FormatterAttrs& attrs) { open_array_section(name); } virtual void open_object_section_with_attrs(const char *name, const FormatterAttrs& attrs) { open_object_section(name); } virtual void dump_string_with_attrs(const char *name, const std::string& s, const FormatterAttrs& attrs) { dump_string(name, s); } }; class JSONFormatter : public Formatter { public: explicit JSONFormatter(bool p = false); void set_status(int status, const char* status_name) override {}; void output_header() override {}; void output_footer() override {}; void enable_line_break() override { m_line_break_enabled = true; } void flush(std::ostream& os) override; using Formatter::flush; // don't hide Formatter::flush(bufferlist &bl) void reset() override; void open_array_section(const char *name) override; void open_array_section_in_ns(const char *name, const char *ns) override; void open_object_section(const char *name) override; void open_object_section_in_ns(const char *name, const char *ns) override; void close_section() override; void dump_unsigned(const char *name, uint64_t u) override; void dump_int(const char *name, int64_t u) override; void dump_float(const char *name, double d) override; void dump_string(const char *name, const std::string& s) override; std::ostream& dump_stream(const char *name) override; void dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap) override; int get_len() const override; void write_raw_data(const char *data) override; private: struct json_formatter_stack_entry_d { int size; bool is_array; json_formatter_stack_entry_d() : size(0), is_array(false) { } }; bool m_pretty; void open_section(const char *name, bool is_array); void print_quoted_string(const std::string& s); void print_name(const char *name); void print_comma(json_formatter_stack_entry_d& entry); void finish_pending_string(); std::stringstream m_ss, m_pending_string; std::list m_stack; bool m_is_pending_string; bool m_line_break_enabled = false; }; class XMLFormatter : public Formatter { public: static const char *XML_1_DTD; XMLFormatter(bool pretty = false, bool lowercased = false, bool underscored = true); void set_status(int status, const char* status_name) override {} void output_header() override; void output_footer() override; void enable_line_break() override { m_line_break_enabled = true; } void flush(std::ostream& os) override; using Formatter::flush; // don't hide Formatter::flush(bufferlist &bl) void reset() override; void open_array_section(const char *name) override; void open_array_section_in_ns(const char *name, const char *ns) override; void open_object_section(const char *name) override; void open_object_section_in_ns(const char *name, const char *ns) override; void close_section() override; void dump_unsigned(const char *name, uint64_t u) override; void dump_int(const char *name, int64_t u) override; void dump_float(const char *name, double d) override; void dump_string(const char *name, const std::string& s) override; std::ostream& dump_stream(const char *name) override; void dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap) override; int get_len() const override; void write_raw_data(const char *data) override; /* with attrs */ void open_array_section_with_attrs(const char *name, const FormatterAttrs& attrs) override; void open_object_section_with_attrs(const char *name, const FormatterAttrs& attrs) override; void dump_string_with_attrs(const char *name, const std::string& s, const FormatterAttrs& attrs) override; protected: void open_section_in_ns(const char *name, const char *ns, const FormatterAttrs *attrs); void finish_pending_string(); void print_spaces(); static std::string escape_xml_str(const char *str); void get_attrs_str(const FormatterAttrs *attrs, std::string& attrs_str); char to_lower_underscore(char c) const; std::stringstream m_ss, m_pending_string; std::deque m_sections; const bool m_pretty; const bool m_lowercased; const bool m_underscored; std::string m_pending_string_name; bool m_header_done; bool m_line_break_enabled = false; }; class TableFormatter : public Formatter { public: explicit TableFormatter(bool keyval = false); void set_status(int status, const char* status_name) override {}; void output_header() override {}; void output_footer() override {}; void enable_line_break() override {}; void flush(std::ostream& os) override; using Formatter::flush; // don't hide Formatter::flush(bufferlist &bl) void reset() override; void open_array_section(const char *name) override; void open_array_section_in_ns(const char *name, const char *ns) override; void open_object_section(const char *name) override; void open_object_section_in_ns(const char *name, const char *ns) override; void open_array_section_with_attrs(const char *name, const FormatterAttrs& attrs) override; void open_object_section_with_attrs(const char *name, const FormatterAttrs& attrs) override; void close_section() override; void dump_unsigned(const char *name, uint64_t u) override; void dump_int(const char *name, int64_t u) override; void dump_float(const char *name, double d) override; void dump_string(const char *name, const std::string& s) override; void dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap) override; void dump_string_with_attrs(const char *name, const std::string& s, const FormatterAttrs& attrs) override; std::ostream& dump_stream(const char *name) override; int get_len() const override; void write_raw_data(const char *data) override; void get_attrs_str(const FormatterAttrs *attrs, std::string& attrs_str); private: void open_section_in_ns(const char *name, const char *ns, const FormatterAttrs *attrs); std::vector< std::vector > > m_vec; std::stringstream m_ss; size_t m_vec_index(const char* name); std::string get_section_name(const char* name); void finish_pending_string(); std::string m_pending_name; bool m_keyval; int m_section_open; std::vector< std::string > m_section; std::map m_section_cnt; std::vector m_column_size; std::vector< std::string > m_column_name; }; } #endif