* for future use and is unused at present.
*
* @param scratch
- * A per-thread scratch space allocated by @ref hs_alloc_scratch().
+ * A per-thread scratch space allocated by @ref hs_alloc_scratch(). This is
+ * allowed to be NULL only if the @a onEvent callback is also NULL.
*
* @param onEvent
* Pointer to a match event callback function. If a NULL pointer is given,
* The stream (as created by @ref hs_open_stream()) to be copied.
*
* @param scratch
- * A per-thread scratch space allocated by @ref hs_alloc_scratch().
+ * A per-thread scratch space allocated by @ref hs_alloc_scratch(). This is
+ * allowed to be NULL only if the @a onEvent callback is also NULL.
*
* @param onEvent
* Pointer to a match event callback function. If a NULL pointer is given,
return HS_INVALID;
}
- if (!scratch || !validScratch(to_id->rose, scratch)) {
- return HS_INVALID;
- }
-
if (onEvent) {
+ if (!scratch || !validScratch(to_id->rose, scratch)) {
+ return HS_INVALID;
+ }
report_eod_matches(to_id, scratch, onEvent, context);
}
hs_error_t hs_reset_stream(hs_stream_t *id, UNUSED unsigned int flags,
hs_scratch_t *scratch, match_event_handler onEvent,
void *context) {
- if (!id || !scratch || !validScratch(id->rose, scratch)) {
+ if (!id) {
return HS_INVALID;
}
- /* user wants eod matches */
if (onEvent) {
+ if (!scratch || !validScratch(id->rose, scratch)) {
+ return HS_INVALID;
+ }
report_eod_matches(id, scratch, onEvent, context);
}
hs_free_database(db);
}
-TEST(HyperscanArgChecks, ResetAndCopyStreamNoScratch) {
+// hs_reset_and_copy_stream: You're allowed to reset and copy a stream with no
+// scratch and no callback.
+TEST(HyperscanArgChecks, ResetAndCopyStreamNoCallbackOrScratch) {
hs_stream_t *stream = nullptr;
hs_stream_t *stream_to = nullptr;
hs_database_t *db = nullptr;
ASSERT_EQ(HS_SUCCESS, err);
err = hs_reset_and_copy_stream(stream_to, stream, nullptr, nullptr, nullptr);
+ ASSERT_EQ(HS_SUCCESS, err);
+
+ hs_close_stream(stream_to, scratch, nullptr, nullptr);
+ hs_close_stream(stream, scratch, nullptr, nullptr);
+ hs_free_scratch(scratch);
+ hs_free_database(db);
+}
+
+// hs_reset_and_copy_stream: If you specify a callback, you must provide
+// scratch.
+TEST(HyperscanArgChecks, ResetAndCopyStreamNoScratch) {
+ hs_stream_t *stream = nullptr;
+ hs_stream_t *stream_to = nullptr;
+ hs_database_t *db = nullptr;
+ hs_compile_error_t *compile_err = nullptr;
+ hs_error_t err = hs_compile("foobar", 0, HS_MODE_STREAM, nullptr, &db,
+ &compile_err);
+ ASSERT_EQ(HS_SUCCESS, err);
+
+ hs_scratch_t *scratch = nullptr;
+ err = hs_alloc_scratch(db, &scratch);
+ ASSERT_EQ(HS_SUCCESS, err);
+
+ err = hs_open_stream(db, 0, &stream);
+ ASSERT_EQ(HS_SUCCESS, err);
+
+ err = hs_open_stream(db, 0, &stream_to);
+ ASSERT_EQ(HS_SUCCESS, err);
+
+ err = hs_reset_and_copy_stream(stream_to, stream, nullptr, dummy_cb,
+ nullptr);
ASSERT_EQ(HS_INVALID, err);
hs_close_stream(stream_to, scratch, nullptr, nullptr);
err = hs_open_stream(db2, 0, &stream_to);
ASSERT_EQ(HS_SUCCESS, err);
- err = hs_reset_and_copy_stream(stream_to, stream, scratch, nullptr, nullptr);
+ err = hs_reset_and_copy_stream(stream_to, stream, scratch, nullptr,
+ nullptr);
ASSERT_EQ(HS_INVALID, err);
hs_close_stream(stream_to, scratch, nullptr, nullptr);
free(local_garbage);
}
+// hs_reset_stream: bad scratch arg
TEST(HyperscanArgChecks, ResetStreamBadScratch) {
hs_database_t *db = nullptr;
hs_compile_error_t *compile_err = nullptr;
ASSERT_EQ(HS_SUCCESS, err);
ASSERT_TRUE(stream != nullptr);
- err = hs_reset_stream(stream, 0, scratch, nullptr, nullptr);
+ err = hs_reset_stream(stream, 0, scratch, dummy_cb, nullptr);
EXPECT_NE(HS_SUCCESS, err);
EXPECT_NE(HS_SCAN_TERMINATED, err);
c.matches.clear();
- err = hs_reset_stream(stream, 0, scratch, nullptr, nullptr);
+ // Note: we do not need matches from this reset operation, so we do not
+ // need to supply a callback or scratch space.
+ err = hs_reset_stream(stream, 0, nullptr, nullptr, nullptr);
ASSERT_EQ(HS_SUCCESS, err);
err = hs_scan_stream(stream, data1, sizeof(data1), 0, scratch, record_cb2,
c.matches.clear();
- err = hs_reset_stream(stream, 0, scratch, nullptr, nullptr);
+ // Note: we do not need matches from this reset operation, so we do not
+ // need to supply a callback or scratch space.
+ err = hs_reset_stream(stream, 0, nullptr, nullptr, nullptr);
ASSERT_EQ(HS_SUCCESS, err);
err = hs_scan_stream(stream, data1, sizeof(data1), 0, scratch, record_cb,
c.matches.clear();
- err = hs_reset_and_copy_stream(stream, stream2, scratch, nullptr, nullptr);
+ err = hs_reset_and_copy_stream(stream, stream2, nullptr, nullptr, nullptr);
ASSERT_EQ(HS_SUCCESS, err);
err = hs_scan_stream(stream, data1, sizeof(data1), 0, scratch, record_cb2,
c.matches.clear();
- err = hs_reset_and_copy_stream(stream, stream2, scratch, nullptr, nullptr);
+ err = hs_reset_and_copy_stream(stream, stream2, nullptr, nullptr, nullptr);
ASSERT_EQ(HS_SUCCESS, err);
err = hs_scan_stream(stream, data1, sizeof(data1), 0, scratch, record_cb,
c.matches.clear();
- err = hs_reset_and_copy_stream(stream2, stream, scratch, nullptr, nullptr);
+ err = hs_reset_and_copy_stream(stream2, stream, nullptr, nullptr, nullptr);
ASSERT_EQ(HS_SUCCESS, err);
err = hs_scan_stream(stream, data1, sizeof(data1), 0, scratch, record_cb,
c.matches.clear();
- err = hs_reset_and_copy_stream(stream2, stream, scratch, nullptr, nullptr);
+ err = hs_reset_and_copy_stream(stream2, stream, nullptr, nullptr, nullptr);
ASSERT_EQ(HS_SUCCESS, err);
err = hs_scan_stream(stream, data1, sizeof(data1), 0, scratch, record_cb,
ASSERT_EQ(HS_SUCCESS, err);
ASSERT_EQ(0U, c.matches.size());
- err = hs_reset_and_copy_stream(stream2, stream, scratch, nullptr, nullptr);
+ err = hs_reset_and_copy_stream(stream2, stream, nullptr, nullptr, nullptr);
ASSERT_EQ(HS_SUCCESS, err);
err = hs_scan_stream(stream, data1, sizeof(data1), 0, scratch, record_cb,