improved scanner interface

This commit is contained in:
2025-10-06 14:21:52 +03:00
parent 131fd891b0
commit 170f969697
2 changed files with 39 additions and 25 deletions

View File

@@ -5,9 +5,9 @@
#pragma once #pragma once
#include <expected> #include <expected>
#include <optional> #include <optional>
#include <span>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include <span>
// ReSharper disable once CppInconsistentNaming // ReSharper disable once CppInconsistentNaming
class unit_test_pattern_scan_read_test_Test; class unit_test_pattern_scan_read_test_Test;
@@ -20,7 +20,6 @@ class unit_test_pattern_scan_corner_case_3_Test;
// ReSharper disable once CppInconsistentNaming // ReSharper disable once CppInconsistentNaming
class unit_test_pattern_scan_corner_case_4_Test; class unit_test_pattern_scan_corner_case_4_Test;
namespace omath namespace omath
{ {
enum class PatternScanError enum class PatternScanError
@@ -34,10 +33,42 @@ namespace omath
friend unit_test_pattern_scan_corner_case_2_Test; friend unit_test_pattern_scan_corner_case_2_Test;
friend unit_test_pattern_scan_corner_case_3_Test; friend unit_test_pattern_scan_corner_case_3_Test;
friend unit_test_pattern_scan_corner_case_4_Test; friend unit_test_pattern_scan_corner_case_4_Test;
public: public:
[[nodiscard]] [[nodiscard]]
static std::optional<std::span<std::byte>::const_iterator> static std::optional<std::span<std::byte>::const_iterator> scan_for_pattern(const std::span<std::byte>& range,
scan_for_pattern(const std::string_view& pattern, const std::span<std::byte>& range); const std::string_view& pattern);
template<class IteratorType>
static IteratorType scan_for_pattern(const IteratorType& begin, const IteratorType& end,
const std::string_view& pattern)
{
const auto parsed_pattern = parse_pattern(pattern);
if (!parsed_pattern) [[unlikely]]
return end;
const auto whole_range_size = static_cast<std::ptrdiff_t>(std::distance(begin, end));
const std::ptrdiff_t scan_size = whole_range_size - static_cast<std::ptrdiff_t>(pattern.size());
for (std::ptrdiff_t i = 0; i < scan_size; i++)
{
bool found = true;
for (std::ptrdiff_t j = 0; j < static_cast<std::ptrdiff_t>(parsed_pattern->size()); j++)
{
found = parsed_pattern->at(j) == std::nullopt || parsed_pattern->at(j) == *(begin + i + j);
if (!found)
break;
}
if (found)
return begin + i;
}
return end;
}
private: private:
[[nodiscard]] [[nodiscard]]
static std::expected<std::vector<std::optional<std::byte>>, PatternScanError> static std::expected<std::vector<std::optional<std::byte>>, PatternScanError>

View File

@@ -8,31 +8,14 @@ namespace omath
{ {
std::optional<std::span<std::byte>::const_iterator> std::optional<std::span<std::byte>::const_iterator>
PatternScanner::scan_for_pattern(const std::string_view& pattern, const std::span<std::byte>& range) PatternScanner::scan_for_pattern(const std::span<std::byte>& range, const std::string_view& pattern)
{ {
const auto parsed_pattern = parse_pattern(pattern); auto result = scan_for_pattern(range.begin(), range.end(), pattern);
if (!parsed_pattern) [[unlikely]] if (result == range.end())
return std::nullopt; return std::nullopt;
const std::ptrdiff_t scan_size = return result;
static_cast<std::ptrdiff_t>(range.size()) - static_cast<std::ptrdiff_t>(pattern.size());
for (std::ptrdiff_t i = 0; i < scan_size; i++)
{
bool found = true;
for (std::ptrdiff_t j = 0; j < static_cast<std::ptrdiff_t>(parsed_pattern->size()); j++)
{
found = parsed_pattern->at(j) == std::nullopt || parsed_pattern->at(j) == *(range.data() + i + j);
if (!found)
break;
}
if (found)
return range.begin() + i;
}
return std::nullopt;
} }
std::expected<std::vector<std::optional<std::byte>>, PatternScanError> std::expected<std::vector<std::optional<std::byte>>, PatternScanError>
PatternScanner::parse_pattern(const std::string_view& pattern_string) PatternScanner::parse_pattern(const std::string_view& pattern_string)