Skip to content

Commit 230a26f

Browse files
committed
Add string helpers in util/strfuns.hpp
1 parent b7a11bc commit 230a26f

File tree

11 files changed

+103
-46
lines changed

11 files changed

+103
-46
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ add_library(lslobj OBJECT
9898
src/util/cast.cpp
9999
src/util/inireader.hpp
100100
src/util/inireader.cpp
101+
src/util/strfuns.hpp
102+
src/util/strfuns.cpp
101103
src/util/uuid.hpp
102104
thirdparty/loguru/loguru.cpp
103105
$<$<BOOL:${LSL_LEGACY_CPP_ABI}>:src/legacy/legacy_abi.cpp src/legacy/legacy_abi.h>

src/api_config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "api_config.h"
22
#include "common.h"
33
#include "util/inireader.hpp"
4+
#include "util/strfuns.hpp"
45
#include <algorithm>
56
#include <cstdlib>
67
#include <exception>

src/common.cpp

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -78,34 +78,3 @@ void lsl::ensure_lsl_initialized() {
7878
#endif
7979
}
8080
}
81-
82-
std::vector<std::string> lsl::splitandtrim(
83-
const std::string &input, char separator, bool keepempty) {
84-
std::vector<std::string> parts;
85-
auto it = input.cbegin();
86-
while (true) {
87-
// Skip whitespace in the beginning
88-
while (it != input.cend() && std::isspace(*it)) ++it;
89-
90-
// find the next separator or end of string
91-
auto endit = std::find(it, input.cend(), separator);
92-
// mark beginning of next part if not at the end
93-
auto next = endit;
94-
95-
// shrink the range so it doesn't include whitespace at the end
96-
while (it < endit && std::isspace(*(endit - 1))) --endit;
97-
if (endit != it || keepempty) parts.emplace_back(it, endit);
98-
99-
if (next != input.cend())
100-
it = next + 1;
101-
else
102-
break;
103-
}
104-
return parts;
105-
}
106-
107-
std::string lsl::trim(const std::string &input) {
108-
auto first = input.find_first_not_of(" \t\r\n"), last = input.find_last_not_of(" \t\r\n");
109-
if (first == std::string::npos || last == std::string::npos) return "";
110-
return input.substr(first, last - first + 1);
111-
}

src/common.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,6 @@ class LIBLSL_CPP_API timeout_error : public std::runtime_error {
8383
explicit timeout_error(const std::string &msg) : std::runtime_error(msg) {}
8484
};
8585

86-
std::string trim(const std::string &input);
87-
std::vector<std::string> splitandtrim(
88-
const std::string &input, char separator = ',', bool keepempty = false);
8986
} // namespace lsl
9087

9188
#endif

src/data_receiver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "sample.h"
66
#include "socket_utils.h"
77
#include "util/cast.hpp"
8+
#include "util/strfuns.hpp"
89
#include <chrono>
910
#include <exception>
1011
#include <iostream>

src/resolve_attempt_udp.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "api_config.h"
33
#include "resolver_impl.h"
44
#include "socket_utils.h"
5+
#include "util/strfuns.hpp"
56
#include <boost/asio/io_context.hpp>
67
#include <boost/asio/ip/address.hpp>
78
#include <boost/asio/ip/multicast.hpp>
@@ -102,16 +103,16 @@ void resolve_attempt_udp::handle_receive_outcome(err_t err, std::size_t len) {
102103
if (!err) {
103104
try {
104105
// first parse & check the query id
105-
std::istringstream is(std::string(resultbuf_, len));
106-
std::string returned_id;
107-
getline(is, returned_id);
108-
returned_id = trim(returned_id);
109-
if (returned_id == query_id_) {
106+
char *bufend = resultbuf_ + len;
107+
char *newlinepos = resultbuf_;
108+
// find the end of the line
109+
while (newlinepos != bufend && *newlinepos != '\n') ++newlinepos;
110+
std::string returned_id(resultbuf_, trim_end(resultbuf_, newlinepos));
111+
112+
if (returned_id == query_id_ && newlinepos != bufend) {
110113
// parse the rest of the query into a stream_info
111114
stream_info_impl info;
112-
std::ostringstream os;
113-
os << is.rdbuf();
114-
info.from_shortinfo_message(os.str());
115+
info.from_shortinfo_message(std::string(newlinepos, bufend));
115116
std::string uid = info.uid();
116117
{
117118
// update the results

src/tcp_server.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "socket_utils.h"
77
#include "stream_info_impl.h"
88
#include "util/cast.hpp"
9+
#include "util/strfuns.hpp"
910
#include <boost/asio/io_context.hpp>
1011
#include <boost/asio/ip/host_name.hpp>
1112
#include <boost/asio/ip/tcp.hpp>

src/udp_server.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#include "udp_server.h"
22
#include "socket_utils.h"
33
#include "stream_info_impl.h"
4+
#include "util/strfuns.hpp"
5+
#include <boost/asio/io_context.hpp>
46
#include <boost/asio/ip/address.hpp>
7+
#include <boost/asio/ip/address_v4.hpp>
58
#include <boost/asio/ip/multicast.hpp>
69
#include <boost/asio/ip/udp.hpp>
7-
#include <boost/asio/io_context.hpp>
8-
#include <boost/asio/ip/address_v4.hpp>
910
#include <exception>
1011
#include <loguru.hpp>
1112
#include <sstream>

src/util/strfuns.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include "strfuns.hpp"
2+
3+
std::vector<std::string> lsl::splitandtrim(
4+
const std::string &input, char separator, bool keepempty) {
5+
std::vector<std::string> parts;
6+
auto it = input.cbegin();
7+
while (true) {
8+
// Skip whitespace in the beginning
9+
it = lsl::trim_begin(it, input.cend());
10+
11+
// find the next separator or end of string
12+
auto endit = it;
13+
while (endit != input.end() && *endit != separator) ++endit;
14+
// mark beginning of next part if not at the end
15+
auto next = endit;
16+
17+
// shrink the range so it doesn't include whitespace at the end
18+
endit = trim_end(it, endit);
19+
if (endit != it || keepempty) parts.emplace_back(it, endit);
20+
21+
if (next != input.cend())
22+
it = next + 1;
23+
else
24+
break;
25+
}
26+
return parts;
27+
}

src/util/strfuns.hpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <vector>
5+
6+
namespace lsl {
7+
8+
inline bool isspace(char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; }
9+
10+
/// trim whitespace at the beginning of a sequence, return position of first non-whitespace character
11+
template <typename IteratorType> IteratorType trim_begin(IteratorType begin, IteratorType end) {
12+
while (begin != end && lsl::isspace(*begin)) ++begin;
13+
return begin;
14+
}
15+
16+
/// trim whitespace at the end of a sequence, return position one past the last non-whitespace character
17+
template <typename IteratorType> IteratorType trim_end(IteratorType begin, IteratorType end) {
18+
while (end > begin && lsl::isspace(*(end - 1))) --end;
19+
return end;
20+
}
21+
22+
/// remove whitespace from the beginning and end of a sequence, modifying both start and end iterators
23+
template <typename IteratorType> void trim(IteratorType &begin, IteratorType &end) {
24+
end = trim_end(begin, end);
25+
begin = trim_begin(begin, end);
26+
}
27+
28+
/// return a string with whitespace at the beginning and end trimmed
29+
inline std::string trim(const std::string &input) {
30+
std::string::const_iterator begin = input.begin(), end = input.end();
31+
lsl::trim(begin, end);
32+
return std::string(begin, end);
33+
}
34+
35+
/// split a separated string like "this,is a,list" into its parts
36+
std::vector<std::string> splitandtrim(
37+
const std::string &input, char separator = ',', bool keepempty = false);
38+
39+
} // namespace lsl

0 commit comments

Comments
 (0)