Source File
archive.go
Belonging Package
internal/txtar
// 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 txtarimport ()// An Archive is a collection of files.type Archive struct {Comment []byteFiles []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 ( *Archive) []byte {var bytes.Buffer.Write(fixNL(.Comment))for , := range .Files {fmt.Fprintf(&, "-- %s --\n", .Name).Write(fixNL(.Data))}return .Bytes()}// ParseFile parses the named file as an archive.func ( string) (*Archive, error) {, := os.ReadFile()if != nil {return nil,}return Parse(), nil}// Parse parses the serialized form of an Archive.// The returned Archive holds slices of data.func ( []byte) *Archive {:= new(Archive)var string.Comment, , = findFileMarker()for != "" {:= File{, nil}.Data, , = findFileMarker().Files = append(.Files, )}return}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( []byte) ( []byte, string, []byte) {var intfor {if , = isMarker([:]); != "" {return [:], ,}:= bytes.Index([:], newlineMarker)if < 0 {return fixNL(), "", nil}+= + 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( []byte) ( string, []byte) {if !bytes.HasPrefix(, marker) {return "", nil}if := bytes.IndexByte(, '\n'); >= 0 {, = [:], [+1:]}if !(bytes.HasSuffix(, markerEnd) && len() >= len(marker)+len(markerEnd)) {return "", nil}return strings.TrimSpace(string([len(marker) : len()-len(markerEnd)])),}// 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( []byte) []byte {if len() == 0 || [len()-1] == '\n' {return}:= make([]byte, len()+1)copy(, )[len()] = '\n'return}
![]() |
The pages are generated with Golds v0.7.9-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |