395: def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks, &block)
396: matches = Diff::LCS.__lcs(seq1, seq2)
397:
398: run_finished_a = run_finished_b = false
399: string = seq1.kind_of?(String)
400:
401: a_size = seq1.size
402: b_size = seq2.size
403: ai = bj = 0
404:
405: (0 .. matches.size).each do |ii|
406: b_line = matches[ii]
407:
408: ax = string ? seq1[ii, 1] : seq1[ii]
409: bx = string ? seq2[bj, 1] : seq2[bj]
410:
411: if b_line.nil?
412: unless ax.nil?
413: event = Diff::LCS::ContextChange.new('-', ii, ax, bj, bx)
414: event = yield event if block_given?
415: callbacks.discard_a(event)
416: end
417: else
418: loop do
419: break unless bj < b_line
420: bx = string ? seq2[bj, 1] : seq2[bj]
421: event = Diff::LCS::ContextChange.new('+', ii, ax, bj, bx)
422: event = yield event if block_given?
423: callbacks.discard_b(event)
424: bj += 1
425: end
426: bx = string ? seq2[bj, 1] : seq2[bj]
427: event = Diff::LCS::ContextChange.new('=', ii, ax, bj, bx)
428: event = yield event if block_given?
429: callbacks.match(event)
430: bj += 1
431: end
432: ai = ii
433: end
434: ai += 1
435:
436:
437:
438: while (ai < a_size) or (bj < b_size)
439:
440: if ai == a_size and bj < b_size
441: if callbacks.respond_to?(:finished_a) and not run_finished_a
442: ax = string ? seq1[-1, 1] : seq1[-1]
443: bx = string ? seq2[bj, 1] : seq2[bj]
444: event = Diff::LCS::ContextChange.new('>', (a_size - 1), ax, bj, bx)
445: event = yield event if block_given?
446: callbacks.finished_a(event)
447: run_finished_a = true
448: else
449: ax = string ? seq1[ai, 1] : seq1[ai]
450: loop do
451: bx = string ? seq2[bj, 1] : seq2[bj]
452: event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
453: event = yield event if block_given?
454: callbacks.discard_b(event)
455: bj += 1
456: break unless bj < b_size
457: end
458: end
459: end
460:
461:
462: if bj == b_size and ai < a_size
463: if callbacks.respond_to?(:finished_b) and not run_finished_b
464: ax = string ? seq1[ai, 1] : seq1[ai]
465: bx = string ? seq2[-1, 1] : seq2[-1]
466: event = Diff::LCS::ContextChange.new('<', ai, ax, (b_size - 1), bx)
467: event = yield event if block_given?
468: callbacks.finished_b(event)
469: run_finished_b = true
470: else
471: bx = string ? seq2[bj, 1] : seq2[bj]
472: loop do
473: ax = string ? seq1[ai, 1] : seq1[ai]
474: event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
475: event = yield event if block_given?
476: callbacks.discard_a(event)
477: ai += 1
478: break unless bj < b_size
479: end
480: end
481: end
482:
483: if ai < a_size
484: ax = string ? seq1[ai, 1] : seq1[ai]
485: bx = string ? seq2[bj, 1] : seq2[bj]
486: event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
487: event = yield event if block_given?
488: callbacks.discard_a(event)
489: ai += 1
490: end
491:
492: if bj < b_size
493: ax = string ? seq1[ai, 1] : seq1[ai]
494: bx = string ? seq2[bj, 1] : seq2[bj]
495: event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
496: event = yield event if block_given?
497: callbacks.discard_b(event)
498: bj += 1
499: end
500: end
501: end