Skip to content

Commit 220b2eb

Browse files
committed
Raise an error when attempting stream resolution with an malformed query
1 parent 1bccbb6 commit 220b2eb

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

include/lsl_cpp.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ namespace lsl {
2626
#include "lsl_c.h"
2727
#endif
2828

29+
/// Assert that no error happened; throw appropriate exception otherwise
30+
int32_t check_error(int32_t ec);
31+
2932
/// Constant to indicate that a stream has variable sampling rate.
3033
const double IRREGULAR_RATE = 0.0;
3134

@@ -649,7 +652,11 @@ namespace lsl {
649652
* @return A vector of stream info objects (excluding their desc field), any of which can
650653
* subsequently be used to open an inlet. The full info can be retrieve from the inlet.
651654
*/
652-
inline std::vector<stream_info> resolve_streams(double wait_time=1.0) { lsl_streaminfo buffer[1024]; return std::vector<stream_info>(&buffer[0],&buffer[lsl_resolve_all(buffer,sizeof(buffer),wait_time)]); }
655+
inline std::vector<stream_info> resolve_streams(double wait_time = 1.0) {
656+
lsl_streaminfo buffer[1024];
657+
int nres = check_error(lsl_resolve_all(buffer, sizeof(buffer), wait_time));
658+
return std::vector<stream_info>(&buffer[0], &buffer[nres]);
659+
}
653660

654661
/** Resolve all streams with a specific value for a given property.
655662
* If the goal is to resolve a specific stream, this method is preferred over resolving all streams and then selecting the desired one.
@@ -661,7 +668,14 @@ namespace lsl {
661668
* @return A vector of matching stream info objects (excluding their meta-data), any of
662669
* which can subsequently be used to open an inlet.
663670
*/
664-
inline std::vector<stream_info> resolve_stream(const std::string &prop, const std::string &value, int32_t minimum=1, double timeout=FOREVER) { lsl_streaminfo buffer[1024]; return std::vector<stream_info>(&buffer[0],&buffer[lsl_resolve_byprop(buffer,sizeof(buffer),(prop.c_str()),(value.c_str()),minimum,timeout)]); }
671+
inline std::vector<stream_info> resolve_stream(const std::string &prop,
672+
const std::string &value, int32_t minimum = 1, double timeout = FOREVER) {
673+
lsl_streaminfo buffer[1024];
674+
int nres = check_error(lsl_resolve_byprop(
675+
buffer, sizeof(buffer), prop.c_str(), value.c_str(), minimum, timeout));
676+
return std::vector<stream_info>(
677+
&buffer[0], &buffer[nres]);
678+
}
665679

666680
/** Resolve all streams that match a given predicate.
667681
*
@@ -677,7 +691,13 @@ namespace lsl {
677691
* @return A vector of matching stream info objects (excluding their meta-data), any of
678692
* which can subsequently be used to open an inlet.
679693
*/
680-
inline std::vector<stream_info> resolve_stream(const std::string &pred, int32_t minimum=1, double timeout=FOREVER) { lsl_streaminfo buffer[1024]; return std::vector<stream_info>(&buffer[0],&buffer[lsl_resolve_bypred(buffer,sizeof(buffer),(pred.c_str()),minimum,timeout)]); }
694+
inline std::vector<stream_info> resolve_stream(
695+
const std::string &pred, int32_t minimum = 1, double timeout = FOREVER) {
696+
lsl_streaminfo buffer[1024];
697+
int nres =
698+
check_error(lsl_resolve_bypred(buffer, sizeof(buffer), pred.c_str(), minimum, timeout));
699+
return std::vector<stream_info>(&buffer[0], &buffer[nres]);
700+
}
681701

682702

683703
// ======================
@@ -687,7 +707,6 @@ namespace lsl {
687707
/** A stream inlet.
688708
* Inlets are used to receive streaming data (and meta-data) from the lab network.
689709
*/
690-
void check_error(int32_t ec);
691710
class stream_inlet {
692711
public:
693712
/** Construct a new stream inlet from a resolved stream info.
@@ -1307,7 +1326,7 @@ namespace lsl {
13071326
* Check error codes returned from the C interface
13081327
* and translate into appropriate exceptions.
13091328
*/
1310-
inline void check_error(int32_t ec) {
1329+
inline int32_t check_error(int32_t ec) {
13111330
if (ec<0) {
13121331
switch(ec) {
13131332
case lsl_timeout_error:
@@ -1322,6 +1341,7 @@ namespace lsl {
13221341
throw std::runtime_error("An unknown error has occurred.");
13231342
}
13241343
}
1344+
return ec;
13251345
}
13261346

13271347
} // end namespace

src/resolver_impl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ resolver_impl::resolver_impl()
6262
}
6363
}
6464

65+
void check_query(const std::string& query) {
66+
try {
67+
pugi::xpath_query(query.c_str());
68+
} catch (std::exception &e) {
69+
throw std::invalid_argument((("Invalid query '" + query) += "': ") += e.what());
70+
}
71+
}
6572

6673
// === resolve functions ===
6774

@@ -70,6 +77,7 @@ resolver_impl::resolver_impl()
7077
* Blocks until at least the minimum number of streams has been resolved, or the timeout fires, or the resolve has been cancelled.
7178
*/
7279
std::vector<stream_info_impl> resolver_impl::resolve_oneshot(const std::string &query, int minimum, double timeout, double minimum_time) {
80+
check_query(query);
7381
// reset the IO service & set up the query parameters
7482
io_->restart();
7583
query_ = query;
@@ -101,6 +109,7 @@ std::vector<stream_info_impl> resolver_impl::resolve_oneshot(const std::string &
101109
}
102110

103111
void resolver_impl::resolve_continuous(const std::string &query, double forget_after) {
112+
check_query(query);
104113
// reset the IO service & set up the query parameters
105114
io_->restart();
106115
query_ = query;

testing/discovery.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@ TEST_CASE("resolve from streaminfo", "[resolver][streaminfo][basic]") {
2323
lsl::stream_inlet(outlet.info());
2424
}
2525

26+
TEST_CASE("Invalid queries are caught before sending the query", "[resolver][streaminfo][basic]") {
27+
REQUIRE_THROWS(lsl::resolve_stream("invalid'query", 0, 0.1));
28+
}
29+
2630
} // namespace

0 commit comments

Comments
 (0)