Kaynağa Gözat

add the communication file format

Sven Czarnian 2 yıl önce
ebeveyn
işleme
272fb3aab0

+ 61 - 0
include/aman/config/CommunicationFileFormat.h

@@ -0,0 +1,61 @@
+/*
+ * @brief Defines the communication file format
+ * @file aman/config/CommunicationFileFormat.h
+ * @author Sven Czarnian <devel@svcz.de>
+ * @copyright Copyright 2021 Sven Czarnian
+ * @license This project is published under the GNU General Public License v3 (GPLv3)
+ */
+
+#pragma once
+
+#include <aman/config/FileFormat.h>
+#include <aman/types/Communication.h>
+
+namespace aman {
+    /**
+     * @brief Defines the parser of communication configurations
+     * @ingroup format
+     *
+     * All configuration entries need to be stored in 'AmanCommunication.txt'.
+     *
+     * The following entries of the configuration exist:
+     * <table>
+     *   <caption id="multi_row">Setting entries</caption>
+     *   <tr>
+     *     <th>Name</th><th>Description</th><th>Default value</th><th>Unit</th>
+     *   </tr>
+     *   <tr>
+     *     <td>URL</td>
+     *     <td>Defines the URL to the backend.</td>
+     *     <td></td><td></td>
+     *   </tr>
+     *   <tr>
+     *     <td>Port</td>
+     *     <td>Defines the port to access the backend.</td>
+     *     <td></td><td></td>
+     *   </tr>
+     *   <tr>
+     *     <td>UID</td>
+     *     <td>Defines the identifier to access the backend.</td>
+     *     <td></td><td></td>
+     *   </tr>
+     * </table>
+     */
+    class CommunicationFileFormat : public FileFormat {
+#ifndef DOXYGEN_IGNORE
+    public:
+        /**
+         * @brief Initializes the communication file format
+         */
+        CommunicationFileFormat();
+
+        /**
+         * @brief Parses the set configuration file
+         * @param[in] filename The path to the configuration file
+         * @param[out] config The resulting configuration
+         * @return True if the configuration file was valid, else false
+         */
+        bool parse(const std::string& filename, Communication& config);
+#endif
+    };
+}

+ 3 - 0
src/CMakeLists.txt

@@ -15,6 +15,7 @@ SET(SOURCE_FILES
     stdafx.h
 )
 SET(SOURCE_CONFIG_FILES
+    config/CommunicationFileFormat.cpp
     config/FileFormat.cpp
     config/IdentifierFileFormat.cpp
 )
@@ -24,6 +25,7 @@ SET(SOURCE_FILES_RES
     ${CMAKE_SOURCE_DIR}/res/targetver.h
 )
 SET(INCLUDE_CONFIG_FILES
+    ${CMAKE_SOURCE_DIR}/include/aman/config/CommunicationFileFormat.h
     ${CMAKE_SOURCE_DIR}/include/aman/config/FileFormat.h
     ${CMAKE_SOURCE_DIR}/include/aman/config/IdentifierFileFormat.h
 )
@@ -42,6 +44,7 @@ ADD_LIBRARY(
         ${SOURCE_FILES}
         ${INCLUDE_CONFIG_FILES}
         ${INCLUDE_HELPER_FILES}
+        ${INCLUDE_TYPES_FILES}
 )
 
 # define the dependencies

+ 100 - 0
src/config/CommunicationFileFormat.cpp

@@ -0,0 +1,100 @@
+/*
+ * Author:
+ *   Sven Czarnian <devel@svcz.de>
+ * Brief:
+ *   Implements the communication file format
+ * Copyright:
+ *   2021 Sven Czarnian
+ * License:
+ *   GNU General Public License v3 (GPLv3)
+ */
+
+#include <fstream>
+
+#include <gsl/gsl>
+
+#include <aman/config/CommunicationFileFormat.h>
+#include <aman/helper/String.h>
+
+using namespace aman;
+
+CommunicationFileFormat::CommunicationFileFormat() :
+        FileFormat() { }
+
+bool CommunicationFileFormat::parse(const std::string& filename, Communication& config) {
+    config.valid = true;
+
+    std::ifstream stream(filename);
+    if (false == stream.is_open()) {
+        this->m_errorMessage = "Unable to open the configuration file: " + filename;
+        this->m_errorLine = 0;
+        config.valid = false;
+        return false;
+    }
+
+    std::string line;
+    std::uint32_t lineOffset = 0;
+    while (std::getline(stream, line)) {
+        std::string value;
+
+        lineOffset += 1;
+
+        /* skip a new line */
+        if (0 == line.length())
+            continue;
+
+        /* trimm the line and check if a comment line is used */
+        std::string trimmed = String::trim(line);
+        if (0 == trimmed.find_first_of('#', 0))
+            continue;
+
+        auto entry = String::splitString(trimmed, "=");
+        if (2 > entry.size()) {
+            this->m_errorLine = lineOffset;
+            this->m_errorMessage = "Invalid configuration entry";
+            config.valid = false;
+            return false;
+        }
+        else if (2 < entry.size()) {
+            for (std::size_t idx = 1; idx < entry.size() - 1; ++idx)
+                value += gsl::at(entry, idx) + "=";
+            value += entry.back();
+        }
+        else {
+            value = gsl::at(entry, 1);
+        }
+
+        /* found an invalid line */
+        if (0 == value.length()) {
+            this->m_errorLine = lineOffset;
+            this->m_errorMessage = "Invalid entry";
+            config.valid = false;
+            return false;
+        }
+
+        if ("URL" == gsl::at(entry, 0)) {
+            config.url = gsl::at(entry, 1);
+        }
+        else if ("Port" == gsl::at(entry, 0)) {
+            config.port = static_cast<std::uint16_t>(std::atoi(gsl::at(entry, 1).c_str()));
+        }
+        else if ("UID" == gsl::at(entry, 0)) {
+            config.identifier = gsl::at(entry, 1);
+        }
+        else {
+            this->m_errorLine = lineOffset;
+            this->m_errorMessage = "Unknown entry: " + gsl::at(entry, 0);
+            config.valid = false;
+            return false;
+        }
+    }
+
+    if (0 == lineOffset) {
+        this->m_errorLine = 0;
+        this->m_errorMessage = "No data found in " + filename;
+        config.valid = false;
+        return false;
+    }
+
+    return true;
+}