Make class for managing list of vc_engine_info_s 04/286204/1
authorSuyeon Hwang <stom.hwang@samsung.com>
Tue, 6 Dec 2022 07:35:41 +0000 (16:35 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Fri, 30 Dec 2022 04:37:53 +0000 (13:37 +0900)
- Requirement:
g_engine_list is shared memory, so thread safe access for g_engine_list
is needed.

- Contents:
This patch makes new classes for accessing list of vc_engine_info_s
instances. Through this patch, all other functions in this module can
access list of vc_engine_info_s instances in a thread safe way using new
class iinstance introduced by this patch.
This new class will protect each engine information element using mutex,
so the class will assure to prevent race condition.

Change-Id: I455a5effb5076119be220936fd26a27143e72081
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
client/CMakeLists.txt
common/VoiceControlEngineInfo.cpp [new file with mode: 0644]
common/VoiceControlEngineInfo.h [new file with mode: 0644]
common/VoiceControlEngines.cpp [new file with mode: 0644]
common/VoiceControlEngines.h [new file with mode: 0644]
common/vc_config_mgr.cpp
server/CMakeLists.txt

index 4f9c4e2..50149cf 100644 (file)
@@ -8,6 +8,8 @@ SET(SRCS
        ../common/vc_command.c
        ../common/vc_command_util.c
        ../common/vc_config_mgr.cpp
+       ../common/VoiceControlEngines.cpp
+       ../common/VoiceControlEngineInfo.cpp
        ../common/VoiceControlConfig.cpp
        ../common/vc_config_parser.c
        ../common/vc_info_parser.c
@@ -19,6 +21,8 @@ SET(SETTING_SRCS
        vc_setting_proxy.c
        vc_setting.c
        ../common/vc_config_mgr.cpp
+       ../common/VoiceControlEngines.cpp
+       ../common/VoiceControlEngineInfo.cpp
        ../common/VoiceControlConfig.cpp
        ../common/vc_config_parser.c
 )
@@ -33,6 +37,8 @@ SET(WIDGET_SRCS
        ../common/vc_command.c
        ../common/vc_command_util.c
        ../common/vc_config_mgr.cpp
+       ../common/VoiceControlEngines.cpp
+       ../common/VoiceControlEngineInfo.cpp
        ../common/VoiceControlConfig.cpp
        ../common/vc_config_parser.c
        ../common/vc_info_parser.c
@@ -53,6 +59,8 @@ SET(MANAGER_SRCS
        ../common/vc_command.c
        ../common/vc_command_util.c
        ../common/vc_config_mgr.cpp
+       ../common/VoiceControlEngines.cpp
+       ../common/VoiceControlEngineInfo.cpp
        ../common/VoiceControlConfig.cpp
        ../common/vc_config_parser.c
        ../common/vc_info_parser.c
diff --git a/common/VoiceControlEngineInfo.cpp b/common/VoiceControlEngineInfo.cpp
new file mode 100644 (file)
index 0000000..2968704
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+*  Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+*  Licensed under the Apache License, Version 2.0 (the "License");
+*  you may not use this file except in compliance with the License.
+*  You may obtain a copy of the License at
+*  http://www.apache.org/licenses/LICENSE-2.0
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+
+
+#include <stdexcept>
+#include <dlog.h>
+
+#include "vc_main.h"
+
+#include "VoiceControlEngineInfo.h"
+
+
+using namespace std;
+
+VoiceControlEngineInfo::VoiceControlEngineInfo(const std::string filePath)
+{
+       SLOG(LOG_INFO, TAG_VCCONFIG, "[Constructor] VoiceControlEngineInfo");
+
+       vc_engine_info_s *engine_info = nullptr;
+       if (0 != vc_parser_get_engine_info(filePath.c_str(), &engine_info) || engine_info == nullptr) {
+               SLOG(LOG_DEBUG, TAG_VCCONFIG, "Fail to get engine info from path (%s)", filePath.c_str());
+               throw runtime_error("operation failed");
+       }
+
+       if (engine_info->name) {
+               __engineName = engine_info->name;
+       }
+       if (engine_info->uuid) {
+               __engineId = engine_info->uuid;
+       }
+       if (engine_info->setting) {
+               __settingPath = engine_info->setting;
+       }
+       if (engine_info->default_lang) {
+               __defaultLanguage = engine_info->default_lang;
+       }
+       __nonFixedSupported = engine_info->non_fixed_support;
+
+       GSList *iter = g_slist_nth(engine_info->languages, 0);
+       while (nullptr != iter) {
+               const char *language = static_cast<const char *>(iter->data);
+               if (language != nullptr) {
+                       __supportedLanguages.push_back(language);
+               }
+
+               iter = g_slist_next(iter);
+       }
+
+       vc_parser_free_engine_info(engine_info);
+}
+
+VoiceControlEngineInfo::~VoiceControlEngineInfo()
+{
+       SLOG(LOG_INFO, TAG_VCCONFIG, "[Destructor] VoiceControlEngineInfo");
+}
+
+void VoiceControlEngineInfo::printOutEngine()
+{
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, " name             : %s", __engineName.c_str());
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, " id               : %s", __engineId.c_str());
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, " setting          : %s", __settingPath.c_str());
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, " default language : %s", __defaultLanguage.c_str());
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, " languages        :");
+
+       if (__supportedLanguages.size() == 0) {
+               SLOG(LOG_DEBUG, TAG_VCCONFIG, "    language is NONE");
+       } else {
+               unsigned int index = 1;
+               for (auto language : __supportedLanguages) {
+                       SLOG(LOG_DEBUG, TAG_VCCONFIG, "    [%uth] %s", index, language.c_str());
+                       index++;
+               }
+       }
+}
+
+bool VoiceControlEngineInfo::isLanguageValid(const std::string language)
+{
+       for (auto supportedLanguage : __supportedLanguages) {
+               SLOG(LOG_DEBUG, TAG_VCCONFIG, "Compare language(%s), Target(%s)", supportedLanguage.c_str(), language.c_str());
+               if (0 == supportedLanguage.compare(language)) {
+                       SLOG(LOG_INFO, TAG_VCCONFIG, "Language(%s) is valid", language.c_str());
+                       return true;
+               }
+       }
+
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Language(%s) is not valid", language.c_str());
+       return false;
+}
+
+std::string VoiceControlEngineInfo::getEngineName()
+{
+       return __engineName;
+}
+
+std::string VoiceControlEngineInfo::getEngineId()
+{
+       return __engineId;
+}
+
+std::string VoiceControlEngineInfo::getSettingPath()
+{
+       return __settingPath;
+}
+
+std::string VoiceControlEngineInfo::getDefaultLanguage()
+{
+       return __defaultLanguage;
+}
+
+std::vector<std::string> VoiceControlEngineInfo::getSupportedLanguages()
+{
+       return __supportedLanguages;
+}
+
+bool VoiceControlEngineInfo::isNonFixedSupported()
+{
+       return __nonFixedSupported;
+}
+
diff --git a/common/VoiceControlEngineInfo.h b/common/VoiceControlEngineInfo.h
new file mode 100644 (file)
index 0000000..910af97
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+*  Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+*  Licensed under the Apache License, Version 2.0 (the "License");
+*  you may not use this file except in compliance with the License.
+*  You may obtain a copy of the License at
+*  http://www.apache.org/licenses/LICENSE-2.0
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+
+
+#ifndef __VC_COMMON_VOICE_CONTROL_ENGINE_INFO_H_
+#define __VC_COMMON_VOICE_CONTROL_ENGINE_INFO_H_
+
+#include <vector>
+#include <string>
+#include <mutex>
+
+#include "vc_config_parser.h"
+
+class VoiceControlEngineInfo {
+public:
+       VoiceControlEngineInfo(const std::string filePath);
+       virtual ~VoiceControlEngineInfo();
+
+       void printOutEngine();
+
+       bool isLanguageValid(const std::string language);
+       std::string getEngineName();
+       std::string getEngineId();
+       std::string getSettingPath();
+       std::string getDefaultLanguage();
+       std::vector<std::string> getSupportedLanguages();
+       bool isNonFixedSupported();
+
+private:
+       std::string __engineName;
+       std::string __engineId;
+       std::string __settingPath;
+       std::string __defaultLanguage;
+       std::vector<std::string> __supportedLanguages;
+       bool __nonFixedSupported;
+};
+
+
+#endif /* __VC_COMMON_VOICE_CONTROL_ENGINE_INFO_H_ */
diff --git a/common/VoiceControlEngines.cpp b/common/VoiceControlEngines.cpp
new file mode 100644 (file)
index 0000000..3143d0c
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+*  Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+*  Licensed under the Apache License, Version 2.0 (the "License");
+*  you may not use this file except in compliance with the License.
+*  You may obtain a copy of the License at
+*  http://www.apache.org/licenses/LICENSE-2.0
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+
+
+#include "vc_main.h"
+
+#include "VoiceControlEngines.h"
+
+using namespace std;
+
+VoiceControlEngines::VoiceControlEngines()
+{
+       SLOG(LOG_INFO, TAG_VCCONFIG, "[Constructor] VoiceControlEngines");
+}
+
+VoiceControlEngines::~VoiceControlEngines()
+{
+       SLOG(LOG_INFO, TAG_VCCONFIG, "[Destructor] VoiceControlEngines");
+}
+
+void VoiceControlEngines::printOutEngineInfo()
+{
+       unique_lock<mutex> lock(__enginesMutex);
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, "@ Engine list @");
+
+       if (0 == __engines.size()) {
+               SLOG(LOG_DEBUG, TAG_VCCONFIG, "  No Engine in engine directory");
+       } else {
+               unsigned int index = 0;
+               for (auto engineInfo : __engines) {
+                       SLOG(LOG_DEBUG, TAG_VCCONFIG, "[%uth]", index);
+                       engineInfo.printOutEngine();
+               }
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, "@@@@");
+}
+
+void VoiceControlEngines::appendEngine(const std::string path)
+{
+       unique_lock<mutex> lock(__enginesMutex);
+
+       try {
+               VoiceControlEngineInfo engineInfo(path);
+               __engines.push_back(engineInfo);
+       } catch (runtime_error &error) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] Fail to append engine info from path(%s)", path.c_str());
+               throw error;
+       }
+}
+
+bool VoiceControlEngines::isEngineIdValid(const std::string engineId)
+{
+       if (engineId.empty()) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] Engine ID is NULL");
+               return false;
+       }
+
+       unique_lock<mutex> lock(__enginesMutex);
+       bool isValid = (nullptr != findEngine(engineId));
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Engine Id(%s) is %svalid", engineId.c_str(), (isValid ? "" : "not "));
+       return isValid;
+}
+
+std::shared_ptr<VoiceControlEngineInfo> VoiceControlEngines::getEngineInfo(const std::string engineId)
+{
+       if (engineId.empty()) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] Engine ID is NULL");
+               return nullptr;
+       }
+
+       unique_lock<mutex> lock(__enginesMutex);
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Get engine info with ID(%s)", engineId.c_str());
+       auto engineInfo = findEngine(engineId);
+       if (engineInfo == nullptr) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] Fail to found engine info");
+               return nullptr;
+       }
+
+       return make_shared<VoiceControlEngineInfo>(*engineInfo);
+}
+
+std::shared_ptr<VoiceControlEngineInfo> VoiceControlEngines::getFirstEngineInfo()
+{
+       unique_lock<mutex> lock(__enginesMutex);
+       if (__engines.size() == 0) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] There is no engine");
+               return nullptr;
+       }
+
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Get first engine info. size(%u)", __engines.size());
+       return make_shared<VoiceControlEngineInfo>(__engines[0]);
+}
+
+VoiceControlEngineInfo *VoiceControlEngines::findEngine(const std::string engineId)
+{
+       if (engineId.empty()) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] Engine ID is NULL");
+               return nullptr;
+       }
+
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Find engine ID (%s)", engineId.c_str());
+       for (auto &engineInfo : __engines) {
+               if (0 == engineInfo.getEngineId().compare(engineId)) {
+                       SLOG(LOG_INFO, TAG_VCCONFIG, "Success to find engine (%s)", engineId.c_str());
+                       return &engineInfo;
+               }
+       }
+
+       SLOG(LOG_ERROR, TAG_VCCONFIG, "There is no engine (%s)", engineId.c_str());
+       return nullptr;
+}
+
+std::vector<VoiceControlEngineInfo> VoiceControlEngines::getEngines()
+{
+       unique_lock<mutex> lock(__enginesMutex);
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Get engines. size(%u)", __engines.size());
+       return __engines;
+}
+
+bool VoiceControlEngines::isEngineEmpty()
+{
+       unique_lock<mutex> lock(__enginesMutex);
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Length of engines (%u)", __engines.size());
+       return __engines.empty();
+}
+
diff --git a/common/VoiceControlEngines.h b/common/VoiceControlEngines.h
new file mode 100644 (file)
index 0000000..ae436a5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+*  Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+*  Licensed under the Apache License, Version 2.0 (the "License");
+*  you may not use this file except in compliance with the License.
+*  You may obtain a copy of the License at
+*  http://www.apache.org/licenses/LICENSE-2.0
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+
+
+#ifndef __VC_COMMON_VOICE_CONTROL_ENGINES_H_
+#define __VC_COMMON_VOICE_CONTROL_ENGINES_H_
+
+#include <vector>
+#include <string>
+#include <mutex>
+#include <memory>
+
+#include "VoiceControlEngineInfo.h"
+
+class VoiceControlEngines {
+public:
+       VoiceControlEngines();
+       virtual ~VoiceControlEngines();
+
+       void printOutEngineInfo();
+
+       void appendEngine(const std::string path);
+
+       bool isEngineIdValid(const std::string engineId);
+       std::shared_ptr<VoiceControlEngineInfo> getEngineInfo(const std::string engineId);
+       std::shared_ptr<VoiceControlEngineInfo> getFirstEngineInfo();
+       std::vector<VoiceControlEngineInfo> getEngines();
+       bool isEngineEmpty();
+
+private:
+       VoiceControlEngineInfo *findEngine(const std::string engineId);
+
+       std::vector<VoiceControlEngineInfo> __engines;
+       std::mutex __enginesMutex;
+};
+
+
+#endif /* __VC_COMMON_VOICE_CONTROL_ENGINES_H_ */
index 2f7940c..60aed36 100644 (file)
@@ -31,6 +31,7 @@
 #include <string>
 
 #include "VoiceControlConfig.h"
+#include "VoiceControlEngines.h"
 
 #include "vc_config_mgr.h"
 #include "vc_config_parser.h"
@@ -78,7 +79,7 @@ static const char* vc_config_tag()
 
 static atomic<bool> g_config_mgr_initialized(false);
 
-static GSList* g_engine_list = NULL;
+static VoiceControlEngines *g_VoiceControlEngines = nullptr;
 
 static GSList* g_config_client_list = NULL;
 
@@ -98,7 +99,6 @@ static int __vc_config_mgr_register_engine_config_updated_event(const char* path
 static int __vc_config_mgr_unregister_engine_config_updated_event();
 static int __vc_config_mgr_set_default_language(const char* language);
 
-int __vc_config_mgr_print_engine_info();
 int __vc_config_mgr_print_client_info();
 
 static gint __compare_uid_in_client_list(gconstpointer a, gconstpointer b)
@@ -132,57 +132,6 @@ static vc_config_client_s *__find_client_info(unsigned int uid)
        return result;
 }
 
-static gint __compare_engine_id_in_engine_list(gconstpointer a, gconstpointer b)
-{
-       const vc_engine_info_s *engine_info = static_cast<const vc_engine_info_s *>(a);
-       const char *engine_id = static_cast<const char *>(b);
-
-       if (NULL == engine_id) {
-               return 1;
-       }
-
-       if (NULL == engine_info || NULL == engine_info->uuid) {
-               return 1;
-       }
-
-       SLOG(LOG_DEBUG, vc_config_tag(), "Compare engine(%s). Target(%s)", engine_info->uuid, engine_id);
-       return strcmp(engine_info->uuid, engine_id);
-}
-
-static vc_engine_info_s *__find_engine_info(const char *engine_id)
-{
-       GSList *target = g_slist_find_custom(g_engine_list,     engine_id, __compare_engine_id_in_engine_list);
-       vc_engine_info_s *result = NULL;
-       if (NULL != target) {
-               result = static_cast<vc_engine_info_s *>(target->data);
-       }
-
-       return result;
-}
-
-static gint __compare_language_in_languages_of_engine_info(gconstpointer a, gconstpointer b)
-{
-       const char *language = static_cast<const char *>(a);
-       const char *target_language = static_cast<const char *>(b);
-
-       if (NULL == language || NULL == target_language) {
-               return 1;
-       }
-
-       SLOG(LOG_DEBUG, vc_config_tag(), "Compare langauge(%s), Target(%s)", language, target_language);
-       return strcmp(language, target_language);
-}
-
-static bool __is_language_valid(vc_engine_info_s *engine_info, const char *language)
-{
-       if (NULL == engine_info || NULL == language) {
-               return false;
-       }
-
-       GSList *target = g_slist_find_custom(engine_info->languages, language, __compare_language_in_languages_of_engine_info);
-       return (NULL != target);
-}
-
 static void __invoke_lang_cb_in_client_list(gpointer data, gpointer user_data)
 {
        vc_config_client_s* client_info = (vc_config_client_s*)data;
@@ -298,39 +247,24 @@ int __vc_config_mgr_check_and_set_default_engine_id(const char* engine_id)
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       if (0 >= g_slist_length(g_engine_list)) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine!!");
-               return VC_CONFIG_ERROR_OPERATION_FAILED;
-       }
-
-       if (NULL != __find_engine_info(engine_id)) {
+       if (g_VoiceControlEngines->isEngineIdValid(engine_id)) {
                SLOG(LOG_DEBUG, vc_config_tag(), "Default engine is valid : %s", engine_id);
                return VC_CONFIG_ERROR_NONE;
        }
 
-       GSList *iter = g_slist_nth(g_engine_list, 0);
-       if (NULL == iter) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No engine in list");
-               return -1;
-       }
-
-       vc_engine_info_s *engine_info = static_cast<vc_engine_info_s *>(iter->data);
-       if (NULL == engine_info) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine info is NULL");
-               return -1;
-       }
-
-       if (NULL == engine_info->uuid) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine id is NULL");
-               return -1;
+       shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getFirstEngineInfo();
+       if (nullptr == engineInfo || engineInfo->getEngineId().empty()) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid engine!!");
+               return VC_CONFIG_ERROR_OPERATION_FAILED;
        }
 
-       SLOG(LOG_DEBUG, vc_config_tag(), "Default engine is changed : %s", engine_info->uuid);
-       if (0 != vc_parser_set_engine(engine_info->uuid)) {
+       string engineId = engineInfo->getEngineId();
+       SLOG(LOG_DEBUG, vc_config_tag(), "Default engine is changed : %s", engineId.c_str());
+       if (0 != vc_parser_set_engine(engineId.c_str())) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save config");
                return -1;
        }
-       g_VoiceControlConfig->setEngineId(engine_info->uuid);
+       g_VoiceControlConfig->setEngineId(engineId.c_str());
 
        return VC_ERROR_NONE;
 }
@@ -342,18 +276,13 @@ bool __vc_config_mgr_check_lang_is_valid(const char* engine_id, const char* lang
                return false;
        }
 
-       if (0 >= g_slist_length(g_engine_list)) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine!!");
-               return false;
-       }
-
-       vc_engine_info_s *engine_info = __find_engine_info(engine_id);
-       if (NULL == engine_info) {
+       shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(engine_id);
+       if (nullptr == engineInfo) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", engine_id);
                return false;
        }
 
-       bool is_language_valid = __is_language_valid(engine_info, language);
+       bool is_language_valid = engineInfo->isLanguageValid(language);
        SLOG(LOG_INFO, vc_config_tag(), "[INFO] Language(%s), is valid(%d)", language, (int)is_language_valid);
 
        return is_language_valid;
@@ -366,23 +295,23 @@ int __vc_config_mgr_select_lang(const char* engine_id, char** language)
                return VC_ERROR_OPERATION_FAILED;
        }
 
-       if (0 >= g_slist_length(g_engine_list)) {
+       if (g_VoiceControlEngines->isEngineEmpty()) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine!!");
                return VC_ERROR_OPERATION_FAILED;
        }
 
-       vc_engine_info_s *engine_info = __find_engine_info(engine_id);
-       if (NULL == engine_info) {
+       shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(engine_id);
+       if (nullptr == engineInfo) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", engine_id);
                return VC_ERROR_INVALID_PARAMETER;
        }
 
-       if (NULL == engine_info->default_lang) {
+       if (engineInfo->getDefaultLanguage().empty()) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] default language of engine info is NULL");
                return VC_CONFIG_ERROR_INVALID_LANGUAGE;
        }
 
-       *language = strdup(engine_info->default_lang);
+       *language = strdup(engineInfo->getDefaultLanguage().c_str());
        if (NULL == *language) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory");
                return VC_CONFIG_ERROR_OUT_OF_MEMORY;
@@ -408,29 +337,8 @@ int __vc_config_release_client(unsigned int uid)
 
 void __vc_config_release_engine()
 {
-       GSList *iter = NULL;
-       vc_engine_info_s *engine_info = NULL;
-
-       if (0 < g_slist_length(g_engine_list)) {
-
-               /* Get a first item */
-               iter = g_slist_nth(g_engine_list, 0);
-
-               while (NULL != iter) {
-                       engine_info = static_cast<vc_engine_info_s *>(iter->data);
-
-                       if (NULL != engine_info) {
-                               g_engine_list = g_slist_remove(g_engine_list, engine_info);
-
-                               vc_parser_free_engine_info(engine_info);
-                       }
-
-                       iter = g_slist_nth(g_engine_list, 0);
-               }
-       }
-
-       g_slist_free(g_engine_list);
-       g_engine_list = nullptr;
+       delete g_VoiceControlEngines;
+       g_VoiceControlEngines = nullptr;
 }
 
 int __vc_config_mgr_get_engine_info()
@@ -440,12 +348,17 @@ int __vc_config_mgr_get_engine_info()
 
        char filepath[512] = {'\0',};
        int filesize;
-       vc_engine_info_s* info = NULL;
 
        SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] Release engine and Unregister engine config");
 
        __vc_config_release_engine();
-       g_engine_list = NULL;
+
+       g_VoiceControlEngines = new(nothrow) VoiceControlEngines();
+       if (g_VoiceControlEngines == nullptr) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate VoiceControlEngines");
+               return VC_CONFIG_ERROR_OUT_OF_MEMORY;
+       }
+
        __vc_config_mgr_unregister_engine_config_updated_event();
 
        SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] default directory : %s", VC_DEFAULT_ENGINE_INFO);
@@ -512,11 +425,13 @@ int __vc_config_mgr_get_engine_info()
 
                                SECURE_SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] Filepath(%s)", filepath);
 
-                               if (0 == vc_parser_get_engine_info(filepath, &info)) {
-                                       g_engine_list = g_slist_append(g_engine_list, info);
+                               try {
+                                       g_VoiceControlEngines->appendEngine(filepath);
                                        if (0 != __vc_config_mgr_register_engine_config_updated_event(filepath)) {
                                                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to register engine config updated event");
                                        }
+                               } catch (exception &error) {
+                                       SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get engine info from filepath(%s). (%s)", filepath, error.what());
                                }
                        }
                } while (NULL != dirp);
@@ -524,7 +439,7 @@ int __vc_config_mgr_get_engine_info()
                closedir(dp);
        }
 
-       if (0 >= g_slist_length(g_engine_list)) {
+       if (g_VoiceControlEngines->isEngineEmpty()) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No engine");
                return -1;
        }
@@ -559,7 +474,8 @@ static Eina_Bool __vc_config_mgr_engine_config_inotify_event_callback(void* data
                if (0 != ret) {
                        SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get engine info when config updated");
                }
-               __vc_config_mgr_print_engine_info();
+
+               g_VoiceControlEngines->printOutEngineInfo();
                string default_language = g_VoiceControlConfig->getCurrentLanguage();
                bool is_language_valid = vc_config_check_default_language_is_valid(default_language.c_str());
                if (false == is_language_valid) {
@@ -838,8 +754,6 @@ static int __initialize_vc_config_mgr()
        }
 
        /* Get file name from default engine directory */
-       __vc_config_release_engine();
-
        if (0 != access(VC_CONFIG_BASE, F_OK)) {
                if (0 != mkdir(VC_CONFIG_BASE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
                        SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to make directory : %s", VC_CONFIG_BASE);
@@ -880,7 +794,7 @@ static int __initialize_vc_config_mgr()
                return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
        }
 
-       __vc_config_mgr_print_engine_info();
+       g_VoiceControlEngines->printOutEngineInfo();
 
        if (0 != __initialize_config_info()) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse configure information");
@@ -1285,31 +1199,24 @@ int vc_config_mgr_get_engine_list(vc_config_supported_engine_cb callback, void*
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       GSList *iter = NULL;
-       vc_engine_info_s *engine_info = NULL;
-
-       if (0 >= g_slist_length(g_engine_list)) {
+       if (g_VoiceControlEngines->isEngineEmpty()) {
                SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Engine list is NULL");
                pthread_mutex_unlock(&vc_config_mgr_mutex);
                return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
        }
 
-       /* Get a first item */
-       iter = g_slist_nth(g_engine_list, 0);
-
-       while (NULL != iter) {
-               engine_info = static_cast<vc_engine_info_s *>(iter->data);
-
-               if (NULL == engine_info) {
-                       SLOG(LOG_ERROR, vc_config_tag(), " Engine info is NULL");
-                       pthread_mutex_unlock(&vc_config_mgr_mutex);
-                       return VC_CONFIG_ERROR_OPERATION_FAILED;
+       auto engines = g_VoiceControlEngines->getEngines();
+       for (auto &engineInfo : engines) {
+               if (false == g_VoiceControlEngines->isEngineIdValid(engineInfo.getEngineId())) {
+                       SLOG(LOG_WARN, vc_config_tag(), "Engine info is not valid. (%s)", engineInfo.getEngineId().c_str());
+                       continue;
                }
 
-               if (false == callback(engine_info->name, engine_info->uuid, engine_info->setting, engine_info->default_lang, engine_info->non_fixed_support, user_data))
+               if (false == callback(engineInfo.getEngineName().c_str(), engineInfo.getEngineId().c_str(), engineInfo.getSettingPath().c_str(),
+                               engineInfo.getDefaultLanguage().c_str(), engineInfo.isNonFixedSupported(), user_data)) {
+                       SLOG(LOG_DEBUG, vc_config_tag(), "Callback returns false. (%s)", engineInfo.getEngineId().c_str());
                        break;
-
-               iter = g_slist_next(iter);
+               }
        }
 
        pthread_mutex_unlock(&vc_config_mgr_mutex);
@@ -1417,7 +1324,6 @@ int vc_config_mgr_set_engine(const char* engine)
        /* Check current engine id with new engine id */
        string default_engine_id = g_VoiceControlConfig->getEngineId();
        if (0 == default_engine_id.compare(engine)) {
-               SLOG(LOG_DEBUG, vc_config_tag(), "Engine is not changed : %s", engine);
                pthread_mutex_unlock(&vc_config_mgr_mutex);
                return VC_CONFIG_ERROR_NONE;
        }
@@ -1431,8 +1337,8 @@ int vc_config_mgr_set_engine(const char* engine)
                return ret;
        }
 
-       vc_engine_info_s *engine_info = __find_engine_info(engine);
-       if (NULL == engine_info) {
+       shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(engine);
+       if (nullptr == engineInfo) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", engine);
                pthread_mutex_unlock(&vc_config_mgr_mutex);
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
@@ -1447,20 +1353,18 @@ int vc_config_mgr_set_engine(const char* engine)
 
        /* Engine is valid*/
        string default_language = g_VoiceControlConfig->getCurrentLanguage();
-       bool is_language_valid = __is_language_valid(engine_info, default_language.c_str());
+       bool is_language_valid = engineInfo->isLanguageValid(default_language);
        SLOG(LOG_ERROR, vc_config_tag(), "[INFO] Language(%s), is valid(%d)", default_language.c_str(), (int)is_language_valid);
 
-       char* lang = NULL;
        if (false == is_language_valid) {
-               GSList *iter_lang = g_slist_nth(engine_info->languages, 0);
-               if (NULL == iter_lang || NULL == iter_lang->data) {
+               auto languages = engineInfo->getSupportedLanguages();
+               if (languages.empty()) {
                        SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get default language. Engine id(%s) is not valid", engine);
                        pthread_mutex_unlock(&vc_config_mgr_mutex);
                        return VC_CONFIG_ERROR_OPERATION_FAILED;
                }
 
-               lang = static_cast<char *>(iter_lang->data);
-               g_VoiceControlConfig->setCurrentLanguage(lang);
+               g_VoiceControlConfig->setCurrentLanguage(languages[0].c_str());
        }
 
        SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Engine changed");
@@ -1479,35 +1383,39 @@ int vc_config_mgr_get_language_list(vc_supported_language_cb callback, void* use
                return -1;
        }
 
-       if (0 >= g_slist_length(g_engine_list)) {
+       if (nullptr == callback) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Callback is null");
+               pthread_mutex_unlock(&vc_config_mgr_mutex);
+               return VC_CONFIG_ERROR_INVALID_PARAMETER;
+       }
+
+       if (g_VoiceControlEngines->isEngineEmpty()) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine");
                pthread_mutex_unlock(&vc_config_mgr_mutex);
                return -1;
        }
 
        string default_engine_id = g_VoiceControlConfig->getEngineId();
-       vc_engine_info_s *engine_info = __find_engine_info(default_engine_id.c_str());
-       if (NULL == engine_info) {
+       shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(default_engine_id);
+       if (nullptr == engineInfo) {
                SLOG(LOG_ERROR, vc_config_tag(), "Fail to find engine information : %s", default_engine_id.c_str());
                pthread_mutex_unlock(&vc_config_mgr_mutex);
                return VC_CONFIG_ERROR_NONE;
        }
 
        /* Get a first item */
-       GSList *iter_lang = g_slist_nth(engine_info->languages, 0);
-
-       while (NULL != iter_lang) {
-               /*Get handle data from list*/
-               char* lang = static_cast<char *>(iter_lang->data);
-
-               SLOG(LOG_INFO, vc_config_tag(), "lang(%s)", lang);
-               if (NULL != lang) {
-                       if (false == callback(lang, user_data))
-                               break;
+       auto languages = engineInfo->getSupportedLanguages();
+       for (auto &language : languages) {
+               SLOG(LOG_INFO, vc_config_tag(), "language (%s)", language.c_str());
+               if (language.empty()) {
+                       SLOG(LOG_WARN, vc_config_tag(), "Language is not valid");
+                       continue;
                }
 
-               /*Get next item*/
-               iter_lang = g_slist_next(iter_lang);
+               if (false == callback(language.c_str(), user_data)) {
+                       SLOG(LOG_DEBUG, vc_config_tag(), "Callback returns false (%s)", language.c_str());
+                       break;
+               }
        }
 
        pthread_mutex_unlock(&vc_config_mgr_mutex);
@@ -1632,21 +1540,15 @@ int vc_config_mgr_get_nonfixed_support(bool* value)
                return -1;
        }
 
-       if (0 >= g_slist_length(g_engine_list)) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine");
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
-               return -1;
-       }
-
        string default_engine_id = g_VoiceControlConfig->getEngineId();
-       vc_engine_info_s *engine_info = __find_engine_info(default_engine_id.c_str());
-       if (NULL == engine_info) {
+       shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(default_engine_id);
+       if (nullptr == engineInfo) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", default_engine_id.c_str());
                pthread_mutex_unlock(&vc_config_mgr_mutex);
                return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
        };
 
-       *value = engine_info->non_fixed_support;
+       *value = engineInfo->isNonFixedSupported();
 
        pthread_mutex_unlock(&vc_config_mgr_mutex);
        return VC_ERROR_NONE;
@@ -1666,18 +1568,9 @@ bool vc_config_check_default_engine_is_valid(const char* engine)
                return false;
        }
 
-       if (0 >= g_slist_length(g_engine_list)) {
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
-               return false;
-       }
-
-       vc_engine_info_s *engine_info = __find_engine_info(engine);
-       if (NULL == engine_info) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", engine);
-       };
-
+       bool is_valid = g_VoiceControlEngines->isEngineIdValid(engine);
        pthread_mutex_unlock(&vc_config_mgr_mutex);
-       return (NULL != engine_info);
+       return is_valid;
 }
 
 bool vc_config_check_default_language_is_valid(const char* language)
@@ -1691,19 +1584,14 @@ bool vc_config_check_default_language_is_valid(const char* language)
                return false;
        }
 
-       if (0 >= g_slist_length(g_engine_list)) {
-               return false;
-       }
-
-
        string default_engine_id = g_VoiceControlConfig->getEngineId();
-       vc_engine_info_s *engine_info = __find_engine_info(default_engine_id.c_str());
-       if (NULL == engine_info) {
+       shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(default_engine_id);
+       if (nullptr == engineInfo) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", default_engine_id.c_str());
                return false;
        };
 
-       bool is_language_valid = __is_language_valid(engine_info, language);
+       bool is_language_valid = engineInfo->isLanguageValid(language);
        SLOG(LOG_INFO, vc_config_tag(), "[INFO] Language(%s), is valid(%d)", language, (int)is_language_valid);
 
        return is_language_valid;
@@ -1735,61 +1623,6 @@ int vc_config_mgr_get_foreground(int* pid)
        return vc_parser_get_foreground(pid);
 }
 
-int __vc_config_mgr_print_engine_info()
-{
-       GSList *iter = NULL;
-       vc_engine_info_s *engine_info = NULL;
-
-       if (0 >= g_slist_length(g_engine_list)) {
-               SLOG(LOG_DEBUG, vc_config_tag(), "@ engine list @");
-               SLOG(LOG_DEBUG, vc_config_tag(), "  No Engine in engine directory");
-               SLOG(LOG_DEBUG, vc_config_tag(), "@@@@");
-               return VC_ERROR_NONE;
-       }
-
-       /* Get a first item */
-       iter = g_slist_nth(g_engine_list, 0);
-
-       SLOG(LOG_DEBUG, vc_config_tag(), "@ engine list @");
-
-       int i = 1;
-       while (NULL != iter) {
-               engine_info = static_cast<vc_engine_info_s *>(iter->data);
-
-               SLOG(LOG_DEBUG, vc_config_tag(), "[%dth]", i);
-               SLOG(LOG_DEBUG, vc_config_tag(), " name : %s", engine_info->name);
-               SLOG(LOG_DEBUG, vc_config_tag(), " id   : %s", engine_info->uuid);
-
-
-               SLOG(LOG_DEBUG, vc_config_tag(), " languages");
-               GSList *iter_lang = NULL;
-               char* lang;
-               if (g_slist_length(engine_info->languages) > 0) {
-                       /* Get a first item */
-                       iter_lang = g_slist_nth(engine_info->languages, 0);
-
-                       int j = 1;
-                       while (NULL != iter_lang) {
-                               /*Get handle data from list*/
-                               lang = static_cast<char *>(iter_lang->data);
-
-                               SLOG(LOG_DEBUG, vc_config_tag(), "  [%dth] %s", j, lang);
-
-                               /*Get next item*/
-                               iter_lang = g_slist_next(iter_lang);
-                               j++;
-                       }
-               } else {
-                       SLOG(LOG_DEBUG, vc_config_tag(), "  language is NONE");
-               }
-               iter = g_slist_next(iter);
-               i++;
-       }
-       SLOG(LOG_DEBUG, vc_config_tag(), "@@@@");
-
-       return VC_ERROR_NONE;
-}
-
 int __vc_config_mgr_print_client_info()
 {
        GSList *iter = NULL;
index 69608e3..11b6213 100644 (file)
@@ -4,6 +4,8 @@ SET(SRCS
        ../common/vc_command.c
        ../common/vc_config_mgr.cpp
        ../common/VoiceControlConfig.cpp
+       ../common/VoiceControlEngines.cpp
+       ../common/VoiceControlEngineInfo.cpp
        ../common/vc_config_parser.c
        ../common/vc_info_parser.c
        ../common/vc_json_parser.c