From b9506ca8dea2aca4cf7b8c1fe50fbe9af9f0cd0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com> Date: Wed, 17 Mar 2021 14:18:36 -0400 Subject: [PATCH] string utils: add string_view split, update base64 Change-Id: Id2d03ca3d645d7178019bf05c1951c6a78019095 --- src/base64.cpp | 22 ++++----------- src/base64.h | 17 ++++++----- src/ice_transport.cpp | 9 ++---- src/ip_utils.cpp | 18 ++++-------- src/jamidht/jamiaccount.cpp | 7 ++--- src/jamidht/namedirectory.cpp | 2 +- src/media/media_encoder.cpp | 13 +++++---- src/string_utils.h | 28 +++++++++++++++++++ .../string_utils/testString_utils.cpp | 20 +++++++++++-- 9 files changed, 81 insertions(+), 55 deletions(-) diff --git a/src/base64.cpp b/src/base64.cpp index c9f5f18775..e2b467d1cf 100644 --- a/src/base64.cpp +++ b/src/base64.cpp @@ -19,9 +19,6 @@ #include "base64.h" #include "sip/sip_utils.h" -#include <stdint.h> -#include <stdlib.h> -#include <iostream> #include <pjlib.h> #include <pjlib-util/base64.h> @@ -29,18 +26,17 @@ namespace jami { namespace base64 { std::string -encode(const std::vector<uint8_t>::const_iterator begin, - const std::vector<uint8_t>::const_iterator end) +encode(std::string_view dat) { - int input_length = std::distance(begin, end); - if (input_length == 0) + if (dat.empty()) return {}; + int input_length = dat.size(); int output_length = PJ_BASE256_TO_BASE64_LEN(input_length); std::string out; out.resize(output_length); - if (pj_base64_encode(&(*begin), input_length, &(*out.begin()), &output_length) != PJ_SUCCESS) { + if (pj_base64_encode((const uint8_t*)dat.data(), input_length, &(*out.begin()), &output_length) != PJ_SUCCESS) { throw base64_exception(); } @@ -48,20 +44,14 @@ encode(const std::vector<uint8_t>::const_iterator begin, return out; } -std::string -encode(const std::vector<uint8_t>& dat) -{ - return encode(dat.cbegin(), dat.cend()); -} - std::vector<uint8_t> -decode(const std::string& str) +decode(std::string_view str) { if (str.empty()) return {}; int output_length = PJ_BASE64_TO_BASE256_LEN(str.length()); - const pj_str_t input(sip_utils::CONST_PJ_STR(str)); + auto input = sip_utils::CONST_PJ_STR(str); std::vector<uint8_t> out; out.resize(output_length); diff --git a/src/base64.h b/src/base64.h index d7ec56614e..cc2b7fe431 100644 --- a/src/base64.h +++ b/src/base64.h @@ -18,23 +18,26 @@ #pragma once -#include <stdint.h> -#include <stddef.h> - #include <string> +#include <string_view> #include <vector> #include <exception> +#include <cstdint> + namespace jami { namespace base64 { class base64_exception : public std::exception {}; -std::string encode(const std::vector<uint8_t>::const_iterator begin, - const std::vector<uint8_t>::const_iterator end); -std::string encode(const std::vector<uint8_t>& dat); -std::vector<uint8_t> decode(const std::string& str); +std::string encode(std::string_view); + +inline std::string encode(const std::vector<uint8_t>& data) { + return encode(std::string_view((const char*)data.data(), data.size())); +} + +std::vector<uint8_t> decode(std::string_view); } // namespace base64 } // namespace jami diff --git a/src/ice_transport.cpp b/src/ice_transport.cpp index d1b45bb5ce..9327dd30f6 100644 --- a/src/ice_transport.cpp +++ b/src/ice_transport.cpp @@ -1560,22 +1560,19 @@ ICESDP IceTransport::parse_SDP(const std::string& sdp_msg, const IceTransport& ice) { ICESDP res; - std::istringstream stream(sdp_msg); - std::string line; int nr = 0; - while (std::getline(stream, line)) { + for (std::string_view line; jami::getline(sdp_msg, line); nr++) { if (nr == 0) { res.rem_ufrag = line; } else if (nr == 1) { res.rem_pwd = line; } else { IceCandidate cand; - if (ice.getCandidateFromSDP(line, cand)) { - JAMI_DBG("Add remote ICE candidate: %s", line.c_str()); + if (ice.getCandidateFromSDP(std::string(line), cand)) { + JAMI_DBG("Add remote ICE candidate: %.*s", (int)line.size(), line.data()); res.rem_candidates.emplace_back(cand); } } - nr++; } return res; } diff --git a/src/ip_utils.cpp b/src/ip_utils.cpp index 39315c3ff4..9759c24679 100644 --- a/src/ip_utils.cpp +++ b/src/ip_utils.cpp @@ -180,23 +180,17 @@ ip_utils::getHostName(char* out, size_t out_len) std::string ip_utils::getGateway(char* localHost, ip_utils::subnet_mask prefix) { - std::string localHostStr(localHost); + std::string_view localHostStr(localHost); if (prefix == ip_utils::subnet_mask::prefix_32bit) - return localHostStr; + return std::string(localHostStr); std::string defaultGw {}; - std::istringstream iss(localHostStr); // Make a vector of each individual number in the ip address. - std::vector<std::string> tokens; - std::string token; - while (std::getline(iss, token, '.')) { - if (!token.empty()) - tokens.push_back(token); - } + std::vector<std::string_view> tokens = split_string(localHostStr, '.'); // Build a gateway address from the individual ip components. - for (unsigned int i = 0; i <= (unsigned int) prefix; i++) + for (unsigned i = 0; i <= (unsigned) prefix; i++) defaultGw += tokens[i] + "."; - for (unsigned int i = (unsigned int) ip_utils::subnet_mask::prefix_32bit; - i > (unsigned int) prefix + 1; + for (unsigned i = (unsigned) ip_utils::subnet_mask::prefix_32bit; + i > (unsigned) prefix + 1; i--) defaultGw += "0."; defaultGw += "1"; diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index 008938f92a..0b67b7e027 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -1929,10 +1929,9 @@ JamiAccount::loadBootstrap() const { std::vector<std::string> bootstrap; if (!hostname_.empty()) { - std::istringstream ss(hostname_); - std::string node_addr; - while (std::getline(ss, node_addr, ';')) - bootstrap.emplace_back(std::move(node_addr)); + std::string_view node_addr; + while (jami::getline(hostname_, 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/jamidht/namedirectory.cpp b/src/jamidht/namedirectory.cpp index 182dc98e1f..45e7c1d75f 100644 --- a/src/jamidht/namedirectory.cpp +++ b/src/jamidht/namedirectory.cpp @@ -360,7 +360,7 @@ NameDirectory::registerName(const std::string& addr, std::stringstream ss; ss << "{\"addr\":\"" << addr << "\",\"owner\":\"" << owner << "\",\"signature\":\"" << signedname << "\",\"publickey\":\"" - << base64::encode(jami::Blob(publickey.begin(), publickey.end())) << "\"}"; + << base64::encode(publickey) << "\"}"; body = ss.str(); } auto request = std::make_shared<Request>(*httpContext_, diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp index c50f824d84..7413778ee9 100644 --- a/src/media/media_encoder.cpp +++ b/src/media/media_encoder.cpp @@ -517,15 +517,16 @@ MediaEncoder::print_sdp() #else const auto sdp_size = outputCtx_->streams[currentStreamIdx_]->codec->extradata_size + 2048; #endif - std::string result; std::string sdp(sdp_size, '\0'); av_sdp_create(&outputCtx_, 1, &(*sdp.begin()), sdp_size); - std::istringstream iss(sdp); - std::string line; - while (std::getline(iss, line)) { + + std::string result; + result.reserve(sdp_size); + std::string_view line; + while (jami::getline(sdp, line)) { /* strip windows line ending */ - line = line.substr(0, line.length() - 1); - result += line + "\n"; + result += line.substr(0, line.length() - 1); + result += "\n"sv; } #ifdef DEBUG_SDP JAMI_DBG("Sending SDP:\n%s", result.c_str()); diff --git a/src/string_utils.h b/src/string_utils.h index 1b9493693c..bd13f4eac9 100644 --- a/src/string_utils.h +++ b/src/string_utils.h @@ -114,6 +114,34 @@ stod(const std::string& str) 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 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') +{ + 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()) + return false; + auto nextStr = str.substr(prevEnd + 1); + line = nextStr.substr(0, nextStr.find(delim)); + } + return true; +} + inline std::vector<std::string_view> split_string(std::string_view str, char delim) { diff --git a/test/unitTest/string_utils/testString_utils.cpp b/test/unitTest/string_utils/testString_utils.cpp index 68d8a51ba4..bb114af6dc 100644 --- a/test/unitTest/string_utils/testString_utils.cpp +++ b/test/unitTest/string_utils/testString_utils.cpp @@ -23,9 +23,12 @@ #include "string_utils.h" #include <string> +#include <string_view> #include "../../test_runner.h" +using namespace std::literals; + namespace jami { namespace test { class StringUtilsTest : public CppUnit::TestFixture { @@ -90,15 +93,26 @@ StringUtilsTest::to_number_test() void StringUtilsTest::split_string_test() { - auto split_string_result = split_string("*fdg454()**{&xcx*", '*'); + constexpr auto data = "*fdg454()**{&xcx*"sv; + auto split_string_result = split_string(data, '*'); CPPUNIT_ASSERT(split_string_result.size() == 2); - CPPUNIT_ASSERT(split_string_result.at(0) == "fdg454()" - && split_string_result.at(1) == "{&xcx"); + CPPUNIT_ASSERT(split_string_result.at(0) == "fdg454()"sv + && split_string_result.at(1) == "{&xcx"sv); auto split_string_to_unsigned_result = split_string_to_unsigned("/4545497//45454/", '/'); CPPUNIT_ASSERT(split_string_to_unsigned_result.size() == 2); CPPUNIT_ASSERT(split_string_to_unsigned_result.at(0) == 4545497 && split_string_to_unsigned_result.at(1) == 45454); + + std::string_view line; + split_string_result.clear(); + 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()); } }} // namespace jami_test -- GitLab