Add helper class to handle PMBus metadata

Add a NamesValues class to help when adding multiple
PMBus registers to a single metadata entry.

It allows one to add multiple name/value pairs to
the object, and provides a get() method to return them
all concatenated.

It currently supports numeric values, up to a uint64_t,
but more types could be added if ever necessary.

The resulting string will look like:
"name1=value1|name2=value2|etc"

Change-Id: I4def8ac313882a0b9efc7cb33488f19ad33f1727
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/names_values.hpp b/names_values.hpp
new file mode 100644
index 0000000..39b5739
--- /dev/null
+++ b/names_values.hpp
@@ -0,0 +1,111 @@
+#include <sstream>
+#include <string>
+
+namespace witherspoon
+{
+namespace power
+{
+namespace util
+{
+
+/**
+ * @class NamesValues
+ *
+ * Builds up a string of name=value pairs for use in
+ * situations like error log metadata.
+ *
+ * Names and values can be added to an instance of this
+ * class, and then calling get() will return a string
+ * that appends them all together.
+ *
+ * Currently, just uint64_t values that will be displayed
+ * in hex are supported.
+ *
+ * For example:
+ *     NamesValues m;
+ *     uint8_t d = 0xFF;
+ *
+ *     m.add("STATUS_VOUT", d);
+ *     m.add("STATUS_WORD", 0xABCD);
+ *
+ *     m.get() //returns: "STATUS_VOUT=0xFF|STATUS_WORD=0xABCD"
+ */
+class NamesValues
+{
+    public:
+
+        NamesValues() = default;
+        NamesValues(const NamesValues&) = default;
+        NamesValues& operator=(const NamesValues&) = default;
+        NamesValues(NamesValues&&) = default;
+        NamesValues& operator=(NamesValues&&) = default;
+
+        /**
+         * Adds a name/value pair to the object
+         *
+         * @param name - the name to add
+         * @param value - the value to add
+         */
+        void add(const std::string& name, uint64_t value)
+        {
+            addDivider();
+            addName(name);
+            addValue(value);
+        }
+
+        /**
+         * Returns a formatted concatenation of all of the names and
+         * their values.
+         *
+         * @return string - "<name1>=<value1>|<name2>=<value2>..etc"
+         */
+        const std::string& get() const
+        {
+            return all;
+        }
+
+    private:
+
+        /**
+         * Adds a name to the object
+         *
+         * @param name - the name to add
+         */
+        void addName(const std::string& name)
+        {
+            all += name + '=';
+        }
+
+        /**
+         * Adds a value to the object
+         *
+         * @param value - the value to add
+         */
+        void addValue(uint64_t value)
+        {
+            std::ostringstream stream;
+            stream << "0x" << std::hex << value;
+            all += stream.str();
+        }
+
+        /**
+         * Adds a divider to the summary string to
+         * break up the name/value pairs
+         */
+        void addDivider()
+        {
+           if (!all.empty())
+           {
+                all += '|';
+           }
+        }
+
+        /**
+         * The string containing all name/value pairs
+         */
+        std::string all;
+};
+
+}
+}
+}