tools: fix nfdc::text::ItemAttributes evaluation order bug
When multiple ItemAttributes::operator() invocations appear on the same
expression, they are not always evaluated left-to-right, causing incorrect
text output.
refs #3864
Change-Id: I4c99c5bc4a76b4becf83f368c9f253c0b254fc05
diff --git a/tests/tools/nfdc/format-helpers.t.cpp b/tests/tools/nfdc/format-helpers.t.cpp
index 99f6966..6184401 100644
--- a/tests/tools/nfdc/format-helpers.t.cpp
+++ b/tests/tools/nfdc/format-helpers.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -71,6 +71,29 @@
BOOST_CHECK(os.is_equal("1,2,3"));
}
+static void
+printItemAttributes(std::ostream& os, bool wantMultiLine)
+{
+ text::ItemAttributes ia(wantMultiLine, 3);
+ os << ia("id") << 500
+ << ia("uri") << "udp4://192.0.2.1:6363"
+ << ia.end();
+}
+
+BOOST_AUTO_TEST_CASE(ItemAttributesSingleLine)
+{
+ output_test_stream os;
+ printItemAttributes(os, false);
+ BOOST_CHECK(os.is_equal("id=500 uri=udp4://192.0.2.1:6363"));
+}
+
+BOOST_AUTO_TEST_CASE(ItemAttributesMultiLine)
+{
+ output_test_stream os;
+ printItemAttributes(os, true);
+ BOOST_CHECK(os.is_equal(" id=500\nuri=udp4://192.0.2.1:6363\n"));
+}
+
BOOST_AUTO_TEST_SUITE_END() // Text
BOOST_AUTO_TEST_SUITE_END() // TestFormatHelpers
diff --git a/tools/nfdc/format-helpers.cpp b/tools/nfdc/format-helpers.cpp
index b6b8258..3d851dd 100644
--- a/tools/nfdc/format-helpers.cpp
+++ b/tools/nfdc/format-helpers.cpp
@@ -128,17 +128,7 @@
ItemAttributes::Attribute
ItemAttributes::operator()(const std::string& attribute)
{
- ++m_count;
- if (m_wantMultiLine) {
- return {m_count > 1,
- {m_maxAttributeWidth - static_cast<int>(attribute.size())},
- attribute};
- }
- else {
- return {false,
- {m_count > 1 ? 1 : 0},
- attribute};
- }
+ return {*this, attribute};
}
std::string
@@ -150,13 +140,21 @@
std::ostream&
operator<<(std::ostream& os, const ItemAttributes::Attribute& attr)
{
- if (attr.wantNewline) {
- os << '\n';
+ ++attr.ia.m_count;
+ if (attr.ia.m_wantMultiLine) {
+ if (attr.ia.m_count > 1) {
+ os << '\n';
+ }
+ os << Spaces{attr.ia.m_maxAttributeWidth - static_cast<int>(attr.attribute.size())};
}
- return os << attr.spaces << attr.attribute << '=';
+ else {
+ if (attr.ia.m_count > 1) {
+ os << ' ';
+ }
+ }
+ return os << attr.attribute << '=';
}
-
std::string
formatSeconds(time::seconds d, bool isLong)
{
diff --git a/tools/nfdc/format-helpers.hpp b/tools/nfdc/format-helpers.hpp
index 4fd2c38..9283855 100644
--- a/tools/nfdc/format-helpers.hpp
+++ b/tools/nfdc/format-helpers.hpp
@@ -140,11 +140,13 @@
struct Attribute
{
- bool wantNewline;
- Spaces spaces;
+ ItemAttributes& ia;
std::string attribute;
};
+ /** \note Caller must ensure ItemAttributes object is alive until after all Attribute objects are
+ * destructed.
+ */
Attribute
operator()(const std::string& attribute);
@@ -155,6 +157,8 @@
bool m_wantMultiLine;
int m_maxAttributeWidth;
int m_count;
+
+ friend std::ostream& operator<<(std::ostream& os, const ItemAttributes::Attribute& attr);
};
std::ostream&