예제 #1
0
 internal DiffgramRemoveSubtrees(XmlDiffNode sourceNode, ulong operationID, bool bSorted)
     : base(operationID)
 {
     this._firstSourceNode = sourceNode;
     this._lastSourceNode  = sourceNode;
     this._bSorted         = bSorted;
 }
예제 #2
0
 internal XmlDiffNode(int position)
 {
     this._parent      = (XmlDiffParentNode)null;
     this._nextSibling = (XmlDiffNode)null;
     this._position    = position;
     this._bExpanded   = false;
 }
예제 #3
0
        private void Sort()
        {
            XmlDiffNode prevSibling = null;

            XmlDiff.SortNodesByPosition(ref _firstSourceNode, ref _lastSourceNode, ref prevSibling);
            _bSorted = true;
        }
예제 #4
0
// Constructor
        internal XmlDiffShrankNode(XmlDiffNode firstNode, XmlDiffNode lastNode) : base(-1)
        {
            Debug.Assert(firstNode != null);
            Debug.Assert(lastNode != null);
            Debug.Assert(firstNode.Position <= lastNode.Position);
            Debug.Assert(firstNode.NodeType != XmlDiffNodeType.Attribute ||
                         (firstNode.NodeType == XmlDiffNodeType.Attribute && firstNode == lastNode));

            _firstNode          = firstNode;
            _lastNode           = lastNode;
            _matchingShrankNode = null;

            // hash value
            XmlDiffNode curNode = firstNode;

            for (;;)
            {
                _hashValue += (_hashValue << 7) + curNode.HashValue;
                if (curNode == lastNode)
                {
                    break;
                }
                curNode = curNode._nextSibling;
            }

            _localAddress = DiffgramOperation.GetRelativeAddressOfNodeset(_firstNode, _lastNode);
        }
예제 #5
0
        // Loads the document from XmlReader
        internal virtual void Load(XmlReader reader, XmlHash xmlHash)
        {
            if (_bLoaded)
            {
                throw new InvalidOperationException("The document already contains data and should not be used again.");
            }

            try
            {
                _curLastChild = null;
                _xmlHash      = xmlHash;

                LoadChildNodes(this, reader, false);

                ComputeHashValue(_xmlHash);
                _bLoaded = true;

    #if DEBUG
                if (XmlDiff.T_LoadedDoc.Enabled)
                {
                    Trace.Write("\nLoaded document " + reader.BaseURI + ": \n");
                    Dump();
                }
    #endif
            }
            finally
            {
                _xmlHash = null;
            }
        }
예제 #6
0
// Methods
        internal virtual void InsertChildNodeAfter(XmlDiffNode childNode, XmlDiffNode newChildNode)
        {
            Debug.Assert(newChildNode != null);
            Debug.Assert(!(newChildNode is XmlDiffAttributeOrNamespace));
            Debug.Assert(childNode == null || childNode._parent == this);
#if DEBUG
            if (newChildNode.NodeType == XmlDiffNodeType.Attribute)
            {
                Debug.Assert(childNode == null ||
                             childNode.NodeType == XmlDiffNodeType.Attribute ||
                             childNode.NodeType == XmlDiffNodeType.Namespace);
            }
#endif

            newChildNode._parent = this;
            if (childNode == null)
            {
                newChildNode._nextSibling = _firstChildNode;
                _firstChildNode           = newChildNode;
            }
            else
            {
                newChildNode._nextSibling = childNode._nextSibling;
                childNode._nextSibling    = newChildNode;
            }

            Debug.Assert(newChildNode.NodesCount > 0);
            _nodesCount += newChildNode.NodesCount;

            if (newChildNode.NodeType != XmlDiffNodeType.Element &&
                !(newChildNode is XmlDiffAttributeOrNamespace))
            {
                _elementChildrenOnly = false;
            }
        }
예제 #7
0
        // compares the node to another one and returns the xmldiff operation for changing this node to the other
        internal override XmlDiffOperation GetDiffOperation(XmlDiffNode changedNode, XmlDiff xmlDiff)
        {
            Debug.Assert(changedNode != null);

            if (changedNode.NodeType != XmlDiffNodeType.ProcessingInstruction)
            {
                return(XmlDiffOperation.Undefined);
            }

            XmlDiffPI changedPI = (XmlDiffPI)changedNode;

            if (Name == changedPI.Name)
            {
                if (Value == changedPI.Value)
                {
                    return(XmlDiffOperation.Match);
                }
                else
                {
                    return(XmlDiffOperation.ChangePI);
                }
            }
            else
            {
                if (Value == changedPI.Value)
                {
                    return(XmlDiffOperation.ChangePI);
                }
                else
                {
                    return(XmlDiffOperation.Undefined);
                }
            }
        }
예제 #8
0
//    internal bool _nodeOrDescendantMatches = false;

// Constructors
        internal XmlDiffNode(int position)
        {
            _parent      = null;
            _nextSibling = null;
            _position    = position;
            _bExpanded   = false;
        }
예제 #9
0
        private XmlDiffNode HTFindAndRemoveMatchingNode(
            Hashtable hashtable,
            XmlDiffNodeListHead nodeListHead,
            XmlDiffNode nodeToMatch)
        {
            var first = nodeListHead._first;
            var node  = first._node;

            if (this.IdenticalSubtrees(node, nodeToMatch))
            {
                if (first._next == null)
                {
                    hashtable.Remove(node.HashValue);
                }
                else
                {
                    nodeListHead._first = first._next;
                }
                return(node);
            }
            while (first._next != null)
            {
                if (this.IdenticalSubtrees(first._node, nodeToMatch))
                {
                    first._next = first._next._next;
                    if (first._next == null)
                    {
                        nodeListHead._last = first;
                    }
                    return(node);
                }
            }
            return(null);
        }
//    internal bool _nodeOrDescendantMatches = false;

// Constructors
    internal XmlDiffNode( int position ) 
	{
        _parent = null;
        _nextSibling = null;
        _position = position;
        _bExpanded = false;
    }
예제 #11
0
        internal static void SortNodesByPosition(
            ref XmlDiffNode firstNode,
            ref XmlDiffNode lastNode,
            ref XmlDiffNode firstPreviousSibbling)
        {
            var parent = firstNode._parent;

            if (firstPreviousSibbling == null && firstNode != parent._firstChildNode)
            {
                firstPreviousSibbling = parent._firstChildNode;
                while (firstPreviousSibbling._nextSibling != firstNode)
                {
                    firstPreviousSibbling = firstPreviousSibbling._nextSibling;
                }
            }
            var nextSibling = lastNode._nextSibling;

            lastNode._nextSibling = null;
            var count = 0;

            for (var xmlDiffNode = firstNode; xmlDiffNode != null; xmlDiffNode = xmlDiffNode._nextSibling)
            {
                ++count;
            }
            if (count >= 5)
            {
                XmlDiff.QuickSortNodes(ref firstNode, ref lastNode, count, firstPreviousSibbling, nextSibling);
            }
            else
            {
                XmlDiff.SlowSortNodes(ref firstNode, ref lastNode, firstPreviousSibbling, nextSibling);
            }
        }
예제 #12
0
        internal override bool IsSameAs(XmlDiffNode node, XmlDiff xmlDiff)
        {
            if (node.NodeType != XmlDiffNodeType.Element)
            {
                return(false);
            }
            var xmlDiffElement = (XmlDiffElement)node;

            if (this.LocalName != xmlDiffElement.LocalName || !xmlDiff.IgnoreNamespaces && (this.NamespaceURI != xmlDiffElement.NamespaceURI || !xmlDiff.IgnorePrefixes && this.Prefix != xmlDiffElement.Prefix))
            {
                return(false);
            }
            var attributeOrNamespace1 = this._attributes;

            while (attributeOrNamespace1 != null && attributeOrNamespace1.NodeType == XmlDiffNodeType.Namespace)
            {
                attributeOrNamespace1 = (XmlDiffAttributeOrNamespace)attributeOrNamespace1._nextSibling;
            }
            var attributeOrNamespace2 = this._attributes;

            while (attributeOrNamespace2 != null && attributeOrNamespace2.NodeType == XmlDiffNodeType.Namespace)
            {
                attributeOrNamespace2 = (XmlDiffAttributeOrNamespace)attributeOrNamespace2._nextSibling;
            }
            for (; attributeOrNamespace1 != null && attributeOrNamespace2 != null; attributeOrNamespace2 = (XmlDiffAttributeOrNamespace)attributeOrNamespace2._nextSibling)
            {
                if (!attributeOrNamespace1.IsSameAs((XmlDiffNode)attributeOrNamespace2, xmlDiff))
                {
                    return(false);
                }
                attributeOrNamespace1 = (XmlDiffAttributeOrNamespace)attributeOrNamespace1._nextSibling;
            }
            return(attributeOrNamespace1 == null && attributeOrNamespace2 == null);
        }
예제 #13
0
        internal override XmlDiffOperation GetDiffOperation(
            XmlDiffNode changedNode,
            XmlDiff xmlDiff)
        {
            if (changedNode.NodeType != XmlDiffNodeType.Element)
            {
                return(XmlDiffOperation.Undefined);
            }
            var xmlDiffElement = (XmlDiffElement)changedNode;
            var flag           = false;

            if (this.LocalName == xmlDiffElement.LocalName)
            {
                if (xmlDiff.IgnoreNamespaces)
                {
                    flag = true;
                }
                else if (this.NamespaceURI == xmlDiffElement.NamespaceURI && (xmlDiff.IgnorePrefixes || this.Prefix == xmlDiffElement.Prefix))
                {
                    flag = true;
                }
            }
            if ((long)xmlDiffElement._allAttributesHash == (long)this._allAttributesHash)
            {
                return(!flag ? XmlDiffOperation.ChangeElementName : XmlDiffOperation.Match);
            }
            var num = ((long)xmlDiffElement._attributesHashAH == (long)this._attributesHashAH ? 0 : 1) + ((long)xmlDiffElement._attributesHashIQ == (long)this._attributesHashIQ ? 0 : 1) + ((long)xmlDiffElement._attributesHashRZ == (long)this._attributesHashRZ ? 0 : 1);

            return(flag ? (XmlDiffOperation)(3 + num) : (XmlDiffOperation)(6 + num));
        }
예제 #14
0
 private void HTRemoveAncestors(Hashtable hashtable, XmlDiffNode node)
 {
     for (var parent = (XmlDiffNode)node._parent; parent != null && this.HTRemoveNode(hashtable, parent); parent = parent._parent)
     {
         parent._bSomeDescendantMatches = true;
     }
 }
예제 #15
0
        // compares the node to another one and returns the xmldiff operation for changing this node to the other
        internal override XmlDiffOperation GetDiffOperation(XmlDiffNode changedNode, XmlDiff xmlDiff)
        {
            Debug.Assert(changedNode != null);

            if (NodeType != changedNode.NodeType)
            {
                return(XmlDiffOperation.Undefined);
            }

            XmlDiffCharData changedCD = changedNode as XmlDiffCharData;

            if (changedCD == null)
            {
                return(XmlDiffOperation.Undefined);
            }

            if (Value == changedCD.Value)
            {
                return(XmlDiffOperation.Match);
            }
            else
            {
                return(XmlDiffOperation.ChangeCharacterData);
            }
        }
    // Loads the document from XmlReader
    internal virtual void Load( XmlReader reader, XmlHash xmlHash ) 
    {
        if ( _bLoaded ) 
            throw new InvalidOperationException( "The document already contains data and should not be used again." );

        try 
        {
            _curLastChild = null;
            _xmlHash = xmlHash;

            LoadChildNodes( this, reader, false );

            ComputeHashValue( _xmlHash );
            _bLoaded = true;

    #if DEBUG
            if ( XmlDiff.T_LoadedDoc.Enabled )
            {
                Trace.Write( "\nLoaded document " + reader.BaseURI + ": \n" );
                Dump();
            }
    #endif
        }
        finally
        {
            _xmlHash = null;
        }
    }
예제 #17
0
// Constructor
        internal DiffgramRemoveSubtrees(XmlDiffNode sourceNode, ulong operationID, bool bSorted) : base(operationID)
        {
            Debug.Assert(sourceNode != null);
            _firstSourceNode = sourceNode;
            _lastSourceNode  = sourceNode;
            _bSorted         = bSorted;
        }
예제 #18
0
 internal static int OrderChildren(XmlDiffNode node1, XmlDiffNode node2)
 {
   var nodeType1 = (int) node1.NodeType;
   var nodeType2 = (int) node2.NodeType;
   if (nodeType1 < nodeType2)
     return -1;
   if (nodeType2 < nodeType1)
     return 1;
   switch (nodeType1)
   {
     case 1:
       return XmlDiffDocument.OrderElements(node1 as XmlDiffElement, node2 as XmlDiffElement);
     case 2:
     case 100:
       return 0;
     case 5:
       return XmlDiffDocument.OrderERs(node1 as XmlDiffER, node2 as XmlDiffER);
     case 7:
       return XmlDiffDocument.OrderPIs(node1 as XmlDiffPI, node2 as XmlDiffPI);
     case 101:
       if (((XmlDiffShrankNode) node1).MatchingShrankNode == ((XmlDiffShrankNode) node2).MatchingShrankNode)
         return 0;
       return node1.HashValue >= node2.HashValue ? 1 : -1;
     default:
       return XmlDiffDocument.OrderCharacterData(node1 as XmlDiffCharData, node2 as XmlDiffCharData);
   }
 }
예제 #19
0
        private static void QuickSortNodes(
            ref XmlDiffNode firstNode,
            ref XmlDiffNode lastNode,
            int count,
            XmlDiffNode firstPreviousSibbling,
            XmlDiffNode lastNextSibling)
        {
            var sortArray   = new XmlDiffNode[(int)checked ((uint)count)];
            var xmlDiffNode = firstNode;
            var index1      = 0;

            while (index1 < count)
            {
                sortArray[index1] = xmlDiffNode;
                ++index1;
                xmlDiffNode = xmlDiffNode._nextSibling;
            }
            XmlDiff.QuickSortNodesRecursion(ref sortArray, 0, count - 1);
            for (var index2 = 0; index2 < count - 1; ++index2)
            {
                sortArray[index2]._nextSibling = sortArray[index2 + 1];
            }
            if (firstPreviousSibbling == null)
            {
                firstNode._parent._firstChildNode = sortArray[0];
            }
            else
            {
                firstPreviousSibbling._nextSibling = sortArray[0];
            }
            sortArray[count - 1]._nextSibling = lastNextSibling;
            firstNode = sortArray[0];
            lastNode  = sortArray[count - 1];
        }
예제 #20
0
 private void PreprocessNode(
     XmlDiffNode node,
     ref XmlDiffNode[] postOrderArray,
     ref int currentIndex)
 {
     if (node.HasChildNodes)
     {
         var node1 = node.FirstChildNode;
         node1._bKeyRoot = false;
         while (true)
         {
             this.PreprocessNode(node1, ref postOrderArray, ref currentIndex);
             node1 = node1._nextSibling;
             if (node1 != null)
             {
                 node1._bKeyRoot = true;
             }
             else
             {
                 break;
             }
         }
         node.Left = node.FirstChildNode.Left;
     }
     else
     {
         node.Left       = currentIndex;
         node.NodesCount = 1;
     }
     postOrderArray[currentIndex++] = node;
 }
예제 #21
0
// Methods
        internal override void WriteTo(XmlWriter xmlWriter, XmlDiff xmlDiff)
        {
            if (!_bSorted)
            {
                Sort();
            }

            xmlWriter.WriteStartElement(XmlDiff.Prefix, "add", XmlDiff.NamespaceUri);
            if (_operationID != 0)
            {
                xmlWriter.WriteAttributeString("opid", _operationID.ToString());
            }

            // namespaces
            if (_bNeedNamespaces)
            {
                Hashtable         definedPrefixes = new Hashtable();
                XmlDiffParentNode parent          = _firstTargetNode._parent;
                while (parent != null)
                {
                    if (parent._bDefinesNamespaces)
                    {
                        XmlDiffElement el = (XmlDiffElement)parent;
                        XmlDiffAttributeOrNamespace curNs = el._attributes;
                        while (curNs != null && curNs.NodeType == XmlDiffNodeType.Namespace)
                        {
                            if (definedPrefixes[curNs.Prefix] == null)
                            {
                                if (curNs.Prefix == string.Empty)
                                {
                                    xmlWriter.WriteAttributeString("xmlns", XmlDiff.XmlnsNamespaceUri, curNs.NamespaceURI);
                                }
                                else
                                {
                                    xmlWriter.WriteAttributeString("xmlns", curNs.Prefix, XmlDiff.XmlnsNamespaceUri, curNs.NamespaceURI);
                                }
                                definedPrefixes[curNs.Prefix] = curNs.Prefix;
                            }
                            curNs = (XmlDiffAttributeOrNamespace)curNs._nextSibling;
                        }
                    }
                    parent = parent._parent;
                }
            }

            // output nodes
            XmlDiffNode node = _firstTargetNode;

            for (;;)
            {
                node.WriteTo(xmlWriter);
                if (node == _lastTargetNode)
                {
                    break;
                }
                node = node._nextSibling;
            }
            xmlWriter.WriteEndElement();
        }
예제 #22
0
        // compares the node to another one and returns true, if the nodes are identical;
        // on elements this method ignores namespace declarations
        internal override bool IsSameAs(XmlDiffNode node, XmlDiff xmlDiff)
        {
            // check node type
            Debug.Assert(node != null);
            if (node.NodeType != XmlDiffNodeType.Element)
            {
                return(false);
            }

            XmlDiffElement element = (XmlDiffElement)node;

            // check element name
            if (LocalName != element.LocalName)
            {
                return(false);
            }
            else if (!xmlDiff.IgnoreNamespaces)
            {
                if (NamespaceURI != element.NamespaceURI)
                {
                    return(false);
                }
                else if (!xmlDiff.IgnorePrefixes)
                {
                    if (Prefix != element.Prefix)
                    {
                        return(false);
                    }
                }
            }

            // ignore namespace definitions - should be first in the list of attributes
            XmlDiffAttributeOrNamespace attr1 = _attributes;

            while (attr1 != null && attr1.NodeType == XmlDiffNodeType.Namespace)
            {
                attr1 = (XmlDiffAttributeOrNamespace)attr1._nextSibling;
            }

            XmlDiffAttributeOrNamespace attr2 = _attributes;

            while (attr2 != null && attr2.NodeType == XmlDiffNodeType.Namespace)
            {
                attr2 = (XmlDiffAttributeOrNamespace)attr2._nextSibling;
            }

            // check attributes
            while (attr1 != null && attr2 != null)
            {
                if (!attr1.IsSameAs(attr2, xmlDiff))
                {
                    return(false);
                }
                attr1 = (XmlDiffAttributeOrNamespace)attr1._nextSibling;
                attr2 = (XmlDiffAttributeOrNamespace)attr2._nextSibling;
            }

            return(attr1 == null && attr2 == null);
        }
예제 #23
0
 internal static string GetRelativeAddressOfInterval(XmlDiffNode firstNode, XmlDiffNode lastNode)
 {
     if (firstNode == lastNode)
     {
         return(firstNode.GetRelativeAddress());
     }
     return(firstNode._parent._firstChildNode == firstNode && lastNode._nextSibling == null ? "*" : firstNode.Position.ToString() + "-" + lastNode.Position.ToString());
 }
예제 #24
0
 internal DiffgramAddSubtrees(XmlDiffNode subtreeRoot, ulong operationID, bool bSorted)
     : base(operationID)
 {
     this._firstTargetNode = subtreeRoot;
     this._lastTargetNode  = subtreeRoot;
     this._bSorted         = bSorted;
     this._bNeedNamespaces = subtreeRoot.NodeType == XmlDiffNodeType.Element;
 }
예제 #25
0
// Constructor
        internal DiffgramAddSubtrees(XmlDiffNode subtreeRoot, ulong operationID, bool bSorted) : base(operationID)
        {
            Debug.Assert(subtreeRoot != null);
            _firstTargetNode = subtreeRoot;
            _lastTargetNode  = subtreeRoot;
            _bSorted         = bSorted;
            _bNeedNamespaces = subtreeRoot.NodeType == XmlDiffNodeType.Element;
        }
예제 #26
0
// Constructor
        internal XmlDiffParentNode(int position) : base(position)
        {
            _firstChildNode      = null;
            _nodesCount          = 1;
            _elementChildrenOnly = true;
            _bDefinesNamespaces  = false;
            _hashValue           = 0;
        }
예제 #27
0
        // compares the node to another one and returns the xmldiff operation for changing this node to the other
        internal override XmlDiffOperation GetDiffOperation(XmlDiffNode changedNode, XmlDiff xmlDiff)
        {
            Debug.Assert(changedNode != null);

            if (changedNode.NodeType != XmlDiffNodeType.Element)
            {
                return(XmlDiffOperation.Undefined);
            }

            XmlDiffElement changedElement = (XmlDiffElement)changedNode;

            // name
            bool bNameMatches = false;

            if (LocalName == changedElement.LocalName)
            {
                if (xmlDiff.IgnoreNamespaces)
                {
                    bNameMatches = true;
                }
                else
                {
                    if (NamespaceURI == changedElement.NamespaceURI &&
                        (xmlDiff.IgnorePrefixes || Prefix == changedElement.Prefix))
                    {
                        bNameMatches = true;
                    }
                }
            }

            // attributes
            if (changedElement._allAttributesHash == _allAttributesHash)
            {
                return(bNameMatches ? XmlDiffOperation.Match : XmlDiffOperation.ChangeElementName);
            }

            int n = (changedElement._attributesHashAH == _attributesHashAH ? 0 : 1) +
                    (changedElement._attributesHashIQ == _attributesHashIQ ? 0 : 1) +
                    (changedElement._attributesHashRZ == _attributesHashRZ ? 0 : 1);

            Debug.Assert((int)XmlDiffOperation.ChangeElementName + 1 == (int)XmlDiffOperation.ChangeElementAttr1);
            Debug.Assert((int)XmlDiffOperation.ChangeElementAttr1 + 1 == (int)XmlDiffOperation.ChangeElementAttr2);
            Debug.Assert((int)XmlDiffOperation.ChangeElementAttr2 + 1 == (int)XmlDiffOperation.ChangeElementAttr3);

            Debug.Assert((int)XmlDiffOperation.ChangeElementAttr3 + 1 == (int)XmlDiffOperation.ChangeElementNameAndAttr1);
            Debug.Assert((int)XmlDiffOperation.ChangeElementNameAndAttr1 + 1 == (int)XmlDiffOperation.ChangeElementNameAndAttr2);
            Debug.Assert((int)XmlDiffOperation.ChangeElementNameAndAttr2 + 1 == (int)XmlDiffOperation.ChangeElementNameAndAttr3);

            Debug.Assert(n != 0);
            if (bNameMatches)
            {
                return((XmlDiffOperation)(((int)XmlDiffOperation.ChangeElementName) + n));
            }
            else
            {
                return((XmlDiffOperation)(((int)XmlDiffOperation.ChangeElementAttr3) + n));
            }
        }
예제 #28
0
 internal bool SetNewLastNode(XmlDiffNode srcNode)
 {
     if (this._operationID != 0UL || this._lastSourceNode._nextSibling != srcNode || (!srcNode.CanMerge || !this._firstSourceNode.CanMerge))
     {
         return(false);
     }
     this._lastSourceNode = srcNode;
     return(true);
 }
예제 #29
0
        private void PreprocessTree(XmlDiffDocument doc, ref XmlDiffNode[] postOrderArray)
        {
            postOrderArray    = new XmlDiffNode[(int)checked ((uint)unchecked (doc.NodesCount + 1))];
            postOrderArray[0] = null;
            var currentIndex = 1;

            this.PreprocessNode(doc, ref postOrderArray, ref currentIndex);
            doc._bKeyRoot = true;
        }
예제 #30
0
        internal bool MergeAddSubtreeAtEnd(XmlDiffNode subtreeRoot)
        {
            Debug.Assert(subtreeRoot.NodeType != XmlDiffNodeType.Attribute);

            DiffgramAddSubtrees addSubtrees = _lastChildOp as DiffgramAddSubtrees;

            return(addSubtrees != null &&
                   addSubtrees.SetNewLastNode(subtreeRoot));
        }
예제 #31
0
 internal DiffgramPosition(XmlDiffNode sourceNode)
     : base(0UL)
 {
     if (sourceNode is XmlDiffShrankNode)
     {
         sourceNode = ((XmlDiffShrankNode)sourceNode)._lastNode;
     }
     this._sourceNode = sourceNode;
 }
예제 #32
0
        internal bool MergeRemoveSubtreeAtEnd(XmlDiffNode subtreeRoot)
        {
            Debug.Assert(!(subtreeRoot is XmlDiffAttributeOrNamespace));

            DiffgramRemoveSubtrees remSubtrees = _lastChildOp as DiffgramRemoveSubtrees;

            return(remSubtrees != null &&
                   remSubtrees.SetNewLastNode(subtreeRoot));
        }
예제 #33
0
        // Constructor
        internal DiffgramAddNode( XmlDiffNode targetNode, ulong operationID )
            : base(operationID)
        {
            Debug.Assert( targetNode != null );
            Debug.Assert( targetNode.NodeType == XmlDiffNodeType.Element ||
                      targetNode.NodeType == XmlDiffNodeType.Attribute ||
                      targetNode.NodeType == XmlDiffNodeType.Namespace ||
                      targetNode.NodeType == XmlDiffNodeType.XmlDeclaration ||
                      targetNode.NodeType == XmlDiffNodeType.DocumentType ||
                      targetNode.NodeType == XmlDiffNodeType.EntityReference );

            _targetNode = targetNode;
        }
예제 #34
0
    internal static string GetRelativeAddressOfNodeset( XmlDiffNode firstNode, XmlDiffNode lastNode )
    {
		Debug.Assert( !( firstNode is XmlDiffAttributeOrNamespace ) &&
			          !( lastNode is XmlDiffAttributeOrNamespace ) );

        int prevPosition = -1;
        bool bInterval = false;
        StringBuilder sb = new StringBuilder();
        XmlDiffNode curNode = firstNode;
        for (;;)
        {
			Debug.Assert( curNode.Position > 0 );

            if ( curNode.Position != prevPosition + 1 ) {
                if ( bInterval ) {
                    sb.Append( prevPosition );
                    bInterval = false;
                    sb.Append( '|' );
                }
                sb.Append( curNode.Position );
                if ( curNode != lastNode ) {
                    if ( curNode._nextSibling.Position == curNode.Position + 1 ) {
                        sb.Append( "-" );
                        bInterval = true;
                    }
                    else
                        sb.Append( '|' );
                }
            }

            if ( curNode == lastNode )
                break;

            prevPosition = curNode.Position;
            curNode = curNode._nextSibling;
        }
        
        if ( bInterval )
            sb.Append( lastNode.Position );

        return sb.ToString();
    }
예제 #35
0
        private void WalkTreeOnAddNode( DiffgramParentOperation diffParent, XmlDiffNode targetNode, XmlDiffNode sourcePositionNode )
        {
            bool bShrankNode = targetNode is XmlDiffShrankNode;

            if ( _bChildOrderSignificant ) {
            if ( sourcePositionNode != null ) {
                diffParent.InsertAtEnd( new DiffgramPosition( sourcePositionNode ) );
            }
            }
            else {
            if ( diffParent._firstChildOp == null && diffParent is Diffgram ) {
                diffParent.InsertAtEnd( new DiffgramPosition( sourcePositionNode ) );
            }
            }

            if ( targetNode._bSomeDescendantMatches && !bShrankNode ) {
            DiffgramOperation addOp = GenerateDiffgramAddWhenDescendantMatches( (XmlDiffParentNode)targetNode );
            diffParent.InsertAtEnd( addOp );
            }
            else {
            // shrank node -> output as 'move' operation
            if ( bShrankNode ) {
                ulong opid = 0;
                XmlDiffShrankNode shrankNode = (XmlDiffShrankNode) targetNode;
                if ( shrankNode.MoveOperationId == 0 )
                    shrankNode.MoveOperationId = GenerateOperationID( XmlDiffDescriptorType.Move );
                opid = shrankNode.MoveOperationId;

                diffParent.InsertAtEnd( new DiffgramCopy( shrankNode.MatchingShrankNode, true, opid ) );
            }
            else {
                switch ( targetNode.NodeType ) {
                    case XmlDiffNodeType.XmlDeclaration:
                    case XmlDiffNodeType.DocumentType:
                    case XmlDiffNodeType.EntityReference:
                        diffParent.InsertAtEnd( new DiffgramAddNode( targetNode, 0 ) );
                        break;
                    default:
                        if ( !diffParent.MergeAddSubtreeAtEnd( targetNode ) ) {
                            diffParent.InsertAtEnd( new DiffgramAddSubtrees( targetNode, 0, !_xmlDiff.IgnoreChildOrder ) );
                        }
                        break;
                }
            }
            }
        }
예제 #36
0
    private void AddNodeToHashTable( Hashtable hashtable, XmlDiffNode node )
    {
        Debug.Assert( hashtable != null );
        Debug.Assert( node != null );
        Debug.Assert( node.NodeType != XmlDiffNodeType.ShrankNode );

        ulong hashValue = node.HashValue;

        XmlDiffNodeListHead nodeListHead = (XmlDiffNodeListHead) hashtable[ hashValue ];
        if ( nodeListHead == null ) {
            hashtable[ hashValue ] = new XmlDiffNodeListHead( new XmlDiffNodeListMember( node, null ) ); 
        }
        else 
        {
            XmlDiffNodeListMember newMember = new XmlDiffNodeListMember( node, null );
            nodeListHead._last._next = newMember;
            nodeListHead._last = newMember;
        }
    }
예제 #37
0
    private void PreprocessNode( XmlDiffNode node, ref XmlDiffNode[] postOrderArray, ref int currentIndex )
    {
        // process children
		if ( node.HasChildNodes )
		{
			Debug.Assert( node.FirstChildNode != null );

#if DEBUG
            int nodesCount = 0;
#endif
			XmlDiffNode curChild = node.FirstChildNode;
			curChild._bKeyRoot = false;
			for (;;)
			{
				PreprocessNode( curChild, ref postOrderArray, ref currentIndex );
#if DEBUG
				nodesCount += curChild.NodesCount;
#endif

				curChild = curChild._nextSibling;
                // 'key root' node is the root node and each node that has a previous sibling node
				if ( curChild != null ) 
                    curChild._bKeyRoot = true;
				else break;
			}

            // leftist leaf in the subtree rooted at 'node'
			node.Left = node.FirstChildNode.Left; 
#if DEBUG
			Debug.Assert( node.NodesCount == nodesCount + 1 );
#endif
		}
		else
		{
            // leftist leaf in the subtree rooted at 'node'
			node.Left = currentIndex; 
            // total number of nodes in the subtree rooted at 'node'
			node.NodesCount = 1;
		}

#if DEBUG
    node._index = currentIndex;
#endif
        // put the node in post-order array
        Debug.Assert( postOrderArray.Length > currentIndex );
        postOrderArray[ currentIndex++ ] = node;
    }
예제 #38
0
        private void WalkTreeOnChangeNode( DiffgramParentOperation diffParent, XmlDiffNode sourceNode, XmlDiffNode targetNode, XmlDiffOperation op )
        {
            Debug.Assert( sourceNode.NodeType != XmlDiffNodeType.Element && targetNode.NodeType != XmlDiffNodeType.Element );

            DiffgramChangeNode changeOp = new DiffgramChangeNode( sourceNode, targetNode, op, 0 );
            if ( sourceNode.HasChildNodes || targetNode.HasChildNodes ) {
            WalkTreeGenerateDiffgramMatch( changeOp, (XmlDiffParentNode) sourceNode, (XmlDiffParentNode) targetNode );
            }
            diffParent.InsertAtEnd( changeOp );
        }
예제 #39
0
    private void HTRemoveDescendants( Hashtable hashtable, XmlDiffNode parent ) {
        if ( !parent._bExpanded || !parent.HasChildNodes )
            return;

        XmlDiffNode curNode = parent.FirstChildNode;
        for (;;)
        {
            Debug.Assert( curNode != null );
            if ( curNode._bExpanded  &&  curNode.HasChildNodes )
            {
                curNode = ((XmlDiffParentNode) curNode)._firstChildNode;
                continue;
            }

            HTRemoveNode( hashtable, curNode );

        TryNext:
            if ( curNode._nextSibling != null )
            {
                curNode = curNode._nextSibling;
                continue;
            }
            else if ( curNode._parent != parent )
            {
                curNode = curNode._parent;
                goto TryNext;
            }
            else {
                break;
            }
        }
    }
예제 #40
0
    private void PreprocessTree( XmlDiffDocument doc, ref XmlDiffNode[] postOrderArray )
    {
        // allocate the array for post-ordered nodes.
        // The index 0 is not used; this is to have the consistent indexing of all arrays in the algorithm;
        postOrderArray = new XmlDiffNode[ doc.NodesCount + 1 ];
        postOrderArray[0] = null;

        // recursivelly process all nodes
        int index = 1;
        PreprocessNode( doc, ref postOrderArray, ref index );

        // root node is a 'key root' node
        doc._bKeyRoot = true;

        Debug.Assert( index - 1 == doc.NodesCount );
    }
예제 #41
0
    private XmlDiffNode HTFindAndRemoveMatchingNode( Hashtable hashtable, XmlDiffNodeListHead nodeListHead, XmlDiffNode nodeToMatch )
    {
        Debug.Assert( hashtable != null );
        Debug.Assert( nodeListHead != null );

        // find matching node in the list
        XmlDiffNodeListMember nodeList = nodeListHead._first;
        XmlDiffNode node = nodeList._node;
        if ( IdenticalSubtrees( node, nodeToMatch ) ) {
            // remove the node itself
            if ( nodeList._next == null ) {
                hashtable.Remove( node.HashValue );
            }
            else {
                Debug.Assert( nodeListHead._first != nodeListHead._last );
                nodeListHead._first = nodeList._next;
            }
            return node;
        } 
        else {
            while ( nodeList._next != null ) {
                if ( IdenticalSubtrees( nodeList._node, nodeToMatch ) ) {
                    nodeList._next = nodeList._next._next;
                    if ( nodeList._next == null ) {
                        nodeListHead._last = nodeList;
                    }
                    return node;
                }
            }
            return null;
        }
    }
예제 #42
0
    // Shrinks the interval of nodes in one or mode XmlDiffShrankNode instances;
    // The shrank interval can contain only adjacent nodes => the position of two adjacent nodes differs by 1.
    private void ShrinkNodeInterval( XmlDiffNode firstSourceNode, XmlDiffNode lastSourceNode, 
                                     XmlDiffNode firstTargetNode, XmlDiffNode lastTargetNode )
    {
		XmlDiffNode sourcePreviousSibling = null;
		XmlDiffNode targetPreviousSibling = null;

        // calculate subtree hash value
        ulong hashValue = 0;
        XmlDiffNode curNode = firstSourceNode;
        for (;;) {
            hashValue += ( hashValue << 7 ) + curNode.HashValue;
            if ( curNode == lastSourceNode )
                break;
            curNode = curNode._nextSibling;
        }

#if DEBUG
        // calculate hash value of the second subtree and make sure they are the same
        ulong hashValue2 = 0;
        curNode = firstTargetNode;
        for (;;) {
            hashValue2 += ( hashValue2 << 7 ) + curNode.HashValue;
            if ( curNode == lastTargetNode )
                break;
            curNode = curNode._nextSibling;
        }
        Debug.Assert( hashValue == hashValue2 );
#endif

        // IgnoreChildOrder -> the nodes has been sorted by name/value before comparing.
        // 'Unsort' the matching interval of nodes (=sort by node position) to
        // group adjacent nodes that can be shrank.
        if ( IgnoreChildOrder  &&  firstSourceNode != lastSourceNode )
        {
			Debug.Assert( firstTargetNode != lastTargetNode );

            SortNodesByPosition( ref firstSourceNode, ref lastSourceNode, ref sourcePreviousSibling );
            SortNodesByPosition( ref firstTargetNode, ref lastTargetNode, ref targetPreviousSibling );
        }

#if DEBUG
        Trace.WriteIf( T_SubtreeMatching.Enabled, "Shrinking nodes: " );
        XmlDiffNode node = firstSourceNode;
        for (;;)
        {
            Trace.WriteIf( T_SubtreeMatching.Enabled, node.OuterXml );
            if ( node == lastSourceNode )
                break;
            node = node._nextSibling;
        }
        Trace.WriteIf( T_SubtreeMatching.Enabled, "\n" );
#endif

        // replace the interval by XmlDiffShrankNode instance
		XmlDiffShrankNode sourceShrankNode = ReplaceNodeIntervalWithShrankNode( firstSourceNode, 
                                                                                lastSourceNode, 
                                                                                sourcePreviousSibling,
                                                                                hashValue );
		XmlDiffShrankNode targetShrankNode = ReplaceNodeIntervalWithShrankNode( firstTargetNode, 
                                                                                lastTargetNode, 
                                                                                targetPreviousSibling,
                                                                                hashValue );

		sourceShrankNode.MatchingShrankNode = targetShrankNode;
		targetShrankNode.MatchingShrankNode = sourceShrankNode;
    }
예제 #43
0
 internal XmlDiffNodeListMember( XmlDiffNode node, XmlDiffNodeListMember next )
 {
     Debug.Assert( node != null );
     _node = node;
     _next = next;
 }
예제 #44
0
	static private void QuickSortNodes( ref XmlDiffNode firstNode, ref XmlDiffNode lastNode, 
		                         int count, XmlDiffNode firstPreviousSibbling, XmlDiffNode lastNextSibling )
	{
		Debug.Assert( count >= MininumNodesForQuicksort );
		Debug.Assert( MininumNodesForQuicksort >= 2 );

		// allocate & fill in the array
		XmlDiffNode[] sortArray = new XmlDiffNode[ count ];
		{
			XmlDiffNode curNode = firstNode;
			for ( int i = 0; i < count; i++, curNode = curNode._nextSibling )
			{
				Debug.Assert( curNode != null );
				sortArray[i] = curNode;
			}
		}

		// sort
		QuickSortNodesRecursion( ref sortArray, 0, count - 1 );

		// link the nodes
		for ( int i = 0; i < count - 1; i++ )
			sortArray[i]._nextSibling = sortArray[i+1];

        if ( firstPreviousSibbling == null )
            firstNode._parent._firstChildNode = sortArray[0];
        else
            firstPreviousSibbling._nextSibling = sortArray[0];

        sortArray[count-1]._nextSibling = lastNextSibling;

        // return
        firstNode = sortArray[0];
        lastNode = sortArray[count-1];
	}
예제 #45
0
	static private void SlowSortNodes( ref XmlDiffNode firstNode, ref XmlDiffNode lastNode, 
		                        XmlDiffNode firstPreviousSibbling, XmlDiffNode lastNextSibling )
	{
        Debug.Assert( firstNode != null );
        Debug.Assert( lastNode != null );

        XmlDiffNode firstSortedNode = firstNode;
        XmlDiffNode lastSortedNode = firstNode;
        XmlDiffNode nodeToSort = firstNode._nextSibling;
		lastSortedNode._nextSibling = null;

        while ( nodeToSort != null )
        {
            XmlDiffNode curNode = firstSortedNode;
            if ( nodeToSort.Position < firstSortedNode.Position )
            {
                XmlDiffNode tmpNode = nodeToSort._nextSibling;
                
                nodeToSort._nextSibling = firstSortedNode;
                firstSortedNode = nodeToSort;

                nodeToSort = tmpNode;
            }
            else
            {
                while ( curNode._nextSibling != null &&
                        nodeToSort.Position > curNode._nextSibling.Position )
                    curNode = curNode._nextSibling;

                XmlDiffNode tmpNode = nodeToSort._nextSibling;

                if ( curNode._nextSibling == null )
                    lastSortedNode = nodeToSort;

                nodeToSort._nextSibling = curNode._nextSibling;
                curNode._nextSibling = nodeToSort;

                nodeToSort = tmpNode;
            }
        }

        // reconnect the sorted part in the tree
        if ( firstPreviousSibbling == null )
            firstNode._parent._firstChildNode = firstSortedNode;
        else
            firstPreviousSibbling._nextSibling = firstSortedNode;

        lastSortedNode._nextSibling = lastNextSibling;

        // return
        firstNode = firstSortedNode;
        lastNode = lastSortedNode;
	}
예제 #46
0
    internal static void SortNodesByPosition( ref XmlDiffNode firstNode,
                                              ref XmlDiffNode lastNode,
                                              ref XmlDiffNode firstPreviousSibbling )
    {
        XmlDiffParentNode parent = firstNode._parent;
        
        // find previous sibling node for the first node
		if ( firstPreviousSibbling == null  &&
			 firstNode != parent._firstChildNode )
		{
			firstPreviousSibbling = parent._firstChildNode;
			while ( firstPreviousSibbling._nextSibling != firstNode )
				firstPreviousSibbling = firstPreviousSibbling._nextSibling;
		}

        // save the next sibling node for the last node
        XmlDiffNode lastNextSibling = lastNode._nextSibling;
        lastNode._nextSibling = null;

		// count the number of nodes to sort
		int count = 0;
		XmlDiffNode curNode = firstNode;
		while ( curNode != null )
		{
            count++;
			curNode = curNode._nextSibling;
		}

		Debug.Assert( count > 0 );
        if ( count >= MininumNodesForQuicksort ) 
            QuickSortNodes( ref firstNode, ref lastNode, count, firstPreviousSibbling, lastNextSibling );
        else
		    SlowSortNodes( ref firstNode, ref lastNode, firstPreviousSibbling, lastNextSibling );
	}
예제 #47
0
 private void RemoveDescendantsFromHashTable( Hashtable hashtable, XmlDiffNode parentNode )
 {
     
 }
예제 #48
0
        private void PostponedRemoveSubtrees( XmlDiffNode sourceNode, ulong operationID,
            int startSourceIndex, int endSourceIndex)
        {
            Debug.Assert( _bBuildingAddTree );
            Debug.Assert( sourceNode != null );

            if ( operationID == 0 &&
             _postponedEditScript._firstES != null )
            {
            Debug.Assert( _postponedEditScript._lastES._startSourceIndex > endSourceIndex );

            DiffgramRemoveSubtrees remSubtrees = _postponedEditScript._lastES._diffOperation as DiffgramRemoveSubtrees;
            if ( remSubtrees != null  &&
                remSubtrees.SetNewFirstNode( sourceNode ) )
            {
                _postponedEditScript._lastES._startSourceIndex = startSourceIndex;
                _postponedEditScript._startSourceIndex = startSourceIndex;
                return;
            }
            }

            PostponedOperation( new DiffgramRemoveSubtrees( sourceNode, operationID, !_xmlDiff.IgnoreChildOrder ), startSourceIndex, endSourceIndex );
        }
예제 #49
0
 private void WalkTreeOnMatchNode( DiffgramParentOperation diffParent, XmlDiffNode sourceNode, XmlDiffNode targetNode, ref XmlDiffNode needPositionSourceNode )
 {
     if ( sourceNode.HasChildNodes || targetNode.HasChildNodes ) {
     DiffgramPosition diffMatch = new DiffgramPosition( sourceNode );
     WalkTreeGenerateDiffgramMatch( diffMatch, (XmlDiffParentNode)sourceNode, (XmlDiffParentNode)targetNode );
     diffParent.InsertAtEnd( diffMatch );
     needPositionSourceNode = null;
     }
     else {
     if ( sourceNode.NodeType == XmlDiffNodeType.ShrankNode ) {
         needPositionSourceNode = ((XmlDiffShrankNode)sourceNode)._lastNode;
     }
     else {
         needPositionSourceNode = sourceNode;
     }
     }
 }
예제 #50
0
        private DiffgramOperation GenerateDiffgramAddWhenDescendantMatches( XmlDiffNode targetParent )
        {
            Debug.Assert( targetParent.HasChildNodes );
            Debug.Assert( targetParent._bSomeDescendantMatches );
            Debug.Assert( targetParent.NodeType != XmlDiffNodeType.ShrankNode );

            DiffgramParentOperation diffOp = new DiffgramAddNode( targetParent, 0 );
            if ( targetParent.NodeType == XmlDiffNodeType.Element ) {
            XmlDiffAttributeOrNamespace attr = ((XmlDiffElement)targetParent)._attributes;
            while ( attr != null ) {
                diffOp.InsertAtEnd( new DiffgramAddNode( attr, 0 ) );
                attr = (XmlDiffAttributeOrNamespace) attr._nextSibling;
            }
            }

            XmlDiffNode child = ((XmlDiffParentNode)targetParent)._firstChildNode;
            while ( child != null )
            {
            if ( child.NodeType == XmlDiffNodeType.ShrankNode )
            {
                XmlDiffShrankNode shrankNode = (XmlDiffShrankNode) child;

                if ( shrankNode.MoveOperationId == 0 )
                    shrankNode.MoveOperationId = GenerateOperationID( XmlDiffDescriptorType.Move );

                diffOp.InsertAtEnd( new DiffgramCopy( shrankNode.MatchingShrankNode, true, shrankNode.MoveOperationId ) );
            }
            else if ( child.HasChildNodes && child._bSomeDescendantMatches )
            {
                diffOp.InsertAtEnd( GenerateDiffgramAddWhenDescendantMatches( (XmlDiffParentNode)child ) );
            }
            else
            {
                if ( !diffOp.MergeAddSubtreeAtEnd( child ) )
                    diffOp.InsertAtEnd( new DiffgramAddSubtrees( child, 0, !_xmlDiff.IgnoreChildOrder ) );
            }

            child = child._nextSibling;
            }
            return diffOp;
        }
예제 #51
0
        private void WalkTreeOnRemoveNode( DiffgramParentOperation diffParent, XmlDiffNode sourceNode )
        {
            bool bShrankNode = sourceNode is XmlDiffShrankNode;

            if ( sourceNode._bSomeDescendantMatches && !bShrankNode )
            {
            DiffgramOperation removeOp = GenerateDiffgramRemoveWhenDescendantMatches( (XmlDiffParentNode)sourceNode );
            diffParent.InsertAtEnd( removeOp );
            }
            else
            {
            ulong opid = 0;
            // shrank node -> output as 'move' operation
            if ( bShrankNode )
            {
                XmlDiffShrankNode shrankNode = (XmlDiffShrankNode) sourceNode;
                if ( shrankNode.MoveOperationId == 0 )
                    shrankNode.MoveOperationId = GenerateOperationID( XmlDiffDescriptorType.Move );
                opid = shrankNode.MoveOperationId;
            }

            if ( opid != 0 ||
                !diffParent.MergeRemoveSubtreeAtEnd( sourceNode ) )
            {
                diffParent.InsertAtEnd( new DiffgramRemoveSubtrees( sourceNode, opid, !_xmlDiff.IgnoreChildOrder ) );
            }
            }
        }
예제 #52
0
        private DiffgramOperation GenerateDiffgramRemoveWhenDescendantMatches( XmlDiffNode sourceParent )
        {
            Debug.Assert( sourceParent._bSomeDescendantMatches );
            Debug.Assert( sourceParent.NodeType != XmlDiffNodeType.ShrankNode );

            DiffgramParentOperation diffOp = new DiffgramRemoveNode( sourceParent, false, 0 );
            XmlDiffNode child = ((XmlDiffParentNode)sourceParent)._firstChildNode;
            while ( child != null )
            {
            if ( child.NodeType == XmlDiffNodeType.ShrankNode )
            {
                XmlDiffShrankNode shrankNode = (XmlDiffShrankNode) child;

                if ( shrankNode.MoveOperationId == 0 )
                    shrankNode.MoveOperationId = GenerateOperationID( XmlDiffDescriptorType.Move );

                diffOp.InsertAtEnd( new DiffgramRemoveSubtrees( child, shrankNode.MoveOperationId, !_xmlDiff.IgnoreChildOrder ) );

            }
            else if ( child.HasChildNodes && child._bSomeDescendantMatches )
            {
                diffOp.InsertAtEnd( GenerateDiffgramRemoveWhenDescendantMatches( (XmlDiffParentNode)child ) );
            }
            else
            {
                if ( !diffOp.MergeRemoveSubtreeAtEnd( child ) )
                    diffOp.InsertAtEnd( new DiffgramRemoveSubtrees( child, 0, !_xmlDiff.IgnoreChildOrder ) );
            }

            child = child._nextSibling;
            }
            return diffOp;
        }
예제 #53
0
 private void HTRemoveAncestors( Hashtable hashtable, XmlDiffNode node )
 {
     XmlDiffNode curAncestorNode = node._parent;
     while ( curAncestorNode != null )
     {
         if ( !HTRemoveNode( hashtable, curAncestorNode ) )
             break;
         curAncestorNode._bSomeDescendantMatches = true;
         curAncestorNode = curAncestorNode._parent;
     }
 }
예제 #54
0
    // returs true if the two subtrees are identical
    private bool IdenticalSubtrees( XmlDiffNode node1, XmlDiffNode node2 )
    {
        if ( node1.HashValue != node2.HashValue )
            return false;
        else
#if VERIFY_HASH_VALUES
            return CompareSubtrees( node1, node2 );
#else
            return true;
#endif
    }
예제 #55
0
    // compares two subtrees and returns true if they are identical
    private bool CompareSubtrees( XmlDiffNode node1, XmlDiffNode node2 )
    {
		Debug.Assert( node1.NodeType != XmlDiffNodeType.Namespace );
		Debug.Assert( node2.NodeType != XmlDiffNodeType.Namespace );

        if ( !node1.IsSameAs( node2, this ) )
            return false;

        if ( !node1.HasChildNodes )
            return true;

        XmlDiffNode childNode1 = ((XmlDiffParentNode)node1).FirstChildNode;
        XmlDiffNode childNode2 = ((XmlDiffParentNode)node2).FirstChildNode;

        while ( childNode1 != null &&
                childNode2 != null )
        {
            if ( !CompareSubtrees( childNode1, childNode2 )) 
                return false;
            childNode1 = childNode1._nextSibling;
            childNode2 = childNode2._nextSibling;
        }

        Debug.Assert( childNode1 == null  &&  childNode2 == null );
        return ( childNode1 == childNode2 );
    }
예제 #56
0
	static private void QuickSortNodesRecursion( ref XmlDiffNode[] sortArray, int firstIndex, int lastIndex )
	{
		Debug.Assert( firstIndex < lastIndex );

		int pivotPosition = sortArray[ ( firstIndex + lastIndex ) / 2 ].Position;
		int i = firstIndex;
		int j = lastIndex;

		while ( i < j )
		{
			while ( sortArray[i].Position < pivotPosition ) i++;
			while ( sortArray[j].Position > pivotPosition ) j--;

			if ( i < j )
			{
				XmlDiffNode tmpNode = sortArray[i];
				sortArray[i] = sortArray[j];
				sortArray[j] = tmpNode;
				i++;
				j--;
			}
			else if ( i == j )
			{
				i++;
				j--;
			}
		}

		if ( firstIndex < j )
			QuickSortNodesRecursion( ref sortArray, firstIndex, j );
		if ( i < lastIndex )
			QuickSortNodesRecursion( ref sortArray, i, lastIndex );
	}
예제 #57
0
    private bool HTRemoveNode( Hashtable hashtable, XmlDiffNode node )
    {
        Debug.Assert( hashtable != null );
        Debug.Assert( node != null );

        XmlDiffNodeListHead xmlNodeListHead = (XmlDiffNodeListHead) hashtable[ node.HashValue ];
        if ( xmlNodeListHead == null ) {
            return false;
        }

        XmlDiffNodeListMember xmlNodeList = xmlNodeListHead._first;
        if ( xmlNodeList._node == node )
        {
            if ( xmlNodeList._next == null ) {
                hashtable.Remove( node.HashValue );
            }
            else {
                Debug.Assert( xmlNodeListHead._first != xmlNodeListHead._last );
                xmlNodeListHead._first = xmlNodeList._next;
            }
        }
        else
        {
            if ( xmlNodeList._next == null ) {
                return false;
            }

            while ( xmlNodeList._next._node != node )
            {
                xmlNodeList = xmlNodeList._next;
                if ( xmlNodeList._next == null ) {
                    return false;
                }
            }

            xmlNodeList._next = xmlNodeList._next._next;
            if ( xmlNodeList._next == null ) {
                xmlNodeListHead._last = xmlNodeList;
            }
        }
        return true;
    }
예제 #58
0
    private bool NodeInHashTable( Hashtable hashtable, XmlDiffNode node ) {
        XmlDiffNodeListHead nodeListHeader = (XmlDiffNodeListHead)hashtable[node.HashValue];
        
        if ( nodeListHeader == null ) {
            return false;
        }

        XmlDiffNodeListMember nodeList = nodeListHeader._first;
        while ( nodeList != null ) {
            if ( nodeList._node == node ) {
                return true;
            }
            nodeList = nodeList._next;
        }
        return false;
    }
예제 #59
0
	private XmlDiffShrankNode ReplaceNodeIntervalWithShrankNode( XmlDiffNode firstNode, 
		                                                         XmlDiffNode lastNode,
		                                                         XmlDiffNode previousSibling,
                                                                 ulong hashValue )
	{
		XmlDiffShrankNode shrankNode = new XmlDiffShrankNode( firstNode, lastNode, hashValue );
		XmlDiffParentNode parent = firstNode._parent;

		// find previous sibling node
		if ( previousSibling == null  &&
			 firstNode != parent._firstChildNode )
		{
			previousSibling = parent._firstChildNode;
			while ( previousSibling._nextSibling != firstNode )
				previousSibling = previousSibling._nextSibling;
		}

		// insert shrank node
		if ( previousSibling == null )
		{
			Debug.Assert( firstNode == parent._firstChildNode );

			shrankNode._nextSibling = parent._firstChildNode;
			parent._firstChildNode = shrankNode;
		}
		else
		{
			shrankNode._nextSibling = previousSibling._nextSibling;
			previousSibling._nextSibling = shrankNode;
		}
        shrankNode._parent = parent;

		// remove the node interval & count the total number of nodes
		XmlDiffNode tmpNode;
        int totalNodesCount = 0;
        do
        {
            tmpNode = shrankNode._nextSibling;
            totalNodesCount += tmpNode.NodesCount;
			shrankNode._nextSibling = shrankNode._nextSibling._nextSibling;

        } while ( tmpNode != lastNode );

        // adjust nodes count
        Debug.Assert( totalNodesCount > 0 );
        if ( totalNodesCount > 1 )
        {
            totalNodesCount--;
            while ( parent != null )
            {
                parent.NodesCount -= totalNodesCount;
                parent = parent._parent;
            }
        }

		return shrankNode;
	}
    // compares the node to another one and returns the xmldiff operation for changing this node to the other
	internal override XmlDiffOperation GetDiffOperation( XmlDiffNode changedNode, XmlDiff xmlDiff )
	{
        if ( changedNode.NodeType != XmlDiffNodeType.Document )
            return XmlDiffOperation.Undefined;
        else 
			return XmlDiffOperation.Match;
	}