Change INI file parser library.
authorRomain Forlot <romain.forlot@iot.bzh>
Wed, 19 Apr 2017 16:28:18 +0000 (18:28 +0200)
committerRomain Forlot <romain.forlot@iot.bzh>
Wed, 19 Apr 2017 16:28:18 +0000 (18:28 +0200)
Much simpler but also a bit limitated. Could be change easily in futur if needed

Change-Id: I06f03f093c9206007e3d0c1e86a35d60111be5f8
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
CAN-binder/libs/ini-config/ini-config.cpp [new file with mode: 0644]
CAN-binder/libs/ini-config/ini-config.hpp [new file with mode: 0644]
CAN-binder/libs/inih [deleted submodule]
CAN-binder/low-can-binding/CMakeLists.txt
CAN-binder/low-can-binding/utils/config-parser.cpp
CAN-binder/low-can-binding/utils/config-parser.hpp

diff --git a/CAN-binder/libs/ini-config/ini-config.cpp b/CAN-binder/libs/ini-config/ini-config.cpp
new file mode 100644 (file)
index 0000000..b670e76
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015, 2016 ,2017 "IoT.bzh"
+ * Author "Loïc Collignon" <loic.collignon@iot.bzh>
+ *
+ * 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 "ini-config.hpp"
+
+bool starts_with(const std::string& text, const std::string& token) 
+{
+       if(text.length() < token.length()) return false;
+       return (text.compare(0, token.length(), token) == 0);
+}
+
+void ini_config::read_file(const std::string& filename)
+{
+       std::ifstream f(filename);
+       if (f)
+       {
+               std::regex r_section("^\\s*\\[([^\\]]+)\\]\\s*(#.*)?$");
+               std::regex r_key("^\\s*([^\\s]+)\\s*=\\s*\"([^\"]+)\"\\s*(#.*)?$");
+               std::string current_section;
+               std::string line;
+               while (std::getline(f, line))
+               {
+                       std::smatch mr;
+
+                       switch (qualify(line))
+                       {
+                       case line_type::section:
+                               if (std::regex_match(line, mr, r_section) && mr.size() >= 2 && mr[1].matched)
+                               {
+                                       current_section = mr[1].str();
+                               }
+                               break;
+                       case line_type::key:
+                               if(std::regex_match(line, mr, r_key) && mr.size() >= 2 && mr[1].matched)
+                               {
+                                       std::string key = current_section + '/' + mr[1].str();
+                                       config_[key] = (mr.size() >= 3 && mr[2].matched) ? mr[2].str() : "";
+                               }
+                               break;
+                       }
+               }
+       }
+}
+
+std::map<std::string, std::string> ini_config::get_keys(const std::string& section)
+{
+       std::map<std::string, std::string> ret;
+       
+       std::string prefix = section + '/';
+       for(auto i = config_.begin();
+               i != config_.end();
+               ++i)
+       {
+               if (starts_with(i->first, prefix))
+               {
+                       ret[i->first] = i->second;
+               }
+       }
+       return ret;
+}
+
+std::string ini_config::get_value(const std::string& section, const std::string& key)
+{
+       return config_[section + '/' + key];
+}
+
+ini_config::line_type ini_config::qualify(std::string& line)
+{
+       if (line.size())
+       {
+               for (std::string::value_type c : line)
+               {
+                       if (c == '#') return line_type::ignore;
+                       if (c == '[') return line_type::section;
+                       if (!std::isspace(c, std::locale("C"))) return line_type::key;
+               }
+       }
+       return line_type::ignore;
+}
\ No newline at end of file
diff --git a/CAN-binder/libs/ini-config/ini-config.hpp b/CAN-binder/libs/ini-config/ini-config.hpp
new file mode 100644 (file)
index 0000000..3a15454
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015, 2016 ,2017 "IoT.bzh"
+ * Author "Loïc Collignon" <loic.collignon@iot.bzh>
+ *
+ * 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 INI_CONFIG_HPP
+#define INI_CONFIG_HPP
+
+#include <string>
+#include <fstream>
+#include <map>
+#include <regex>
+#include <algorithm>
+
+// Représente un fichier de configuration.
+class ini_config
+{
+public:
+       using map = std::map<std::string, std::string>;
+
+       void read_file(const std::string& filename);
+
+       map get_keys(const std::string& section);
+       std::string get_value(const std::string& section, const std::string& key);
+
+       typename map::size_type size() const { return config_.size(); }
+       typename map::iterator begin() { return config_.begin(); }
+       typename map::iterator end() { return config_.end(); }
+       typename map::const_iterator cbegin() const { return config_.cbegin(); }
+       typename map::const_iterator cend() const { return config_.cend(); }
+       typename map::reverse_iterator rbegin() { return config_.rbegin(); }
+       typename map::reverse_iterator rend() { return config_.rend(); }
+       typename map::const_reverse_iterator crbegin() const { return config_.crbegin(); }
+       typename map::const_reverse_iterator crend() const { return config_.crend(); }
+
+private:
+       map config_;
+
+       enum class line_type
+       {
+               ignore = 0,
+               section = 1,
+               key = 2
+       };
+
+       line_type qualify(std::string& line);
+};
+
+#endif // INI_CONFIG_HPP
diff --git a/CAN-binder/libs/inih b/CAN-binder/libs/inih
deleted file mode 160000 (submodule)
index 3706abf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 3706abf10c66599695a3f08e460774ffa7f40ef9
index 7359ac7..84abfaf 100644 (file)
@@ -35,12 +35,12 @@ PROJECT_TARGET_ADD(low-can-binding)
 
        # Library dependencies (include updates automatically)
        TARGET_LINK_LIBRARIES(${TARGET_NAME}
+               ini-config
                openxc-message-format
                nanopb
                uds-c
                isotp-c
                bitfield-c
-               inih
                ${link_libraries}
        )
 
index cb344be..dd500d3 100644 (file)
 
 namespace utils
 {
-       /// @brief constructor using a POSIX file handle as input.
-       ///
-       /// @param conf_file - a POSIX file handle to the INI configuration file
-       config_parser_t::config_parser_t(int conf_file)
-               : config_content_(fdopen(conf_file, "r"))
-       {
-               ::close(conf_file);
-       }
-
        /// @brief constructor using path to file
        config_parser_t::config_parser_t(std::string conf_file)
-               : config_content_{INIReader(conf_file)}
-       {}
+               : config_content_{}
+       {
+               config_content_.read_file(conf_file);
+       }
 
        /// @brief read the conf_file_ and parse it into an INIReader object
        /// to search into later.
        bool config_parser_t::check_conf()
        {
-               if (config_content_.ParseError() < 0)
+               if (config_content_.size() <= 0)
                {
                        ERROR(binder_interface, "read_conf: Can't load the INI config file.");
                        return false;
@@ -58,18 +51,10 @@ namespace utils
        {
                std::vector<std::string> devices_name;
 
-               std::set<std::string> sections = config_content_.GetSections();
-               for(const auto& sectionsIt : sections)
+               std::map<std::string, std::string> bus_mapping = config_content_.get_keys("CANbus-mapping");
+               for(const auto& busIt : bus_mapping )
                {
-                       if(sectionsIt == "CANbus-mapping")
-                       {
-                               std::set<std::string> fields = config_content_.GetFields(sectionsIt);
-                               for(const auto& fieldsIt : fields)
-                               {
-                                       std::string val = config_content_.Get(sectionsIt, fieldsIt, "INVALID");
-                                       devices_name.push_back(val);
-                               }       
-                       }
+                       devices_name.push_back(busIt.second);
                }
 
                return devices_name;
index 2d50485..a181d9e 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <string>
 #include <vector>
-#include "INIReader.h"
+#include "ini-config.hpp"
 
 namespace utils
 {
@@ -33,10 +33,9 @@ namespace utils
        class config_parser_t
        {
        private:
-               INIReader config_content_; /*!< config_content_ - Parsed content of INI file.*/
+               ini_config config_content_; /*!< config_content_ - Parsed content of INI file.*/
 
        public:
-               config_parser_t(int conf_file);
                config_parser_t(std::string conf_file);
 
                bool check_conf();