From f03fa158116cfd65659d14698c91446dc9bdb4c4 Mon Sep 17 00:00:00 2001
From: imarom <imarom@cisco.com>
Date: Mon, 27 Jun 2016 17:15:05 +0300
Subject: draft #3 of client config

---
 src/utl_yaml.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 61 insertions(+), 8 deletions(-)

(limited to 'src/utl_yaml.cpp')

diff --git a/src/utl_yaml.cpp b/src/utl_yaml.cpp
index 828817e4..bf30d661 100755
--- a/src/utl_yaml.cpp
+++ b/src/utl_yaml.cpp
@@ -21,7 +21,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-
+#include <istream>
 
 #define INADDRSZ 4
 
@@ -65,8 +65,8 @@ static int my_inet_pton4(const char *src, unsigned char *dst)
 
 
 bool utl_yaml_read_ip_addr(const YAML::Node& node, 
-                         std::string name,
-                         uint32_t & val){
+                           const std::string &name,
+                           uint32_t & val){
     std::string tmp;
     uint32_t ip;
     bool res=false;
@@ -83,8 +83,61 @@ bool utl_yaml_read_ip_addr(const YAML::Node& node,
     return (res);
 }
 
+static void
+split_str_by_delimiter(std::string str, char delim, std::vector<std::string> &tokens) {
+    size_t pos = 0;
+    std::string token;
+
+    while ((pos = str.find(delim)) != std::string::npos) {
+        token = str.substr(0, pos);
+        tokens.push_back(token);
+        str.erase(0, pos + 1);
+    }
+
+    if (str.size() > 0) {
+        tokens.push_back(str);
+    }
+}
+
+bool utl_yaml_read_mac_addr(const YAML::Node &node,
+                            const std::string &name,
+                            uint64_t &val) {
+
+    std::string mac_str;
+
+    if (!node.FindValue(name)) {
+        return false;
+    }
+
+    node[name] >> mac_str;
+
+    std::vector<std::string> tokens;
+    split_str_by_delimiter(mac_str, ':', tokens);
+
+    if (tokens.size() != 6) {
+        throw YAML::InvalidScalar(node[name].GetMark());
+    }
+
+    val = 0;
+
+    for (int i = 0; i < 6 ; i++) {
+        char *endptr = NULL;
+        unsigned long octet = strtoul(tokens[i].c_str(), &endptr, 16);
+
+        if ( (*endptr != 0) || (octet > 0xff) ) {
+            throw YAML::InvalidScalar(node[name].GetMark());
+        }
+
+        //mac_addr[i] = (uint8_t)octet;
+        val = (val << 8) + octet;
+    }   
+                  
+    return true;
+}
+
+
 bool utl_yaml_read_uint32(const YAML::Node& node, 
-                          std::string name,
+                          const std::string &name,
                           uint32_t & val){
     bool res=false;
     if ( node.FindValue(name) ) {
@@ -95,8 +148,8 @@ bool utl_yaml_read_uint32(const YAML::Node& node,
 }
 
 bool utl_yaml_read_uint16(const YAML::Node& node, 
-                       std::string name,
-                       uint16_t & val){
+                          const std::string &name,
+                          uint16_t & val){
     uint32_t val_tmp;
     bool res=false;
     if ( node.FindValue(name) ) {
@@ -109,8 +162,8 @@ bool utl_yaml_read_uint16(const YAML::Node& node,
 }
 
 bool utl_yaml_read_bool(const YAML::Node& node, 
-                       std::string name,
-                       bool & val){
+                        const std::string &name,
+                        bool & val){
     bool res=false;
     if ( node.FindValue(name) ) {
         node[name] >> val ;
-- 
cgit 


From 1dfd42ceb79677e171d5dedcac34900776574000 Mon Sep 17 00:00:00 2001
From: imarom <imarom@cisco.com>
Date: Wed, 29 Jun 2016 10:35:54 +0300
Subject: added enhanced parsing for the YAML wrapper module

---
 src/utl_yaml.cpp | 225 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 181 insertions(+), 44 deletions(-)

(limited to 'src/utl_yaml.cpp')

diff --git a/src/utl_yaml.cpp b/src/utl_yaml.cpp
index bf30d661..22772ffe 100755
--- a/src/utl_yaml.cpp
+++ b/src/utl_yaml.cpp
@@ -83,6 +83,33 @@ bool utl_yaml_read_ip_addr(const YAML::Node& node,
     return (res);
 }
 
+
+
+bool utl_yaml_read_uint32(const YAML::Node& node, 
+                          const std::string &name,
+                          uint32_t & val){
+    bool res=false;
+    if ( node.FindValue(name) ) {
+        node[name] >> val ;
+        res=true;
+    }
+    return (res);
+}
+
+bool utl_yaml_read_uint16(const YAML::Node& node, 
+                          const std::string &name,
+                          uint16_t & val){
+    uint32_t val_tmp;
+    bool res=false;
+    if ( node.FindValue(name) ) {
+        node[name] >> val_tmp ;
+        val = (uint16_t)val_tmp;
+        res=true;
+    }
+
+    return (res);
+}
+
 static void
 split_str_by_delimiter(std::string str, char delim, std::vector<std::string> &tokens) {
     size_t pos = 0;
@@ -99,23 +126,13 @@ split_str_by_delimiter(std::string str, char delim, std::vector<std::string> &to
     }
 }
 
-bool utl_yaml_read_mac_addr(const YAML::Node &node,
-                            const std::string &name,
-                            uint64_t &val) {
-
-    std::string mac_str;
-
-    if (!node.FindValue(name)) {
-        return false;
-    }
-
-    node[name] >> mac_str;
-
+static bool mac2uint64(const std::string &mac_str, uint64_t &mac_num) {
     std::vector<std::string> tokens;
-    split_str_by_delimiter(mac_str, ':', tokens);
+    uint64_t val;
 
+    split_str_by_delimiter(mac_str, ':', tokens);
     if (tokens.size() != 6) {
-        throw YAML::InvalidScalar(node[name].GetMark());
+        return false;
     }
 
     val = 0;
@@ -125,51 +142,171 @@ bool utl_yaml_read_mac_addr(const YAML::Node &node,
         unsigned long octet = strtoul(tokens[i].c_str(), &endptr, 16);
 
         if ( (*endptr != 0) || (octet > 0xff) ) {
-            throw YAML::InvalidScalar(node[name].GetMark());
+            return false;
         }
 
-        //mac_addr[i] = (uint8_t)octet;
         val = (val << 8) + octet;
-    }   
-                  
+    }
+
+    mac_num = val;
+
     return true;
 }
 
+/************************
+ * YAML Parser Wrapper
+ *
+ ***********************/
+bool
+YAMLParserWrapper::parse_bool(const YAML::Node &node, const std::string &name, bool def) {
+    if (!node.FindValue(name)) {
+        return def;
+    }
 
-bool utl_yaml_read_uint32(const YAML::Node& node, 
-                          const std::string &name,
-                          uint32_t & val){
-    bool res=false;
-    if ( node.FindValue(name) ) {
-        node[name] >> val ;
-        res=true;
+    return parse_bool(node, name);
+}
+
+bool
+YAMLParserWrapper::parse_bool(const YAML::Node &node, const std::string &name) {
+    try {
+        bool val;
+        node[name] >> val;
+        return (val);
+
+    } catch (const YAML::InvalidScalar &ex) {
+        parse_err("expecting true/false for field '" + name + "'", node[name]);
+
+    } catch (const YAML::KeyNotFound &ex) {
+        parse_err("cannot locate mandatory field '" + name + "'", node);
     }
-    return (res);
+
+    assert(0);
 }
 
-bool utl_yaml_read_uint16(const YAML::Node& node, 
-                          const std::string &name,
-                          uint16_t & val){
-    uint32_t val_tmp;
-    bool res=false;
-    if ( node.FindValue(name) ) {
-        node[name] >> val_tmp ;
-        val = (uint16_t)val_tmp;
-        res=true;
+const YAML::Node &
+YAMLParserWrapper::parse_list(const YAML::Node &node, const std::string &name) {
+
+    try {
+        const YAML::Node &val = node[name];
+        if (val.Type() != YAML::NodeType::Sequence) {
+            throw YAML::InvalidScalar(node[name].GetMark());
+        }
+        return val;
+
+    } catch (const YAML::InvalidScalar &ex) {
+        parse_err("expecting sequence/list for field '" + name + "'", node[name]);
+
+    } catch (const YAML::KeyNotFound &ex) {
+        parse_err("cannot locate mandatory field '" + name + "'", node);
     }
 
-    return (res);
+    assert(0);
 }
 
-bool utl_yaml_read_bool(const YAML::Node& node, 
-                        const std::string &name,
-                        bool & val){
-    bool res=false;
-    if ( node.FindValue(name) ) {
-        node[name] >> val ;
-        res=true;
+const YAML::Node &
+YAMLParserWrapper::parse_map(const YAML::Node &node, const std::string &name) {
+
+    try {
+        const YAML::Node &val = node[name];
+        if (val.Type() != YAML::NodeType::Map) {
+            throw YAML::InvalidScalar(node[name].GetMark());
+        }
+        return val;
+
+    } catch (const YAML::InvalidScalar &ex) {
+        parse_err("expecting map for field '" + name + "'", node[name]);
+
+    } catch (const YAML::KeyNotFound &ex) {
+        parse_err("cannot locate mandatory field '" + name + "'", node);
+    }
+
+    assert(0);
+}
+
+uint32_t
+YAMLParserWrapper::parse_ip(const YAML::Node &node, const std::string &name) {
+    
+
+    try {
+        std::string ip_str;
+        uint32_t    ip_num;
+
+        node[name] >> ip_str;
+        int rc = my_inet_pton4((char *)ip_str.c_str(), (unsigned char *)&ip_num);
+        if (!rc) {
+            parse_err("invalid IP address: " + ip_str, node[name]);
+        }
+
+        return PKT_NTOHL(ip_num);
+
+    } catch (const YAML::InvalidScalar &ex) {
+        parse_err("expecting valid IP address for field '" + name + "'", node[name]);
+
+    } catch (const YAML::KeyNotFound &ex) {
+        parse_err("cannot locate mandatory field '" + name + "'", node);
     }
-    return( res);
+
+    assert(0);
+}
+
+uint64_t
+YAMLParserWrapper::parse_mac_addr(const YAML::Node &node, const std::string &name) {
+
+    std::string mac_str;
+    uint64_t    mac_num;
+
+    try {
+
+        node[name] >> mac_str;
+        bool rc = mac2uint64(mac_str, mac_num);
+        if (!rc) {
+            parse_err("invalid MAC address: " + mac_str, node[name]);
+        }
+        return mac_num;
+
+    } catch (const YAML::InvalidScalar &ex) {
+        parse_err("expecting true/false for field '" + name + "'", node[name]);
+
+    } catch (const YAML::KeyNotFound &ex) {
+        parse_err("cannot locate mandatory field '" + name + "'", node);
+    }
+
+    assert(0);
 }
 
+uint64_t 
+YAMLParserWrapper::parse_uint(const YAML::Node &node, const std::string &name, uint64_t low, uint64_t high) {
+
+    try {
+
+        uint64_t val;
+        node[name] >> val;
+
+        if ( (val < low) || (val > high) ) {
+            std::stringstream ss;
+            ss << "valid range for field '" << name << "' is: [" << low << " - " << high << "]";
+            parse_err(ss.str(), node[name]);
+        }
+
+        return (val);
+
+    } catch (const YAML::InvalidScalar &ex) {
+        parse_err("expecting true/false for field '" + name + "'", node[name]);
+
+    } catch (const YAML::KeyNotFound &ex) {
+        parse_err("cannot locate mandatory field '" + name + "'", node);
+    }
+
+    assert(0);
+}
+
+void
+YAMLParserWrapper::parse_err(const std::string &err, const YAML::Node &node) const {
+    std::stringstream ss;
+
+    ss << "\n*** '" << m_header << "' - YAML parsing error at line " << node.GetMark().line << ": ";
+    ss << err;
+
+    throw std::runtime_error(ss.str());
+}
 
-- 
cgit 


From 4242bc5ec3aa8816db9bdd57bd1f732da4305555 Mon Sep 17 00:00:00 2001
From: imarom <imarom@cisco.com>
Date: Wed, 29 Jun 2016 15:39:46 +0300
Subject: client configuration: refactoring

---
 src/utl_yaml.cpp | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

(limited to 'src/utl_yaml.cpp')

diff --git a/src/utl_yaml.cpp b/src/utl_yaml.cpp
index 22772ffe..444031c6 100755
--- a/src/utl_yaml.cpp
+++ b/src/utl_yaml.cpp
@@ -249,6 +249,15 @@ YAMLParserWrapper::parse_ip(const YAML::Node &node, const std::string &name) {
     assert(0);
 }
 
+uint64_t
+YAMLParserWrapper::parse_mac_addr(const YAML::Node &node, const std::string &name, uint64_t def) {
+    if (!node.FindValue(name)) {
+        return def;
+    }
+
+    return parse_mac_addr(node, name);
+}
+
 uint64_t
 YAMLParserWrapper::parse_mac_addr(const YAML::Node &node, const std::string &name) {
 
@@ -274,6 +283,15 @@ YAMLParserWrapper::parse_mac_addr(const YAML::Node &node, const std::string &nam
     assert(0);
 }
 
+uint64_t 
+YAMLParserWrapper::parse_uint(const YAML::Node &node, const std::string &name, uint64_t low, uint64_t high, uint64_t def) {
+    if (!node.FindValue(name)) {
+        return def;
+    }
+
+    return parse_uint(node, name, low, high);
+}
+
 uint64_t 
 YAMLParserWrapper::parse_uint(const YAML::Node &node, const std::string &name, uint64_t low, uint64_t high) {
 
@@ -310,3 +328,11 @@ YAMLParserWrapper::parse_err(const std::string &err, const YAML::Node &node) con
     throw std::runtime_error(ss.str());
 }
 
+void
+YAMLParserWrapper::parse_err(const std::string &err) const {
+    std::stringstream ss;
+
+    ss << "\n*** '" << m_header << "' - YAML parsing error: " << err;
+
+    throw std::runtime_error(ss.str());
+}
-- 
cgit 


From c6c4a4307a8a0ae17d3e26c9dc98b874dd5ee60b Mon Sep 17 00:00:00 2001
From: imarom <imarom@cisco.com>
Date: Sun, 3 Jul 2016 10:55:49 +0300
Subject: client config - cosmetics and gtest back on

---
 src/utl_yaml.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/utl_yaml.cpp')

diff --git a/src/utl_yaml.cpp b/src/utl_yaml.cpp
index 444031c6..66c83ac8 100755
--- a/src/utl_yaml.cpp
+++ b/src/utl_yaml.cpp
@@ -322,7 +322,7 @@ void
 YAMLParserWrapper::parse_err(const std::string &err, const YAML::Node &node) const {
     std::stringstream ss;
 
-    ss << "\n*** '" << m_header << "' - YAML parsing error at line " << node.GetMark().line << ": ";
+    ss << "'" << m_header << "' - YAML parsing error at line " << node.GetMark().line << ": ";
     ss << err;
 
     throw std::runtime_error(ss.str());
@@ -332,7 +332,7 @@ void
 YAMLParserWrapper::parse_err(const std::string &err) const {
     std::stringstream ss;
 
-    ss << "\n*** '" << m_header << "' - YAML parsing error: " << err;
+    ss << "'" << m_header << "' - YAML parsing error: " << err;
 
     throw std::runtime_error(ss.str());
 }
-- 
cgit 


From 483dfb7c5021d7dc9e2c7f10c9b76101441c7203 Mon Sep 17 00:00:00 2001
From: imarom <imarom@cisco.com>
Date: Sun, 3 Jul 2016 15:38:59 +0300
Subject: slowpath features bit to avoid multiple IFs

---
 src/utl_yaml.cpp | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

(limited to 'src/utl_yaml.cpp')

diff --git a/src/utl_yaml.cpp b/src/utl_yaml.cpp
index 66c83ac8..8352e887 100755
--- a/src/utl_yaml.cpp
+++ b/src/utl_yaml.cpp
@@ -22,6 +22,8 @@ limitations under the License.
 */
 
 #include <istream>
+#include <fstream>
+#include "common/basic_utils.h"
 
 #define INADDRSZ 4
 
@@ -157,6 +159,27 @@ static bool mac2uint64(const std::string &mac_str, uint64_t &mac_num) {
  * YAML Parser Wrapper
  *
  ***********************/
+void
+YAMLParserWrapper::load(YAML::Node &root) {
+    std::stringstream ss;
+
+    /* first check file exists */
+    if (!utl_is_file_exists(m_filename)){
+        ss << "file '" << m_filename << "' does not exists";
+        throw std::runtime_error(ss.str());
+    }
+
+    std::ifstream fin(m_filename);
+
+    try {
+        YAML::Parser base_parser(fin);
+        base_parser.GetNextDocument(root);
+
+    } catch (const YAML::Exception &e) {
+        parse_err(e.what());
+    }
+}
+
 bool
 YAMLParserWrapper::parse_bool(const YAML::Node &node, const std::string &name, bool def) {
     if (!node.FindValue(name)) {
@@ -322,7 +345,7 @@ void
 YAMLParserWrapper::parse_err(const std::string &err, const YAML::Node &node) const {
     std::stringstream ss;
 
-    ss << "'" << m_header << "' - YAML parsing error at line " << node.GetMark().line << ": ";
+    ss << "'" << m_filename << "' - YAML parsing error at line " << node.GetMark().line << ": ";
     ss << err;
 
     throw std::runtime_error(ss.str());
@@ -332,7 +355,7 @@ void
 YAMLParserWrapper::parse_err(const std::string &err) const {
     std::stringstream ss;
 
-    ss << "'" << m_header << "' - YAML parsing error: " << err;
+    ss << "'" << m_filename << "' - YAML parsing error: " << err;
 
     throw std::runtime_error(ss.str());
 }
-- 
cgit