PEL: Represent the SRC ASCII string field

In the SRC section of a PEL, there is a field called the 'ASCII string'.
This is the string of 32 characters that shows up on the panel when the
SRC function is chosen, and usually when people refer to an SRC, the
first 8 characters of this field is what they are referring to.

This new class handles that string.  It will belong to the SRC section
object.

For BMC error SRCs, it looks like: BDSSRRRR
Where:
    BD = "BD", indicating a BMC error SRC
    SS = subsystem value from PEL spec
    RRRR = reason code of the error

The remaining 24 characters are spaces (' ').

For example:
    "BD8D1234                        "

For BMC power* related errors, the value is:

    "11001234                        "

Where the difference is the "11" instead of "BD", and the following
2 bytes are always "00".

* 'power' means comes from the repository that monitors for power
  faults.  This is different purely to help keep field service
  documentation the same as in previous IBM server generations.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I6e7292e7f5b501428999781b1a5ee5c243a63ac6
diff --git a/extensions/openpower-pels/ascii_string.hpp b/extensions/openpower-pels/ascii_string.hpp
new file mode 100644
index 0000000..d3ede0f
--- /dev/null
+++ b/extensions/openpower-pels/ascii_string.hpp
@@ -0,0 +1,103 @@
+#pragma once
+
+#include "registry.hpp"
+#include "stream.hpp"
+
+#include <string>
+
+namespace openpower
+{
+namespace pels
+{
+namespace src
+{
+
+const size_t asciiStringSize = 32;
+
+/**
+ * @class AsciiString
+ *
+ * This represents the ASCII string field in the SRC PEL section.
+ * This 32 character string shows up on the panel on a function 11.
+ *
+ * The first 2 characters are the SRC type, like 'BD' or '11'.
+ * Next is the subsystem, like '8D', if a BD SRC, otherwise '00'.
+ * Next is the reason code, like 'AAAA'.
+ * The rest is filled in with spaces.
+ */
+class AsciiString
+{
+  public:
+    AsciiString() = delete;
+    ~AsciiString() = default;
+    AsciiString(const AsciiString&) = default;
+    AsciiString& operator=(const AsciiString&) = default;
+    AsciiString(AsciiString&&) = default;
+    AsciiString& operator=(AsciiString&&) = default;
+
+    /**
+     * @brief Constructor
+     *
+     * Fills in this class's data fields from the stream.
+     *
+     * @param[in] pel - the PEL data stream
+     */
+    explicit AsciiString(Stream& stream);
+
+    /**
+     * @brief Constructor
+     *
+     * Fills in the class from the registry entry
+     */
+    explicit AsciiString(const message::Entry& entry);
+
+    /**
+     * @brief Flatten the object into the stream
+     *
+     * @param[in] stream - The stream to write to
+     */
+    void flatten(Stream& stream);
+
+    /**
+     * @brief Fills in the object from the stream data
+     *
+     * @param[in] stream - The stream to read from
+     */
+    void unflatten(Stream& stream);
+
+    /**
+     * @brief Return the 32 character ASCII string data
+     *
+     * @return std::string - The data
+     */
+    std::string get() const;
+
+  private:
+    /**
+     * @brief Converts a byte of raw data to 2 characters
+     *        and writes it to the offset.
+     *
+     * For example, if string is: "AABBCCDD"
+     *
+     * setByte(0, 0x11);
+     * setByte(1, 0x22);
+     * setByte(2, 0x33);
+     * setByte(3, 0x44);
+     *
+     * results in "11223344"
+     *
+     * @param[in] offset - The offset into the ascii string
+     * @param[in] value - The value to write (0x55 -> "55")
+     */
+    void setByte(size_t offset, uint8_t value);
+
+    /**
+     * @brief The ASCII string itself
+     */
+    std::array<char, asciiStringSize> _string;
+};
+
+} // namespace src
+
+} // namespace pels
+} // namespace openpower