std::search on single-pass range
Asked Answered
A

1

8

I'd like to read from a std::istream until a certain sequence of characters is found, i.e., I'd like to implement the following interface:

void read_until (std::istream &is, std::string_view needle);

Using std::istreambuf_iterator, I believe this is equivalent to a combination of std::search on a single-pass iterator. Unfortunately, the std::boyer_moore_searcher needs random-access iterators.

Are there any easy implementations of the above interface using the C++ standard library (and a bit of memory proportional to the size of sv), or do I have to code it myself?

Alfredoalfresco answered 26/2, 2018 at 21:30 Comment(3)
And where exactly are you reading this data into? Or are you simply going to advance the stream to that point?Allure
Simply advancing the stream. For example when parsing and I expect a certain keyword next, and I don't want to be very picky and just say "skip everything until you have found that sequence of characters".Alfredoalfresco
Um, std::search works on any forward iterator. Now, your istream iterator isn't a forward iterator, but you don't need random access at least.Ardellardella
A
1
void read_until (std::istream &is, std::string_view needle) {
  if (needle.size()==0) return;
  std::string buff;
  buff.reserve(needle.size());
  auto it = std::find_if( std::istream_iterator<char>(is), std::istream_iterator<char>(), [&](char c) {
    buff.push_back(c);
    if (buff.size() < needle.size()) {
      return false;
    }
    if (buff == needle)
      return true;
    buff.erase(buff.begin());
    return false;
  });
}

that is the best I can do with std algorithms.

For optimization, using a circular buff might save a bit of work.

Ardellardella answered 2/10, 2018 at 18:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.