Пример #1
0
        public STATE state; /* compare state for section */

        #endregion Fields

        #region Constructors

        public Section( Line firstParam, Line lastParam )
        {
            first		= firstParam;
            last		= lastParam;
            link		= null;
            correspond	= null;
            state		= STATE.NONE;
            leftbase	= 1;
            rightbase	= 1;
        }
Пример #2
0
        public void compare( ListAnchor secsComposite, ListAnchor linesLeft, ListAnchor linesRight, bool isIgnoreBlanks )
        {
            Section wholeLeft, wholeRight;
            ListAnchor secsLeft  = new ListAnchor();
            ListAnchor secsRight = new ListAnchor();

            bool bChanges;
            do {
                bChanges = false;	/* we have made no changes so far this time round the loop */

                /* make a section covering the whole file */
                wholeLeft  = new Section( (Line)linesLeft. GetHead(), (Line)linesLeft.GetTail()  );
                wholeRight = new Section( (Line)linesRight.GetHead(), (Line)linesRight.GetTail() );

                /* link up matching unique lines between these sections */
                if( wholeLeft.Match( wholeRight, isIgnoreBlanks ) ) bChanges = true;

                /* discard previous section lists if made */
                secsLeft. RemoveAll();
                secsRight.RemoveAll();
                /* build new section lists for both files */
                Section.MakeList( secsLeft,  linesLeft,  true ,isIgnoreBlanks);
                Section.MakeList( secsRight, linesRight, false,isIgnoreBlanks);

                /* match up sections - make links and corresponds between
                 * sections. Attempts to section_match corresponding
                 * sections that are not matched. returns true if any
                 * further links were made */
                if( Section.MatchList( secsLeft, secsRight, isIgnoreBlanks ) ) bChanges = true;

            /* repeat as long as we keep adding new links */
            } while( bChanges );

            /* all possible lines linked, and section lists made .
             * combine the two section lists to get a view of the
             * whole comparison - the composite section list. This also
             * sets the state of each section in the composite list. */
            Section.MakeComposite( secsComposite, secsLeft, secsRight );
        }
Пример #3
0
        /***************************************************************************
         * Function: ExpandAnchor
         * Purpose:
         * Given an anchor point (two lines that we think should match),
         * try to link them, and the lines above and below them for as long
         * as the lines can be linked (are the same, are unlinked).
         * Return true if we make any links.  */
        public static bool ExpandAnchor(Section sec1, Line line1, Section sec2, Line line2,bool isIgnoreBlanks)
        {
            /* when a line is matched we set bChanges.	If we notice some
             * blank lines, but do NOT link any new non-blank lines, we
             * do NOT set bChanges.	 (If we did it would cause a closed
             * loop as they would get noticed again next time.	line_link
             * only returns true if it is a NEW link).
             * At this stage we are only interested in making links, not in
             * the size of the section that results (that fun comes later).
             * therefore trailing blanks at the end of a section are not
             * interesting and we don't look for them. */
            bool bChanges = false;

            /* We handle the section limits by using a sentinel which is one
             * past the end of the section.	 (If the section ends at the end
             * of the list then the sentinel is null). */
            Line leftend  = (Line)sec1.last.GetNext();
            Line rightend = (Line)sec2.last.GetNext();

            /* null lines shall not match */
            if ((line1 == null) || (line2 == null)) return false;

            /* check all lines forward until fail to link (because null,
             * not matching, or already linked). include the passed in anchor point since this has not
             * yet been linked. If blanks are ignorable then skip over any number of whole
             * blank lines. */
            Line left  = line1;
            Line right = line2;
            for(;;){
                if( left.Link( right, isIgnoreBlanks ) ){
                    bChanges = true;
                    left  = (Line)left.GetNext();
                    right = (Line)right.GetNext();
                    if( left == leftend || right == rightend ) break;
                }
                else if( isIgnoreBlanks ){
                    /* even though no match, maybe an ignorable blank? */
                    bool moved = false;
                    moved |= AbsorbAnyBlanks( ref left,  leftend, /*bMoveToNext=*/true);
                    moved |= AbsorbAnyBlanks( ref right, rightend,/*bMoveToNext=*/true);
                    if( !moved ) break; /* it didn't match and we didn't move on */
                    if( left == leftend || right == rightend ) break;
                }
                else break;
            }

            /* check all matches going backwards from anchor point
               but only if it was a real anchor	 (could have been
               end-of-section/end-of-file and non-matching). */
            if( line1.link == null ) return bChanges;

            left  = (Line)line1.GetPrev();
            right = (Line)line2.GetPrev();
            if( left == null || right == null ) return bChanges;

            leftend	 = (Line)sec1.first.GetPrev();
            rightend = (Line)sec2.first.GetPrev();

            for(;;){
                if( left.Link(right,isIgnoreBlanks) ){
                    bChanges = true;
                    left  = (Line)left.GetPrev();
                    right = (Line)right.GetPrev();
                    if( left == leftend || right == rightend ) break;
                }
                else if( isIgnoreBlanks ){
                    /* even though no match, maybe an ignorable blank? */
                    bool moved = false;
                    moved |= AbsorbAnyBlanks( ref left,  leftend, /*bMoveToNext=*/false);
                    moved |= AbsorbAnyBlanks( ref right, rightend, /*bMoveToNext=*/false);
                    if( !moved ) break; /* it didn't match and we didn't move on */
                    if( left == leftend || right == rightend ) break;
                }
                else break;
            }

            return bChanges;
        }
Пример #4
0
        public bool Match(Section sec,bool isIgnoreBlanks)
        {
            if (/*(this == null)||*/ (sec == null)) return(false);
            if ((first == null) || (sec.first == null)) return(false);
            /* ASSERT if first is non-null, so is last */
            /* attempt to link the first line of each file, and
             * if matched, expand as long as we keep matching*/
            bool bLinked = false;
            bLinked |= ExpandAnchor(this, first, sec, sec.first, isIgnoreBlanks );

            /* attempt to link the last lines of each file and
             * expand upwards */
            bLinked |= ExpandAnchor(this, last, sec, sec.last,	  isIgnoreBlanks );

            /* build a tree of lines, indexed by the line hashcode.
             * a ctree will hold only the first value of any given key, but
             * it will keep track of the number of items inserted on this key.
             * thus we can keep count of the number of times this line
             * (or at least this hashcode) appears.*/
            Tree ctleft	 = MakeCTree(isIgnoreBlanks);
            Tree ctright = sec.MakeCTree(isIgnoreBlanks);

            /* for each unlinked line in one list (doesnt matter which), find if
             * appears once only in each list. if so, link, and expand
             * the link to link lines before and after the matching line
             * as long as they continue to match.*/
            for( Line line = first; line != null; line = (Line)line.GetNext() ) {

                if( ( line.link == null ) &&
                   ( ctleft .getcount( line.GetHashcode(isIgnoreBlanks) ) == 1 ) &&
                   ( ctright.getcount( line.GetHashcode(isIgnoreBlanks) ) == 1) ){

                    /* line appears exactly once in each list */
                    Line line2 = (Line)ctright.find( line.GetHashcode(isIgnoreBlanks) ).data;
                    bLinked |= ExpandAnchor( this, line, sec, line2, isIgnoreBlanks );
                }

                if( line == last ) break;
            }

            return bLinked;
        }
Пример #5
0
        /***************************************************************************
         * Function: TakeSection
         * Purpose:
         * Add a section to the composite list. Called from make_composites
         * to copy a section, add it to the composite list and set the state,
         * leftbase and rightbase.	 Note that the state could be STATE.SAME
         * with a null section on the left.	 May NOT call with STATE.SAME and
         * a null right section! */
        public static void TakeSection(ListAnchor compo, Section left, Section right, STATE state)
        {
            Section sec = null;

            /* select which section is being output, and change the state to indicate it has been output */
            switch( state ){
                case STATE.SAME:
                    /* both the same. we mark both as output, and
                     * take the right one.	It is possible that the
                     * left one could be null (an ignorable blank section) */
                    if( left != null ) left.state = STATE.MARKED;
                    right.state = STATE.MARKED;
                    sec = right;
                    break;

                case STATE.LEFTONLY:
                case STATE.MOVEDLEFT:
                    sec = left;
                    left.state = STATE.MARKED;
                    break;

                case STATE.RIGHTONLY:
                case STATE.MOVEDRIGHT:
                    sec = right;
                    right.state = STATE.MARKED;
                    break;
            }

            /* create a new section on the list */
            Section newsec = new Section( sec.first, sec.last );
            compo.AddTail( newsec );

            newsec.state = state;

            if (left != null)	newsec.leftbase = left.first.linenr;
            else				newsec.leftbase = 0;

            if (right != null)	newsec.rightbase = right.first.linenr;
            else				newsec.rightbase = 0;
        }
Пример #6
0
 /***************************************************************************
 * Function: section_makelist
 * Purpose:
 * Make a list of sections by traversing a list of lines. Consecutive
 * linked lines that are linked to consecutive lines are put in a single
 * section. Blocks of unlinked lines are placed in a section.
 * If isIgnoreBlanks is set then we first try to link them as normal.
 * but if they won't link then we just skip over them and keep them
 * in the same section.
 * Left must be set true iff the list of lines is a left hand section.
 * Returns a handle to a list of sections */
 public static void MakeList(ListAnchor sections, ListAnchor linelist, bool left,bool isIgnoreBlanks)
 {
     /* for each line in the list */
     for( Line line1 = (Line)linelist.GetHead(); line1 != null; line1 = (Line)line1.GetNext() ){
         /* is it linked ? */
         bool matched;
         Line line2;
         if( line1.link != null || ( isIgnoreBlanks && line1.IsBlank() ) ){
             line2 = FindEndOfMatched(line1,isIgnoreBlanks);
             matched = true;
         } else {
             line2 = FindEndOfUnmatched(line1);
             matched = false;
         }
         Section sect = new Section(line1, line2);	/* create the section and add to list */
         sections.AddTail( sect );
         sect.state = (
               matched ? STATE.SAME
             : left	  ? STATE.LEFTONLY
             :			STATE.RIGHTONLY
             );
         line1 = line2;	/* advance to end of section (no-op if 1 line section) */
     }
 }