2016-06-15 23:48:41 +02:00
|
|
|
#ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_
|
|
|
|
#define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_
|
|
|
|
|
|
|
|
#include <framework/container/BinaryTree.h>
|
|
|
|
#include <framework/globalfunctions/matching/SerializeableMatcherIF.h>
|
|
|
|
#include <framework/serialize/SerializeAdapter.h>
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class MatchTree: public SerializeableMatcherIF<T>, public BinaryTree<
|
|
|
|
SerializeableMatcherIF<T>> {
|
|
|
|
public:
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
static const uint8_t INTERFACE_ID = CLASS_ID::MATCH_TREE_CLASS;
|
2016-06-15 23:48:41 +02:00
|
|
|
static const ReturnValue_t TOO_DETAILED_REQUEST = MAKE_RETURN_CODE(1);
|
|
|
|
static const ReturnValue_t TOO_GENERAL_REQUEST = MAKE_RETURN_CODE(2);
|
|
|
|
static const ReturnValue_t NO_MATCH = MAKE_RETURN_CODE(3);
|
|
|
|
static const ReturnValue_t FULL = MAKE_RETURN_CODE(4);
|
2018-07-12 16:29:32 +02:00
|
|
|
static const ReturnValue_t NEW_NODE_CREATED = MAKE_RETURN_CODE(5);
|
2016-06-15 23:48:41 +02:00
|
|
|
|
|
|
|
typedef typename BinaryTree<SerializeableMatcherIF<T>>::iterator iterator;
|
|
|
|
typedef BinaryNode<SerializeableMatcherIF<T>> Node;
|
|
|
|
static const bool AND = true; //LEFT
|
|
|
|
static const bool OR = false; //RIGHT
|
|
|
|
MatchTree(BinaryNode<SerializeableMatcherIF<T>>* root,
|
|
|
|
uint8_t maxDepth = -1) :
|
|
|
|
BinaryTree<SerializeableMatcherIF<T>>(root), maxDepth(maxDepth) {
|
|
|
|
}
|
|
|
|
MatchTree(iterator root, uint8_t maxDepth = -1) :
|
|
|
|
BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(
|
|
|
|
maxDepth) {
|
|
|
|
}
|
|
|
|
MatchTree() :
|
|
|
|
BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {
|
|
|
|
}
|
|
|
|
virtual ~MatchTree() {
|
|
|
|
}
|
|
|
|
virtual bool match(T number) {
|
2018-07-12 16:29:32 +02:00
|
|
|
return matchesTree(number);
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
bool matchesTree(T number) {
|
2016-06-15 23:48:41 +02:00
|
|
|
iterator iter = this->begin();
|
2018-07-12 16:29:32 +02:00
|
|
|
if (iter == this->end()) {
|
|
|
|
return false;
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
return matchSubtree(iter, number);
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2020-04-05 17:58:39 +02:00
|
|
|
ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
|
|
|
const size_t max_size, bool bigEndian) const {
|
2016-06-15 23:48:41 +02:00
|
|
|
iterator iter = this->begin();
|
|
|
|
uint8_t count = this->countRight(iter);
|
|
|
|
ReturnValue_t result = SerializeAdapter<uint8_t>::serialize(&count,
|
|
|
|
buffer, size, max_size, bigEndian);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if (iter == this->end()) {
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
|
|
|
result = iter->serialize(buffer, size, max_size, bigEndian);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if (maxDepth > 0) {
|
|
|
|
MatchTree<T> temp(iter.left(), maxDepth - 1);
|
|
|
|
result = temp.serialize(buffer, size, max_size, bigEndian);
|
|
|
|
}
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
iter = iter.right();
|
|
|
|
while (iter != this->end()) {
|
|
|
|
result = iter->serialize(buffer, size, max_size, bigEndian);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if (maxDepth > 0) {
|
|
|
|
MatchTree<T> temp(iter.left(), maxDepth - 1);
|
|
|
|
result = temp.serialize(buffer, size, max_size, bigEndian);
|
|
|
|
}
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
iter = iter.right();
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-04-05 21:54:11 +02:00
|
|
|
size_t getSerializedSize() const {
|
2016-06-15 23:48:41 +02:00
|
|
|
//Analogous to serialize!
|
|
|
|
uint32_t size = 1; //One for count
|
|
|
|
iterator iter = this->begin();
|
|
|
|
if (iter == this->end()) {
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
//Count object itself
|
|
|
|
size += iter->getSerializedSize();
|
|
|
|
//Handle everything below on AND side
|
|
|
|
if (maxDepth > 0) {
|
|
|
|
MatchTree<T> temp(iter.left(), maxDepth - 1);
|
|
|
|
size += temp.getSerializedSize();
|
|
|
|
}
|
|
|
|
//Handle everything on OR side
|
|
|
|
iter = iter.right();
|
|
|
|
//Iterate over every object on the OR branch
|
|
|
|
while (iter != this->end()) {
|
|
|
|
size += iter->getSerializedSize();
|
|
|
|
if (maxDepth > 0) {
|
|
|
|
//If we are allowed to go deeper, handle AND elements.
|
|
|
|
MatchTree<T> temp(iter.left(), maxDepth - 1);
|
|
|
|
size += temp.getSerializedSize();
|
|
|
|
}
|
|
|
|
iter = iter.right();
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2020-04-15 15:53:46 +02:00
|
|
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
2018-07-12 16:29:32 +02:00
|
|
|
bool bigEndian) {
|
2016-06-15 23:48:41 +02:00
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
bool isOnAndBranch(iterator position) {
|
|
|
|
if ((position == this->end()) || (position.up() == this->end())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (position.up().left() == position) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
//SHOULDDO: What to do if insertion/deletion fails. Throw event?
|
2016-06-15 23:48:41 +02:00
|
|
|
ReturnValue_t removeElementAndAllChildren(iterator position) {
|
2018-07-12 16:29:32 +02:00
|
|
|
auto children = this->erase(position);
|
2016-06-15 23:48:41 +02:00
|
|
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
|
|
|
if (children.first != this->end()) {
|
|
|
|
result = removeElementAndAllChildren(children.first);
|
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
2016-06-15 23:48:41 +02:00
|
|
|
if (children.second != this->end()) {
|
|
|
|
result = removeElementAndAllChildren(children.second);
|
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
2016-06-15 23:48:41 +02:00
|
|
|
//Delete element itself.
|
|
|
|
return cleanUpElement(position);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t removeElementAndReconnectChildren(iterator position) {
|
|
|
|
if (position == this->end()) {
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
|
|
|
//Delete everything from the AND branch.
|
|
|
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
|
|
|
if (position.left() != this->end()) {
|
|
|
|
result = removeElementAndAllChildren(position.left());
|
2018-07-12 16:29:32 +02:00
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
2018-07-12 16:29:32 +02:00
|
|
|
|
2016-06-15 23:48:41 +02:00
|
|
|
if (position.right() != this->end()) {
|
|
|
|
//There's something at the OR branch, reconnect to parent.
|
|
|
|
if (isOnAndBranch(position)) {
|
|
|
|
//Either one hierarchy up AND branch...
|
2018-07-12 16:29:32 +02:00
|
|
|
this->insert(AND, position.up(), position.right().element);
|
2016-06-15 23:48:41 +02:00
|
|
|
} else {
|
|
|
|
//or on another OR'ed element (or install new root node).
|
2018-07-12 16:29:32 +02:00
|
|
|
this->insert(OR, position.up(), position.right().element);
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (isOnAndBranch(position)) {
|
|
|
|
//Recursively delete parent node as well, because it is not expected to be there anymore.
|
|
|
|
return removeElementAndReconnectChildren(position.up());
|
|
|
|
} else {
|
|
|
|
//simply delete self.
|
2018-07-12 16:29:32 +02:00
|
|
|
this->erase(position);
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
//Delete element itself.
|
|
|
|
return cleanUpElement(position);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ReturnValue_t cleanUpElement(iterator position) {
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
bool matchSubtree(iterator iter, T number) {
|
|
|
|
bool isMatch = iter->match(number);
|
|
|
|
if (isMatch) {
|
|
|
|
if (iter.left() == this->end()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
isMatch = matchSubtree(iter.left(), number);
|
|
|
|
if (isMatch) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (iter.right() == this->end()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return matchSubtree(iter.right(), number);
|
|
|
|
}
|
2016-06-15 23:48:41 +02:00
|
|
|
private:
|
|
|
|
uint8_t maxDepth;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_ */
|