Example of the Config File#

A Config File contains a configuration of a system in a TOML-like structure.

[Configuration]
Version = 100

[[Component]]
Path = "module_example.sdv"
Class = "class_example"
Name = "object_name_example"
Message = "It's me"
Id = 42
Pi = 3.1415926
Boolean = true
Array = [ 1, 2, 3 , 5 , 7, 11, 13, 17 ]
Table = { a = 77, b = 1.2, c = "das ist ein string" }
[Configuration]
Version = 100

[[Component]]
Path = "module_example.sdv"
Class = "class_example"
Name = "object_name_example"
Message = "It's me"
Id = 42
Pi = 3.1415926
Boolean = true
Array = [ 1, 2, 3 , 5 , 7, 11, 13, 17 ]
Table = { a = 77, b = 1.2, c = "das ist ein string" }

A Config File must contain a version information.

[Configuration]
Version = 100

[[Component]]
Path = "module_example.sdv"
Class = "class_example"
Name = "object_name_example"
Message = "It's me"
Id = 42
Pi = 3.1415926
Boolean = true
Array = [ 1, 2, 3 , 5 , 7, 11, 13, 17 ]
Table = { a = 77, b = 1.2, c = "das ist ein string" }

To load a VAPI Component the path/name to the binary file and the class name is required.

[Configuration]
Version = 100

[[Component]]
Path = "module_example.sdv"
Class = "class_example"
Name = "object_name_example"
Message = "It's me"
Id = 42
Pi = 3.1415926
Boolean = true
Array = [ 1, 2, 3 , 5 , 7, 11, 13, 17 ]
Table = { a = 77, b = 1.2, c = "das ist ein string" }

The object name is optional. With that multiple VAPI Component s of the same class can be created.

[Configuration]
Version = 100

[[Component]]
Path = "module_example.sdv"
Class = "class_example"
Name = "object_name_example"
Message = "It's me"
Id = 42
Pi = 3.1415926
Boolean = true
Array = [ 1, 2, 3 , 5 , 7, 11, 13, 17 ]
Table = { a = 77, b = 1.2, c = "das ist ein string" }

The rest are user defined variables of any type including arrays and further tables. With that any data could be in the configuration file

Setting one or more folders for the modules:

sdv::app::CAppControl appcontrol;
auto bResult = appcontrol.AddModuleSearchDir("../../tests/bin");
bResult &= appcontrol.AddModuleSearchDir("../../bin"); // even more can be added

Setting one or more folders for the config files:

appcontrol.SetConfigMode();
bResult &= appcontrol.AddConfigSearchDir("ApplicationConfigFiles");
bResult &= appcontrol.AddConfigSearchDir("ServiceConfigFiles"); // even more can be added

Following shows how to parse the configuration example above.

#include <iostream>
#include <support/component_impl.h>
#include <support/toml.h>

class DemoConfigurationComponent : public sdv::CSdvObject, public sdv::IObjectControl
{
  public:
    BEGIN_SDV_INTERFACE_MAP()
        SDV_INTERFACE_ENTRY(sdv::IObjectControl)
    END_SDV_INTERFACE_MAP()

    DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
    DECLARE_OBJECT_CLASS_NAME("Configuration_Example")

    /**
    * @brief initialize function to register, access the task timer interface from platform abstraction.
    * After initialization 'CreateTimer' function is called to execute the task periodically.
    * @param[in] rssObjectConfig An object configuration is currently not used by this demo component.
    */
    virtual void Initialize([[maybe_unused]] const sdv::u8string& rssObjectConfig) override
    {
        try
        {
            sdv::toml::CTOMLParser config(rssObjectConfig.c_str());

            sdv::toml::CNode messageNode = config.GetDirect("Message");
            if (messageNode.GetType() == sdv::toml::ENodeType::node_string)
            {
                m_Message = static_cast<std::string>(messageNode.GetValue());
            }

            sdv::toml::CNode idNode = config.GetDirect("Id");
            if (idNode.GetType() == sdv::toml::ENodeType::node_integer)
            {
                m_Id = static_cast<int32_t>(idNode.GetValue());
            }

            sdv::toml::CNode floatNode = config.GetDirect("Pi");
            if (floatNode.GetType() == sdv::toml::ENodeType::node_floating_point)
            {
                m_Pi = static_cast<float>(floatNode.GetValue());
            }

            sdv::toml::CNode boolNode = config.GetDirect("Boolean");
            if (boolNode.GetType() == sdv::toml::ENodeType::node_boolean)
            {
                m_IsValid = static_cast<bool>(boolNode.GetValue());
            }

            sdv::toml::CNodeCollection arrayNodes = config.GetDirect("Array");
            if (arrayNodes.GetType() == sdv::toml::ENodeType::node_array)
            {
                for (size_t nIndex = 0; nIndex < arrayNodes.GetCount(); nIndex++)
                {
                    sdv::toml::CNode node = arrayNodes[nIndex];
                    if (node.GetType() == sdv::toml::ENodeType::node_integer)
                    {
                        m_Counters.push_back(static_cast<uint32_t>(node.GetValue()));
                    }
                }
            }

            sdv::toml::CNodeCollection tableNodes = config.GetDirect("Table");
            if (tableNodes.GetType() == sdv::toml::ENodeType::node_table)
            {
                if (tableNodes.GetCount() >= 3)
                {
                    m_TableA = static_cast<uint32_t>(tableNodes[0].GetValue());
                    m_TableB = static_cast<float>(tableNodes[1].GetValue());
                    m_TableC = static_cast<std::string>(tableNodes[2].GetValue());
                }
            }

            auto table_a = config.GetDirect("Table.a");
            auto table_b = config.GetDirect("Table.b");
            auto table_c = config.GetDirect("Table.c");
            m_DirectTableA = static_cast<uint32_t>(table_a.GetValue());
            m_DirectTableB = static_cast<float>(table_b.GetValue());
            m_DirectTableC = static_cast<std::string>(table_c.GetValue());
        }
        catch (const sdv::toml::XTOMLParseException& e)
        {
            SDV_LOG_ERROR("Parsing error: ", e.what());

            m_status = sdv::EObjectStatus::initialization_failure;
            return;
        }

        PrintAllVariables();

        m_status = sdv::EObjectStatus::initialized;
    };

    /**
    * @brief Gets the current status of the object
    * @return EObjectStatus The current status of the object
    */
    virtual sdv::EObjectStatus GetStatus() const override
    {
        return m_status;
    };

    /**
     * @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
     * @param[in] eMode The operation mode, the component should run in.
     */
    void SetOperationMode(/*in*/ sdv::EOperationMode eMode)
    {
        switch (eMode)
        {
        case sdv::EOperationMode::configuring:
            if (m_status == sdv::EObjectStatus::running || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::configuring;
            break;
        case sdv::EOperationMode::running:
            if (m_status == sdv::EObjectStatus::configuring || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::running;
            break;
        default:
            break;
        }
    }

    /**
    * @brief Shutdown function is to shutdown the execution of periodic task.
    * Timer ID of the task is used to shutdown the specific task.
    */
    virtual void Shutdown() override
    {
        m_status = sdv::EObjectStatus::destruction_pending;
    }

    /**
    * @brief Print all global variables to console
    */
    void PrintAllVariables()
    {
        std::cout << "\nValues parsed during initialization:\n" << std::endl;
        std::cout << "string: " << m_Message.c_str() << std::endl;
        std::cout << "integer: " << std::to_string(m_Id) << std::endl;
        std::cout << "float: " << std::to_string(m_Pi) << std::endl;
        std::cout << "bool: " << std::to_string(m_IsValid) << std::endl;
        std::cout << "table column a: " << std::to_string(m_TableA) << "     " << std::to_string(m_DirectTableA) << std::endl;
        std::cout << "table column b: " << std::to_string(m_TableB) << "     " << std::to_string(m_DirectTableB) << std::endl;
        std::cout << "table column c: " << m_TableC.c_str() << "     " << m_DirectTableC.c_str() << std::endl;
        std::cout << "array: ";
        for (auto counter : m_Counters)
        {
            std::cout << std::to_string(counter) << ", ";
        }
        std::cout << std::endl;
    }

  private:
    std::atomic<sdv::EObjectStatus> m_status = {sdv::EObjectStatus::initialization_pending}; //!< To update the object status when it changes.

    std::string           m_Message = "";
    int32_t               m_Id = -1;
    float                 m_Pi = 0.0;
    bool                  m_IsValid = false;
    std::vector<uint32_t> m_Counters;
    uint32_t              m_TableA = 0;
    float                 m_TableB = 0.0;
    std::string           m_TableC = "";
    uint32_t              m_DirectTableA = 0;
    float                 m_DirectTableB = 0.0;
    std::string           m_DirectTableC = "";
};

DEFINE_SDV_OBJECT(DemoConfigurationComponent)
#include <iostream>
#include <support/component_impl.h>
#include <support/toml.h>

class DemoConfigurationComponent : public sdv::CSdvObject, public sdv::IObjectControl
{
  public:
    BEGIN_SDV_INTERFACE_MAP()
        SDV_INTERFACE_ENTRY(sdv::IObjectControl)
    END_SDV_INTERFACE_MAP()

    DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
    DECLARE_OBJECT_CLASS_NAME("Configuration_Example")

    /**
    * @brief initialize function to register, access the task timer interface from platform abstraction.
    * After initialization 'CreateTimer' function is called to execute the task periodically.
    * @param[in] rssObjectConfig An object configuration is currently not used by this demo component.
    */
    virtual void Initialize([[maybe_unused]] const sdv::u8string& rssObjectConfig) override
    {
        try
        {
            sdv::toml::CTOMLParser config(rssObjectConfig.c_str());

            sdv::toml::CNode messageNode = config.GetDirect("Message");
            if (messageNode.GetType() == sdv::toml::ENodeType::node_string)
            {
                m_Message = static_cast<std::string>(messageNode.GetValue());
            }

            sdv::toml::CNode idNode = config.GetDirect("Id");
            if (idNode.GetType() == sdv::toml::ENodeType::node_integer)
            {
                m_Id = static_cast<int32_t>(idNode.GetValue());
            }

            sdv::toml::CNode floatNode = config.GetDirect("Pi");
            if (floatNode.GetType() == sdv::toml::ENodeType::node_floating_point)
            {
                m_Pi = static_cast<float>(floatNode.GetValue());
            }

            sdv::toml::CNode boolNode = config.GetDirect("Boolean");
            if (boolNode.GetType() == sdv::toml::ENodeType::node_boolean)
            {
                m_IsValid = static_cast<bool>(boolNode.GetValue());
            }

            sdv::toml::CNodeCollection arrayNodes = config.GetDirect("Array");
            if (arrayNodes.GetType() == sdv::toml::ENodeType::node_array)
            {
                for (size_t nIndex = 0; nIndex < arrayNodes.GetCount(); nIndex++)
                {
                    sdv::toml::CNode node = arrayNodes[nIndex];
                    if (node.GetType() == sdv::toml::ENodeType::node_integer)
                    {
                        m_Counters.push_back(static_cast<uint32_t>(node.GetValue()));
                    }
                }
            }

            sdv::toml::CNodeCollection tableNodes = config.GetDirect("Table");
            if (tableNodes.GetType() == sdv::toml::ENodeType::node_table)
            {
                if (tableNodes.GetCount() >= 3)
                {
                    m_TableA = static_cast<uint32_t>(tableNodes[0].GetValue());
                    m_TableB = static_cast<float>(tableNodes[1].GetValue());
                    m_TableC = static_cast<std::string>(tableNodes[2].GetValue());
                }
            }

            auto table_a = config.GetDirect("Table.a");
            auto table_b = config.GetDirect("Table.b");
            auto table_c = config.GetDirect("Table.c");
            m_DirectTableA = static_cast<uint32_t>(table_a.GetValue());
            m_DirectTableB = static_cast<float>(table_b.GetValue());
            m_DirectTableC = static_cast<std::string>(table_c.GetValue());
        }
        catch (const sdv::toml::XTOMLParseException& e)
        {
            SDV_LOG_ERROR("Parsing error: ", e.what());

            m_status = sdv::EObjectStatus::initialization_failure;
            return;
        }

        PrintAllVariables();

        m_status = sdv::EObjectStatus::initialized;
    };

    /**
    * @brief Gets the current status of the object
    * @return EObjectStatus The current status of the object
    */
    virtual sdv::EObjectStatus GetStatus() const override
    {
        return m_status;
    };

    /**
     * @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
     * @param[in] eMode The operation mode, the component should run in.
     */
    void SetOperationMode(/*in*/ sdv::EOperationMode eMode)
    {
        switch (eMode)
        {
        case sdv::EOperationMode::configuring:
            if (m_status == sdv::EObjectStatus::running || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::configuring;
            break;
        case sdv::EOperationMode::running:
            if (m_status == sdv::EObjectStatus::configuring || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::running;
            break;
        default:
            break;
        }
    }

    /**
    * @brief Shutdown function is to shutdown the execution of periodic task.
    * Timer ID of the task is used to shutdown the specific task.
    */
    virtual void Shutdown() override
    {
        m_status = sdv::EObjectStatus::destruction_pending;
    }

    /**
    * @brief Print all global variables to console
    */
    void PrintAllVariables()
    {
        std::cout << "\nValues parsed during initialization:\n" << std::endl;
        std::cout << "string: " << m_Message.c_str() << std::endl;
        std::cout << "integer: " << std::to_string(m_Id) << std::endl;
        std::cout << "float: " << std::to_string(m_Pi) << std::endl;
        std::cout << "bool: " << std::to_string(m_IsValid) << std::endl;
        std::cout << "table column a: " << std::to_string(m_TableA) << "     " << std::to_string(m_DirectTableA) << std::endl;
        std::cout << "table column b: " << std::to_string(m_TableB) << "     " << std::to_string(m_DirectTableB) << std::endl;
        std::cout << "table column c: " << m_TableC.c_str() << "     " << m_DirectTableC.c_str() << std::endl;
        std::cout << "array: ";
        for (auto counter : m_Counters)
        {
            std::cout << std::to_string(counter) << ", ";
        }
        std::cout << std::endl;
    }

  private:
    std::atomic<sdv::EObjectStatus> m_status = {sdv::EObjectStatus::initialization_pending}; //!< To update the object status when it changes.

    std::string           m_Message = "";
    int32_t               m_Id = -1;
    float                 m_Pi = 0.0;
    bool                  m_IsValid = false;
    std::vector<uint32_t> m_Counters;
    uint32_t              m_TableA = 0;
    float                 m_TableB = 0.0;
    std::string           m_TableC = "";
    uint32_t              m_DirectTableA = 0;
    float                 m_DirectTableB = 0.0;
    std::string           m_DirectTableC = "";
};

DEFINE_SDV_OBJECT(DemoConfigurationComponent)

The access to the variables is very easy with the sdv::toml::CTOMLParser. Just get direct access, validate the data type and get the value.

#include <iostream>
#include <support/component_impl.h>
#include <support/toml.h>

class DemoConfigurationComponent : public sdv::CSdvObject, public sdv::IObjectControl
{
  public:
    BEGIN_SDV_INTERFACE_MAP()
        SDV_INTERFACE_ENTRY(sdv::IObjectControl)
    END_SDV_INTERFACE_MAP()

    DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
    DECLARE_OBJECT_CLASS_NAME("Configuration_Example")

    /**
    * @brief initialize function to register, access the task timer interface from platform abstraction.
    * After initialization 'CreateTimer' function is called to execute the task periodically.
    * @param[in] rssObjectConfig An object configuration is currently not used by this demo component.
    */
    virtual void Initialize([[maybe_unused]] const sdv::u8string& rssObjectConfig) override
    {
        try
        {
            sdv::toml::CTOMLParser config(rssObjectConfig.c_str());

            sdv::toml::CNode messageNode = config.GetDirect("Message");
            if (messageNode.GetType() == sdv::toml::ENodeType::node_string)
            {
                m_Message = static_cast<std::string>(messageNode.GetValue());
            }

            sdv::toml::CNode idNode = config.GetDirect("Id");
            if (idNode.GetType() == sdv::toml::ENodeType::node_integer)
            {
                m_Id = static_cast<int32_t>(idNode.GetValue());
            }

            sdv::toml::CNode floatNode = config.GetDirect("Pi");
            if (floatNode.GetType() == sdv::toml::ENodeType::node_floating_point)
            {
                m_Pi = static_cast<float>(floatNode.GetValue());
            }

            sdv::toml::CNode boolNode = config.GetDirect("Boolean");
            if (boolNode.GetType() == sdv::toml::ENodeType::node_boolean)
            {
                m_IsValid = static_cast<bool>(boolNode.GetValue());
            }

            sdv::toml::CNodeCollection arrayNodes = config.GetDirect("Array");
            if (arrayNodes.GetType() == sdv::toml::ENodeType::node_array)
            {
                for (size_t nIndex = 0; nIndex < arrayNodes.GetCount(); nIndex++)
                {
                    sdv::toml::CNode node = arrayNodes[nIndex];
                    if (node.GetType() == sdv::toml::ENodeType::node_integer)
                    {
                        m_Counters.push_back(static_cast<uint32_t>(node.GetValue()));
                    }
                }
            }

            sdv::toml::CNodeCollection tableNodes = config.GetDirect("Table");
            if (tableNodes.GetType() == sdv::toml::ENodeType::node_table)
            {
                if (tableNodes.GetCount() >= 3)
                {
                    m_TableA = static_cast<uint32_t>(tableNodes[0].GetValue());
                    m_TableB = static_cast<float>(tableNodes[1].GetValue());
                    m_TableC = static_cast<std::string>(tableNodes[2].GetValue());
                }
            }

            auto table_a = config.GetDirect("Table.a");
            auto table_b = config.GetDirect("Table.b");
            auto table_c = config.GetDirect("Table.c");
            m_DirectTableA = static_cast<uint32_t>(table_a.GetValue());
            m_DirectTableB = static_cast<float>(table_b.GetValue());
            m_DirectTableC = static_cast<std::string>(table_c.GetValue());
        }
        catch (const sdv::toml::XTOMLParseException& e)
        {
            SDV_LOG_ERROR("Parsing error: ", e.what());

            m_status = sdv::EObjectStatus::initialization_failure;
            return;
        }

        PrintAllVariables();

        m_status = sdv::EObjectStatus::initialized;
    };

    /**
    * @brief Gets the current status of the object
    * @return EObjectStatus The current status of the object
    */
    virtual sdv::EObjectStatus GetStatus() const override
    {
        return m_status;
    };

    /**
     * @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
     * @param[in] eMode The operation mode, the component should run in.
     */
    void SetOperationMode(/*in*/ sdv::EOperationMode eMode)
    {
        switch (eMode)
        {
        case sdv::EOperationMode::configuring:
            if (m_status == sdv::EObjectStatus::running || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::configuring;
            break;
        case sdv::EOperationMode::running:
            if (m_status == sdv::EObjectStatus::configuring || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::running;
            break;
        default:
            break;
        }
    }

    /**
    * @brief Shutdown function is to shutdown the execution of periodic task.
    * Timer ID of the task is used to shutdown the specific task.
    */
    virtual void Shutdown() override
    {
        m_status = sdv::EObjectStatus::destruction_pending;
    }

    /**
    * @brief Print all global variables to console
    */
    void PrintAllVariables()
    {
        std::cout << "\nValues parsed during initialization:\n" << std::endl;
        std::cout << "string: " << m_Message.c_str() << std::endl;
        std::cout << "integer: " << std::to_string(m_Id) << std::endl;
        std::cout << "float: " << std::to_string(m_Pi) << std::endl;
        std::cout << "bool: " << std::to_string(m_IsValid) << std::endl;
        std::cout << "table column a: " << std::to_string(m_TableA) << "     " << std::to_string(m_DirectTableA) << std::endl;
        std::cout << "table column b: " << std::to_string(m_TableB) << "     " << std::to_string(m_DirectTableB) << std::endl;
        std::cout << "table column c: " << m_TableC.c_str() << "     " << m_DirectTableC.c_str() << std::endl;
        std::cout << "array: ";
        for (auto counter : m_Counters)
        {
            std::cout << std::to_string(counter) << ", ";
        }
        std::cout << std::endl;
    }

  private:
    std::atomic<sdv::EObjectStatus> m_status = {sdv::EObjectStatus::initialization_pending}; //!< To update the object status when it changes.

    std::string           m_Message = "";
    int32_t               m_Id = -1;
    float                 m_Pi = 0.0;
    bool                  m_IsValid = false;
    std::vector<uint32_t> m_Counters;
    uint32_t              m_TableA = 0;
    float                 m_TableB = 0.0;
    std::string           m_TableC = "";
    uint32_t              m_DirectTableA = 0;
    float                 m_DirectTableB = 0.0;
    std::string           m_DirectTableC = "";
};

DEFINE_SDV_OBJECT(DemoConfigurationComponent)

The configuration can include very complex data including tables. It’s not required to get from top to down, a direct access is also possible.

#include <iostream>
#include <support/component_impl.h>
#include <support/toml.h>

class DemoConfigurationComponent : public sdv::CSdvObject, public sdv::IObjectControl
{
  public:
    BEGIN_SDV_INTERFACE_MAP()
        SDV_INTERFACE_ENTRY(sdv::IObjectControl)
    END_SDV_INTERFACE_MAP()

    DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
    DECLARE_OBJECT_CLASS_NAME("Configuration_Example")

    /**
    * @brief initialize function to register, access the task timer interface from platform abstraction.
    * After initialization 'CreateTimer' function is called to execute the task periodically.
    * @param[in] rssObjectConfig An object configuration is currently not used by this demo component.
    */
    virtual void Initialize([[maybe_unused]] const sdv::u8string& rssObjectConfig) override
    {
        try
        {
            sdv::toml::CTOMLParser config(rssObjectConfig.c_str());

            sdv::toml::CNode messageNode = config.GetDirect("Message");
            if (messageNode.GetType() == sdv::toml::ENodeType::node_string)
            {
                m_Message = static_cast<std::string>(messageNode.GetValue());
            }

            sdv::toml::CNode idNode = config.GetDirect("Id");
            if (idNode.GetType() == sdv::toml::ENodeType::node_integer)
            {
                m_Id = static_cast<int32_t>(idNode.GetValue());
            }

            sdv::toml::CNode floatNode = config.GetDirect("Pi");
            if (floatNode.GetType() == sdv::toml::ENodeType::node_floating_point)
            {
                m_Pi = static_cast<float>(floatNode.GetValue());
            }

            sdv::toml::CNode boolNode = config.GetDirect("Boolean");
            if (boolNode.GetType() == sdv::toml::ENodeType::node_boolean)
            {
                m_IsValid = static_cast<bool>(boolNode.GetValue());
            }

            sdv::toml::CNodeCollection arrayNodes = config.GetDirect("Array");
            if (arrayNodes.GetType() == sdv::toml::ENodeType::node_array)
            {
                for (size_t nIndex = 0; nIndex < arrayNodes.GetCount(); nIndex++)
                {
                    sdv::toml::CNode node = arrayNodes[nIndex];
                    if (node.GetType() == sdv::toml::ENodeType::node_integer)
                    {
                        m_Counters.push_back(static_cast<uint32_t>(node.GetValue()));
                    }
                }
            }

            sdv::toml::CNodeCollection tableNodes = config.GetDirect("Table");
            if (tableNodes.GetType() == sdv::toml::ENodeType::node_table)
            {
                if (tableNodes.GetCount() >= 3)
                {
                    m_TableA = static_cast<uint32_t>(tableNodes[0].GetValue());
                    m_TableB = static_cast<float>(tableNodes[1].GetValue());
                    m_TableC = static_cast<std::string>(tableNodes[2].GetValue());
                }
            }

            auto table_a = config.GetDirect("Table.a");
            auto table_b = config.GetDirect("Table.b");
            auto table_c = config.GetDirect("Table.c");
            m_DirectTableA = static_cast<uint32_t>(table_a.GetValue());
            m_DirectTableB = static_cast<float>(table_b.GetValue());
            m_DirectTableC = static_cast<std::string>(table_c.GetValue());
        }
        catch (const sdv::toml::XTOMLParseException& e)
        {
            SDV_LOG_ERROR("Parsing error: ", e.what());

            m_status = sdv::EObjectStatus::initialization_failure;
            return;
        }

        PrintAllVariables();

        m_status = sdv::EObjectStatus::initialized;
    };

    /**
    * @brief Gets the current status of the object
    * @return EObjectStatus The current status of the object
    */
    virtual sdv::EObjectStatus GetStatus() const override
    {
        return m_status;
    };

    /**
     * @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
     * @param[in] eMode The operation mode, the component should run in.
     */
    void SetOperationMode(/*in*/ sdv::EOperationMode eMode)
    {
        switch (eMode)
        {
        case sdv::EOperationMode::configuring:
            if (m_status == sdv::EObjectStatus::running || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::configuring;
            break;
        case sdv::EOperationMode::running:
            if (m_status == sdv::EObjectStatus::configuring || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::running;
            break;
        default:
            break;
        }
    }

    /**
    * @brief Shutdown function is to shutdown the execution of periodic task.
    * Timer ID of the task is used to shutdown the specific task.
    */
    virtual void Shutdown() override
    {
        m_status = sdv::EObjectStatus::destruction_pending;
    }

    /**
    * @brief Print all global variables to console
    */
    void PrintAllVariables()
    {
        std::cout << "\nValues parsed during initialization:\n" << std::endl;
        std::cout << "string: " << m_Message.c_str() << std::endl;
        std::cout << "integer: " << std::to_string(m_Id) << std::endl;
        std::cout << "float: " << std::to_string(m_Pi) << std::endl;
        std::cout << "bool: " << std::to_string(m_IsValid) << std::endl;
        std::cout << "table column a: " << std::to_string(m_TableA) << "     " << std::to_string(m_DirectTableA) << std::endl;
        std::cout << "table column b: " << std::to_string(m_TableB) << "     " << std::to_string(m_DirectTableB) << std::endl;
        std::cout << "table column c: " << m_TableC.c_str() << "     " << m_DirectTableC.c_str() << std::endl;
        std::cout << "array: ";
        for (auto counter : m_Counters)
        {
            std::cout << std::to_string(counter) << ", ";
        }
        std::cout << std::endl;
    }

  private:
    std::atomic<sdv::EObjectStatus> m_status = {sdv::EObjectStatus::initialization_pending}; //!< To update the object status when it changes.

    std::string           m_Message = "";
    int32_t               m_Id = -1;
    float                 m_Pi = 0.0;
    bool                  m_IsValid = false;
    std::vector<uint32_t> m_Counters;
    uint32_t              m_TableA = 0;
    float                 m_TableB = 0.0;
    std::string           m_TableC = "";
    uint32_t              m_DirectTableA = 0;
    float                 m_DirectTableB = 0.0;
    std::string           m_DirectTableC = "";
};

DEFINE_SDV_OBJECT(DemoConfigurationComponent)

These functions just implement the IObjectControl interface.

#include <iostream>
#include <support/component_impl.h>
#include <support/toml.h>

class DemoConfigurationComponent : public sdv::CSdvObject, public sdv::IObjectControl
{
  public:
    BEGIN_SDV_INTERFACE_MAP()
        SDV_INTERFACE_ENTRY(sdv::IObjectControl)
    END_SDV_INTERFACE_MAP()

    DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
    DECLARE_OBJECT_CLASS_NAME("Configuration_Example")

    /**
    * @brief initialize function to register, access the task timer interface from platform abstraction.
    * After initialization 'CreateTimer' function is called to execute the task periodically.
    * @param[in] rssObjectConfig An object configuration is currently not used by this demo component.
    */
    virtual void Initialize([[maybe_unused]] const sdv::u8string& rssObjectConfig) override
    {
        try
        {
            sdv::toml::CTOMLParser config(rssObjectConfig.c_str());

            sdv::toml::CNode messageNode = config.GetDirect("Message");
            if (messageNode.GetType() == sdv::toml::ENodeType::node_string)
            {
                m_Message = static_cast<std::string>(messageNode.GetValue());
            }

            sdv::toml::CNode idNode = config.GetDirect("Id");
            if (idNode.GetType() == sdv::toml::ENodeType::node_integer)
            {
                m_Id = static_cast<int32_t>(idNode.GetValue());
            }

            sdv::toml::CNode floatNode = config.GetDirect("Pi");
            if (floatNode.GetType() == sdv::toml::ENodeType::node_floating_point)
            {
                m_Pi = static_cast<float>(floatNode.GetValue());
            }

            sdv::toml::CNode boolNode = config.GetDirect("Boolean");
            if (boolNode.GetType() == sdv::toml::ENodeType::node_boolean)
            {
                m_IsValid = static_cast<bool>(boolNode.GetValue());
            }

            sdv::toml::CNodeCollection arrayNodes = config.GetDirect("Array");
            if (arrayNodes.GetType() == sdv::toml::ENodeType::node_array)
            {
                for (size_t nIndex = 0; nIndex < arrayNodes.GetCount(); nIndex++)
                {
                    sdv::toml::CNode node = arrayNodes[nIndex];
                    if (node.GetType() == sdv::toml::ENodeType::node_integer)
                    {
                        m_Counters.push_back(static_cast<uint32_t>(node.GetValue()));
                    }
                }
            }

            sdv::toml::CNodeCollection tableNodes = config.GetDirect("Table");
            if (tableNodes.GetType() == sdv::toml::ENodeType::node_table)
            {
                if (tableNodes.GetCount() >= 3)
                {
                    m_TableA = static_cast<uint32_t>(tableNodes[0].GetValue());
                    m_TableB = static_cast<float>(tableNodes[1].GetValue());
                    m_TableC = static_cast<std::string>(tableNodes[2].GetValue());
                }
            }

            auto table_a = config.GetDirect("Table.a");
            auto table_b = config.GetDirect("Table.b");
            auto table_c = config.GetDirect("Table.c");
            m_DirectTableA = static_cast<uint32_t>(table_a.GetValue());
            m_DirectTableB = static_cast<float>(table_b.GetValue());
            m_DirectTableC = static_cast<std::string>(table_c.GetValue());
        }
        catch (const sdv::toml::XTOMLParseException& e)
        {
            SDV_LOG_ERROR("Parsing error: ", e.what());

            m_status = sdv::EObjectStatus::initialization_failure;
            return;
        }

        PrintAllVariables();

        m_status = sdv::EObjectStatus::initialized;
    };

    /**
    * @brief Gets the current status of the object
    * @return EObjectStatus The current status of the object
    */
    virtual sdv::EObjectStatus GetStatus() const override
    {
        return m_status;
    };

    /**
     * @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
     * @param[in] eMode The operation mode, the component should run in.
     */
    void SetOperationMode(/*in*/ sdv::EOperationMode eMode)
    {
        switch (eMode)
        {
        case sdv::EOperationMode::configuring:
            if (m_status == sdv::EObjectStatus::running || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::configuring;
            break;
        case sdv::EOperationMode::running:
            if (m_status == sdv::EObjectStatus::configuring || m_status == sdv::EObjectStatus::initialized)
                m_status = sdv::EObjectStatus::running;
            break;
        default:
            break;
        }
    }

    /**
    * @brief Shutdown function is to shutdown the execution of periodic task.
    * Timer ID of the task is used to shutdown the specific task.
    */
    virtual void Shutdown() override
    {
        m_status = sdv::EObjectStatus::destruction_pending;
    }

    /**
    * @brief Print all global variables to console
    */
    void PrintAllVariables()
    {
        std::cout << "\nValues parsed during initialization:\n" << std::endl;
        std::cout << "string: " << m_Message.c_str() << std::endl;
        std::cout << "integer: " << std::to_string(m_Id) << std::endl;
        std::cout << "float: " << std::to_string(m_Pi) << std::endl;
        std::cout << "bool: " << std::to_string(m_IsValid) << std::endl;
        std::cout << "table column a: " << std::to_string(m_TableA) << "     " << std::to_string(m_DirectTableA) << std::endl;
        std::cout << "table column b: " << std::to_string(m_TableB) << "     " << std::to_string(m_DirectTableB) << std::endl;
        std::cout << "table column c: " << m_TableC.c_str() << "     " << m_DirectTableC.c_str() << std::endl;
        std::cout << "array: ";
        for (auto counter : m_Counters)
        {
            std::cout << std::to_string(counter) << ", ";
        }
        std::cout << std::endl;
    }

  private:
    std::atomic<sdv::EObjectStatus> m_status = {sdv::EObjectStatus::initialization_pending}; //!< To update the object status when it changes.

    std::string           m_Message = "";
    int32_t               m_Id = -1;
    float                 m_Pi = 0.0;
    bool                  m_IsValid = false;
    std::vector<uint32_t> m_Counters;
    uint32_t              m_TableA = 0;
    float                 m_TableB = 0.0;
    std::string           m_TableC = "";
    uint32_t              m_DirectTableA = 0;
    float                 m_DirectTableB = 0.0;
    std::string           m_DirectTableC = "";
};

DEFINE_SDV_OBJECT(DemoConfigurationComponent)

These are the variables required for the parsing of the example. The example can be found in the code examples.