Return list of 5-tuples describing how to turn a into b. Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the tuple preceding it, and likewise for j1 == the previous j2. The tags are characters, with these meanings: '
()
| 377 | // |
| 378 | // 'e' (equal): a[i1:i2] == b[j1:j2] |
| 379 | func (m *SequenceMatcher) GetOpCodes() []OpCode { |
| 380 | if m.opCodes != nil { |
| 381 | return m.opCodes |
| 382 | } |
| 383 | i, j := 0, 0 |
| 384 | matching := m.GetMatchingBlocks() |
| 385 | opCodes := make([]OpCode, 0, len(matching)) |
| 386 | for _, m := range matching { |
| 387 | // invariant: we've pumped out correct diffs to change |
| 388 | // a[:i] into b[:j], and the next matching block is |
| 389 | // a[ai:ai+size] == b[bj:bj+size]. So we need to pump |
| 390 | // out a diff to change a[i:ai] into b[j:bj], pump out |
| 391 | // the matching block, and move (i,j) beyond the match |
| 392 | ai, bj, size := m.A, m.B, m.Size |
| 393 | tag := byte(0) |
| 394 | if i < ai && j < bj { |
| 395 | tag = 'r' |
| 396 | } else if i < ai { |
| 397 | tag = 'd' |
| 398 | } else if j < bj { |
| 399 | tag = 'i' |
| 400 | } |
| 401 | if tag > 0 { |
| 402 | opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) |
| 403 | } |
| 404 | i, j = ai+size, bj+size |
| 405 | // the list of matching blocks is terminated by a |
| 406 | // sentinel with size 0 |
| 407 | if size > 0 { |
| 408 | opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) |
| 409 | } |
| 410 | } |
| 411 | m.opCodes = opCodes |
| 412 | return m.opCodes |
| 413 | } |
| 414 | |
| 415 | // Isolate change clusters by eliminating ranges with no changes. |
| 416 | // |