File: path.go

package info (click to toggle)
golang-github-caspr-io-yamlpath 0.0~git20200722.502e8d1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 116 kB
  • sloc: makefile: 11
file content (111 lines) | stat: -rw-r--r-- 2,142 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
package segments

import "fmt"

func ParseSegment(path string) ([]YamlPathSegment, error) {
	if path[0] == '/' {
		return parseSegment(path[1:], '/')
	}

	return parseSegment(path, '.')
}

func parseSegment(path string, separator rune) ([]YamlPathSegment, error) {
	segments := []YamlPathSegment{}
	currentSegment := []rune{}
	i := 0

	for i < len(path) {
		r := rune(path[i])
		switch r {
		case separator:
			if err := addSegment(currentSegment, &segments); err != nil {
				return nil, err
			}

			currentSegment = []rune{}
		case '\\':
			i++
			r = rune(path[i])
			currentSegment = append(currentSegment, r)
		case '"', '\'':
			if err := addSegment(currentSegment, &segments); err != nil {
				return nil, err
			}

			currentSegment = []rune{}

			p, endIdx, err := parsePathUntil(path, i+1, r, false) //nolint:gomnd
			if err != nil {
				return nil, err
			}

			segments = append(segments, p)
			i = endIdx
		case '[':
			if err := addSegment(currentSegment, &segments); err != nil {
				return nil, err
			}

			currentSegment = []rune{}

			p, endIdx, err := parsePathUntil(path, i, ']', true)
			if err != nil {
				return nil, err
			}

			segments = append(segments, p)
			i = endIdx
		default:
			currentSegment = append(currentSegment, r)
		}
		i++
	}

	if len(currentSegment) > 0 {
		if err := addSegment(currentSegment, &segments); err != nil {
			return nil, err
		}
	}

	return segments, nil
}

func addSegment(segment []rune, segments *[]YamlPathSegment) error {
	if len(segment) == 0 {
		return nil
	}

	p, err := DetectSegment(string(segment))
	if err != nil {
		return err
	}

	l := append(*segments, p)
	*segments = l

	return nil
}

func parsePathUntil(path string, idx int, stopOn rune, inclusive bool) (YamlPathSegment, int, error) {
	segment := []rune{}
	i := idx

	for i < len(path) {
		r := rune(path[i])
		segment = append(segment, r)

		if r == stopOn {
			if !inclusive {
				segment = segment[0 : len(segment)-1]
			}

			ypp, err := DetectSegment(string(segment))

			return ypp, i + 1, err
		}
		i++
	}

	return nil, -1, fmt.Errorf("could not find terminating '%c' in path '%s'", stopOn, path[idx:])
}