#include <boost/format.hpp>
-static char tolower_underscore(const char b) {
- return ' ' == b ? '_' : std::tolower(b);
-}
-
// -----------------------
namespace ceph {
const char *XMLFormatter::XML_1_DTD =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
-XMLFormatter::XMLFormatter(bool pretty, bool lowercased_underscored)
+XMLFormatter::XMLFormatter(bool pretty, bool lowercased, bool underscored)
: m_pretty(pretty),
- m_lowercased_underscored(lowercased_underscored)
+ m_lowercased(lowercased),
+ m_underscored(underscored)
{
reset();
}
finish_pending_string();
std::string section = m_sections.back();
- if (m_lowercased_underscored) {
- std::transform(section.begin(), section.end(), section.begin(),
- tolower_underscore);
- }
+ std::transform(section.begin(), section.end(), section.begin(),
+ [this](char c) { return this->to_lower_underscore(c); });
m_sections.pop_back();
print_spaces();
m_ss << "</" << section << ">";
void XMLFormatter::dump_unsigned(const char *name, uint64_t u)
{
std::string e(name);
- if (m_lowercased_underscored) {
- std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
- }
+ std::transform(e.begin(), e.end(), e.begin(),
+ [this](char c) { return this->to_lower_underscore(c); });
+
print_spaces();
m_ss << "<" << e << ">" << u << "</" << e << ">";
if (m_pretty)
void XMLFormatter::dump_int(const char *name, int64_t u)
{
std::string e(name);
- if (m_lowercased_underscored) {
- std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
- }
+ std::transform(e.begin(), e.end(), e.begin(),
+ [this](char c) { return this->to_lower_underscore(c); });
+
print_spaces();
m_ss << "<" << e << ">" << u << "</" << e << ">";
if (m_pretty)
void XMLFormatter::dump_float(const char *name, double d)
{
std::string e(name);
- if (m_lowercased_underscored) {
- std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
- }
+ std::transform(e.begin(), e.end(), e.begin(),
+ [this](char c) { return this->to_lower_underscore(c); });
+
print_spaces();
m_ss << "<" << e << ">" << d << "</" << e << ">";
if (m_pretty)
void XMLFormatter::dump_string(const char *name, const std::string& s)
{
std::string e(name);
- if (m_lowercased_underscored) {
- std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
- }
+ std::transform(e.begin(), e.end(), e.begin(),
+ [this](char c) { return this->to_lower_underscore(c); });
+
print_spaces();
m_ss << "<" << e << ">" << escape_xml_str(s.c_str()) << "</" << e << ">";
if (m_pretty)
void XMLFormatter::dump_string_with_attrs(const char *name, const std::string& s, const FormatterAttrs& attrs)
{
std::string e(name);
- if (m_lowercased_underscored) {
- std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
- }
+ std::transform(e.begin(), e.end(), e.begin(),
+ [this](char c) { return this->to_lower_underscore(c); });
+
std::string attrs_str;
get_attrs_str(&attrs, attrs_str);
print_spaces();
{
char buf[LARGE_SIZE];
vsnprintf(buf, LARGE_SIZE, fmt, ap);
-
std::string e(name);
- if (m_lowercased_underscored) {
- std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
- }
+ std::transform(e.begin(), e.end(), e.begin(),
+ [this](char c) { return this->to_lower_underscore(c); });
+
print_spaces();
if (ns) {
m_ss << "<" << e << " xmlns=\"" << ns << "\">" << buf << "</" << e << ">";
}
std::string e(name);
- if (m_lowercased_underscored) {
- std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
- }
+ std::transform(e.begin(), e.end(), e.begin(),
+ [this](char c) { return this->to_lower_underscore(c); });
if (ns) {
m_ss << "<" << e << attrs_str << " xmlns=\"" << ns << "\">";
return std::string(&escaped[0]);
}
+char XMLFormatter::to_lower_underscore(char c) const
+{
+ if (m_underscored && c == ' ') {
+ return '_';
+ } else if (m_lowercased) {
+ return std::tolower(c);
+ }
+ return c;
+}
+
TableFormatter::TableFormatter(bool keyval) : m_keyval(keyval)
{
reset();
class XMLFormatter : public Formatter {
public:
static const char *XML_1_DTD;
- XMLFormatter(bool pretty = false, bool lowercased_underscored = false);
+ XMLFormatter(bool pretty = false, bool lowercased = false, bool underscored = true);
virtual void set_status(int status, const char* status_name) {}
virtual void output_header();
void open_array_section_with_attrs(const char *name, const FormatterAttrs& attrs);
void open_object_section_with_attrs(const char *name, const FormatterAttrs& attrs);
void dump_string_with_attrs(const char *name, const std::string& s, const FormatterAttrs& attrs);
+
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<std::string> m_sections;
- bool m_pretty;
- bool m_lowercased_underscored;
+ const bool m_pretty;
+ const bool m_lowercased;
+ const bool m_underscored;
std::string m_pending_string_name;
bool m_header_done;
};
add_ceph_unittest(unittest_tableformatter ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_tableformatter)
target_link_libraries(unittest_tableformatter global)
+add_executable(unittest_xmlformatter
+ test_xmlformatter.cc
+ )
+add_ceph_unittest(unittest_xmlformatter ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_xmlformatter)
+target_link_libraries(unittest_xmlformatter ceph-common)
+
# unittest_bit_vector
add_executable(unittest_bit_vector
test_bit_vector.cc
--- /dev/null
+#include "gtest/gtest.h"
+
+#include "common/Formatter.h"
+#include <sstream>
+#include <string>
+
+using namespace ceph;
+
+
+TEST(xmlformatter, oneline)
+{
+
+ std::stringstream sout;
+ XMLFormatter formatter;
+ formatter.dump_int("integer", 10);
+ formatter.dump_float("float", 10.0);
+ formatter.dump_string("string", "string");
+ formatter.flush(sout);
+ std::string cmp = "<integer>10</integer><float>10</float><string>string</string>";
+ EXPECT_EQ(cmp, sout.str());
+}
+
+TEST(xmlformatter, multiline)
+{
+ std::stringstream sout;
+ XMLFormatter formatter;
+ formatter.dump_int("integer", 10);
+ formatter.dump_float("float", 10.0);
+ formatter.dump_string("string", "string");
+ formatter.dump_int("integer", 20);
+ formatter.dump_float("float", 20.0);
+ formatter.dump_string("string", "string");
+
+ std::string cmp = ""
+ "<integer>10</integer><float>10</float><string>string</string>"
+ "<integer>20</integer><float>20</float><string>string</string>";
+
+ formatter.flush(sout);
+ EXPECT_EQ(cmp, sout.str());
+}
+
+TEST(xmlformatter, multiflush)
+{
+ std::stringstream sout1;
+ std::stringstream sout2;
+ XMLFormatter formatter;
+ formatter.dump_int("integer", 10);
+ formatter.dump_float("float", 10.0);
+ formatter.dump_string("string", "string");
+ formatter.flush(sout1);
+
+ std::string cmp = ""
+ "<integer>10</integer>"
+ "<float>10</float>"
+ "<string>string</string>";
+
+ EXPECT_EQ(cmp, sout1.str());
+
+ formatter.dump_int("integer", 20);
+ formatter.dump_float("float", 20.0);
+ formatter.dump_string("string", "string");
+ formatter.flush(sout2);
+
+ cmp = ""
+ "<integer>20</integer>"
+ "<float>20</float>"
+ "<string>string</string>";
+
+ EXPECT_EQ(cmp, sout2.str());
+}
+
+TEST(xmlformatter, pretty)
+{
+ std::stringstream sout;
+ XMLFormatter formatter(
+ true, // pretty
+ false, // lowercased
+ false); // underscored
+ formatter.open_object_section("xml");
+ formatter.dump_int("Integer", 10);
+ formatter.dump_float("Float", 10.0);
+ formatter.dump_string("String", "String");
+ formatter.close_section();
+ formatter.flush(sout);
+ std::string cmp = ""
+ "<xml>\n"
+ " <Integer>10</Integer>\n"
+ " <Float>10</Float>\n"
+ " <String>String</String>\n"
+ "</xml>\n\n";
+ EXPECT_EQ(cmp, sout.str());
+}
+
+TEST(xmlformatter, lowercased)
+{
+ std::stringstream sout;
+ XMLFormatter formatter(
+ false, // pretty
+ true, // lowercased
+ false); // underscored
+ formatter.dump_int("Integer", 10);
+ formatter.dump_float("Float", 10.0);
+ formatter.dump_string("String", "String");
+ formatter.flush(sout);
+ std::string cmp = ""
+ "<integer>10</integer>"
+ "<float>10</float>"
+ "<string>String</string>";
+ EXPECT_EQ(cmp, sout.str());
+}
+
+TEST(xmlformatter, underscored)
+{
+ std::stringstream sout;
+ XMLFormatter formatter(
+ false, // pretty
+ false, // lowercased
+ true); // underscored
+ formatter.dump_int("Integer Item", 10);
+ formatter.dump_float("Float Item", 10.0);
+ formatter.dump_string("String Item", "String");
+ formatter.flush(sout);
+ std::string cmp = ""
+ "<Integer_Item>10</Integer_Item>"
+ "<Float_Item>10</Float_Item>"
+ "<String_Item>String</String_Item>";
+
+ EXPECT_EQ(cmp, sout.str());
+}
+
+TEST(xmlformatter, lowercased_underscored)
+{
+ std::stringstream sout;
+ XMLFormatter formatter(
+ false, // pretty
+ true, // lowercased
+ true); // underscored
+ formatter.dump_int("Integer Item", 10);
+ formatter.dump_float("Float Item", 10.0);
+ formatter.dump_string("String Item", "String");
+ formatter.flush(sout);
+ std::string cmp = ""
+ "<integer_item>10</integer_item>"
+ "<float_item>10</float_item>"
+ "<string_item>String</string_item>";
+ EXPECT_EQ(cmp, sout.str());
+}
+
+TEST(xmlformatter, pretty_lowercased_underscored)
+{
+ std::stringstream sout;
+ XMLFormatter formatter(
+ true, // pretty
+ true, // lowercased
+ true); // underscored
+ formatter.dump_int("Integer Item", 10);
+ formatter.dump_float("Float Item", 10.0);
+ formatter.dump_string("String Item", "String");
+ formatter.flush(sout);
+ std::string cmp = ""
+ "<integer_item>10</integer_item>\n"
+ "<float_item>10</float_item>\n"
+ "<string_item>String</string_item>\n\n";
+ EXPECT_EQ(cmp, sout.str());
+}