Fixed stream seek problem. Fixed CompoundFile::Save()

This commit is contained in:
Ivan Morozov
2022-08-25 16:51:41 +03:00
parent 85b3ccafc4
commit 1d0e88553e
42 changed files with 5458 additions and 0 deletions

View File

@ -0,0 +1,41 @@
#pragma once
//#include "../../DocxFormat/Source/Base/Nullable.h"
#include <memory>
namespace RedBlackTree
{
class IRBNode;
using PIRBNode = std::shared_ptr<IRBNode>;
using WPIRBNode = std::weak_ptr<IRBNode>;
enum Color
{
RED = 0,
BLACK = 1
};
class IRBNode
{
public:
virtual void setLeft(PIRBNode pNode) = 0;
virtual void setRight(PIRBNode pNode) = 0;
virtual PIRBNode getLeft() const = 0;
virtual PIRBNode getRight() const = 0;
virtual void setColor(Color clr) = 0;
virtual Color getColor()const = 0;
virtual void setParent(PIRBNode pParent) = 0;
virtual PIRBNode getParent() const = 0;
virtual PIRBNode Grandparent() const = 0;
virtual PIRBNode Sibling() const = 0;
virtual PIRBNode Uncle() const = 0;
virtual void AssignValueTo(PIRBNode other) = 0;
virtual int CompareTo(const PIRBNode& other) const = 0;
virtual std::wstring ToString() const = 0;
};
}

View File

@ -0,0 +1,434 @@
#include "rbtree.h"
#include "rbtreeexception.h"
using namespace RedBlackTree;
RBTree::RBTree(PIRBNode root) : root(root)
{}
const PIRBNode RBTree::getRoot() const
{
return root;
}
void RBTree::setRoot(const PIRBNode &newRoot)
{
root = newRoot;
}
bool RBTree::TryLookup(PIRBNode templ, PIRBNode &val)
{
PIRBNode n = LookupNode(templ);
if (n == nullptr)
{
val.reset();
return false;
}
else
{
val = n;
return true;
}
}
void RBTree::Insert(PIRBNode newNode)
{
newNode->setColor(Color::RED);
PIRBNode insertedNode = newNode;
if (getRoot() == nullptr)
{
setRoot(insertedNode);
}
else
{
PIRBNode n = getRoot();
while (true)
{
int compResult = newNode->CompareTo(n);
if (compResult == 0)
{
throw RBTreeDuplicatedItemException(L"RBNode " + newNode->ToString() + L" already present in tree");
//n->Value = value;
//return;
}
else if (compResult < 0)
{
if (n->getLeft() == nullptr)
{
n->setLeft(insertedNode);
break;
}
else
{
n = n->getLeft();
}
}
else
{
//assert compResult > 0;
if (n->getRight() == nullptr)
{
n->setRight(insertedNode);
break;
}
else
{
n = n->getRight();
}
}
}
insertedNode->setParent(n);
}
InsertCase1(insertedNode);
// if (NodeInserted != nullptr)
// {
// NodeInserted(insertedNode);
// }
//Trace.WriteLine(" ");
//Print();
}
void RBTree::Delete(PIRBNode templ, PIRBNode &deletedAlt)
{
deletedAlt.reset();
PIRBNode n = LookupNode(templ);
templ = n;
if (n == nullptr)
return; // Key not found, do nothing
if (n->getLeft() != nullptr && n->getRight() != nullptr)
{
// Copy key/value from predecessor and then delete it instead
PIRBNode pred = MaximumNode(n->getLeft());
pred->AssignValueTo(n);
n = pred;
deletedAlt = pred;
}
//assert n->left == null || n->right == null;
PIRBNode child = (n->getRight() == nullptr) ? n->getLeft() : n->getRight();
if (NodeColor(n) == Color::BLACK)
{
n->setColor(NodeColor(child));
DeleteCase1(n);
}
ReplaceNode(n, child);
if (NodeColor(getRoot()) == Color::RED)
{
getRoot()->setColor(Color::BLACK);
}
return;
}
void RBTree::VisitTree(Action<PIRBNode> action)
{
PIRBNode walker = getRoot();
if (walker != nullptr)
DoVisitTree(action, walker);
}
Color RBTree::NodeColor(PIRBNode n)
{
return n == nullptr ? Color::BLACK : n->getColor();
}
PIRBNode RBTree::MaximumNode(PIRBNode n)
{
while (n->getRight() != nullptr)
{
n = n->getRight();
}
return n;
}
PIRBNode RBTree::LookupNode(PIRBNode templ)
{
PIRBNode n = getRoot();
while (n != nullptr)
{
int compResult = templ->CompareTo(n);
if (compResult == 0)
{
return n;
}
else if (compResult < 0)
{
n = n->getLeft();
}
else
{
//assert compResult > 0;
n = n->getRight();
}
}
return n;
}
void RBTree::ReplaceNode(PIRBNode oldn, PIRBNode newn)
{
if (oldn->getParent() == nullptr)
{
setRoot(newn);
}
else
{
if (oldn == oldn->getParent()->getLeft())
oldn->getParent()->setLeft(newn);
else
oldn->getParent()->setRight(newn);
}
if (newn != nullptr)
{
newn->setParent(oldn->getParent());
}
}
void RBTree::RotateLeft(PIRBNode n)
{
PIRBNode r = n->getRight();
ReplaceNode(n, r);
n->setRight(r->getLeft());
if (r->getLeft() != nullptr)
{
r->getLeft()->setParent(n);
}
r->setLeft(n);
n->setParent(r);
}
void RBTree::RotateRight(PIRBNode n)
{
PIRBNode l = n->getLeft();
ReplaceNode(n, l);
n->setLeft(l->getRight());
if (l->getRight() != nullptr)
{
l->getRight()->setParent(n);
}
l->setRight(n);
n->setParent(l);
}
void RBTree::InsertCase1(PIRBNode n)
{
if (n->getParent() == nullptr)
n->setColor(Color::BLACK);
else
InsertCase2(n);
}
void RBTree::InsertCase2(PIRBNode n)
{
if (NodeColor(n->getParent()) == Color::BLACK)
return; // Tree is still valid
else
InsertCase3(n);
}
void RBTree::InsertCase3(PIRBNode n)
{
if (NodeColor(n->Uncle()) == Color::RED)
{
n->getParent()->setColor(Color::BLACK);
n->Uncle()->setColor(Color::BLACK);
n->Grandparent()->setColor(Color::RED);
InsertCase1(n->Grandparent());
}
else
{
InsertCase4(n);
}
}
void RBTree::InsertCase4(PIRBNode n)
{
if (n == n->getParent()->getRight() && n->getParent() == n->Grandparent()->getLeft())
{
RotateLeft(n->getParent());
n = n->getLeft();
}
else if (n == n->getParent()->getLeft() && n->getParent() == n->Grandparent()->getRight())
{
RotateRight(n->getParent());
n = n->getRight();
}
InsertCase5(n);
}
void RBTree::InsertCase5(PIRBNode n)
{
n->getParent()->setColor(Color::BLACK);
n->Grandparent()->setColor(Color::RED);
if (n == n->getParent()->getLeft() && n->getParent() == n->Grandparent()->getLeft())
{
RotateRight(n->Grandparent());
}
else
{
//assert n == n->getParent().right && n->getParent() == n->grandparent().right;
RotateLeft(n->Grandparent());
}
}
void RBTree::DeleteCase1(PIRBNode n)
{
if (n->getParent() == nullptr)
return;
else
DeleteCase2(n);
}
void RBTree::DeleteCase2(PIRBNode n)
{
if (NodeColor(n->Sibling()) == Color::RED)
{
n->getParent()->setColor(Color::RED);
n->Sibling()->setColor(Color::BLACK);
if (n == n->getParent()->getLeft())
RotateLeft(n->getParent());
else
RotateRight(n->getParent());
}
DeleteCase3(n);
}
void RBTree::DeleteCase3(PIRBNode n)
{
if (NodeColor(n->getParent()) == Color::BLACK &&
NodeColor(n->Sibling()) == Color::BLACK &&
NodeColor(n->Sibling()->getLeft()) == Color::BLACK &&
NodeColor(n->Sibling()->getRight()) == Color::BLACK)
{
n->Sibling()->setColor(Color::RED);
DeleteCase1(n->getParent());
}
else
DeleteCase4(n);
}
void RBTree::DeleteCase4(PIRBNode n)
{
if (NodeColor(n->getParent()) == Color::RED &&
NodeColor(n->Sibling()) == Color::BLACK &&
NodeColor(n->Sibling()->getLeft()) == Color::BLACK &&
NodeColor(n->Sibling()->getRight()) == Color::BLACK)
{
n->Sibling()->setColor(Color::RED);
n->getParent()->setColor(Color::BLACK);
}
else
DeleteCase5(n);
}
void RBTree::DeleteCase5(PIRBNode n)
{
if (n == n->getParent()->getLeft() &&
NodeColor(n->Sibling()) == Color::BLACK &&
NodeColor(n->Sibling()->getLeft()) == Color::RED &&
NodeColor(n->Sibling()->getRight()) == Color::BLACK)
{
n->Sibling()->setColor(Color::RED);
n->Sibling()->getLeft()->setColor(Color::BLACK);
RotateRight(n->Sibling());
}
else if (n == n->getParent()->getRight() &&
NodeColor(n->Sibling()) == Color::BLACK &&
NodeColor(n->Sibling()->getRight()) == Color::RED &&
NodeColor(n->Sibling()->getLeft()) == Color::BLACK)
{
n->Sibling()->setColor(Color::RED);
n->Sibling()->getRight()->setColor(Color::BLACK);
RotateLeft(n->Sibling());
}
DeleteCase6(n);
}
void RBTree::DeleteCase6(PIRBNode n)
{
n->Sibling()->setColor(NodeColor(n->getParent()));
n->getParent()->setColor(Color::BLACK);
if (n == n->getParent()->getLeft())
{
//assert nodeColor(n->sibling().right) == Color::RED;
n->Sibling()->getRight()->setColor(Color::BLACK);
RotateLeft(n->getParent());
}
else
{
//assert nodeColor(n->sibling().left) == Color::RED;
n->Sibling()->getLeft()->setColor(Color::BLACK);
RotateRight(n->getParent());
}
}
void RBTree::DoVisitTree(Action<PIRBNode> action, PIRBNode walker)
{
if (walker->getLeft() != nullptr)
{
DoVisitTree(action, walker->getLeft());
}
if (action != nullptr)
action(walker);
if (walker->getRight() != nullptr)
{
DoVisitTree(action, walker->getRight());
}
}
void RBTree::VisitTreeNodes(Action<PIRBNode> action)
{
//IN Order visit
PIRBNode walker = getRoot();
if (walker != nullptr)
DoVisitTreeNodes(action, walker);
}
void RBTree::DoVisitTreeNodes(Action<PIRBNode> action, PIRBNode walker)
{
if (walker->getLeft() != nullptr)
{
DoVisitTreeNodes(action, walker->getLeft());
}
if (action != nullptr)
action(walker);
if (walker->getRight() != nullptr)
{
DoVisitTreeNodes(action, walker->getRight());
}
}
RBTree::iterator::iterator(RBTree &tree, bool end)
{
Action<PIRBNode> inserter = [&] (PIRBNode pNode)
{
heap.push_back(pNode);
};
tree.VisitTreeNodes(inserter);
current = end ? heap.end() : heap.begin();
}

View File

@ -0,0 +1,77 @@
#pragma once
#include "irbnode.h"
#include <iterator>
#include <functional>
#include <list>
namespace RedBlackTree
{
template <class T>
using Action = std::function<void(T)>;
class RBTree
{
public:
RBTree(){}
RBTree(PIRBNode root);
const PIRBNode getRoot() const;
void setRoot(const PIRBNode &newRoot);
bool TryLookup(PIRBNode templ, PIRBNode& val);
void Insert(PIRBNode newNode);
void Delete(PIRBNode templ, PIRBNode& deletedAlt);
void VisitTree(Action<PIRBNode> action);
void VisitTreeNodes(Action<PIRBNode> action);
private:
static Color NodeColor(PIRBNode n);
static PIRBNode MaximumNode(PIRBNode n);
PIRBNode LookupNode(PIRBNode templ);
void ReplaceNode(PIRBNode oldn, PIRBNode newn);
void RotateLeft(PIRBNode n);
void RotateRight(PIRBNode n);
void InsertCase1(PIRBNode n);
void InsertCase2(PIRBNode n);
void InsertCase3(PIRBNode n);
void InsertCase4(PIRBNode n);
void InsertCase5(PIRBNode n);
void DeleteCase1(PIRBNode n);
void DeleteCase2(PIRBNode n);
void DeleteCase3(PIRBNode n);
void DeleteCase4(PIRBNode n);
void DeleteCase5(PIRBNode n);
void DeleteCase6(PIRBNode n);
void DoVisitTree(Action<PIRBNode> action, PIRBNode walker);
void DoVisitTreeNodes(Action<PIRBNode> action, PIRBNode walker);
public:
// todo this from C# and it's weak realization
class iterator : public std::iterator<std::bidirectional_iterator_tag, std::ptrdiff_t, IRBNode, IRBNode*, PIRBNode>
{
std::list<WPIRBNode> heap;
std::list<WPIRBNode>::iterator current;
public:
iterator(RBTree &tree, bool end = false);
inline iterator& operator++() {++current; return *this;}
inline iterator& operator--() {--current; return *this;}
inline bool operator==(const iterator &other) const {return current == other.current;}
inline bool operator!=(const iterator &other) const {return current != other.current;}
inline PIRBNode operator*() {return current->lock();}
inline iterator end() {current = heap.end(); return *this;}
};
iterator&& begin() {return std::move(iterator(*this));}
iterator&& end() {return std::move(iterator(*this).end());}
private:
PIRBNode root;
};
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <exception>
#include <string>
namespace RedBlackTree
{
class RBTreeException : virtual public std::exception
{
public:
RBTreeException() {}
RBTreeException(std::wstring message) : errorMessage(message) {}
RBTreeException(std::wstring message, std::exception& ex) : std::exception(ex), errorMessage(message) {}
virtual ~RBTreeException() throw () {}
virtual const wchar_t* what_w() const throw () {
return errorMessage.c_str();
}
protected:
std::wstring errorMessage;
};
class RBTreeDuplicatedItemException : public RBTreeException
{
public:
RBTreeDuplicatedItemException(std::wstring msg)
: RBTreeException(msg)
{
}
};
}