void SearchTree::compile() { assert(!m_ready); // at the top level assign root as the failure node std::queue<SearchNode*> nodesByLevel; for (std::size_t i = 0; i < m_rootNode.getNextSize(); ++i) { SearchNode* next = m_rootNode.getNext(static_cast<const unsigned char>(i)); if (!next) { m_rootNode.setNext(static_cast<const unsigned char>(i), &m_rootNode); } else { next->setFailure(&m_rootNode); nodesByLevel.push(next); } } // now loop through all levels computing failure nodes. Push more on as needed while (!nodesByLevel.empty()) { SearchNode* currentNode = nodesByLevel.front(); for (std::size_t i = 0; i < currentNode->getNextSize(); ++i) { SearchNode* next = currentNode->getNext(static_cast<const unsigned char>(i)); if (next) { nodesByLevel.push(next); next->setFailure( currentNode->getFailure()->getNext( static_cast<const unsigned char>(i))); if (!next->getFailure()->getStoredData().empty()) { next->addReturnValues(next->getFailure()->getStoredData()); } } else { currentNode->setNext(static_cast<const unsigned char>(i), currentNode->getFailure()->getNext( static_cast<const unsigned char>(i))); } } nodesByLevel.pop(); } m_ready = true; }
std::set<const char*> SearchTree::findOffsets(const char* const p_inputString, const std::size_t p_inputLength) { std::set<const char*> returnValue; SearchNode* currentNode = &m_rootNode; const char* end = p_inputString + p_inputLength; for (const char* start = p_inputString; start < end; ++start) { currentNode = currentNode->getNext(*start); if (!currentNode->getStoredData().empty()) { returnValue.insert(start - 3); } } return returnValue; }
std::set<void*> SearchTree::search(const unsigned char* const p_inputString, const std::size_t p_inputLength) { assert(m_ready && p_inputString != NULL); std::set<void*> returnValue; SearchNode* currentNode = &m_rootNode; const unsigned char* end = p_inputString + p_inputLength; for (const unsigned char* start = p_inputString; start < end; ++start) { currentNode = currentNode->getNext(*start); if (!currentNode->getStoredData().empty()) { const std::set<void*>& mergeThis(currentNode->getStoredData()); returnValue.insert(mergeThis.begin(), mergeThis.end()); } } return returnValue; }