]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Add XMLFormatter and unit test
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Tue, 2 Aug 2011 21:30:18 +0000 (14:30 -0700)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Tue, 2 Aug 2011 21:30:31 +0000 (14:30 -0700)
Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
src/common/Formatter.cc
src/common/Formatter.h
src/test/formatter.cc

index 84d78ef0d913db3d15d014b5ac5753aa4862e115..8123cf32b2e2e21fd05601acdaa52b92d78686cb 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <vector>
 
 // -----------------------
 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.back() << ">";
+  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 << "</" << e << ">";
+  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 << "</" << e << ">";
+  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 << "</" << e << ">";
+  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()) << "</" << e << ">";
+  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) << "</" << e << ">";
+  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 << ">";
+    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<char> 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<char> escaped(len, '\0');
+  escape_xml_attr(str, &escaped[0]);
+  return std::string(&escaped[0]);
+}
+
 }
index 210d0818798ef3e664dd1b8900b521b2292cc31b..faa1d00e8ba59b7c89b9ee6d0065f22e40c27fb2 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef CEPH_FORMATTER_H
 #define CEPH_FORMATTER_H
 
+#include <deque>
 #include <inttypes.h>
 #include <iostream>
 #include <list>
@@ -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<std::string> m_sections;
+  bool m_pretty;
+  std::string m_pending_string_name;
+};
+
 }
 #endif
index 0a2bdbabc9e7d913bed6cc46b525103e2e3728a9..c34980d565eac6c9ed2d2996050d3379729912af 100644 (file)
@@ -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(), "<foo><a>1</a><b>2</b><c>3</c></foo>");
+}
+
+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(), "<foo><bar>\
+<int>263882790666240</int>\
+<unsigned>9223372036854775809</unsigned>\
+<float>1.234</float>\
+</bar><string>str</string>\
+</foo>");
+}
+
+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(), "<blah>hithere</blah>");
+}
+
+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(), "<foo><blah>hithere</blah></foo>");
+}
+
+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(), "<foo><blah>hithere</blah><pi>3.14</pi></foo>");
+}