#include "include/buffer.h"
#include <set>
+#include <limits>
#include <boost/format.hpp>
// -----------------------
void JSONFormatter::add_value(const char *name, T val)
{
std::stringstream ss;
+ ss.precision(std::numeric_limits<T>::max_digits10);
ss << val;
add_value(name, ss.str(), false);
}
void JSONFormatter::dump_float(const char *name, double d)
{
- char foo[30];
- snprintf(foo, sizeof(foo), "%lf", d);
- add_value(name, foo, false);
+ add_value(name, d);
}
void JSONFormatter::dump_string(const char *name, std::string_view s)
m_ss << "\n";
}
-void XMLFormatter::dump_unsigned(const char *name, uint64_t u)
+template <class T>
+void XMLFormatter::add_value(const char *name, T val)
{
std::string e(name);
std::transform(e.begin(), e.end(), e.begin(),
[this](char c) { return this->to_lower_underscore(c); });
print_spaces();
- m_ss << "<" << e << ">" << u << "</" << e << ">";
+ m_ss.precision(std::numeric_limits<T>::max_digits10);
+ m_ss << "<" << e << ">" << val << "</" << e << ">";
if (m_pretty)
m_ss << "\n";
}
-void XMLFormatter::dump_int(const char *name, int64_t u)
+void XMLFormatter::dump_unsigned(const char *name, uint64_t u)
{
- std::string e(name);
- std::transform(e.begin(), e.end(), e.begin(),
- [this](char c) { return this->to_lower_underscore(c); });
+ add_value(name, u);
+}
- print_spaces();
- m_ss << "<" << e << ">" << u << "</" << e << ">";
- if (m_pretty)
- m_ss << "\n";
+void XMLFormatter::dump_int(const char *name, int64_t s)
+{
+ add_value(name, s);
}
void XMLFormatter::dump_float(const char *name, double d)
{
- std::string e(name);
- 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)
- m_ss << "\n";
+ add_value(name, d);
}
void XMLFormatter::dump_string(const char *name, std::string_view s)
}
}
-void TableFormatter::dump_unsigned(const char *name, uint64_t u)
-{
+template <class T>
+void TableFormatter::add_value(const char *name, T val) {
finish_pending_string();
size_t i = m_vec_index(name);
- m_ss << u;
+ m_ss.precision(std::numeric_limits<double>::max_digits10);
+ m_ss << val;
+
m_vec[i].push_back(std::make_pair(get_section_name(name), m_ss.str()));
m_ss.clear();
m_ss.str("");
}
-void TableFormatter::dump_int(const char *name, int64_t u)
+void TableFormatter::dump_unsigned(const char *name, uint64_t u)
{
- finish_pending_string();
- size_t i = m_vec_index(name);
- m_ss << u;
- m_vec[i].push_back(std::make_pair(get_section_name(name), m_ss.str()));
- m_ss.clear();
- m_ss.str("");
+ add_value(name, u);
}
-void TableFormatter::dump_float(const char *name, double d)
+void TableFormatter::dump_int(const char *name, int64_t s)
{
- finish_pending_string();
- size_t i = m_vec_index(name);
- m_ss << d;
+ add_value(name, s);
+}
- m_vec[i].push_back(std::make_pair(get_section_name(name), m_ss.str()));
- m_ss.clear();
- m_ss.str("");
+void TableFormatter::dump_float(const char *name, double d)
+{
+ add_value(name, d);
}
void TableFormatter::dump_string(const char *name, std::string_view s)
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_int(const char *name, int64_t s) override;
void dump_float(const char *name, double d) override;
void dump_string(const char *name, std::string_view s) override;
std::ostream& dump_stream(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_int(const char *name, int64_t s) override;
void dump_float(const char *name, double d) override;
void dump_string(const char *name, std::string_view s) override;
std::ostream& dump_stream(const char *name) override;
std::string m_pending_string_name;
bool m_header_done;
bool m_line_break_enabled = false;
+ private:
+ template <class T>
+ void add_value(const char *name, T val);
};
class TableFormatter : public Formatter {
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_int(const char *name, int64_t s) override;
void dump_float(const char *name, double d) override;
void dump_string(const char *name, std::string_view s) override;
void dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap) override;
void get_attrs_str(const FormatterAttrs *attrs, std::string& attrs_str);
private:
+ template <class T>
+ void add_value(const char *name, T val);
void open_section_in_ns(const char *name, const char *ns, const FormatterAttrs *attrs);
std::vector< std::vector<std::pair<std::string, std::string> > > m_vec;
std::stringstream m_ss;
"bucket_id": -3,
"weight_set": [
[
- 1.000000,
- 2.000000,
- 5.000000
+ 1,
+ 2,
+ 5
],
[
- 3.000000,
- 2.000000,
- 5.000000
+ 3,
+ 2,
+ 5
]
],
"ids": [
"bucket_id": -2,
"weight_set": [
[
- 1.000000
+ 1
],
[
- 3.000000
+ 3
]
]
}
"bucket_id": -2,
"weight_set": [
[
- 1.000000
+ 1
],
[
- 3.000000
+ 3
]
]
},
"bucket_id": -3,
"weight_set": [
[
- 1.000000,
- 2.000000,
- 5.000000
+ 1,
+ 2,
+ 5
],
[
- 3.000000,
- 2.000000,
- 5.000000
+ 3,
+ 2,
+ 5
]
],
"ids": [
"name": "osd.0",
"type": "osd",
"type_id": 0,
- "crush_weight": 1.000000,
+ "crush_weight": 1,
"depth": 3,
"pool_weights": {},
"exists": 0,
"status": "down",
- "reweight": 0.000000,
- "primary_affinity": 1.000000
+ "reweight": 0,
+ "primary_affinity": 1
},
{
"id": 1,
"name": "osd.1",
"type": "osd",
"type_id": 0,
- "crush_weight": 1.000000,
+ "crush_weight": 1,
"depth": 3,
"pool_weights": {},
"exists": 0,
"status": "down",
- "reweight": 0.000000,
- "primary_affinity": 1.000000
+ "reweight": 0,
+ "primary_affinity": 1
},
{
"id": 2,
"name": "osd.2",
"type": "osd",
"type_id": 0,
- "crush_weight": 1.000000,
+ "crush_weight": 1,
"depth": 3,
"pool_weights": {},
"exists": 0,
"status": "down",
- "reweight": 0.000000,
- "primary_affinity": 1.000000
+ "reweight": 0,
+ "primary_affinity": 1
}
],
"stray": []
EXPECT_EQ(cmp, sout.str());
}
+TEST(tableformatter, longfloat)
+{
+ std::stringstream sout;
+ TableFormatter formatter;
+ formatter.dump_float("float", 1.0 / 7);
+ formatter.flush(sout);
+
+ std::string cmp = ""
+ "+----------------------+\n"
+ "| float |\n"
+ "+----------------------+\n"
+ "| 0.14285714285714285 |\n"
+ "+----------------------+\n";
+ EXPECT_EQ(cmp, sout.str());
+}
+
TEST(tableformatter, multiline)
{
std::stringstream sout;
fmt.close_section();
fmt.flush(oss);
ASSERT_EQ(oss.str(), "{\"bar\":{\"int\":263882790666240,\
-\"unsigned\":9223372036854775809,\"float\":1.234000},\
+\"unsigned\":9223372036854775809,\"float\":1.234},\
\"string\":\"str\"}");
}
+TEST(JsonFormatter, CunningFloats) {
+ ostringstream oss;
+ JSONFormatter fmt(false);
+ fmt.open_object_section("foo");
+ fmt.dump_float("long", 1.0 / 7);
+ fmt.dump_float("big", 12345678901234567890.0);
+ fmt.close_section();
+ fmt.flush(oss);
+ ASSERT_EQ(oss.str(), "{\"long\":0.14285714285714285,\"big\":1.2345678901234567e+19}");
+}
+
TEST(JsonFormatter, Empty) {
ostringstream oss;
JSONFormatter fmt(false);
fmt.open_array_section("foo");
fmt.dump_stream("blah") << "hithere";
- fmt.dump_float("pi", 3.14);
+ fmt.dump_float("pi", 0.128);
fmt.close_section();
fmt.flush(oss);
- ASSERT_EQ(oss.str(), "<foo><blah>hithere</blah><pi>3.14</pi></foo>");
+ ASSERT_EQ(oss.str(), "<foo><blah>hithere</blah><pi>0.128</pi></foo>");
}
TEST(XmlFormatter, DTD) {
fmt.output_header();
fmt.open_array_section("foo");
fmt.dump_stream("blah") << "hithere";
- fmt.dump_float("pi", 3.14);
+ fmt.dump_float("pi", 0.128);
fmt.close_section();
fmt.flush(oss);
ASSERT_EQ(oss.str(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
- "<foo><blah>hithere</blah><pi>3.14</pi></foo>");
+ "<foo><blah>hithere</blah><pi>0.128</pi></foo>");
}
TEST(XmlFormatter, Clear) {
fmt.output_header();
fmt.open_array_section("foo");
fmt.dump_stream("blah") << "hithere";
- fmt.dump_float("pi", 3.14);
+ fmt.dump_float("pi", 0.128);
fmt.close_section();
fmt.flush(oss);
ASSERT_EQ(oss.str(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
- "<foo><blah>hithere</blah><pi>3.14</pi></foo>");
+ "<foo><blah>hithere</blah><pi>0.128</pi></foo>");
ostringstream oss2;
fmt.flush(oss2);
fmt.open_array_section_in_ns("foo",
"http://s3.amazonaws.com/doc/2006-03-01/");
fmt.dump_stream("blah") << "hithere";
- fmt.dump_float("pi", 3.14);
+ fmt.dump_float("pi", 0.128);
fmt.close_section();
fmt.flush(oss);
ASSERT_EQ(oss.str(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<foo xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">"
- "<blah>hithere</blah><pi>3.14</pi></foo>");
+ "<blah>hithere</blah><pi>0.128</pi></foo>");
}
TEST(XmlFormatter, DumpFormatNameSpaceTest) {
fmt.open_array_section("foo");
fmt.dump_stream("blah") << "hithere";
- fmt.dump_float("pi", 3.14);
+ fmt.dump_float("pi", 0.128);
fmt.close_section();
fmt.flush(oss);
- ASSERT_EQ(oss.str(), "<foo><li>blah: hithere</li><li>pi: 3.14</li></foo>");
+ ASSERT_EQ(oss.str(), "<foo><li>blah: hithere</li><li>pi: 0.128</li></foo>");
}
TEST(HtmlFormatter, DTD) {
fmt.write_raw_data(HTMLFormatter::XML_1_DTD);
fmt.open_array_section("foo");
fmt.dump_stream("blah") << "hithere";
- fmt.dump_float("pi", 3.14);
+ fmt.dump_float("pi", 0.128);
fmt.close_section();
fmt.flush(oss);
ASSERT_EQ(oss.str(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
- "<foo><li>blah: hithere</li><li>pi: 3.14</li></foo>");
+ "<foo><li>blah: hithere</li><li>pi: 0.128</li></foo>");
}
TEST(HtmlFormatter, Clear) {
fmt.write_raw_data(HTMLFormatter::XML_1_DTD);
fmt.open_array_section("foo");
fmt.dump_stream("blah") << "hithere";
- fmt.dump_float("pi", 3.14);
+ fmt.dump_float("pi", 0.128);
fmt.close_section();
fmt.flush(oss);
ASSERT_EQ(oss.str(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
- "<foo><li>blah: hithere</li><li>pi: 3.14</li></foo>");
+ "<foo><li>blah: hithere</li><li>pi: 0.128</li></foo>");
ostringstream oss2;
fmt.flush(oss2);
fmt.open_array_section_in_ns("foo",
"http://s3.amazonaws.com/doc/2006-03-01/");
fmt.dump_stream("blah") << "hithere";
- fmt.dump_float("pi", 3.14);
+ fmt.dump_float("pi", 0.128);
fmt.close_section();
fmt.flush(oss);
ASSERT_EQ(oss.str(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<foo xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">"
- "<li>blah: hithere</li><li>pi: 3.14</li></foo>");
+ "<li>blah: hithere</li><li>pi: 0.128</li></foo>");
}
TEST(HtmlFormatter, DumpFormatNameSpaceTest) {