Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / txtar / archive.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/txtar/archive.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/txtar/archive.go
new file mode 100644 (file)
index 0000000..c384f33
--- /dev/null
@@ -0,0 +1,140 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package txtar implements a trivial text-based file archive format.
+//
+// The goals for the format are:
+//
+//     - be trivial enough to create and edit by hand.
+//     - be able to store trees of text files describing go command test cases.
+//     - diff nicely in git history and code reviews.
+//
+// Non-goals include being a completely general archive format,
+// storing binary data, storing file modes, storing special files like
+// symbolic links, and so on.
+//
+// Txtar format
+//
+// A txtar archive is zero or more comment lines and then a sequence of file entries.
+// Each file entry begins with a file marker line of the form "-- FILENAME --"
+// and is followed by zero or more file content lines making up the file data.
+// The comment or file content ends at the next file marker line.
+// The file marker line must begin with the three-byte sequence "-- "
+// and end with the three-byte sequence " --", but the enclosed
+// file name can be surrounding by additional white space,
+// all of which is stripped.
+//
+// If the txtar file is missing a trailing newline on the final line,
+// parsers should consider a final newline to be present anyway.
+//
+// There are no possible syntax errors in a txtar archive.
+package txtar
+
+import (
+       "bytes"
+       "fmt"
+       "io/ioutil"
+       "strings"
+)
+
+// An Archive is a collection of files.
+type Archive struct {
+       Comment []byte
+       Files   []File
+}
+
+// A File is a single file in an archive.
+type File struct {
+       Name string // name of file ("foo/bar.txt")
+       Data []byte // text content of file
+}
+
+// Format returns the serialized form of an Archive.
+// It is assumed that the Archive data structure is well-formed:
+// a.Comment and all a.File[i].Data contain no file marker lines,
+// and all a.File[i].Name is non-empty.
+func Format(a *Archive) []byte {
+       var buf bytes.Buffer
+       buf.Write(fixNL(a.Comment))
+       for _, f := range a.Files {
+               fmt.Fprintf(&buf, "-- %s --\n", f.Name)
+               buf.Write(fixNL(f.Data))
+       }
+       return buf.Bytes()
+}
+
+// ParseFile parses the named file as an archive.
+func ParseFile(file string) (*Archive, error) {
+       data, err := ioutil.ReadFile(file)
+       if err != nil {
+               return nil, err
+       }
+       return Parse(data), nil
+}
+
+// Parse parses the serialized form of an Archive.
+// The returned Archive holds slices of data.
+func Parse(data []byte) *Archive {
+       a := new(Archive)
+       var name string
+       a.Comment, name, data = findFileMarker(data)
+       for name != "" {
+               f := File{name, nil}
+               f.Data, name, data = findFileMarker(data)
+               a.Files = append(a.Files, f)
+       }
+       return a
+}
+
+var (
+       newlineMarker = []byte("\n-- ")
+       marker        = []byte("-- ")
+       markerEnd     = []byte(" --")
+)
+
+// findFileMarker finds the next file marker in data,
+// extracts the file name, and returns the data before the marker,
+// the file name, and the data after the marker.
+// If there is no next marker, findFileMarker returns before = fixNL(data), name = "", after = nil.
+func findFileMarker(data []byte) (before []byte, name string, after []byte) {
+       var i int
+       for {
+               if name, after = isMarker(data[i:]); name != "" {
+                       return data[:i], name, after
+               }
+               j := bytes.Index(data[i:], newlineMarker)
+               if j < 0 {
+                       return fixNL(data), "", nil
+               }
+               i += j + 1 // positioned at start of new possible marker
+       }
+}
+
+// isMarker checks whether data begins with a file marker line.
+// If so, it returns the name from the line and the data after the line.
+// Otherwise it returns name == "" with an unspecified after.
+func isMarker(data []byte) (name string, after []byte) {
+       if !bytes.HasPrefix(data, marker) {
+               return "", nil
+       }
+       if i := bytes.IndexByte(data, '\n'); i >= 0 {
+               data, after = data[:i], data[i+1:]
+       }
+       if !bytes.HasSuffix(data, markerEnd) {
+               return "", nil
+       }
+       return strings.TrimSpace(string(data[len(marker) : len(data)-len(markerEnd)])), after
+}
+
+// If data is empty or ends in \n, fixNL returns data.
+// Otherwise fixNL returns a new slice consisting of data with a final \n added.
+func fixNL(data []byte) []byte {
+       if len(data) == 0 || data[len(data)-1] == '\n' {
+               return data
+       }
+       d := make([]byte, len(data)+1)
+       copy(d, data)
+       d[len(data)] = '\n'
+       return d
+}