From 70f585c843061e814c8b24e1172790365215e9c9 Mon Sep 17 00:00:00 2001 From: Colin Patrick McCabe Date: Tue, 2 Aug 2011 14:30:18 -0700 Subject: [PATCH] Add XMLFormatter and unit test Signed-off-by: Colin McCabe --- src/common/Formatter.cc | 147 ++++++++++++++++++++++++++++++++++++++++ src/common/Formatter.h | 28 ++++++++ src/test/formatter.cc | 70 +++++++++++++++++++ 3 files changed, 245 insertions(+) diff --git a/src/common/Formatter.cc b/src/common/Formatter.cc index 84d78ef0d913d..8123cf32b2e2e 100644 --- a/src/common/Formatter.cc +++ b/src/common/Formatter.cc @@ -23,6 +23,7 @@ #include #include #include +#include // ----------------------- namespace ceph { @@ -196,4 +197,150 @@ void JSONFormatter::dump_format(const char *name, const char *fmt, ...) print_quoted_string(buf); } +XMLFormatter:: +XMLFormatter(bool p) + : m_pretty(p) +{ +} + +void XMLFormatter:: +flush(std::ostream& os) +{ + finish_pending_string(); + assert(m_sections.empty()); + os << m_ss.str(); + m_ss.clear(); +} + +void XMLFormatter:: +open_array_section(const char *name) +{ + open_section(name); +} + +void XMLFormatter:: +open_object_section(const char *name) +{ + open_section(name); +} + +void XMLFormatter:: +close_section() +{ + assert(!m_sections.empty()); + + print_spaces(false); + m_ss << ""; + m_sections.pop_back(); +} + +void XMLFormatter:: +dump_unsigned(const char *name, uint64_t u) +{ + std::string e(escape_xml_str(name)); + print_spaces(true); + m_ss << "<" << e << ">" << u << ""; + if (m_pretty) + m_ss << "\n"; +} + +void XMLFormatter:: +dump_int(const char *name, int64_t u) +{ + std::string e(escape_xml_str(name)); + print_spaces(true); + m_ss << "<" << e << ">" << u << ""; + if (m_pretty) + m_ss << "\n"; +} + +void XMLFormatter:: +dump_float(const char *name, double d) +{ + std::string e(escape_xml_str(name)); + print_spaces(true); + m_ss << "<" << e << ">" << d << ""; + if (m_pretty) + m_ss << "\n"; +} + +void XMLFormatter:: +dump_string(const char *name, std::string s) +{ + std::string e(escape_xml_str(name)); + print_spaces(true); + m_ss << "<" << e << ">" << escape_xml_str(s.c_str()) << ""; + if (m_pretty) + m_ss << "\n"; +} + +std::ostream& XMLFormatter:: +dump_stream(const char *name) +{ + assert(m_pending_string_name.empty()); + m_pending_string_name = escape_xml_str(name); + m_ss << "<" << m_pending_string_name << ">"; + return m_pending_string; +} + +void XMLFormatter:: +dump_format(const char *name, const char *fmt, ...) +{ + char buf[LARGE_SIZE]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, LARGE_SIZE, fmt, ap); + va_end(ap); + + std::string e(escape_xml_str(name)); + print_spaces(true); + m_ss << "<" << e << ">" << escape_xml_str(buf) << ""; + if (m_pretty) + m_ss << "\n"; +} + +void XMLFormatter:: +open_section(const char *name) +{ + print_spaces(false); + std::string escaped_name(escape_xml_str(name)); + m_sections.push_back(escaped_name); + m_ss << "<" << escaped_name << ">"; +} + +void XMLFormatter:: +finish_pending_string() +{ + if (!m_pending_string_name.empty()) { + m_ss << escape_xml_str(m_pending_string.str().c_str()) + << ""; + m_pending_string_name.clear(); + if (m_pretty) { + m_ss << "\n"; + } + } +} + +void XMLFormatter:: +print_spaces(bool extra_space) +{ + finish_pending_string(); + if (m_pretty) { + std::vector spaces(m_sections.size(), ' '); + if (extra_space) + spaces.push_back(' '); + spaces.push_back('\0'); + m_ss << &spaces[0]; + } +} + +std::string XMLFormatter:: +escape_xml_str(const char *str) +{ + int len = escape_xml_attr_len(str); + std::vector escaped(len, '\0'); + escape_xml_attr(str, &escaped[0]); + return std::string(&escaped[0]); +} + } diff --git a/src/common/Formatter.h b/src/common/Formatter.h index 210d0818798ef..faa1d00e8ba59 100644 --- a/src/common/Formatter.h +++ b/src/common/Formatter.h @@ -1,6 +1,7 @@ #ifndef CEPH_FORMATTER_H #define CEPH_FORMATTER_H +#include #include #include #include @@ -65,5 +66,32 @@ class JSONFormatter : public Formatter { bool m_is_pending_string; }; +class XMLFormatter : public Formatter { + public: + XMLFormatter(bool p=false); + + void flush(std::ostream& os); + void open_array_section(const char *name); + void open_object_section(const char *name); + void close_section(); + void dump_unsigned(const char *name, uint64_t u); + void dump_int(const char *name, int64_t u); + void dump_float(const char *name, double d); + void dump_string(const char *name, std::string s); + std::ostream& dump_stream(const char *name); + void dump_format(const char *name, const char *fmt, ...); + + private: + void open_section(const char *name); + void finish_pending_string(); + void print_spaces(bool extra_space); + static std::string escape_xml_str(const char *str); + + std::stringstream m_ss, m_pending_string; + std::deque m_sections; + bool m_pretty; + std::string m_pending_string_name; +}; + } #endif diff --git a/src/test/formatter.cc b/src/test/formatter.cc index 0a2bdbabc9e7d..c34980d565eac 100644 --- a/src/test/formatter.cc +++ b/src/test/formatter.cc @@ -55,3 +55,73 @@ TEST(JsonFormatter, Empty) { fmt.flush(oss); ASSERT_EQ(oss.str(), ""); } + +TEST(XmlFormatter, Simple1) { + ostringstream oss; + XMLFormatter fmt(false); + fmt.open_object_section("foo"); + fmt.dump_int("a", 1); + fmt.dump_int("b", 2); + fmt.dump_int("c", 3); + fmt.close_section(); + fmt.flush(oss); + ASSERT_EQ(oss.str(), "123"); +} + +TEST(XmlFormatter, Simple2) { + ostringstream oss; + XMLFormatter fmt(false); + fmt.open_object_section("foo"); + fmt.open_object_section("bar"); + fmt.dump_int("int", 0xf00000000000ll); + fmt.dump_unsigned("unsigned", 0x8000000000000001llu); + fmt.dump_float("float", 1.234); + fmt.close_section(); + fmt.dump_string("string", "str"); + fmt.close_section(); + fmt.flush(oss); + ASSERT_EQ(oss.str(), "\ +263882790666240\ +9223372036854775809\ +1.234\ +str\ +"); +} + +TEST(XmlFormatter, Empty) { + ostringstream oss; + XMLFormatter fmt(false); + fmt.flush(oss); + ASSERT_EQ(oss.str(), ""); +} + +TEST(XmlFormatter, DumpStream1) { + ostringstream oss; + XMLFormatter fmt(false); + fmt.dump_stream("blah") << "hithere"; + fmt.flush(oss); + ASSERT_EQ(oss.str(), "hithere"); +} + +TEST(XmlFormatter, DumpStream2) { + ostringstream oss; + XMLFormatter fmt(false); + + fmt.open_array_section("foo"); + fmt.dump_stream("blah") << "hithere"; + fmt.close_section(); + fmt.flush(oss); + ASSERT_EQ(oss.str(), "hithere"); +} + +TEST(XmlFormatter, DumpStream3) { + ostringstream oss; + XMLFormatter fmt(false); + + fmt.open_array_section("foo"); + fmt.dump_stream("blah") << "hithere"; + fmt.dump_float("pi", 3.14); + fmt.close_section(); + fmt.flush(oss); + ASSERT_EQ(oss.str(), "hithere3.14"); +} -- 2.39.5