File: filereader.go

package info (click to toggle)
goawk 1.29.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,560 kB
  • sloc: awk: 3,060; yacc: 198; fortran: 189; python: 131; sh: 58; makefile: 12
file content (55 lines) | stat: -rw-r--r-- 1,438 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Package parseutil contains various utilities for parsing GoAWK source code.
package parseutil

import (
	"bytes"
	"io"
)

// FileReader serves two purposes:
// 1. read input sources and join them into a single source (slice of bytes)
// 2. track the lines counts of each input source
type FileReader struct {
	files  []file
	source bytes.Buffer
}

type file struct {
	path  string
	lines int
}

// AddFile adds a single source file.
func (fr *FileReader) AddFile(path string, source io.Reader) error {
	curLen := fr.source.Len()
	_, err := fr.source.ReadFrom(source)
	if err != nil {
		return err
	}
	if !bytes.HasSuffix(fr.source.Bytes(), []byte("\n")) {
		// Append newline to file in case it doesn't end with one
		fr.source.WriteByte('\n')
	}
	content := fr.source.Bytes()[curLen:]
	lines := bytes.Count(content, []byte("\n"))
	fr.files = append(fr.files, file{path, lines})
	return nil
}

// FileLine resolves an overall line number from the concatenated source code
// to the local line number in that source file (identified by path).
func (fr *FileReader) FileLine(line int) (path string, fileLine int) {
	startLine := 1
	for _, f := range fr.files {
		if line >= startLine && line < startLine+f.lines {
			return f.path, line - startLine + 1
		}
		startLine += f.lines
	}
	return "", 0
}

// Source returns the concatenated source code from all files added.
func (fr *FileReader) Source() []byte {
	return fr.source.Bytes()
}