585: def traverse_balanced(seq1, seq2, callbacks = Diff::LCS::BalancedCallbacks)
586: matches = Diff::LCS.__lcs(seq1, seq2)
587: a_size = seq1.size
588: b_size = seq2.size
589: ai = bj = mb = 0
590: ma = -1
591: string = seq1.kind_of?(String)
592:
593:
594: loop do
595:
596: loop do
597: ma += 1
598: break unless ma < matches.size and matches[ma].nil?
599: end
600:
601: break if ma >= matches.size
602: mb = matches[ma]
603:
604:
605: while (ai < ma) or (bj < mb)
606: ax = string ? seq1[ai, 1] : seq1[ai]
607: bx = string ? seq2[bj, 1] : seq2[bj]
608:
609: case [(ai < ma), (bj < mb)]
610: when [true, true]
611: if callbacks.respond_to?(:change)
612: event = Diff::LCS::ContextChange.new('!', ai, ax, bj, bx)
613: event = yield event if block_given?
614: callbacks.change(event)
615: ai += 1
616: bj += 1
617: else
618: event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
619: event = yield event if block_given?
620: callbacks.discard_a(event)
621: ai += 1
622: ax = string ? seq1[ai, 1] : seq1[ai]
623: event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
624: event = yield event if block_given?
625: callbacks.discard_b(event)
626: bj += 1
627: end
628: when [true, false]
629: event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
630: event = yield event if block_given?
631: callbacks.discard_a(event)
632: ai += 1
633: when [false, true]
634: event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
635: event = yield event if block_given?
636: callbacks.discard_b(event)
637: bj += 1
638: end
639: end
640:
641:
642: ax = string ? seq1[ai, 1] : seq1[ai]
643: bx = string ? seq2[bj, 1] : seq2[bj]
644: event = Diff::LCS::ContextChange.new('=', ai, ax, bj, bx)
645: event = yield event if block_given?
646: callbacks.match(event)
647: ai += 1
648: bj += 1
649: end
650:
651: while (ai < a_size) or (bj < b_size)
652: ax = string ? seq1[ai, 1] : seq1[ai]
653: bx = string ? seq2[bj, 1] : seq2[bj]
654:
655: case [(ai < a_size), (bj < b_size)]
656: when [true, true]
657: if callbacks.respond_to?(:change)
658: event = Diff::LCS::ContextChange.new('!', ai, ax, bj, bx)
659: event = yield event if block_given?
660: callbacks.change(event)
661: ai += 1
662: bj += 1
663: else
664: event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
665: event = yield event if block_given?
666: callbacks.discard_a(event)
667: ai += 1
668: ax = string ? seq1[ai, 1] : seq1[ai]
669: event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
670: event = yield event if block_given?
671: callbacks.discard_b(event)
672: bj += 1
673: end
674: when [true, false]
675: event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
676: event = yield event if block_given?
677: callbacks.discard_a(event)
678: ai += 1
679: when [false, true]
680: event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
681: event = yield event if block_given?
682: callbacks.discard_b(event)
683: bj += 1
684: end
685: end
686: end