utils.go raw
1 package utils
2
3 import (
4 "fmt"
5 "io"
6 "os"
7 "strings"
8 "unicode"
9 )
10
11 func ReadFileTail(filePath string, maxLen int) (data []byte, err error) {
12 f, err := os.Open(filePath)
13 if err != nil {
14 return nil, fmt.Errorf("failed to open file: %w", err)
15 }
16 defer func() {
17 err = f.Close()
18 if err != nil {
19 err = fmt.Errorf("failed to close file: %w", err)
20 data = nil
21 }
22 }()
23
24 var dataReader io.Reader = f
25
26 if maxLen > 0 {
27 stat, err := f.Stat()
28 if err != nil {
29 return nil, fmt.Errorf("failed to stat file: %w", err)
30 }
31
32 if stat.Size() > int64(maxLen) {
33 _, err = f.Seek(-int64(maxLen), io.SeekEnd)
34 if err != nil {
35 return nil, fmt.Errorf("failed to seek file: %w", err)
36 }
37 }
38
39 dataReader = io.LimitReader(f, int64(maxLen))
40 }
41
42 data, err = io.ReadAll(dataReader)
43 if err != nil {
44 return nil, fmt.Errorf("failed to read file: %w", err)
45 }
46
47 return data, nil
48 }
49
50 // filters values from a slice
51 func Filter[T any](s []T, f func(T) bool) []T {
52 var r []T
53 for _, v := range s {
54 if f(v) {
55 r = append(r, v)
56 }
57 }
58 return r
59 }
60
61 func ParseCommandLine(s string) ([]string, error) {
62 args := make([]string, 0)
63 var currentArg strings.Builder
64 inQuotes := false
65 escaped := false
66
67 for _, r := range s {
68 switch {
69 case escaped:
70 currentArg.WriteRune(r)
71 escaped = false
72 case r == '\\':
73 escaped = true
74 case r == '"':
75 inQuotes = !inQuotes
76 case unicode.IsSpace(r) && !inQuotes:
77 if currentArg.Len() > 0 {
78 args = append(args, currentArg.String())
79 currentArg.Reset()
80 }
81 default:
82 currentArg.WriteRune(r)
83 }
84 }
85
86 if escaped || inQuotes {
87 return nil, fmt.Errorf("unexpected end of string")
88 }
89
90 if currentArg.Len() > 0 {
91 args = append(args, currentArg.String())
92 }
93
94 return args, nil
95 }
96