Copyright (c) 2012-2016 The go-diff authors. All rights reserved. https://github.com/sergi/go-diff See the included LICENSE file for license details. go-diff is a Go implementation of Google's Diff, Match, and Patch library Original library is Copyright (c) 2006 Google Inc. http://code.google.com/p/google-diff-match-patch/

package diffmatchpatch

import (
	
	
	
	
	
	
	
)
Patch represents one patch operation.
String emulates GNU diff's format. Header: @@ -382,8 +481,9 @@ Indices are printed as 1-based, not 0-based.
func ( *Patch) () string {
	var ,  string

	if .Length1 == 0 {
		 = strconv.Itoa(.Start1) + ",0"
	} else if .Length1 == 1 {
		 = strconv.Itoa(.Start1 + 1)
	} else {
		 = strconv.Itoa(.Start1+1) + "," + strconv.Itoa(.Length1)
	}

	if .Length2 == 0 {
		 = strconv.Itoa(.Start2) + ",0"
	} else if .Length2 == 1 {
		 = strconv.Itoa(.Start2 + 1)
	} else {
		 = strconv.Itoa(.Start2+1) + "," + strconv.Itoa(.Length2)
	}

	var  bytes.Buffer
	_, _ = .WriteString("@@ -" +  + " +" +  + " @@\n")
Escape the body of the patch with %xx notation.
	for ,  := range .diffs {
		switch .Type {
		case DiffInsert:
			_, _ = .WriteString("+")
		case DiffDelete:
			_, _ = .WriteString("-")
		case DiffEqual:
			_, _ = .WriteString(" ")
		}

		_, _ = .WriteString(strings.Replace(url.QueryEscape(.Text), "+", " ", -1))
		_, _ = .WriteString("\n")
	}

	return unescaper.Replace(.String())
}
PatchAddContext increases the context until it is unique, but doesn't let the pattern expand beyond MatchMaxBits.
func ( *DiffMatchPatch) ( Patch,  string) Patch {
	if len() == 0 {
		return 
	}

	 := [.Start2 : .Start2+.Length1]
	 := 0
Look for the first and last matches of pattern in text. If two different matches are found, increase the pattern length.
	for strings.Index(, ) != strings.LastIndex(, ) &&
		len() < .MatchMaxBits-2*.PatchMargin {
		 += .PatchMargin
		 := max(0, .Start2-)
		 := min(len(), .Start2+.Length1+)
		 = [:]
Add one chunk for good luck.
	 += .PatchMargin
Add the prefix.
	 := [max(0, .Start2-):.Start2]
	if len() != 0 {
		.diffs = append([]Diff{Diff{DiffEqual, }}, .diffs...)
Add the suffix.
	 := [.Start2+.Length1 : min(len(), .Start2+.Length1+)]
	if len() != 0 {
		.diffs = append(.diffs, Diff{DiffEqual, })
	}
Roll back the start points.
	.Start1 -= len()
Extend the lengths.
	.Length1 += len() + len()
	.Length2 += len() + len()

	return 
}
PatchMake computes a list of patches.
func ( *DiffMatchPatch) ( ...interface{}) []Patch {
	if len() == 1 {
		,  := [0].([]Diff)
		 := .DiffText1()
		return .(, )
	} else if len() == 2 {
		 := [0].(string)
		switch t := [1].(type) {
		case string:
			 := .DiffMain(, , true)
			if len() > 2 {
				 = .DiffCleanupSemantic()
				 = .DiffCleanupEfficiency()
			}
			return .(, )
		case []Diff:
			return .patchMake2(, )
		}
	} else if len() == 3 {
		return .([0], [2])
	}
	return []Patch{}
}
patchMake2 computes a list of patches to turn text1 into text2. text2 is not provided, diffs are the delta between text1 and text2.
Check for null inputs not needed since null can't be passed in C#.
	 := []Patch{}
	if len() == 0 {
		return  // Get rid of the null case.
	}

	 := Patch{}
	 := 0 // Number of characters into the text1 string.
Start with text1 (prepatchText) and apply the diffs until we arrive at text2 (postpatchText). We recreate the patches one by one to determine context info.
	 := 
	 := 

	for ,  := range  {
A new patch starts here.
			.Start1 = 
			.Start2 = 
		}

		switch .Type {
		case DiffInsert:
			.diffs = append(.diffs, )
			.Length2 += len(.Text)
			 = [:] +
				.Text + [:]
		case DiffDelete:
			.Length1 += len(.Text)
			.diffs = append(.diffs, )
			 = [:] + [+len(.Text):]
		case DiffEqual:
			if len(.Text) <= 2*.PatchMargin &&
Small equality inside a patch.
				.diffs = append(.diffs, )
				.Length1 += len(.Text)
				.Length2 += len(.Text)
			}
Time for a new patch.
				if len(.diffs) != 0 {
					 = .PatchAddContext(, )
					 = append(, )
Unlike Unidiff, our patch lists have a rolling context. http://code.google.com/p/google-diff-match-patch/wiki/Unidiff Update prepatch text & pos to reflect the application of the just completed patch.
					 = 
					 = 
				}
			}
		}
Update the current character count.
		if .Type != DiffInsert {
			 += len(.Text)
		}
		if .Type != DiffDelete {
			 += len(.Text)
		}
	}
Pick up the leftover patch if not empty.
	if len(.diffs) != 0 {
		 = .PatchAddContext(, )
		 = append(, )
	}

	return 
}
PatchDeepCopy returns an array that is identical to a given an array of patches.
func ( *DiffMatchPatch) ( []Patch) []Patch {
	 := []Patch{}
	for ,  := range  {
		 := Patch{}
		for ,  := range .diffs {
			.diffs = append(.diffs, Diff{
				.Type,
				.Text,
			})
		}
		.Start1 = .Start1
		.Start2 = .Start2
		.Length1 = .Length1
		.Length2 = .Length2
		 = append(, )
	}
	return 
}
PatchApply merges a set of patches onto the text. Returns a patched text, as well as an array of true/false values indicating which patches were applied.
func ( *DiffMatchPatch) ( []Patch,  string) (string, []bool) {
	if len() == 0 {
		return , []bool{}
	}
Deep copy the patches so that no changes are made to originals.
	 = .PatchDeepCopy()

	 := .PatchAddPadding()
	 =  +  + 
	 = .PatchSplitMax()

delta keeps track of the offset between the expected and actual location of the previous patch. If there are patches expected at positions 10 and 20, but the first patch was found at 12, delta is 2 and the second patch has an effective expected position of 22.
	 := 0
	 := make([]bool, len())
	for ,  := range  {
		 := .Start2 + 
		 := .DiffText1(.diffs)
		var  int
		 := -1
PatchSplitMax will only provide an oversized pattern in the case of a monster delete.
			 = .MatchMain(, [:.MatchMaxBits], )
			if  != -1 {
				 = .MatchMain(,
					[len()-.MatchMaxBits:], +len()-.MatchMaxBits)
Can't find valid trailing context. Drop this patch.
					 = -1
				}
			}
		} else {
			 = .MatchMain(, , )
		}
No match found. :(
Subtract the delta for this failed patch from subsequent patches.
			 -= .Length2 - .Length1
Found a match. :)
			[] = true
			 =  - 
			var  string
			if  == -1 {
				 = [:int(math.Min(float64(+len()), float64(len())))]
			} else {
				 = [:int(math.Min(float64(+.MatchMaxBits), float64(len())))]
			}
Perfect match, just shove the Replacement text in.
				 = [:] + .DiffText2(.diffs) + [+len():]
Imperfect match. Run a diff to get a framework of equivalent indices.
				 := .DiffMain(, , false)
The end points match, but the content is unacceptably bad.
					[] = false
				} else {
					 = .DiffCleanupSemanticLossless()
					 := 0
					for ,  := range .diffs {
						if .Type != DiffEqual {
							 := .DiffXIndex(, )
Insertion
								 = [:+] + .Text + [+:]
Deletion
								 :=  + 
								 = [:] +
									[+.DiffXIndex(, +len(.Text))-:]
							}
						}
						if .Type != DiffDelete {
							 += len(.Text)
						}
					}
				}
			}
		}
		++
Strip the padding off.
	 = [len() : len()+(len()-2*len())]
	return , 
}
PatchAddPadding adds some padding on text start and end so that edges can match something. Intended to be called only from within patchApply.
func ( *DiffMatchPatch) ( []Patch) string {
	 := .PatchMargin
	 := ""
	for  := 1;  <= ; ++ {
		 += string()
	}
Bump all the patches forward.
	for  := range  {
		[].Start1 += 
		[].Start2 += 
	}
Add some padding on start of first diff.
Add nullPadding equality.
		[0].diffs = append([]Diff{Diff{DiffEqual, }}, [0].diffs...)
		[0].Start1 -=  // Should be 0.
		[0].Start2 -=  // Should be 0.
		[0].Length1 += 
		[0].Length2 += 
Grow first equality.
		 :=  - len([0].diffs[0].Text)
		[0].diffs[0].Text = [len([0].diffs[0].Text):] + [0].diffs[0].Text
		[0].Start1 -= 
		[0].Start2 -= 
		[0].Length1 += 
		[0].Length2 += 
	}
Add some padding on end of last diff.
	 := len() - 1
Add nullPadding equality.
		[].diffs = append([].diffs, Diff{DiffEqual, })
		[].Length1 += 
		[].Length2 += 
Grow last equality.
		 := [].diffs[len([].diffs)-1]
		 :=  - len(.Text)
		[].diffs[len([].diffs)-1].Text += [:]
		[].Length1 += 
		[].Length2 += 
	}

	return 
}
PatchSplitMax looks through the patches and breaks up any which are longer than the maximum limit of the match algorithm. Intended to be called only from within patchApply.
func ( *DiffMatchPatch) ( []Patch) []Patch {
	 := .MatchMaxBits
	for  := 0;  < len(); ++ {
		if [].Length1 <=  {
			continue
		}
Remove the big old patch.
		 = append([:], [+1:]...)
		--

		 := .Start1
		 := .Start2
		 := ""
Create one of several smaller patches.
			 := Patch{}
			 := true
			.Start1 =  - len()
			.Start2 =  - len()
			if len() != 0 {
				.Length1 = len()
				.Length2 = len()
				.diffs = append(.diffs, Diff{DiffEqual, })
			}
			for len(.diffs) != 0 && .Length1 < -.PatchMargin {
				 := .diffs[0].Type
				 := .diffs[0].Text
Insertions are harmless.
					.Length2 += len()
					 += len()
					.diffs = append(.diffs, .diffs[0])
					.diffs = .diffs[1:]
					 = false
This is a large deletion. Let it pass in one chunk.
					.Length1 += len()
					 += len()
					 = false
					.diffs = append(.diffs, Diff{, })
					.diffs = .diffs[1:]
Deletion or equality. Only take as much as we can stomach.
					 = [:min(len(), -.Length1-.PatchMargin)]

					.Length1 += len()
					 += len()
					if  == DiffEqual {
						.Length2 += len()
						 += len()
					} else {
						 = false
					}
					.diffs = append(.diffs, Diff{, })
					if  == .diffs[0].Text {
						.diffs = .diffs[1:]
					} else {
						.diffs[0].Text =
							.diffs[0].Text[len():]
					}
				}
Compute the head context for the next patch.
			 = .DiffText2(.diffs)
			 = [max(0, len()-.PatchMargin):]

Append the end context for this patch.
			if len(.DiffText1(.diffs)) > .PatchMargin {
				 = .DiffText1(.diffs)[:.PatchMargin]
			} else {
				 = .DiffText1(.diffs)
			}

			if len() != 0 {
				.Length1 += len()
				.Length2 += len()
				if len(.diffs) != 0 && .diffs[len(.diffs)-1].Type == DiffEqual {
					.diffs[len(.diffs)-1].Text += 
				} else {
					.diffs = append(.diffs, Diff{DiffEqual, })
				}
			}
			if ! {
				++
				 = append([:], append([]Patch{}, [:]...)...)
			}
		}
	}
	return 
}
PatchToText takes a list of patches and returns a textual representation.
func ( *DiffMatchPatch) ( []Patch) string {
	var  bytes.Buffer
	for ,  := range  {
		_, _ = .WriteString(.String())
	}
	return .String()
}
PatchFromText parses a textual representation of patches and returns a List of Patch objects.
func ( *DiffMatchPatch) ( string) ([]Patch, error) {
	 := []Patch{}
	if len() == 0 {
		return , nil
	}
	 := strings.Split(, "\n")
	 := 0
	 := regexp.MustCompile("^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$")

	var  Patch
	var  uint8
	var  string
	for  < len() {

		if !.MatchString([]) {
			return , errors.New("Invalid patch string: " + [])
		}

		 = Patch{}
		 := .FindStringSubmatch([])

		.Start1, _ = strconv.Atoi([1])
		if len([2]) == 0 {
			.Start1--
			.Length1 = 1
		} else if [2] == "0" {
			.Length1 = 0
		} else {
			.Start1--
			.Length1, _ = strconv.Atoi([2])
		}

		.Start2, _ = strconv.Atoi([3])

		if len([4]) == 0 {
			.Start2--
			.Length2 = 1
		} else if [4] == "0" {
			.Length2 = 0
		} else {
			.Start2--
			.Length2, _ = strconv.Atoi([4])
		}
		++

		for  < len() {
			if len([]) > 0 {
				 = [][0]
			} else {
				++
				continue
			}

			 = [][1:]
			 = strings.Replace(, "+", "%2b", -1)
			, _ = url.QueryUnescape()
Deletion.
				.diffs = append(.diffs, Diff{DiffDelete, })
Insertion.
				.diffs = append(.diffs, Diff{DiffInsert, })
Minor equality.
				.diffs = append(.diffs, Diff{DiffEqual, })
Start of next patch.
				break
WTF?
				return , errors.New("Invalid patch mode '" + string() + "' in: " + string())
			}
			++
		}

		 = append(, )
	}
	return , nil