path.gno

1.45 Kb ยท 78 lines
 1package json
 2
 3import (
 4	"errors"
 5)
 6
 7// ParsePath takes a JSONPath string and returns a slice of strings representing the path segments.
 8func ParsePath(path string) ([]string, error) {
 9	buf := newBuffer([]byte(path))
10	result := make([]string, 0)
11
12	for {
13		b, err := buf.current()
14		if err != nil {
15			break
16		}
17
18		switch {
19		case b == dollarSign || b == atSign:
20			result = append(result, string(b))
21			buf.step()
22
23		case b == dot:
24			buf.step()
25
26			if next, _ := buf.current(); next == dot {
27				buf.step()
28				result = append(result, "..")
29
30				extractNextSegment(buf, &result)
31			} else {
32				extractNextSegment(buf, &result)
33			}
34
35		case b == bracketOpen:
36			start := buf.index
37			buf.step()
38
39			for {
40				if buf.index >= buf.length || buf.data[buf.index] == bracketClose {
41					break
42				}
43
44				buf.step()
45			}
46
47			if buf.index >= buf.length {
48				return nil, errors.New("unexpected end of path")
49			}
50
51			segment := string(buf.sliceFromIndices(start+1, buf.index))
52			result = append(result, segment)
53
54			buf.step()
55
56		default:
57			buf.step()
58		}
59	}
60
61	return result, nil
62}
63
64// extractNextSegment extracts the segment from the current index
65// to the next significant character and adds it to the resulting slice.
66func extractNextSegment(buf *buffer, result *[]string) {
67	start := buf.index
68	buf.skipToNextSignificantToken()
69
70	if buf.index <= start {
71		return
72	}
73
74	segment := string(buf.sliceFromIndices(start, buf.index))
75	if segment != "" {
76		*result = append(*result, segment)
77	}
78}