Roll out error message utils

This code should really be in a cpp/hpp file, not in a generated python
script.  The python script housed this temporarily to allow us to
generate the registries.  It's time to roll it out.

Tested: Message registries generate successfully on GET.  Redfish
service validator passes.

Change-Id: I7aca2d0a7fac6d530511421b667ff732617df61e
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/meson.build b/meson.build
index ffc0c14..9c16bde 100644
--- a/meson.build
+++ b/meson.build
@@ -358,6 +358,7 @@
     'http/mutual_tls.cpp',
     'redfish-core/src/dbus_log_watcher.cpp',
     'redfish-core/src/error_messages.cpp',
+    'redfish-core/src/error_message_utils.cpp',
     'redfish-core/src/event_log.cpp',
     'redfish-core/src/filesystem_log_watcher.cpp',
     'redfish-core/src/filter_expr_executor.cpp',
diff --git a/redfish-core/include/error_message_utils.hpp b/redfish-core/include/error_message_utils.hpp
new file mode 100644
index 0000000..75015bc
--- /dev/null
+++ b/redfish-core/include/error_message_utils.hpp
@@ -0,0 +1,24 @@
+#include <nlohmann/json.hpp>
+
+#include <string_view>
+
+namespace redfish
+{
+
+namespace messages
+{
+
+constexpr const char* messageVersionPrefix = "Base.1.19.0.";
+constexpr const char* messageAnnotation = "@Message.ExtendedInfo";
+
+void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source);
+void addMessageToJsonRoot(nlohmann::json& target,
+                          const nlohmann::json& message);
+
+void addMessageToJson(nlohmann::json& target, const nlohmann::json& message,
+                      std::string_view fieldPath);
+
+void addMessageToErrorJson(nlohmann::json& target,
+                           const nlohmann::json& message);
+} // namespace messages
+} // namespace redfish
diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
index d9a3bb3..3b700ae 100644
--- a/redfish-core/include/error_messages.hpp
+++ b/redfish-core/include/error_messages.hpp
@@ -25,14 +25,6 @@
 
 namespace messages
 {
-constexpr const char* messageVersionPrefix = "Base.1.19.0.";
-constexpr const char* messageAnnotation = "@Message.ExtendedInfo";
-
-/**
- * @brief Moves all error messages from the |source| JSON to |target|
- */
-void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source);
-
 /**
  * @brief Formats Success message into JSON
  * Message body: "The request completed successfully."
diff --git a/redfish-core/include/utils/query_param.hpp b/redfish-core/include/utils/query_param.hpp
index a867338..b579190 100644
--- a/redfish-core/include/utils/query_param.hpp
+++ b/redfish-core/include/utils/query_param.hpp
@@ -5,6 +5,7 @@
 
 #include "app.hpp"
 #include "async_resp.hpp"
+#include "error_message_utils.hpp"
 #include "error_messages.hpp"
 #include "filter_expr_executor.hpp"
 #include "filter_expr_printer.hpp"
diff --git a/redfish-core/src/error_message_utils.cpp b/redfish-core/src/error_message_utils.cpp
new file mode 100644
index 0000000..ae7829a
--- /dev/null
+++ b/redfish-core/src/error_message_utils.cpp
@@ -0,0 +1,124 @@
+#include "error_message_utils.hpp"
+
+#include "logging.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <string>
+#include <string_view>
+
+namespace redfish
+{
+
+namespace messages
+{
+
+void addMessageToErrorJson(nlohmann::json& target,
+                           const nlohmann::json& message)
+{
+    auto& error = target["error"];
+
+    // If this is the first error message, fill in the information from the
+    // first error message to the top level struct
+    if (!error.is_object())
+    {
+        auto messageIdIterator = message.find("MessageId");
+        if (messageIdIterator == message.end())
+        {
+            BMCWEB_LOG_CRITICAL(
+                "Attempt to add error message without MessageId");
+            return;
+        }
+
+        auto messageFieldIterator = message.find("Message");
+        if (messageFieldIterator == message.end())
+        {
+            BMCWEB_LOG_CRITICAL("Attempt to add error message without Message");
+            return;
+        }
+        error["code"] = *messageIdIterator;
+        error["message"] = *messageFieldIterator;
+    }
+    else
+    {
+        // More than 1 error occurred, so the message has to be generic
+        error["code"] = std::string(messageVersionPrefix) + "GeneralError";
+        error["message"] = "A general error has occurred. See Resolution for "
+                           "information on how to resolve the error.";
+    }
+
+    // This check could technically be done in the default construction
+    // branch above, but because we need the pointer to the extended info field
+    // anyway, it's more efficient to do it here.
+    auto& extendedInfo = error[messages::messageAnnotation];
+    if (!extendedInfo.is_array())
+    {
+        extendedInfo = nlohmann::json::array();
+    }
+
+    extendedInfo.push_back(message);
+}
+
+void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source)
+{
+    if (!source.is_object())
+    {
+        return;
+    }
+    auto errorIt = source.find("error");
+    if (errorIt == source.end())
+    {
+        // caller puts error message in root
+        messages::addMessageToErrorJson(target, source);
+        source.clear();
+        return;
+    }
+    auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
+    if (extendedInfoIt == errorIt->end())
+    {
+        return;
+    }
+    const nlohmann::json::array_t* extendedInfo =
+        (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
+    if (extendedInfo == nullptr)
+    {
+        source.erase(errorIt);
+        return;
+    }
+    for (const nlohmann::json& message : *extendedInfo)
+    {
+        addMessageToErrorJson(target, message);
+    }
+    source.erase(errorIt);
+}
+
+void addMessageToJsonRoot(nlohmann::json& target, const nlohmann::json& message)
+{
+    if (!target[messages::messageAnnotation].is_array())
+    {
+        // Force object to be an array
+        target[messages::messageAnnotation] = nlohmann::json::array();
+    }
+
+    target[messages::messageAnnotation].push_back(message);
+}
+
+void addMessageToJson(nlohmann::json& target, const nlohmann::json& message,
+                      std::string_view fieldPath)
+{
+    std::string extendedInfo(fieldPath);
+    extendedInfo += messages::messageAnnotation;
+
+    nlohmann::json& field = target[extendedInfo];
+    if (!field.is_array())
+    {
+        // Force object to be an array
+        field = nlohmann::json::array();
+    }
+
+    // Object exists and it is an array so we can just push in the message
+    field.push_back(message);
+}
+
+} // namespace messages
+} // namespace redfish
diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
index 4e2ede8..5325849 100644
--- a/redfish-core/src/error_messages.cpp
+++ b/redfish-core/src/error_messages.cpp
@@ -10,6 +10,7 @@
  ***************************************************************/
 #include "error_messages.hpp"
 
+#include "error_message_utils.hpp"
 #include "http_response.hpp"
 #include "logging.hpp"
 #include "registries.hpp"
@@ -39,115 +40,6 @@
 namespace messages
 {
 
-static void addMessageToErrorJson(nlohmann::json& target,
-                                  const nlohmann::json& message)
-{
-    auto& error = target["error"];
-
-    // If this is the first error message, fill in the information from the
-    // first error message to the top level struct
-    if (!error.is_object())
-    {
-        auto messageIdIterator = message.find("MessageId");
-        if (messageIdIterator == message.end())
-        {
-            BMCWEB_LOG_CRITICAL(
-                "Attempt to add error message without MessageId");
-            return;
-        }
-
-        auto messageFieldIterator = message.find("Message");
-        if (messageFieldIterator == message.end())
-        {
-            BMCWEB_LOG_CRITICAL("Attempt to add error message without Message");
-            return;
-        }
-        error["code"] = *messageIdIterator;
-        error["message"] = *messageFieldIterator;
-    }
-    else
-    {
-        // More than 1 error occurred, so the message has to be generic
-        error["code"] = std::string(messageVersionPrefix) + "GeneralError";
-        error["message"] = "A general error has occurred. See Resolution for "
-                           "information on how to resolve the error.";
-    }
-
-    // This check could technically be done in the default construction
-    // branch above, but because we need the pointer to the extended info field
-    // anyway, it's more efficient to do it here.
-    auto& extendedInfo = error[messages::messageAnnotation];
-    if (!extendedInfo.is_array())
-    {
-        extendedInfo = nlohmann::json::array();
-    }
-
-    extendedInfo.push_back(message);
-}
-
-void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source)
-{
-    if (!source.is_object())
-    {
-        return;
-    }
-    auto errorIt = source.find("error");
-    if (errorIt == source.end())
-    {
-        // caller puts error message in root
-        messages::addMessageToErrorJson(target, source);
-        source.clear();
-        return;
-    }
-    auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
-    if (extendedInfoIt == errorIt->end())
-    {
-        return;
-    }
-    const nlohmann::json::array_t* extendedInfo =
-        (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
-    if (extendedInfo == nullptr)
-    {
-        source.erase(errorIt);
-        return;
-    }
-    for (const nlohmann::json& message : *extendedInfo)
-    {
-        addMessageToErrorJson(target, message);
-    }
-    source.erase(errorIt);
-}
-
-static void addMessageToJsonRoot(nlohmann::json& target,
-                                 const nlohmann::json& message)
-{
-    if (!target[messages::messageAnnotation].is_array())
-    {
-        // Force object to be an array
-        target[messages::messageAnnotation] = nlohmann::json::array();
-    }
-
-    target[messages::messageAnnotation].push_back(message);
-}
-
-static void addMessageToJson(nlohmann::json& target,
-                             const nlohmann::json& message,
-                             std::string_view fieldPath)
-{
-    std::string extendedInfo(fieldPath);
-    extendedInfo += messages::messageAnnotation;
-
-    nlohmann::json& field = target[extendedInfo];
-    if (!field.is_array())
-    {
-        // Force object to be an array
-        field = nlohmann::json::array();
-    }
-
-    // Object exists and it is an array so we can just push in the message
-    field.push_back(message);
-}
-
 static nlohmann::json getLog(redfish::registries::base::Index name,
                              std::span<const std::string_view> args)
 {
diff --git a/scripts/parse_registries.py b/scripts/parse_registries.py
index e172923..0e566aa 100755
--- a/scripts/parse_registries.py
+++ b/scripts/parse_registries.py
@@ -434,21 +434,6 @@
 {
 """
         )
-        if registry_name == "Base":
-            out.write(
-                f'constexpr const char* messageVersionPrefix = "{registry_name}.{registry_version}.";'
-            )
-            out.write(
-                """
-            constexpr const char* messageAnnotation = "@Message.ExtendedInfo";
-
-            /**
-            * @brief Moves all error messages from the |source| JSON to |target|
-            */
-            void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source);
-
-        """
-            )
         for entry_id, entry in messages.items():
             message = entry["Message"]
             for index in range(1, 10):
@@ -494,6 +479,7 @@
         headers.append('"registries.hpp"')
         if registry_name == "Base":
             reg_name_lower = "base"
+            headers.append('"error_message_utils.hpp"')
             headers.append('"http_response.hpp"')
             headers.append('"logging.hpp"')
             headers.append("<boost/beast/http/field.hpp>")
@@ -531,120 +517,6 @@
 {
 """
         )
-
-        if registry_name == "Base":
-            out.write(
-                """
-static void addMessageToErrorJson(nlohmann::json& target,
-                                  const nlohmann::json& message)
-{
-    auto& error = target["error"];
-
-    // If this is the first error message, fill in the information from the
-    // first error message to the top level struct
-    if (!error.is_object())
-    {
-        auto messageIdIterator = message.find("MessageId");
-        if (messageIdIterator == message.end())
-        {
-            BMCWEB_LOG_CRITICAL(
-                "Attempt to add error message without MessageId");
-            return;
-        }
-
-        auto messageFieldIterator = message.find("Message");
-        if (messageFieldIterator == message.end())
-        {
-            BMCWEB_LOG_CRITICAL("Attempt to add error message without Message");
-            return;
-        }
-        error["code"] = *messageIdIterator;
-        error["message"] = *messageFieldIterator;
-    }
-    else
-    {
-        // More than 1 error occurred, so the message has to be generic
-        error["code"] = std::string(messageVersionPrefix) + "GeneralError";
-        error["message"] = "A general error has occurred. See Resolution for "
-                           "information on how to resolve the error.";
-    }
-
-    // This check could technically be done in the default construction
-    // branch above, but because we need the pointer to the extended info field
-    // anyway, it's more efficient to do it here.
-    auto& extendedInfo = error[messages::messageAnnotation];
-    if (!extendedInfo.is_array())
-    {
-        extendedInfo = nlohmann::json::array();
-    }
-
-    extendedInfo.push_back(message);
-}
-
-void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source)
-{
-    if (!source.is_object())
-    {
-        return;
-    }
-    auto errorIt = source.find("error");
-    if (errorIt == source.end())
-    {
-        // caller puts error message in root
-        messages::addMessageToErrorJson(target, source);
-        source.clear();
-        return;
-    }
-    auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
-    if (extendedInfoIt == errorIt->end())
-    {
-        return;
-    }
-    const nlohmann::json::array_t* extendedInfo =
-        (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
-    if (extendedInfo == nullptr)
-    {
-        source.erase(errorIt);
-        return;
-    }
-    for (const nlohmann::json& message : *extendedInfo)
-    {
-        addMessageToErrorJson(target, message);
-    }
-    source.erase(errorIt);
-}
-
-static void addMessageToJsonRoot(nlohmann::json& target,
-                                 const nlohmann::json& message)
-{
-    if (!target[messages::messageAnnotation].is_array())
-    {
-        // Force object to be an array
-        target[messages::messageAnnotation] = nlohmann::json::array();
-    }
-
-    target[messages::messageAnnotation].push_back(message);
-}
-
-static void addMessageToJson(nlohmann::json& target,
-                             const nlohmann::json& message,
-                             std::string_view fieldPath)
-{
-    std::string extendedInfo(fieldPath);
-    extendedInfo += messages::messageAnnotation;
-
-    nlohmann::json& field = target[extendedInfo];
-    if (!field.is_array())
-    {
-        // Force object to be an array
-        field = nlohmann::json::array();
-    }
-
-    // Object exists and it is an array so we can just push in the message
-    field.push_back(message);
-}
-"""
-            )
         out.write(
             """
 static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name,
diff --git a/test/redfish-core/include/utils/query_param_test.cpp b/test/redfish-core/include/utils/query_param_test.cpp
index d037bd8..d9025c0 100644
--- a/test/redfish-core/include/utils/query_param_test.cpp
+++ b/test/redfish-core/include/utils/query_param_test.cpp
@@ -2,7 +2,6 @@
 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
 #include "bmcweb_config.h"
 
-#include "error_messages.hpp"
 #include "http_response.hpp"
 #include "utils/query_param.hpp"