Exemplo n.º 1
0
func diffLists(dq *diffQueue, w io.Writer, p types.Path, v1, v2 types.List) {
	wroteHeader := false
	splices := v2.Diff(v1)
	for _, splice := range splices {
		if splice.SpRemoved == splice.SpAdded {
			for i := uint64(0); i < splice.SpRemoved; i++ {
				lastEl := v1.Get(splice.SpAt + i)
				newEl := v2.Get(splice.SpFrom + i)
				if canCompare(lastEl, newEl) {
					idx := types.Number(splice.SpAt + i)
					p1 := p.AddIndex(idx)
					dq.PushBack(diffInfo{p1, idx, lastEl, newEl})
				} else {
					wroteHeader = writeHeader(w, wroteHeader, p)
					line(w, subPrefix, nil, v1.Get(splice.SpAt+i))
					line(w, addPrefix, nil, v2.Get(splice.SpFrom+i))
				}
			}
		} else {
			for i := uint64(0); i < splice.SpRemoved; i++ {
				wroteHeader = writeHeader(w, wroteHeader, p)
				line(w, subPrefix, nil, v1.Get(splice.SpAt+i))
			}
			for i := uint64(0); i < splice.SpAdded; i++ {
				wroteHeader = writeHeader(w, wroteHeader, p)
				line(w, addPrefix, nil, v2.Get(splice.SpFrom+i))
			}
		}
	}
	writeFooter(w, wroteHeader)
}
Exemplo n.º 2
0
func diffLists(w io.Writer, p types.Path, v1, v2 types.List) (err error) {
	spliceChan := make(chan types.Splice)
	stopChan := make(chan struct{}, 1) // buffer size of 1, so this won't block if diff already finished

	go func() {
		v2.Diff(v1, spliceChan, stopChan)
		close(spliceChan)
	}()

	wroteHdr := false

	for splice := range spliceChan {
		if err != nil {
			break
		}

		if splice.SpRemoved == splice.SpAdded {
			// Heuristic: list only has modifications.
			for i := uint64(0); i < splice.SpRemoved; i++ {
				lastEl := v1.Get(splice.SpAt + i)
				newEl := v2.Get(splice.SpFrom + i)
				if shouldDescend(lastEl, newEl) {
					idx := types.Number(splice.SpAt + i)
					writeFooter(w, &wroteHdr)
					err = diff(w, p.AddIndex(idx), idx, lastEl, newEl)
				} else {
					writeHeader(w, p, &wroteHdr)
					line(w, DEL, nil, v1.Get(splice.SpAt+i))
					err = line(w, ADD, nil, v2.Get(splice.SpFrom+i))
				}
			}
			continue
		}

		// Heuristic: list only has additions/removals.
		for i := uint64(0); i < splice.SpRemoved && err == nil; i++ {
			writeHeader(w, p, &wroteHdr)
			err = line(w, DEL, nil, v1.Get(splice.SpAt+i))
		}
		for i := uint64(0); i < splice.SpAdded && err == nil; i++ {
			writeHeader(w, p, &wroteHdr)
			err = line(w, ADD, nil, v2.Get(splice.SpFrom+i))
		}
	}

	err = writeFooter(w, &wroteHdr)

	if err != nil {
		stopChan <- struct{}{}
		// Wait for diff to stop.
		for range spliceChan {
		}
	}
	return
}
Exemplo n.º 3
0
func diffOrdered(w io.Writer, p types.Path, lf lineFunc, df diffFunc, kf, v1, v2 valueFunc) (err error) {
	changeChan := make(chan types.ValueChanged)
	stopChan := make(chan struct{}, 1) // buffer size of 1, so this won't block if diff already finished

	go func() {
		df(changeChan, stopChan)
		close(changeChan)
	}()

	wroteHdr := false

	for change := range changeChan {
		if err != nil {
			break
		}

		k := kf(change.V)

		switch change.ChangeType {
		case types.DiffChangeAdded:
			writeHeader(w, p, &wroteHdr)
			err = lf(w, ADD, k, v2(change.V))
		case types.DiffChangeRemoved:
			writeHeader(w, p, &wroteHdr)
			err = lf(w, DEL, k, v1(change.V))
		case types.DiffChangeModified:
			c1, c2 := v1(change.V), v2(change.V)
			if shouldDescend(c1, c2) {
				writeFooter(w, &wroteHdr)
				err = diff(w, p.AddIndex(k), change.V, c1, c2)
			} else {
				writeHeader(w, p, &wroteHdr)
				lf(w, DEL, k, c1)
				err = lf(w, ADD, k, c2)
			}
		default:
			panic("unknown change type")
		}
	}

	writeFooter(w, &wroteHdr)

	if err != nil {
		stopChan <- struct{}{}
		// Wait for diff to stop.
		for range changeChan {
		}
	}
	return
}
Exemplo n.º 4
0
func diffLists(w io.Writer, p types.Path, v1, v2 types.List) {
	spliceChan := make(chan types.Splice)
	stopChan := make(chan struct{}, 1) // buffer size of 1, so this won't block if diff already finished

	defer stop(stopChan)
	go func() {
		v2.Diff(v1, spliceChan, stopChan)
		close(spliceChan)
	}()

	wroteHeader := false

	for splice := range spliceChan {
		if splice.SpRemoved == splice.SpAdded {
			for i := uint64(0); i < splice.SpRemoved; i++ {
				lastEl := v1.Get(splice.SpAt + i)
				newEl := v2.Get(splice.SpFrom + i)
				if shouldDescend(lastEl, newEl) {
					idx := types.Number(splice.SpAt + i)
					diff(w, p.AddIndex(idx), idx, lastEl, newEl)
				} else {
					wroteHeader = writeHeader(w, wroteHeader, p)
					line(w, DEL, nil, v1.Get(splice.SpAt+i))
					line(w, ADD, nil, v2.Get(splice.SpFrom+i))
				}
			}
		} else {
			for i := uint64(0); i < splice.SpRemoved; i++ {
				wroteHeader = writeHeader(w, wroteHeader, p)
				line(w, DEL, nil, v1.Get(splice.SpAt+i))
			}
			for i := uint64(0); i < splice.SpAdded; i++ {
				wroteHeader = writeHeader(w, wroteHeader, p)
				line(w, ADD, nil, v2.Get(splice.SpFrom+i))
			}
		}
	}

	writeFooter(w, wroteHeader)
}
Exemplo n.º 5
0
func diffMaps(w io.Writer, p types.Path, v1, v2 types.Map) {
	changeChan := make(chan types.ValueChanged)
	stopChan := make(chan struct{}, 1) // buffer size of 1, so this won't block if diff already finished

	defer stop(stopChan)
	go func() {
		v2.Diff(v1, changeChan, stopChan)
		close(changeChan)
	}()

	wroteHeader := false

	for change := range changeChan {
		switch change.ChangeType {
		case types.DiffChangeAdded:
			wroteHeader = writeHeader(w, wroteHeader, p)
			line(w, ADD, change.V, v2.Get(change.V))
		case types.DiffChangeRemoved:
			wroteHeader = writeHeader(w, wroteHeader, p)
			line(w, DEL, change.V, v1.Get(change.V))
		case types.DiffChangeModified:
			c1, c2 := v1.Get(change.V), v2.Get(change.V)
			if shouldDescend(c1, c2) {
				wroteHeader = writeFooter(w, wroteHeader)
				diff(w, p.AddIndex(change.V), change.V, c1, c2)
			} else {
				wroteHeader = writeHeader(w, wroteHeader, p)
				line(w, DEL, change.V, c1)
				line(w, ADD, change.V, c2)
			}
		default:
			panic("unknown change type")
		}
	}

	writeFooter(w, wroteHeader)
}