File: source.go

package info (click to toggle)
goda 0.5.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 416 kB
  • sloc: makefile: 9
file content (133 lines) | stat: -rw-r--r-- 2,030 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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package stat

import (
	"errors"
	"io"
	"os"

	"github.com/loov/goda/internal/memory"
)

// Source contains basic analysis of arbitrary source code.
type Source struct {
	// Files count in this stat.
	Files int
	// Binary file count.
	Binary int
	// Size in bytes of all files.
	Size memory.Bytes
	// Count of non-empty lines.
	Lines int
	// Count of empty lines.
	Blank int
}

func (c *Source) Add(s Source) {
	c.Files += s.Files
	c.Binary += s.Binary
	c.Size += s.Size

	c.Blank += s.Blank
	c.Lines += s.Lines
}

func SourceFromBytes(data []byte) Source {
	count := Source{Files: 1}
	if len(data) == 0 {
		return count
	}
	count.Size += memory.Bytes(len(data))

	emptyline := true
	for _, c := range data {
		switch c {
		case 0x0:

			count.Blank = 0
			count.Lines = 0
			count.Files = 0
			count.Binary = 1

			return count
		case '\n':
			if emptyline {
				count.Blank++
			} else {
				count.Lines++
			}
			emptyline = true
		case '\r', ' ', '\t': // ignore
		default:
			emptyline = false
		}
	}
	if !emptyline {
		count.Lines++
	}

	return count
}

var ErrEmptyFile = errors.New("empty file")

func SourceFromPath(path string) (Source, error) {
	count := Source{
		Files: 1,
	}

	file, err := os.Open(path)
	if err != nil {
		return count, err
	}
	defer file.Close()

	stat, err := file.Stat()
	if err != nil {
		return count, err
	}
	if stat.Size() <= 0 {
		return count, ErrEmptyFile
	}
	count.Size += memory.Bytes(stat.Size())

	buf := make([]byte, 8196)
	emptyline := true
	for {
		n, err := file.Read(buf)
		if err != nil && err != io.EOF {
			return count, err
		}

		for _, c := range buf[:n] {
			switch c {
			case 0x0:

				count.Blank = 0
				count.Lines = 0
				count.Files = 0
				count.Binary = 1

				return count, nil
			case '\n':
				if emptyline {
					count.Blank++
				} else {
					count.Lines++
				}
				emptyline = true
			case '\r', ' ', '\t': // ignore
			default:
				emptyline = false
			}
		}
		if err == io.EOF {
			break
		}
	}

	if !emptyline {
		count.Lines++
	}

	return count, nil
}