cpp-utilities/io/buffersearch.cpp

81 lines
3.0 KiB
C++

#include "./buffersearch.h"
using namespace std;
namespace CppUtilities {
/*!
* \class BufferSearch
* \brief The BufferSearch struct invokes a callback if an initially given search term occurs in consecutively provided buffers.
* \remarks
* - The class works without making internal copies of the specified buffers, except for the search result.
* - The callback is invoked after the search term has been found and one of the specified termination characters occurred. The
* search result is passed to the callback.
* - The "search result" is the data after the last character of the search term and before any of the specified termination
* characters.
* - If no termination characters are specified, the callback is invoked directly after the search term occurred (with an empty
* search result).
* - If the specified give-up term has occurred, operator() will exit early and the specified callback will not be invoked
* anymore.
* - If the callback has been invoked, operator() will exit early and the callback will not be invoked anymore (even if the
* search term occurs again). Call reset() after consuming the result within the callback to continue the search.
*/
/*!
* \brief Processes the specified \a buffer. Invokes the callback according to the remarks mentioned in the class documentation.
*/
void BufferSearch::operator()(const std::string_view::value_type *buffer, std::size_t bufferSize)
{
if (m_hasResult || (!m_giveUpTerm.empty() && m_giveUpTermIterator == m_giveUpTerm.end())) {
return;
}
for (auto i = buffer, end = buffer + bufferSize; i != end; ++i) {
const auto currentChar = *i;
if (m_searchTermIterator == m_searchTerm.end()) {
if (m_terminationChars.empty()) {
m_hasResult = true;
} else {
for (const auto &terminationChar : m_terminationChars) {
if (currentChar == terminationChar) {
m_hasResult = true;
break;
}
}
}
if (m_hasResult) {
m_callback(*this, std::move(m_result));
return;
}
m_result += currentChar;
continue;
}
if (currentChar == *m_searchTermIterator) {
++m_searchTermIterator;
} else {
m_searchTermIterator = m_searchTerm.begin();
}
if (m_giveUpTerm.empty()) {
continue;
}
if (currentChar == *m_giveUpTermIterator) {
++m_giveUpTermIterator;
} else {
m_giveUpTermIterator = m_giveUpTerm.begin();
}
}
}
/*!
* \brief Resets the search to its initial state (assuming no characters of the search term or give-up term have been found yet).
*/
void BufferSearch::reset()
{
m_searchTermIterator = m_searchTerm.begin();
m_giveUpTermIterator = m_giveUpTerm.begin();
m_terminationTermIterator = m_terminationTerm.begin();
m_hasResult = false;
m_result.clear();
}
} // namespace CppUtilities