summaryrefslogtreecommitdiff
path: root/vendor/github.com/cilium/ebpf/internal/output.go
blob: aeab37fcfafe9d7b3aeec04d83ba1939b16722a2 (plain)
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
package internal

import (
	"bytes"
	"errors"
	"go/format"
	"go/scanner"
	"io"
	"strings"
	"unicode"
)

// Identifier turns a C style type or field name into an exportable Go equivalent.
func Identifier(str string) string {
	prev := rune(-1)
	return strings.Map(func(r rune) rune {
		// See https://golang.org/ref/spec#Identifiers
		switch {
		case unicode.IsLetter(r):
			if prev == -1 {
				r = unicode.ToUpper(r)
			}

		case r == '_':
			switch {
			// The previous rune was deleted, or we are at the
			// beginning of the string.
			case prev == -1:
				fallthrough

			// The previous rune is a lower case letter or a digit.
			case unicode.IsDigit(prev) || (unicode.IsLetter(prev) && unicode.IsLower(prev)):
				// delete the current rune, and force the
				// next character to be uppercased.
				r = -1
			}

		case unicode.IsDigit(r):

		default:
			// Delete the current rune. prev is unchanged.
			return -1
		}

		prev = r
		return r
	}, str)
}

// WriteFormatted outputs a formatted src into out.
//
// If formatting fails it returns an informative error message.
func WriteFormatted(src []byte, out io.Writer) error {
	formatted, err := format.Source(src)
	if err == nil {
		_, err = out.Write(formatted)
		return err
	}

	var el scanner.ErrorList
	if !errors.As(err, &el) {
		return err
	}

	var nel scanner.ErrorList
	for _, err := range el {
		if !err.Pos.IsValid() {
			nel = append(nel, err)
			continue
		}

		buf := src[err.Pos.Offset:]
		nl := bytes.IndexRune(buf, '\n')
		if nl == -1 {
			nel = append(nel, err)
			continue
		}

		err.Msg += ": " + string(buf[:nl])
		nel = append(nel, err)
	}

	return nel
}