From 4278222938706c1bd7ead3080be52b1e2f45d6df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Thu, 25 Mar 2021 22:31:42 -0400
Subject: [PATCH] getline: use input string as stream, skip empty

Change-Id: I2ea856c183df317eab45a5d6d5533ef1b3b6a0df
---
 src/ice_transport.cpp                         |  2 +-
 src/ice_transport.h                           |  2 +-
 src/jamidht/jamiaccount.cpp                   |  4 +--
 src/media/media_encoder.cpp                   |  5 +--
 src/sip/sipaccount.cpp                        | 22 +++++-------
 src/string_utils.h                            | 35 ++++++++++---------
 .../string_utils/testString_utils.cpp         |  7 ++--
 7 files changed, 38 insertions(+), 39 deletions(-)

diff --git a/src/ice_transport.cpp b/src/ice_transport.cpp
index 9327dd30f6..3b0514f9ff 100644
--- a/src/ice_transport.cpp
+++ b/src/ice_transport.cpp
@@ -1557,7 +1557,7 @@ IceTransport::isTCPEnabled()
 }
 
 ICESDP
-IceTransport::parse_SDP(const std::string& sdp_msg, const IceTransport& ice)
+IceTransport::parse_SDP(std::string_view sdp_msg, const IceTransport& ice)
 {
     ICESDP res;
     int nr = 0;
diff --git a/src/ice_transport.h b/src/ice_transport.h
index 171b9f1c7e..6d74a0ecbb 100644
--- a/src/ice_transport.h
+++ b/src/ice_transport.h
@@ -253,7 +253,7 @@ public:
 
     bool isTCPEnabled();
 
-    static ICESDP parse_SDP(const std::string& sdp_msg, const IceTransport& ice);
+    static ICESDP parse_SDP(std::string_view sdp_msg, const IceTransport& ice);
 
     void setDefaultRemoteAddress(int comp_id, const IpAddr& addr);
 
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index f1fb6008b8..c6c3056846 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -1929,8 +1929,8 @@ JamiAccount::loadBootstrap() const
 {
     std::vector<std::string> bootstrap;
     if (!hostname_.empty()) {
-        std::string_view node_addr;
-        while (jami::getline(hostname_, node_addr, ';'))
+        std::string_view stream(hostname_), node_addr;
+        while (jami::getline(stream, node_addr, ';'))
             bootstrap.emplace_back(node_addr);
         for (const auto& b : bootstrap)
             JAMI_DBG("[Account %s] Bootstrap node: %s", getAccountID().c_str(), b.c_str());
diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp
index 7413778ee9..225efd05b9 100644
--- a/src/media/media_encoder.cpp
+++ b/src/media/media_encoder.cpp
@@ -522,8 +522,9 @@ MediaEncoder::print_sdp()
 
     std::string result;
     result.reserve(sdp_size);
-    std::string_view line;
-    while (jami::getline(sdp, line)) {
+
+    std::string_view steam(sdp), line;
+    while (jami::getline(steam, line)) {
         /* strip windows line ending */
         result += line.substr(0, line.length() - 1);
         result += "\n"sv;
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index e124c1054b..bc2f41091f 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -1291,19 +1291,15 @@ SIPAccount::initTlsConfiguration()
 
     ciphers_.clear();
 #if PJ_VERSION_NUM > (2 << 24 | 2 << 16)
-    if (not tlsCiphers_.empty()) {
-        std::stringstream ss(tlsCiphers_);
-        std::string item;
-        while (std::getline(ss, item, ' ')) {
-            if (item.empty())
-                continue;
-            auto item_cid = pj_ssl_cipher_id(item.c_str());
-            if (item_cid != PJ_TLS_UNKNOWN_CIPHER) {
-                JAMI_WARN("Valid cipher: %s", item.c_str());
-                ciphers_.push_back(item_cid);
-            } else
-                JAMI_ERR("Invalid cipher: %s", item.c_str());
-        }
+    std::string_view stream(tlsCiphers_), item;
+    while (jami::getline(stream, item, ' ')) {
+        std::string cipher(item);
+        auto item_cid = pj_ssl_cipher_id(cipher.c_str());
+        if (item_cid != PJ_TLS_UNKNOWN_CIPHER) {
+            JAMI_WARN("Valid cipher: %s", cipher.c_str());
+            ciphers_.push_back(item_cid);
+        } else
+            JAMI_ERR("Invalid cipher: %s", cipher.c_str());
     }
 #endif
     ciphers_.erase(std::remove_if(ciphers_.begin(),
diff --git a/src/string_utils.h b/src/string_utils.h
index bd13f4eac9..e95776d881 100644
--- a/src/string_utils.h
+++ b/src/string_utils.h
@@ -27,6 +27,7 @@
 #include <algorithm>
 #include <regex>
 #include <iterator>
+
 #ifdef _WIN32
 #include <WTypes.h>
 #endif
@@ -116,30 +117,32 @@ std::string_view trim(std::string_view s);
 
 /**
  * Split a string_view with an API similar to std::getline.
- * @param str The input string to iterate on.
- * @param line The output substring, also used as an iterator.
- *             It must be default-initialised when this function is used 
- *             for the first time with a given string,
- *             and should not be modified by the caller during iteration.
+ * @param str The input string stream to iterate on, trimed of line during iteration.
+ * @param line The output substring.
  * @param delim The delimiter.
  * @return True if line was set, false if the end of the input was reached.
  */
 inline
-bool getline(const std::string_view str, std::string_view& line, char delim = '\n')
+bool getline_full(std::string_view& str, std::string_view& line, char delim = '\n')
 {
     if (str.empty())
         return false;
-    if (line.data() == nullptr) {
-        // first iteration
-        line = str.substr(0, str.find(delim));
-    } else {
-        size_t prevEnd = line.data() + line.size() - str.data();
-        if (prevEnd >= str.size())
+    auto pos = str.find(delim);
+    line = str.substr(0, pos);
+    str.remove_prefix(pos < str.size() ? pos + 1 : str.size());
+    return true;
+}
+
+/**
+ * Similar to @getline_full but skips empty results.
+ */
+inline
+bool getline(std::string_view& str, std::string_view& line, char delim = '\n') {
+    do {
+        if (!getline_full(str, line, delim))
             return false;
-        auto nextStr = str.substr(prevEnd + 1);
-        line = nextStr.substr(0, nextStr.find(delim));
-    }
-    return  true;
+    } while (line.empty());
+    return true;
 }
 
 inline
diff --git a/test/unitTest/string_utils/testString_utils.cpp b/test/unitTest/string_utils/testString_utils.cpp
index bb114af6dc..2215d7a71b 100644
--- a/test/unitTest/string_utils/testString_utils.cpp
+++ b/test/unitTest/string_utils/testString_utils.cpp
@@ -109,10 +109,9 @@ StringUtilsTest::split_string_test()
     while (jami::getline(data, line, '*')) {
         split_string_result.emplace_back(line);
     }
-    CPPUNIT_ASSERT_EQUAL(4, split_string_result.size());
-    CPPUNIT_ASSERT_EQUAL(true, split_string_result.at(0).empty());
-    CPPUNIT_ASSERT_EQUAL("fdg454()"sv, split_string_result.at(1));
-    CPPUNIT_ASSERT_EQUAL(true, split_string_result.at(2).empty());
+    CPPUNIT_ASSERT(split_string_result.size() == 2);
+    CPPUNIT_ASSERT(split_string_result.at(0) == "fdg454()"sv
+                   && split_string_result.at(1) == "{&xcx"sv);
 }
 
 }} // namespace jami_test
-- 
GitLab