1// Package gjson provides searching for json strings.
2package gjson
3
4import (
5	"encoding/json"
6	"strconv"
7	"strings"
8	"time"
9	"unicode/utf16"
10	"unicode/utf8"
11	"unsafe"
12
13	"github.com/tidwall/match"
14	"github.com/tidwall/pretty"
15)
16
17// Type is Result type
18type Type int
19
20const (
21	// Null is a null json value
22	Null Type = iota
23	// False is a json false boolean
24	False
25	// Number is json number
26	Number
27	// String is a json string
28	String
29	// True is a json true boolean
30	True
31	// JSON is a raw block of JSON
32	JSON
33)
34
35// String returns a string representation of the type.
36func (t Type) String() string {
37	switch t {
38	default:
39		return ""
40	case Null:
41		return "Null"
42	case False:
43		return "False"
44	case Number:
45		return "Number"
46	case String:
47		return "String"
48	case True:
49		return "True"
50	case JSON:
51		return "JSON"
52	}
53}
54
55// Result represents a json value that is returned from Get().
56type Result struct {
57	// Type is the json type
58	Type Type
59	// Raw is the raw json
60	Raw string
61	// Str is the json string
62	Str string
63	// Num is the json number
64	Num float64
65	// Index of raw value in original json, zero means index unknown
66	Index int
67}
68
69// String returns a string representation of the value.
70func (t Result) String() string {
71	switch t.Type {
72	default:
73		return ""
74	case False:
75		return "false"
76	case Number:
77		if len(t.Raw) == 0 {
78			// calculated result
79			return strconv.FormatFloat(t.Num, 'f', -1, 64)
80		}
81		var i int
82		if t.Raw[0] == '-' {
83			i++
84		}
85		for ; i < len(t.Raw); i++ {
86			if t.Raw[i] < '0' || t.Raw[i] > '9' {
87				return strconv.FormatFloat(t.Num, 'f', -1, 64)
88			}
89		}
90		return t.Raw
91	case String:
92		return t.Str
93	case JSON:
94		return t.Raw
95	case True:
96		return "true"
97	}
98}
99
100// Bool returns an boolean representation.
101func (t Result) Bool() bool {
102	switch t.Type {
103	default:
104		return false
105	case True:
106		return true
107	case String:
108		b, _ := strconv.ParseBool(strings.ToLower(t.Str))
109		return b
110	case Number:
111		return t.Num != 0
112	}
113}
114
115// Int returns an integer representation.
116func (t Result) Int() int64 {
117	switch t.Type {
118	default:
119		return 0
120	case True:
121		return 1
122	case String:
123		n, _ := parseInt(t.Str)
124		return n
125	case Number:
126		// try to directly convert the float64 to int64
127		i, ok := safeInt(t.Num)
128		if ok {
129			return i
130		}
131		// now try to parse the raw string
132		i, ok = parseInt(t.Raw)
133		if ok {
134			return i
135		}
136		// fallback to a standard conversion
137		return int64(t.Num)
138	}
139}
140
141// Uint returns an unsigned integer representation.
142func (t Result) Uint() uint64 {
143	switch t.Type {
144	default:
145		return 0
146	case True:
147		return 1
148	case String:
149		n, _ := parseUint(t.Str)
150		return n
151	case Number:
152		// try to directly convert the float64 to uint64
153		i, ok := safeInt(t.Num)
154		if ok && i >= 0 {
155			return uint64(i)
156		}
157		// now try to parse the raw string
158		u, ok := parseUint(t.Raw)
159		if ok {
160			return u
161		}
162		// fallback to a standard conversion
163		return uint64(t.Num)
164	}
165}
166
167// Float returns an float64 representation.
168func (t Result) Float() float64 {
169	switch t.Type {
170	default:
171		return 0
172	case True:
173		return 1
174	case String:
175		n, _ := strconv.ParseFloat(t.Str, 64)
176		return n
177	case Number:
178		return t.Num
179	}
180}
181
182// Time returns a time.Time representation.
183func (t Result) Time() time.Time {
184	res, _ := time.Parse(time.RFC3339, t.String())
185	return res
186}
187
188// Array returns back an array of values.
189// If the result represents a non-existent value, then an empty array will be
190// returned. If the result is not a JSON array, the return value will be an
191// array containing one result.
192func (t Result) Array() []Result {
193	if t.Type == Null {
194		return []Result{}
195	}
196	if t.Type != JSON {
197		return []Result{t}
198	}
199	r := t.arrayOrMap('[', false)
200	return r.a
201}
202
203// IsObject returns true if the result value is a JSON object.
204func (t Result) IsObject() bool {
205	return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '{'
206}
207
208// IsArray returns true if the result value is a JSON array.
209func (t Result) IsArray() bool {
210	return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '['
211}
212
213// ForEach iterates through values.
214// If the result represents a non-existent value, then no values will be
215// iterated. If the result is an Object, the iterator will pass the key and
216// value of each item. If the result is an Array, the iterator will only pass
217// the value of each item. If the result is not a JSON array or object, the
218// iterator will pass back one value equal to the result.
219func (t Result) ForEach(iterator func(key, value Result) bool) {
220	if !t.Exists() {
221		return
222	}
223	if t.Type != JSON {
224		iterator(Result{}, t)
225		return
226	}
227	json := t.Raw
228	var keys bool
229	var i int
230	var key, value Result
231	for ; i < len(json); i++ {
232		if json[i] == '{' {
233			i++
234			key.Type = String
235			keys = true
236			break
237		} else if json[i] == '[' {
238			i++
239			break
240		}
241		if json[i] > ' ' {
242			return
243		}
244	}
245	var str string
246	var vesc bool
247	var ok bool
248	for ; i < len(json); i++ {
249		if keys {
250			if json[i] != '"' {
251				continue
252			}
253			s := i
254			i, str, vesc, ok = parseString(json, i+1)
255			if !ok {
256				return
257			}
258			if vesc {
259				key.Str = unescape(str[1 : len(str)-1])
260			} else {
261				key.Str = str[1 : len(str)-1]
262			}
263			key.Raw = str
264			key.Index = s
265		}
266		for ; i < len(json); i++ {
267			if json[i] <= ' ' || json[i] == ',' || json[i] == ':' {
268				continue
269			}
270			break
271		}
272		s := i
273		i, value, ok = parseAny(json, i, true)
274		if !ok {
275			return
276		}
277		value.Index = s
278		if !iterator(key, value) {
279			return
280		}
281	}
282}
283
284// Map returns back an map of values. The result should be a JSON array.
285func (t Result) Map() map[string]Result {
286	if t.Type != JSON {
287		return map[string]Result{}
288	}
289	r := t.arrayOrMap('{', false)
290	return r.o
291}
292
293// Get searches result for the specified path.
294// The result should be a JSON array or object.
295func (t Result) Get(path string) Result {
296	return Get(t.Raw, path)
297}
298
299type arrayOrMapResult struct {
300	a  []Result
301	ai []interface{}
302	o  map[string]Result
303	oi map[string]interface{}
304	vc byte
305}
306
307func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) {
308	var json = t.Raw
309	var i int
310	var value Result
311	var count int
312	var key Result
313	if vc == 0 {
314		for ; i < len(json); i++ {
315			if json[i] == '{' || json[i] == '[' {
316				r.vc = json[i]
317				i++
318				break
319			}
320			if json[i] > ' ' {
321				goto end
322			}
323		}
324	} else {
325		for ; i < len(json); i++ {
326			if json[i] == vc {
327				i++
328				break
329			}
330			if json[i] > ' ' {
331				goto end
332			}
333		}
334		r.vc = vc
335	}
336	if r.vc == '{' {
337		if valueize {
338			r.oi = make(map[string]interface{})
339		} else {
340			r.o = make(map[string]Result)
341		}
342	} else {
343		if valueize {
344			r.ai = make([]interface{}, 0)
345		} else {
346			r.a = make([]Result, 0)
347		}
348	}
349	for ; i < len(json); i++ {
350		if json[i] <= ' ' {
351			continue
352		}
353		// get next value
354		if json[i] == ']' || json[i] == '}' {
355			break
356		}
357		switch json[i] {
358		default:
359			if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {
360				value.Type = Number
361				value.Raw, value.Num = tonum(json[i:])
362				value.Str = ""
363			} else {
364				continue
365			}
366		case '{', '[':
367			value.Type = JSON
368			value.Raw = squash(json[i:])
369			value.Str, value.Num = "", 0
370		case 'n':
371			value.Type = Null
372			value.Raw = tolit(json[i:])
373			value.Str, value.Num = "", 0
374		case 't':
375			value.Type = True
376			value.Raw = tolit(json[i:])
377			value.Str, value.Num = "", 0
378		case 'f':
379			value.Type = False
380			value.Raw = tolit(json[i:])
381			value.Str, value.Num = "", 0
382		case '"':
383			value.Type = String
384			value.Raw, value.Str = tostr(json[i:])
385			value.Num = 0
386		}
387		i += len(value.Raw) - 1
388
389		if r.vc == '{' {
390			if count%2 == 0 {
391				key = value
392			} else {
393				if valueize {
394					if _, ok := r.oi[key.Str]; !ok {
395						r.oi[key.Str] = value.Value()
396					}
397				} else {
398					if _, ok := r.o[key.Str]; !ok {
399						r.o[key.Str] = value
400					}
401				}
402			}
403			count++
404		} else {
405			if valueize {
406				r.ai = append(r.ai, value.Value())
407			} else {
408				r.a = append(r.a, value)
409			}
410		}
411	}
412end:
413	return
414}
415
416// Parse parses the json and returns a result.
417//
418// This function expects that the json is well-formed, and does not validate.
419// Invalid json will not panic, but it may return back unexpected results.
420// If you are consuming JSON from an unpredictable source then you may want to
421// use the Valid function first.
422func Parse(json string) Result {
423	var value Result
424	for i := 0; i < len(json); i++ {
425		if json[i] == '{' || json[i] == '[' {
426			value.Type = JSON
427			value.Raw = json[i:] // just take the entire raw
428			break
429		}
430		if json[i] <= ' ' {
431			continue
432		}
433		switch json[i] {
434		default:
435			if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {
436				value.Type = Number
437				value.Raw, value.Num = tonum(json[i:])
438			} else {
439				return Result{}
440			}
441		case 'n':
442			value.Type = Null
443			value.Raw = tolit(json[i:])
444		case 't':
445			value.Type = True
446			value.Raw = tolit(json[i:])
447		case 'f':
448			value.Type = False
449			value.Raw = tolit(json[i:])
450		case '"':
451			value.Type = String
452			value.Raw, value.Str = tostr(json[i:])
453		}
454		break
455	}
456	return value
457}
458
459// ParseBytes parses the json and returns a result.
460// If working with bytes, this method preferred over Parse(string(data))
461func ParseBytes(json []byte) Result {
462	return Parse(string(json))
463}
464
465func squash(json string) string {
466	// expects that the lead character is a '[' or '{' or '(' or '"'
467	// squash the value, ignoring all nested arrays and objects.
468	var i, depth int
469	if json[0] != '"' {
470		i, depth = 1, 1
471	}
472	for ; i < len(json); i++ {
473		if json[i] >= '"' && json[i] <= '}' {
474			switch json[i] {
475			case '"':
476				i++
477				s2 := i
478				for ; i < len(json); i++ {
479					if json[i] > '\\' {
480						continue
481					}
482					if json[i] == '"' {
483						// look for an escaped slash
484						if json[i-1] == '\\' {
485							n := 0
486							for j := i - 2; j > s2-1; j-- {
487								if json[j] != '\\' {
488									break
489								}
490								n++
491							}
492							if n%2 == 0 {
493								continue
494							}
495						}
496						break
497					}
498				}
499				if depth == 0 {
500					if i >= len(json) {
501						return json
502					}
503					return json[:i+1]
504				}
505			case '{', '[', '(':
506				depth++
507			case '}', ']', ')':
508				depth--
509				if depth == 0 {
510					return json[:i+1]
511				}
512			}
513		}
514	}
515	return json
516}
517
518func tonum(json string) (raw string, num float64) {
519	for i := 1; i < len(json); i++ {
520		// less than dash might have valid characters
521		if json[i] <= '-' {
522			if json[i] <= ' ' || json[i] == ',' {
523				// break on whitespace and comma
524				raw = json[:i]
525				num, _ = strconv.ParseFloat(raw, 64)
526				return
527			}
528			// could be a '+' or '-'. let's assume so.
529			continue
530		}
531		if json[i] < ']' {
532			// probably a valid number
533			continue
534		}
535		if json[i] == 'e' || json[i] == 'E' {
536			// allow for exponential numbers
537			continue
538		}
539		// likely a ']' or '}'
540		raw = json[:i]
541		num, _ = strconv.ParseFloat(raw, 64)
542		return
543	}
544	raw = json
545	num, _ = strconv.ParseFloat(raw, 64)
546	return
547}
548
549func tolit(json string) (raw string) {
550	for i := 1; i < len(json); i++ {
551		if json[i] < 'a' || json[i] > 'z' {
552			return json[:i]
553		}
554	}
555	return json
556}
557
558func tostr(json string) (raw string, str string) {
559	// expects that the lead character is a '"'
560	for i := 1; i < len(json); i++ {
561		if json[i] > '\\' {
562			continue
563		}
564		if json[i] == '"' {
565			return json[:i+1], json[1:i]
566		}
567		if json[i] == '\\' {
568			i++
569			for ; i < len(json); i++ {
570				if json[i] > '\\' {
571					continue
572				}
573				if json[i] == '"' {
574					// look for an escaped slash
575					if json[i-1] == '\\' {
576						n := 0
577						for j := i - 2; j > 0; j-- {
578							if json[j] != '\\' {
579								break
580							}
581							n++
582						}
583						if n%2 == 0 {
584							continue
585						}
586					}
587					break
588				}
589			}
590			var ret string
591			if i+1 < len(json) {
592				ret = json[:i+1]
593			} else {
594				ret = json[:i]
595			}
596			return ret, unescape(json[1:i])
597		}
598	}
599	return json, json[1:]
600}
601
602// Exists returns true if value exists.
603//
604//  if gjson.Get(json, "name.last").Exists(){
605//		println("value exists")
606//  }
607func (t Result) Exists() bool {
608	return t.Type != Null || len(t.Raw) != 0
609}
610
611// Value returns one of these types:
612//
613//	bool, for JSON booleans
614//	float64, for JSON numbers
615//	Number, for JSON numbers
616//	string, for JSON string literals
617//	nil, for JSON null
618//	map[string]interface{}, for JSON objects
619//	[]interface{}, for JSON arrays
620//
621func (t Result) Value() interface{} {
622	if t.Type == String {
623		return t.Str
624	}
625	switch t.Type {
626	default:
627		return nil
628	case False:
629		return false
630	case Number:
631		return t.Num
632	case JSON:
633		r := t.arrayOrMap(0, true)
634		if r.vc == '{' {
635			return r.oi
636		} else if r.vc == '[' {
637			return r.ai
638		}
639		return nil
640	case True:
641		return true
642	}
643}
644
645func parseString(json string, i int) (int, string, bool, bool) {
646	var s = i
647	for ; i < len(json); i++ {
648		if json[i] > '\\' {
649			continue
650		}
651		if json[i] == '"' {
652			return i + 1, json[s-1 : i+1], false, true
653		}
654		if json[i] == '\\' {
655			i++
656			for ; i < len(json); i++ {
657				if json[i] > '\\' {
658					continue
659				}
660				if json[i] == '"' {
661					// look for an escaped slash
662					if json[i-1] == '\\' {
663						n := 0
664						for j := i - 2; j > 0; j-- {
665							if json[j] != '\\' {
666								break
667							}
668							n++
669						}
670						if n%2 == 0 {
671							continue
672						}
673					}
674					return i + 1, json[s-1 : i+1], true, true
675				}
676			}
677			break
678		}
679	}
680	return i, json[s-1:], false, false
681}
682
683func parseNumber(json string, i int) (int, string) {
684	var s = i
685	i++
686	for ; i < len(json); i++ {
687		if json[i] <= ' ' || json[i] == ',' || json[i] == ']' ||
688			json[i] == '}' {
689			return i, json[s:i]
690		}
691	}
692	return i, json[s:]
693}
694
695func parseLiteral(json string, i int) (int, string) {
696	var s = i
697	i++
698	for ; i < len(json); i++ {
699		if json[i] < 'a' || json[i] > 'z' {
700			return i, json[s:i]
701		}
702	}
703	return i, json[s:]
704}
705
706type arrayPathResult struct {
707	part    string
708	path    string
709	pipe    string
710	piped   bool
711	more    bool
712	alogok  bool
713	arrch   bool
714	alogkey string
715	query   struct {
716		on    bool
717		all   bool
718		path  string
719		op    string
720		value string
721	}
722}
723
724func parseArrayPath(path string) (r arrayPathResult) {
725	for i := 0; i < len(path); i++ {
726		if path[i] == '|' {
727			r.part = path[:i]
728			r.pipe = path[i+1:]
729			r.piped = true
730			return
731		}
732		if path[i] == '.' {
733			r.part = path[:i]
734			if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1]) {
735				r.pipe = path[i+1:]
736				r.piped = true
737			} else {
738				r.path = path[i+1:]
739				r.more = true
740			}
741			return
742		}
743		if path[i] == '#' {
744			r.arrch = true
745			if i == 0 && len(path) > 1 {
746				if path[1] == '.' {
747					r.alogok = true
748					r.alogkey = path[2:]
749					r.path = path[:1]
750				} else if path[1] == '[' || path[1] == '(' {
751					// query
752					r.query.on = true
753					qpath, op, value, _, fi, vesc, ok :=
754						parseQuery(path[i:])
755					if !ok {
756						// bad query, end now
757						break
758					}
759					if len(value) > 2 && value[0] == '"' &&
760						value[len(value)-1] == '"' {
761						value = value[1 : len(value)-1]
762						if vesc {
763							value = unescape(value)
764						}
765					}
766					r.query.path = qpath
767					r.query.op = op
768					r.query.value = value
769
770					i = fi - 1
771					if i+1 < len(path) && path[i+1] == '#' {
772						r.query.all = true
773					}
774				}
775			}
776			continue
777		}
778	}
779	r.part = path
780	r.path = ""
781	return
782}
783
784// splitQuery takes a query and splits it into three parts:
785//   path, op, middle, and right.
786// So for this query:
787//   #(first_name=="Murphy").last
788// Becomes
789//   first_name   # path
790//   =="Murphy"   # middle
791//   .last        # right
792// Or,
793//   #(service_roles.#(=="one")).cap
794// Becomes
795//   service_roles.#(=="one")   # path
796//                              # middle
797//   .cap                       # right
798func parseQuery(query string) (
799	path, op, value, remain string, i int, vesc, ok bool,
800) {
801	if len(query) < 2 || query[0] != '#' ||
802		(query[1] != '(' && query[1] != '[') {
803		return "", "", "", "", i, false, false
804	}
805	i = 2
806	j := 0 // start of value part
807	depth := 1
808	for ; i < len(query); i++ {
809		if depth == 1 && j == 0 {
810			switch query[i] {
811			case '!', '=', '<', '>', '%':
812				// start of the value part
813				j = i
814				continue
815			}
816		}
817		if query[i] == '\\' {
818			i++
819		} else if query[i] == '[' || query[i] == '(' {
820			depth++
821		} else if query[i] == ']' || query[i] == ')' {
822			depth--
823			if depth == 0 {
824				break
825			}
826		} else if query[i] == '"' {
827			// inside selector string, balance quotes
828			i++
829			for ; i < len(query); i++ {
830				if query[i] == '\\' {
831					vesc = true
832					i++
833				} else if query[i] == '"' {
834					break
835				}
836			}
837		}
838	}
839	if depth > 0 {
840		return "", "", "", "", i, false, false
841	}
842	if j > 0 {
843		path = trim(query[2:j])
844		value = trim(query[j:i])
845		remain = query[i+1:]
846		// parse the compare op from the value
847		var opsz int
848		switch {
849		case len(value) == 1:
850			opsz = 1
851		case value[0] == '!' && value[1] == '=':
852			opsz = 2
853		case value[0] == '!' && value[1] == '%':
854			opsz = 2
855		case value[0] == '<' && value[1] == '=':
856			opsz = 2
857		case value[0] == '>' && value[1] == '=':
858			opsz = 2
859		case value[0] == '=' && value[1] == '=':
860			value = value[1:]
861			opsz = 1
862		case value[0] == '<':
863			opsz = 1
864		case value[0] == '>':
865			opsz = 1
866		case value[0] == '=':
867			opsz = 1
868		case value[0] == '%':
869			opsz = 1
870		}
871		op = value[:opsz]
872		value = trim(value[opsz:])
873	} else {
874		path = trim(query[2:i])
875		remain = query[i+1:]
876	}
877	return path, op, value, remain, i + 1, vesc, true
878}
879
880func trim(s string) string {
881left:
882	if len(s) > 0 && s[0] <= ' ' {
883		s = s[1:]
884		goto left
885	}
886right:
887	if len(s) > 0 && s[len(s)-1] <= ' ' {
888		s = s[:len(s)-1]
889		goto right
890	}
891	return s
892}
893
894// peek at the next byte and see if it's a '@', '[', or '{'.
895func isDotPiperChar(c byte) bool {
896	return !DisableModifiers && (c == '@' || c == '[' || c == '{')
897}
898
899type objectPathResult struct {
900	part  string
901	path  string
902	pipe  string
903	piped bool
904	wild  bool
905	more  bool
906}
907
908func parseObjectPath(path string) (r objectPathResult) {
909	for i := 0; i < len(path); i++ {
910		if path[i] == '|' {
911			r.part = path[:i]
912			r.pipe = path[i+1:]
913			r.piped = true
914			return
915		}
916		if path[i] == '.' {
917			r.part = path[:i]
918			if i < len(path)-1 && isDotPiperChar(path[i+1]) {
919				r.pipe = path[i+1:]
920				r.piped = true
921			} else {
922				r.path = path[i+1:]
923				r.more = true
924			}
925			return
926		}
927		if path[i] == '*' || path[i] == '?' {
928			r.wild = true
929			continue
930		}
931		if path[i] == '\\' {
932			// go into escape mode. this is a slower path that
933			// strips off the escape character from the part.
934			epart := []byte(path[:i])
935			i++
936			if i < len(path) {
937				epart = append(epart, path[i])
938				i++
939				for ; i < len(path); i++ {
940					if path[i] == '\\' {
941						i++
942						if i < len(path) {
943							epart = append(epart, path[i])
944						}
945						continue
946					} else if path[i] == '.' {
947						r.part = string(epart)
948						if i < len(path)-1 && isDotPiperChar(path[i+1]) {
949							r.pipe = path[i+1:]
950							r.piped = true
951						} else {
952							r.path = path[i+1:]
953						}
954						r.more = true
955						return
956					} else if path[i] == '|' {
957						r.part = string(epart)
958						r.pipe = path[i+1:]
959						r.piped = true
960						return
961					} else if path[i] == '*' || path[i] == '?' {
962						r.wild = true
963					}
964					epart = append(epart, path[i])
965				}
966			}
967			// append the last part
968			r.part = string(epart)
969			return
970		}
971	}
972	r.part = path
973	return
974}
975
976func parseSquash(json string, i int) (int, string) {
977	// expects that the lead character is a '[' or '{' or '('
978	// squash the value, ignoring all nested arrays and objects.
979	// the first '[' or '{' or '(' has already been read
980	s := i
981	i++
982	depth := 1
983	for ; i < len(json); i++ {
984		if json[i] >= '"' && json[i] <= '}' {
985			switch json[i] {
986			case '"':
987				i++
988				s2 := i
989				for ; i < len(json); i++ {
990					if json[i] > '\\' {
991						continue
992					}
993					if json[i] == '"' {
994						// look for an escaped slash
995						if json[i-1] == '\\' {
996							n := 0
997							for j := i - 2; j > s2-1; j-- {
998								if json[j] != '\\' {
999									break
1000								}
1001								n++
1002							}
1003							if n%2 == 0 {
1004								continue
1005							}
1006						}
1007						break
1008					}
1009				}
1010			case '{', '[', '(':
1011				depth++
1012			case '}', ']', ')':
1013				depth--
1014				if depth == 0 {
1015					i++
1016					return i, json[s:i]
1017				}
1018			}
1019		}
1020	}
1021	return i, json[s:]
1022}
1023
1024func parseObject(c *parseContext, i int, path string) (int, bool) {
1025	var pmatch, kesc, vesc, ok, hit bool
1026	var key, val string
1027	rp := parseObjectPath(path)
1028	if !rp.more && rp.piped {
1029		c.pipe = rp.pipe
1030		c.piped = true
1031	}
1032	for i < len(c.json) {
1033		for ; i < len(c.json); i++ {
1034			if c.json[i] == '"' {
1035				// parse_key_string
1036				// this is slightly different from getting s string value
1037				// because we don't need the outer quotes.
1038				i++
1039				var s = i
1040				for ; i < len(c.json); i++ {
1041					if c.json[i] > '\\' {
1042						continue
1043					}
1044					if c.json[i] == '"' {
1045						i, key, kesc, ok = i+1, c.json[s:i], false, true
1046						goto parse_key_string_done
1047					}
1048					if c.json[i] == '\\' {
1049						i++
1050						for ; i < len(c.json); i++ {
1051							if c.json[i] > '\\' {
1052								continue
1053							}
1054							if c.json[i] == '"' {
1055								// look for an escaped slash
1056								if c.json[i-1] == '\\' {
1057									n := 0
1058									for j := i - 2; j > 0; j-- {
1059										if c.json[j] != '\\' {
1060											break
1061										}
1062										n++
1063									}
1064									if n%2 == 0 {
1065										continue
1066									}
1067								}
1068								i, key, kesc, ok = i+1, c.json[s:i], true, true
1069								goto parse_key_string_done
1070							}
1071						}
1072						break
1073					}
1074				}
1075				key, kesc, ok = c.json[s:], false, false
1076			parse_key_string_done:
1077				break
1078			}
1079			if c.json[i] == '}' {
1080				return i + 1, false
1081			}
1082		}
1083		if !ok {
1084			return i, false
1085		}
1086		if rp.wild {
1087			if kesc {
1088				pmatch = match.Match(unescape(key), rp.part)
1089			} else {
1090				pmatch = match.Match(key, rp.part)
1091			}
1092		} else {
1093			if kesc {
1094				pmatch = rp.part == unescape(key)
1095			} else {
1096				pmatch = rp.part == key
1097			}
1098		}
1099		hit = pmatch && !rp.more
1100		for ; i < len(c.json); i++ {
1101			switch c.json[i] {
1102			default:
1103				continue
1104			case '"':
1105				i++
1106				i, val, vesc, ok = parseString(c.json, i)
1107				if !ok {
1108					return i, false
1109				}
1110				if hit {
1111					if vesc {
1112						c.value.Str = unescape(val[1 : len(val)-1])
1113					} else {
1114						c.value.Str = val[1 : len(val)-1]
1115					}
1116					c.value.Raw = val
1117					c.value.Type = String
1118					return i, true
1119				}
1120			case '{':
1121				if pmatch && !hit {
1122					i, hit = parseObject(c, i+1, rp.path)
1123					if hit {
1124						return i, true
1125					}
1126				} else {
1127					i, val = parseSquash(c.json, i)
1128					if hit {
1129						c.value.Raw = val
1130						c.value.Type = JSON
1131						return i, true
1132					}
1133				}
1134			case '[':
1135				if pmatch && !hit {
1136					i, hit = parseArray(c, i+1, rp.path)
1137					if hit {
1138						return i, true
1139					}
1140				} else {
1141					i, val = parseSquash(c.json, i)
1142					if hit {
1143						c.value.Raw = val
1144						c.value.Type = JSON
1145						return i, true
1146					}
1147				}
1148			case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
1149				i, val = parseNumber(c.json, i)
1150				if hit {
1151					c.value.Raw = val
1152					c.value.Type = Number
1153					c.value.Num, _ = strconv.ParseFloat(val, 64)
1154					return i, true
1155				}
1156			case 't', 'f', 'n':
1157				vc := c.json[i]
1158				i, val = parseLiteral(c.json, i)
1159				if hit {
1160					c.value.Raw = val
1161					switch vc {
1162					case 't':
1163						c.value.Type = True
1164					case 'f':
1165						c.value.Type = False
1166					}
1167					return i, true
1168				}
1169			}
1170			break
1171		}
1172	}
1173	return i, false
1174}
1175func queryMatches(rp *arrayPathResult, value Result) bool {
1176	rpv := rp.query.value
1177	if len(rpv) > 0 && rpv[0] == '~' {
1178		// convert to bool
1179		rpv = rpv[1:]
1180		if value.Bool() {
1181			value = Result{Type: True}
1182		} else {
1183			value = Result{Type: False}
1184		}
1185	}
1186	if !value.Exists() {
1187		return false
1188	}
1189	if rp.query.op == "" {
1190		// the query is only looking for existence, such as:
1191		//   friends.#(name)
1192		// which makes sure that the array "friends" has an element of
1193		// "name" that exists
1194		return true
1195	}
1196	switch value.Type {
1197	case String:
1198		switch rp.query.op {
1199		case "=":
1200			return value.Str == rpv
1201		case "!=":
1202			return value.Str != rpv
1203		case "<":
1204			return value.Str < rpv
1205		case "<=":
1206			return value.Str <= rpv
1207		case ">":
1208			return value.Str > rpv
1209		case ">=":
1210			return value.Str >= rpv
1211		case "%":
1212			return match.Match(value.Str, rpv)
1213		case "!%":
1214			return !match.Match(value.Str, rpv)
1215		}
1216	case Number:
1217		rpvn, _ := strconv.ParseFloat(rpv, 64)
1218		switch rp.query.op {
1219		case "=":
1220			return value.Num == rpvn
1221		case "!=":
1222			return value.Num != rpvn
1223		case "<":
1224			return value.Num < rpvn
1225		case "<=":
1226			return value.Num <= rpvn
1227		case ">":
1228			return value.Num > rpvn
1229		case ">=":
1230			return value.Num >= rpvn
1231		}
1232	case True:
1233		switch rp.query.op {
1234		case "=":
1235			return rpv == "true"
1236		case "!=":
1237			return rpv != "true"
1238		case ">":
1239			return rpv == "false"
1240		case ">=":
1241			return true
1242		}
1243	case False:
1244		switch rp.query.op {
1245		case "=":
1246			return rpv == "false"
1247		case "!=":
1248			return rpv != "false"
1249		case "<":
1250			return rpv == "true"
1251		case "<=":
1252			return true
1253		}
1254	}
1255	return false
1256}
1257func parseArray(c *parseContext, i int, path string) (int, bool) {
1258	var pmatch, vesc, ok, hit bool
1259	var val string
1260	var h int
1261	var alog []int
1262	var partidx int
1263	var multires []byte
1264	rp := parseArrayPath(path)
1265	if !rp.arrch {
1266		n, ok := parseUint(rp.part)
1267		if !ok {
1268			partidx = -1
1269		} else {
1270			partidx = int(n)
1271		}
1272	}
1273	if !rp.more && rp.piped {
1274		c.pipe = rp.pipe
1275		c.piped = true
1276	}
1277
1278	procQuery := func(qval Result) bool {
1279		if rp.query.all {
1280			if len(multires) == 0 {
1281				multires = append(multires, '[')
1282			}
1283		}
1284		var res Result
1285		if qval.Type == JSON {
1286			res = qval.Get(rp.query.path)
1287		} else {
1288			if rp.query.path != "" {
1289				return false
1290			}
1291			res = qval
1292		}
1293		if queryMatches(&rp, res) {
1294			if rp.more {
1295				left, right, ok := splitPossiblePipe(rp.path)
1296				if ok {
1297					rp.path = left
1298					c.pipe = right
1299					c.piped = true
1300				}
1301				res = qval.Get(rp.path)
1302			} else {
1303				res = qval
1304			}
1305			if rp.query.all {
1306				raw := res.Raw
1307				if len(raw) == 0 {
1308					raw = res.String()
1309				}
1310				if raw != "" {
1311					if len(multires) > 1 {
1312						multires = append(multires, ',')
1313					}
1314					multires = append(multires, raw...)
1315				}
1316			} else {
1317				c.value = res
1318				return true
1319			}
1320		}
1321		return false
1322	}
1323	for i < len(c.json)+1 {
1324		if !rp.arrch {
1325			pmatch = partidx == h
1326			hit = pmatch && !rp.more
1327		}
1328		h++
1329		if rp.alogok {
1330			alog = append(alog, i)
1331		}
1332		for ; ; i++ {
1333			var ch byte
1334			if i > len(c.json) {
1335				break
1336			} else if i == len(c.json) {
1337				ch = ']'
1338			} else {
1339				ch = c.json[i]
1340			}
1341			switch ch {
1342			default:
1343				continue
1344			case '"':
1345				i++
1346				i, val, vesc, ok = parseString(c.json, i)
1347				if !ok {
1348					return i, false
1349				}
1350				if rp.query.on {
1351					var qval Result
1352					if vesc {
1353						qval.Str = unescape(val[1 : len(val)-1])
1354					} else {
1355						qval.Str = val[1 : len(val)-1]
1356					}
1357					qval.Raw = val
1358					qval.Type = String
1359					if procQuery(qval) {
1360						return i, true
1361					}
1362				} else if hit {
1363					if rp.alogok {
1364						break
1365					}
1366					if vesc {
1367						c.value.Str = unescape(val[1 : len(val)-1])
1368					} else {
1369						c.value.Str = val[1 : len(val)-1]
1370					}
1371					c.value.Raw = val
1372					c.value.Type = String
1373					return i, true
1374				}
1375			case '{':
1376				if pmatch && !hit {
1377					i, hit = parseObject(c, i+1, rp.path)
1378					if hit {
1379						if rp.alogok {
1380							break
1381						}
1382						return i, true
1383					}
1384				} else {
1385					i, val = parseSquash(c.json, i)
1386					if rp.query.on {
1387						if procQuery(Result{Raw: val, Type: JSON}) {
1388							return i, true
1389						}
1390					} else if hit {
1391						if rp.alogok {
1392							break
1393						}
1394						c.value.Raw = val
1395						c.value.Type = JSON
1396						return i, true
1397					}
1398				}
1399			case '[':
1400				if pmatch && !hit {
1401					i, hit = parseArray(c, i+1, rp.path)
1402					if hit {
1403						if rp.alogok {
1404							break
1405						}
1406						return i, true
1407					}
1408				} else {
1409					i, val = parseSquash(c.json, i)
1410					if rp.query.on {
1411						if procQuery(Result{Raw: val, Type: JSON}) {
1412							return i, true
1413						}
1414					} else if hit {
1415						if rp.alogok {
1416							break
1417						}
1418						c.value.Raw = val
1419						c.value.Type = JSON
1420						return i, true
1421					}
1422				}
1423			case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
1424				i, val = parseNumber(c.json, i)
1425				if rp.query.on {
1426					var qval Result
1427					qval.Raw = val
1428					qval.Type = Number
1429					qval.Num, _ = strconv.ParseFloat(val, 64)
1430					if procQuery(qval) {
1431						return i, true
1432					}
1433				} else if hit {
1434					if rp.alogok {
1435						break
1436					}
1437					c.value.Raw = val
1438					c.value.Type = Number
1439					c.value.Num, _ = strconv.ParseFloat(val, 64)
1440					return i, true
1441				}
1442			case 't', 'f', 'n':
1443				vc := c.json[i]
1444				i, val = parseLiteral(c.json, i)
1445				if rp.query.on {
1446					var qval Result
1447					qval.Raw = val
1448					switch vc {
1449					case 't':
1450						qval.Type = True
1451					case 'f':
1452						qval.Type = False
1453					}
1454					if procQuery(qval) {
1455						return i, true
1456					}
1457				} else if hit {
1458					if rp.alogok {
1459						break
1460					}
1461					c.value.Raw = val
1462					switch vc {
1463					case 't':
1464						c.value.Type = True
1465					case 'f':
1466						c.value.Type = False
1467					}
1468					return i, true
1469				}
1470			case ']':
1471				if rp.arrch && rp.part == "#" {
1472					if rp.alogok {
1473						left, right, ok := splitPossiblePipe(rp.alogkey)
1474						if ok {
1475							rp.alogkey = left
1476							c.pipe = right
1477							c.piped = true
1478						}
1479						var jsons = make([]byte, 0, 64)
1480						jsons = append(jsons, '[')
1481						for j, k := 0, 0; j < len(alog); j++ {
1482							idx := alog[j]
1483							for idx < len(c.json) {
1484								switch c.json[idx] {
1485								case ' ', '\t', '\r', '\n':
1486									idx++
1487									continue
1488								}
1489								break
1490							}
1491							if idx < len(c.json) && c.json[idx] != ']' {
1492								_, res, ok := parseAny(c.json, idx, true)
1493								if ok {
1494									res := res.Get(rp.alogkey)
1495									if res.Exists() {
1496										if k > 0 {
1497											jsons = append(jsons, ',')
1498										}
1499										raw := res.Raw
1500										if len(raw) == 0 {
1501											raw = res.String()
1502										}
1503										jsons = append(jsons, []byte(raw)...)
1504										k++
1505									}
1506								}
1507							}
1508						}
1509						jsons = append(jsons, ']')
1510						c.value.Type = JSON
1511						c.value.Raw = string(jsons)
1512						return i + 1, true
1513					}
1514					if rp.alogok {
1515						break
1516					}
1517
1518					c.value.Type = Number
1519					c.value.Num = float64(h - 1)
1520					c.value.Raw = strconv.Itoa(h - 1)
1521					c.calcd = true
1522					return i + 1, true
1523				}
1524				if !c.value.Exists() {
1525					if len(multires) > 0 {
1526						c.value = Result{
1527							Raw:  string(append(multires, ']')),
1528							Type: JSON,
1529						}
1530					} else if rp.query.all {
1531						c.value = Result{
1532							Raw:  "[]",
1533							Type: JSON,
1534						}
1535					}
1536				}
1537				return i + 1, false
1538			}
1539			break
1540		}
1541	}
1542	return i, false
1543}
1544
1545func splitPossiblePipe(path string) (left, right string, ok bool) {
1546	// take a quick peek for the pipe character. If found we'll split the piped
1547	// part of the path into the c.pipe field and shorten the rp.
1548	var possible bool
1549	for i := 0; i < len(path); i++ {
1550		if path[i] == '|' {
1551			possible = true
1552			break
1553		}
1554	}
1555	if !possible {
1556		return
1557	}
1558
1559	if len(path) > 0 && path[0] == '{' {
1560		squashed := squash(path[1:])
1561		if len(squashed) < len(path)-1 {
1562			squashed = path[:len(squashed)+1]
1563			remain := path[len(squashed):]
1564			if remain[0] == '|' {
1565				return squashed, remain[1:], true
1566			}
1567		}
1568		return
1569	}
1570
1571	// split the left and right side of the path with the pipe character as
1572	// the delimiter. This is a little tricky because we'll need to basically
1573	// parse the entire path.
1574	for i := 0; i < len(path); i++ {
1575		if path[i] == '\\' {
1576			i++
1577		} else if path[i] == '.' {
1578			if i == len(path)-1 {
1579				return
1580			}
1581			if path[i+1] == '#' {
1582				i += 2
1583				if i == len(path) {
1584					return
1585				}
1586				if path[i] == '[' || path[i] == '(' {
1587					var start, end byte
1588					if path[i] == '[' {
1589						start, end = '[', ']'
1590					} else {
1591						start, end = '(', ')'
1592					}
1593					// inside selector, balance brackets
1594					i++
1595					depth := 1
1596					for ; i < len(path); i++ {
1597						if path[i] == '\\' {
1598							i++
1599						} else if path[i] == start {
1600							depth++
1601						} else if path[i] == end {
1602							depth--
1603							if depth == 0 {
1604								break
1605							}
1606						} else if path[i] == '"' {
1607							// inside selector string, balance quotes
1608							i++
1609							for ; i < len(path); i++ {
1610								if path[i] == '\\' {
1611									i++
1612								} else if path[i] == '"' {
1613									break
1614								}
1615							}
1616						}
1617					}
1618				}
1619			}
1620		} else if path[i] == '|' {
1621			return path[:i], path[i+1:], true
1622		}
1623	}
1624	return
1625}
1626
1627// ForEachLine iterates through lines of JSON as specified by the JSON Lines
1628// format (http://jsonlines.org/).
1629// Each line is returned as a GJSON Result.
1630func ForEachLine(json string, iterator func(line Result) bool) {
1631	var res Result
1632	var i int
1633	for {
1634		i, res, _ = parseAny(json, i, true)
1635		if !res.Exists() {
1636			break
1637		}
1638		if !iterator(res) {
1639			return
1640		}
1641	}
1642}
1643
1644type subSelector struct {
1645	name string
1646	path string
1647}
1648
1649// parseSubSelectors returns the subselectors belonging to a '[path1,path2]' or
1650// '{"field1":path1,"field2":path2}' type subSelection. It's expected that the
1651// first character in path is either '[' or '{', and has already been checked
1652// prior to calling this function.
1653func parseSubSelectors(path string) (sels []subSelector, out string, ok bool) {
1654	modifer := 0
1655	depth := 1
1656	colon := 0
1657	start := 1
1658	i := 1
1659	pushSel := func() {
1660		var sel subSelector
1661		if colon == 0 {
1662			sel.path = path[start:i]
1663		} else {
1664			sel.name = path[start:colon]
1665			sel.path = path[colon+1 : i]
1666		}
1667		sels = append(sels, sel)
1668		colon = 0
1669		start = i + 1
1670	}
1671	for ; i < len(path); i++ {
1672		switch path[i] {
1673		case '\\':
1674			i++
1675		case '@':
1676			if modifer == 0 && i > 0 && (path[i-1] == '.' || path[i-1] == '|') {
1677				modifer = i
1678			}
1679		case ':':
1680			if modifer == 0 && colon == 0 && depth == 1 {
1681				colon = i
1682			}
1683		case ',':
1684			if depth == 1 {
1685				pushSel()
1686			}
1687		case '"':
1688			i++
1689		loop:
1690			for ; i < len(path); i++ {
1691				switch path[i] {
1692				case '\\':
1693					i++
1694				case '"':
1695					break loop
1696				}
1697			}
1698		case '[', '(', '{':
1699			depth++
1700		case ']', ')', '}':
1701			depth--
1702			if depth == 0 {
1703				pushSel()
1704				path = path[i+1:]
1705				return sels, path, true
1706			}
1707		}
1708	}
1709	return
1710}
1711
1712// nameOfLast returns the name of the last component
1713func nameOfLast(path string) string {
1714	for i := len(path) - 1; i >= 0; i-- {
1715		if path[i] == '|' || path[i] == '.' {
1716			if i > 0 {
1717				if path[i-1] == '\\' {
1718					continue
1719				}
1720			}
1721			return path[i+1:]
1722		}
1723	}
1724	return path
1725}
1726
1727func isSimpleName(component string) bool {
1728	for i := 0; i < len(component); i++ {
1729		if component[i] < ' ' {
1730			return false
1731		}
1732		switch component[i] {
1733		case '[', ']', '{', '}', '(', ')', '#', '|':
1734			return false
1735		}
1736	}
1737	return true
1738}
1739
1740func appendJSONString(dst []byte, s string) []byte {
1741	for i := 0; i < len(s); i++ {
1742		if s[i] < ' ' || s[i] == '\\' || s[i] == '"' || s[i] > 126 {
1743			d, _ := json.Marshal(s)
1744			return append(dst, string(d)...)
1745		}
1746	}
1747	dst = append(dst, '"')
1748	dst = append(dst, s...)
1749	dst = append(dst, '"')
1750	return dst
1751}
1752
1753type parseContext struct {
1754	json  string
1755	value Result
1756	pipe  string
1757	piped bool
1758	calcd bool
1759	lines bool
1760}
1761
1762// Get searches json for the specified path.
1763// A path is in dot syntax, such as "name.last" or "age".
1764// When the value is found it's returned immediately.
1765//
1766// A path is a series of keys separated by a dot.
1767// A key may contain special wildcard characters '*' and '?'.
1768// To access an array value use the index as the key.
1769// To get the number of elements in an array or to access a child path, use
1770// the '#' character.
1771// The dot and wildcard character can be escaped with '\'.
1772//
1773//  {
1774//    "name": {"first": "Tom", "last": "Anderson"},
1775//    "age":37,
1776//    "children": ["Sara","Alex","Jack"],
1777//    "friends": [
1778//      {"first": "James", "last": "Murphy"},
1779//      {"first": "Roger", "last": "Craig"}
1780//    ]
1781//  }
1782//  "name.last"          >> "Anderson"
1783//  "age"                >> 37
1784//  "children"           >> ["Sara","Alex","Jack"]
1785//  "children.#"         >> 3
1786//  "children.1"         >> "Alex"
1787//  "child*.2"           >> "Jack"
1788//  "c?ildren.0"         >> "Sara"
1789//  "friends.#.first"    >> ["James","Roger"]
1790//
1791// This function expects that the json is well-formed, and does not validate.
1792// Invalid json will not panic, but it may return back unexpected results.
1793// If you are consuming JSON from an unpredictable source then you may want to
1794// use the Valid function first.
1795func Get(json, path string) Result {
1796	if len(path) > 1 {
1797		if !DisableModifiers {
1798			if path[0] == '@' {
1799				// possible modifier
1800				var ok bool
1801				var npath string
1802				var rjson string
1803				npath, rjson, ok = execModifier(json, path)
1804				if ok {
1805					path = npath
1806					if len(path) > 0 && (path[0] == '|' || path[0] == '.') {
1807						res := Get(rjson, path[1:])
1808						res.Index = 0
1809						return res
1810					}
1811					return Parse(rjson)
1812				}
1813			}
1814		}
1815		if path[0] == '[' || path[0] == '{' {
1816			// using a subselector path
1817			kind := path[0]
1818			var ok bool
1819			var subs []subSelector
1820			subs, path, ok = parseSubSelectors(path)
1821			if ok {
1822				if len(path) == 0 || (path[0] == '|' || path[0] == '.') {
1823					var b []byte
1824					b = append(b, kind)
1825					var i int
1826					for _, sub := range subs {
1827						res := Get(json, sub.path)
1828						if res.Exists() {
1829							if i > 0 {
1830								b = append(b, ',')
1831							}
1832							if kind == '{' {
1833								if len(sub.name) > 0 {
1834									if sub.name[0] == '"' && Valid(sub.name) {
1835										b = append(b, sub.name...)
1836									} else {
1837										b = appendJSONString(b, sub.name)
1838									}
1839								} else {
1840									last := nameOfLast(sub.path)
1841									if isSimpleName(last) {
1842										b = appendJSONString(b, last)
1843									} else {
1844										b = appendJSONString(b, "_")
1845									}
1846								}
1847								b = append(b, ':')
1848							}
1849							var raw string
1850							if len(res.Raw) == 0 {
1851								raw = res.String()
1852								if len(raw) == 0 {
1853									raw = "null"
1854								}
1855							} else {
1856								raw = res.Raw
1857							}
1858							b = append(b, raw...)
1859							i++
1860						}
1861					}
1862					b = append(b, kind+2)
1863					var res Result
1864					res.Raw = string(b)
1865					res.Type = JSON
1866					if len(path) > 0 {
1867						res = res.Get(path[1:])
1868					}
1869					res.Index = 0
1870					return res
1871				}
1872			}
1873		}
1874	}
1875	var i int
1876	var c = &parseContext{json: json}
1877	if len(path) >= 2 && path[0] == '.' && path[1] == '.' {
1878		c.lines = true
1879		parseArray(c, 0, path[2:])
1880	} else {
1881		for ; i < len(c.json); i++ {
1882			if c.json[i] == '{' {
1883				i++
1884				parseObject(c, i, path)
1885				break
1886			}
1887			if c.json[i] == '[' {
1888				i++
1889				parseArray(c, i, path)
1890				break
1891			}
1892		}
1893	}
1894	if c.piped {
1895		res := c.value.Get(c.pipe)
1896		res.Index = 0
1897		return res
1898	}
1899	fillIndex(json, c)
1900	return c.value
1901}
1902
1903// GetBytes searches json for the specified path.
1904// If working with bytes, this method preferred over Get(string(data), path)
1905func GetBytes(json []byte, path string) Result {
1906	return getBytes(json, path)
1907}
1908
1909// runeit returns the rune from the the \uXXXX
1910func runeit(json string) rune {
1911	n, _ := strconv.ParseUint(json[:4], 16, 64)
1912	return rune(n)
1913}
1914
1915// unescape unescapes a string
1916func unescape(json string) string {
1917	var str = make([]byte, 0, len(json))
1918	for i := 0; i < len(json); i++ {
1919		switch {
1920		default:
1921			str = append(str, json[i])
1922		case json[i] < ' ':
1923			return string(str)
1924		case json[i] == '\\':
1925			i++
1926			if i >= len(json) {
1927				return string(str)
1928			}
1929			switch json[i] {
1930			default:
1931				return string(str)
1932			case '\\':
1933				str = append(str, '\\')
1934			case '/':
1935				str = append(str, '/')
1936			case 'b':
1937				str = append(str, '\b')
1938			case 'f':
1939				str = append(str, '\f')
1940			case 'n':
1941				str = append(str, '\n')
1942			case 'r':
1943				str = append(str, '\r')
1944			case 't':
1945				str = append(str, '\t')
1946			case '"':
1947				str = append(str, '"')
1948			case 'u':
1949				if i+5 > len(json) {
1950					return string(str)
1951				}
1952				r := runeit(json[i+1:])
1953				i += 5
1954				if utf16.IsSurrogate(r) {
1955					// need another code
1956					if len(json[i:]) >= 6 && json[i] == '\\' &&
1957						json[i+1] == 'u' {
1958						// we expect it to be correct so just consume it
1959						r = utf16.DecodeRune(r, runeit(json[i+2:]))
1960						i += 6
1961					}
1962				}
1963				// provide enough space to encode the largest utf8 possible
1964				str = append(str, 0, 0, 0, 0, 0, 0, 0, 0)
1965				n := utf8.EncodeRune(str[len(str)-8:], r)
1966				str = str[:len(str)-8+n]
1967				i-- // backtrack index by one
1968			}
1969		}
1970	}
1971	return string(str)
1972}
1973
1974// Less return true if a token is less than another token.
1975// The caseSensitive paramater is used when the tokens are Strings.
1976// The order when comparing two different type is:
1977//
1978//  Null < False < Number < String < True < JSON
1979//
1980func (t Result) Less(token Result, caseSensitive bool) bool {
1981	if t.Type < token.Type {
1982		return true
1983	}
1984	if t.Type > token.Type {
1985		return false
1986	}
1987	if t.Type == String {
1988		if caseSensitive {
1989			return t.Str < token.Str
1990		}
1991		return stringLessInsensitive(t.Str, token.Str)
1992	}
1993	if t.Type == Number {
1994		return t.Num < token.Num
1995	}
1996	return t.Raw < token.Raw
1997}
1998
1999func stringLessInsensitive(a, b string) bool {
2000	for i := 0; i < len(a) && i < len(b); i++ {
2001		if a[i] >= 'A' && a[i] <= 'Z' {
2002			if b[i] >= 'A' && b[i] <= 'Z' {
2003				// both are uppercase, do nothing
2004				if a[i] < b[i] {
2005					return true
2006				} else if a[i] > b[i] {
2007					return false
2008				}
2009			} else {
2010				// a is uppercase, convert a to lowercase
2011				if a[i]+32 < b[i] {
2012					return true
2013				} else if a[i]+32 > b[i] {
2014					return false
2015				}
2016			}
2017		} else if b[i] >= 'A' && b[i] <= 'Z' {
2018			// b is uppercase, convert b to lowercase
2019			if a[i] < b[i]+32 {
2020				return true
2021			} else if a[i] > b[i]+32 {
2022				return false
2023			}
2024		} else {
2025			// neither are uppercase
2026			if a[i] < b[i] {
2027				return true
2028			} else if a[i] > b[i] {
2029				return false
2030			}
2031		}
2032	}
2033	return len(a) < len(b)
2034}
2035
2036// parseAny parses the next value from a json string.
2037// A Result is returned when the hit param is set.
2038// The return values are (i int, res Result, ok bool)
2039func parseAny(json string, i int, hit bool) (int, Result, bool) {
2040	var res Result
2041	var val string
2042	for ; i < len(json); i++ {
2043		if json[i] == '{' || json[i] == '[' {
2044			i, val = parseSquash(json, i)
2045			if hit {
2046				res.Raw = val
2047				res.Type = JSON
2048			}
2049			return i, res, true
2050		}
2051		if json[i] <= ' ' {
2052			continue
2053		}
2054		switch json[i] {
2055		case '"':
2056			i++
2057			var vesc bool
2058			var ok bool
2059			i, val, vesc, ok = parseString(json, i)
2060			if !ok {
2061				return i, res, false
2062			}
2063			if hit {
2064				res.Type = String
2065				res.Raw = val
2066				if vesc {
2067					res.Str = unescape(val[1 : len(val)-1])
2068				} else {
2069					res.Str = val[1 : len(val)-1]
2070				}
2071			}
2072			return i, res, true
2073		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
2074			i, val = parseNumber(json, i)
2075			if hit {
2076				res.Raw = val
2077				res.Type = Number
2078				res.Num, _ = strconv.ParseFloat(val, 64)
2079			}
2080			return i, res, true
2081		case 't', 'f', 'n':
2082			vc := json[i]
2083			i, val = parseLiteral(json, i)
2084			if hit {
2085				res.Raw = val
2086				switch vc {
2087				case 't':
2088					res.Type = True
2089				case 'f':
2090					res.Type = False
2091				}
2092				return i, res, true
2093			}
2094		}
2095	}
2096	return i, res, false
2097}
2098
2099// GetMany searches json for the multiple paths.
2100// The return value is a Result array where the number of items
2101// will be equal to the number of input paths.
2102func GetMany(json string, path ...string) []Result {
2103	res := make([]Result, len(path))
2104	for i, path := range path {
2105		res[i] = Get(json, path)
2106	}
2107	return res
2108}
2109
2110// GetManyBytes searches json for the multiple paths.
2111// The return value is a Result array where the number of items
2112// will be equal to the number of input paths.
2113func GetManyBytes(json []byte, path ...string) []Result {
2114	res := make([]Result, len(path))
2115	for i, path := range path {
2116		res[i] = GetBytes(json, path)
2117	}
2118	return res
2119}
2120
2121func validpayload(data []byte, i int) (outi int, ok bool) {
2122	for ; i < len(data); i++ {
2123		switch data[i] {
2124		default:
2125			i, ok = validany(data, i)
2126			if !ok {
2127				return i, false
2128			}
2129			for ; i < len(data); i++ {
2130				switch data[i] {
2131				default:
2132					return i, false
2133				case ' ', '\t', '\n', '\r':
2134					continue
2135				}
2136			}
2137			return i, true
2138		case ' ', '\t', '\n', '\r':
2139			continue
2140		}
2141	}
2142	return i, false
2143}
2144func validany(data []byte, i int) (outi int, ok bool) {
2145	for ; i < len(data); i++ {
2146		switch data[i] {
2147		default:
2148			return i, false
2149		case ' ', '\t', '\n', '\r':
2150			continue
2151		case '{':
2152			return validobject(data, i+1)
2153		case '[':
2154			return validarray(data, i+1)
2155		case '"':
2156			return validstring(data, i+1)
2157		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
2158			return validnumber(data, i+1)
2159		case 't':
2160			return validtrue(data, i+1)
2161		case 'f':
2162			return validfalse(data, i+1)
2163		case 'n':
2164			return validnull(data, i+1)
2165		}
2166	}
2167	return i, false
2168}
2169func validobject(data []byte, i int) (outi int, ok bool) {
2170	for ; i < len(data); i++ {
2171		switch data[i] {
2172		default:
2173			return i, false
2174		case ' ', '\t', '\n', '\r':
2175			continue
2176		case '}':
2177			return i + 1, true
2178		case '"':
2179		key:
2180			if i, ok = validstring(data, i+1); !ok {
2181				return i, false
2182			}
2183			if i, ok = validcolon(data, i); !ok {
2184				return i, false
2185			}
2186			if i, ok = validany(data, i); !ok {
2187				return i, false
2188			}
2189			if i, ok = validcomma(data, i, '}'); !ok {
2190				return i, false
2191			}
2192			if data[i] == '}' {
2193				return i + 1, true
2194			}
2195			i++
2196			for ; i < len(data); i++ {
2197				switch data[i] {
2198				default:
2199					return i, false
2200				case ' ', '\t', '\n', '\r':
2201					continue
2202				case '"':
2203					goto key
2204				}
2205			}
2206			return i, false
2207		}
2208	}
2209	return i, false
2210}
2211func validcolon(data []byte, i int) (outi int, ok bool) {
2212	for ; i < len(data); i++ {
2213		switch data[i] {
2214		default:
2215			return i, false
2216		case ' ', '\t', '\n', '\r':
2217			continue
2218		case ':':
2219			return i + 1, true
2220		}
2221	}
2222	return i, false
2223}
2224func validcomma(data []byte, i int, end byte) (outi int, ok bool) {
2225	for ; i < len(data); i++ {
2226		switch data[i] {
2227		default:
2228			return i, false
2229		case ' ', '\t', '\n', '\r':
2230			continue
2231		case ',':
2232			return i, true
2233		case end:
2234			return i, true
2235		}
2236	}
2237	return i, false
2238}
2239func validarray(data []byte, i int) (outi int, ok bool) {
2240	for ; i < len(data); i++ {
2241		switch data[i] {
2242		default:
2243			for ; i < len(data); i++ {
2244				if i, ok = validany(data, i); !ok {
2245					return i, false
2246				}
2247				if i, ok = validcomma(data, i, ']'); !ok {
2248					return i, false
2249				}
2250				if data[i] == ']' {
2251					return i + 1, true
2252				}
2253			}
2254		case ' ', '\t', '\n', '\r':
2255			continue
2256		case ']':
2257			return i + 1, true
2258		}
2259	}
2260	return i, false
2261}
2262func validstring(data []byte, i int) (outi int, ok bool) {
2263	for ; i < len(data); i++ {
2264		if data[i] < ' ' {
2265			return i, false
2266		} else if data[i] == '\\' {
2267			i++
2268			if i == len(data) {
2269				return i, false
2270			}
2271			switch data[i] {
2272			default:
2273				return i, false
2274			case '"', '\\', '/', 'b', 'f', 'n', 'r', 't':
2275			case 'u':
2276				for j := 0; j < 4; j++ {
2277					i++
2278					if i >= len(data) {
2279						return i, false
2280					}
2281					if !((data[i] >= '0' && data[i] <= '9') ||
2282						(data[i] >= 'a' && data[i] <= 'f') ||
2283						(data[i] >= 'A' && data[i] <= 'F')) {
2284						return i, false
2285					}
2286				}
2287			}
2288		} else if data[i] == '"' {
2289			return i + 1, true
2290		}
2291	}
2292	return i, false
2293}
2294func validnumber(data []byte, i int) (outi int, ok bool) {
2295	i--
2296	// sign
2297	if data[i] == '-' {
2298		i++
2299		if i == len(data) {
2300			return i, false
2301		}
2302		if data[i] < '0' || data[i] > '9' {
2303			return i, false
2304		}
2305	}
2306	// int
2307	if i == len(data) {
2308		return i, false
2309	}
2310	if data[i] == '0' {
2311		i++
2312	} else {
2313		for ; i < len(data); i++ {
2314			if data[i] >= '0' && data[i] <= '9' {
2315				continue
2316			}
2317			break
2318		}
2319	}
2320	// frac
2321	if i == len(data) {
2322		return i, true
2323	}
2324	if data[i] == '.' {
2325		i++
2326		if i == len(data) {
2327			return i, false
2328		}
2329		if data[i] < '0' || data[i] > '9' {
2330			return i, false
2331		}
2332		i++
2333		for ; i < len(data); i++ {
2334			if data[i] >= '0' && data[i] <= '9' {
2335				continue
2336			}
2337			break
2338		}
2339	}
2340	// exp
2341	if i == len(data) {
2342		return i, true
2343	}
2344	if data[i] == 'e' || data[i] == 'E' {
2345		i++
2346		if i == len(data) {
2347			return i, false
2348		}
2349		if data[i] == '+' || data[i] == '-' {
2350			i++
2351		}
2352		if i == len(data) {
2353			return i, false
2354		}
2355		if data[i] < '0' || data[i] > '9' {
2356			return i, false
2357		}
2358		i++
2359		for ; i < len(data); i++ {
2360			if data[i] >= '0' && data[i] <= '9' {
2361				continue
2362			}
2363			break
2364		}
2365	}
2366	return i, true
2367}
2368
2369func validtrue(data []byte, i int) (outi int, ok bool) {
2370	if i+3 <= len(data) && data[i] == 'r' && data[i+1] == 'u' &&
2371		data[i+2] == 'e' {
2372		return i + 3, true
2373	}
2374	return i, false
2375}
2376func validfalse(data []byte, i int) (outi int, ok bool) {
2377	if i+4 <= len(data) && data[i] == 'a' && data[i+1] == 'l' &&
2378		data[i+2] == 's' && data[i+3] == 'e' {
2379		return i + 4, true
2380	}
2381	return i, false
2382}
2383func validnull(data []byte, i int) (outi int, ok bool) {
2384	if i+3 <= len(data) && data[i] == 'u' && data[i+1] == 'l' &&
2385		data[i+2] == 'l' {
2386		return i + 3, true
2387	}
2388	return i, false
2389}
2390
2391// Valid returns true if the input is valid json.
2392//
2393//  if !gjson.Valid(json) {
2394//  	return errors.New("invalid json")
2395//  }
2396//  value := gjson.Get(json, "name.last")
2397//
2398func Valid(json string) bool {
2399	_, ok := validpayload(stringBytes(json), 0)
2400	return ok
2401}
2402
2403// ValidBytes returns true if the input is valid json.
2404//
2405//  if !gjson.Valid(json) {
2406//  	return errors.New("invalid json")
2407//  }
2408//  value := gjson.Get(json, "name.last")
2409//
2410// If working with bytes, this method preferred over ValidBytes(string(data))
2411//
2412func ValidBytes(json []byte) bool {
2413	_, ok := validpayload(json, 0)
2414	return ok
2415}
2416
2417func parseUint(s string) (n uint64, ok bool) {
2418	var i int
2419	if i == len(s) {
2420		return 0, false
2421	}
2422	for ; i < len(s); i++ {
2423		if s[i] >= '0' && s[i] <= '9' {
2424			n = n*10 + uint64(s[i]-'0')
2425		} else {
2426			return 0, false
2427		}
2428	}
2429	return n, true
2430}
2431
2432func parseInt(s string) (n int64, ok bool) {
2433	var i int
2434	var sign bool
2435	if len(s) > 0 && s[0] == '-' {
2436		sign = true
2437		i++
2438	}
2439	if i == len(s) {
2440		return 0, false
2441	}
2442	for ; i < len(s); i++ {
2443		if s[i] >= '0' && s[i] <= '9' {
2444			n = n*10 + int64(s[i]-'0')
2445		} else {
2446			return 0, false
2447		}
2448	}
2449	if sign {
2450		return n * -1, true
2451	}
2452	return n, true
2453}
2454
2455// safeInt validates a given JSON number
2456// ensures it lies within the minimum and maximum representable JSON numbers
2457func safeInt(f float64) (n int64, ok bool) {
2458	//  https://tc39.es/ecma262/#sec-number.min_safe_integer || https://tc39.es/ecma262/#sec-number.max_safe_integer
2459	if f < -9007199254740991 || f > 9007199254740991 {
2460		return 0, false
2461	}
2462	return int64(f), true
2463}
2464
2465// execModifier parses the path to find a matching modifier function.
2466// then input expects that the path already starts with a '@'
2467func execModifier(json, path string) (pathOut, res string, ok bool) {
2468	name := path[1:]
2469	var hasArgs bool
2470	for i := 1; i < len(path); i++ {
2471		if path[i] == ':' {
2472			pathOut = path[i+1:]
2473			name = path[1:i]
2474			hasArgs = len(pathOut) > 0
2475			break
2476		}
2477		if path[i] == '|' {
2478			pathOut = path[i:]
2479			name = path[1:i]
2480			break
2481		}
2482		if path[i] == '.' {
2483			pathOut = path[i:]
2484			name = path[1:i]
2485			break
2486		}
2487	}
2488	if fn, ok := modifiers[name]; ok {
2489		var args string
2490		if hasArgs {
2491			var parsedArgs bool
2492			switch pathOut[0] {
2493			case '{', '[', '"':
2494				res := Parse(pathOut)
2495				if res.Exists() {
2496					args = squash(pathOut)
2497					pathOut = pathOut[len(args):]
2498					parsedArgs = true
2499				}
2500			}
2501			if !parsedArgs {
2502				idx := strings.IndexByte(pathOut, '|')
2503				if idx == -1 {
2504					args = pathOut
2505					pathOut = ""
2506				} else {
2507					args = pathOut[:idx]
2508					pathOut = pathOut[idx:]
2509				}
2510			}
2511		}
2512		return pathOut, fn(json, args), true
2513	}
2514	return pathOut, res, false
2515}
2516
2517// unwrap removes the '[]' or '{}' characters around json
2518func unwrap(json string) string {
2519	json = trim(json)
2520	if len(json) >= 2 && (json[0] == '[' || json[0] == '{') {
2521		json = json[1 : len(json)-1]
2522	}
2523	return json
2524}
2525
2526// DisableModifiers will disable the modifier syntax
2527var DisableModifiers = false
2528
2529var modifiers = map[string]func(json, arg string) string{
2530	"pretty":  modPretty,
2531	"ugly":    modUgly,
2532	"reverse": modReverse,
2533	"this":    modThis,
2534	"flatten": modFlatten,
2535	"join":    modJoin,
2536	"valid":   modValid,
2537}
2538
2539// AddModifier binds a custom modifier command to the GJSON syntax.
2540// This operation is not thread safe and should be executed prior to
2541// using all other gjson function.
2542func AddModifier(name string, fn func(json, arg string) string) {
2543	modifiers[name] = fn
2544}
2545
2546// ModifierExists returns true when the specified modifier exists.
2547func ModifierExists(name string, fn func(json, arg string) string) bool {
2548	_, ok := modifiers[name]
2549	return ok
2550}
2551
2552// cleanWS remove any non-whitespace from string
2553func cleanWS(s string) string {
2554	for i := 0; i < len(s); i++ {
2555		switch s[i] {
2556		case ' ', '\t', '\n', '\r':
2557			continue
2558		default:
2559			var s2 []byte
2560			for i := 0; i < len(s); i++ {
2561				switch s[i] {
2562				case ' ', '\t', '\n', '\r':
2563					s2 = append(s2, s[i])
2564				}
2565			}
2566			return string(s2)
2567		}
2568	}
2569	return s
2570}
2571
2572// @pretty modifier makes the json look nice.
2573func modPretty(json, arg string) string {
2574	if len(arg) > 0 {
2575		opts := *pretty.DefaultOptions
2576		Parse(arg).ForEach(func(key, value Result) bool {
2577			switch key.String() {
2578			case "sortKeys":
2579				opts.SortKeys = value.Bool()
2580			case "indent":
2581				opts.Indent = cleanWS(value.String())
2582			case "prefix":
2583				opts.Prefix = cleanWS(value.String())
2584			case "width":
2585				opts.Width = int(value.Int())
2586			}
2587			return true
2588		})
2589		return bytesString(pretty.PrettyOptions(stringBytes(json), &opts))
2590	}
2591	return bytesString(pretty.Pretty(stringBytes(json)))
2592}
2593
2594// @this returns the current element. Can be used to retrieve the root element.
2595func modThis(json, arg string) string {
2596	return json
2597}
2598
2599// @ugly modifier removes all whitespace.
2600func modUgly(json, arg string) string {
2601	return bytesString(pretty.Ugly(stringBytes(json)))
2602}
2603
2604// @reverse reverses array elements or root object members.
2605func modReverse(json, arg string) string {
2606	res := Parse(json)
2607	if res.IsArray() {
2608		var values []Result
2609		res.ForEach(func(_, value Result) bool {
2610			values = append(values, value)
2611			return true
2612		})
2613		out := make([]byte, 0, len(json))
2614		out = append(out, '[')
2615		for i, j := len(values)-1, 0; i >= 0; i, j = i-1, j+1 {
2616			if j > 0 {
2617				out = append(out, ',')
2618			}
2619			out = append(out, values[i].Raw...)
2620		}
2621		out = append(out, ']')
2622		return bytesString(out)
2623	}
2624	if res.IsObject() {
2625		var keyValues []Result
2626		res.ForEach(func(key, value Result) bool {
2627			keyValues = append(keyValues, key, value)
2628			return true
2629		})
2630		out := make([]byte, 0, len(json))
2631		out = append(out, '{')
2632		for i, j := len(keyValues)-2, 0; i >= 0; i, j = i-2, j+1 {
2633			if j > 0 {
2634				out = append(out, ',')
2635			}
2636			out = append(out, keyValues[i+0].Raw...)
2637			out = append(out, ':')
2638			out = append(out, keyValues[i+1].Raw...)
2639		}
2640		out = append(out, '}')
2641		return bytesString(out)
2642	}
2643	return json
2644}
2645
2646// @flatten an array with child arrays.
2647//   [1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,[6,7]]
2648// The {"deep":true} arg can be provide for deep flattening.
2649//   [1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,6,7]
2650// The original json is returned when the json is not an array.
2651func modFlatten(json, arg string) string {
2652	res := Parse(json)
2653	if !res.IsArray() {
2654		return json
2655	}
2656	var deep bool
2657	if arg != "" {
2658		Parse(arg).ForEach(func(key, value Result) bool {
2659			if key.String() == "deep" {
2660				deep = value.Bool()
2661			}
2662			return true
2663		})
2664	}
2665	var out []byte
2666	out = append(out, '[')
2667	var idx int
2668	res.ForEach(func(_, value Result) bool {
2669		var raw string
2670		if value.IsArray() {
2671			if deep {
2672				raw = unwrap(modFlatten(value.Raw, arg))
2673			} else {
2674				raw = unwrap(value.Raw)
2675			}
2676		} else {
2677			raw = value.Raw
2678		}
2679		raw = strings.TrimSpace(raw)
2680		if len(raw) > 0 {
2681			if idx > 0 {
2682				out = append(out, ',')
2683			}
2684			out = append(out, raw...)
2685			idx++
2686		}
2687		return true
2688	})
2689	out = append(out, ']')
2690	return bytesString(out)
2691}
2692
2693// @join multiple objects into a single object.
2694//   [{"first":"Tom"},{"last":"Smith"}] -> {"first","Tom","last":"Smith"}
2695// The arg can be "true" to specify that duplicate keys should be preserved.
2696//   [{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":37,"age":41}
2697// Without preserved keys:
2698//   [{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":41}
2699// The original json is returned when the json is not an object.
2700func modJoin(json, arg string) string {
2701	res := Parse(json)
2702	if !res.IsArray() {
2703		return json
2704	}
2705	var preserve bool
2706	if arg != "" {
2707		Parse(arg).ForEach(func(key, value Result) bool {
2708			if key.String() == "preserve" {
2709				preserve = value.Bool()
2710			}
2711			return true
2712		})
2713	}
2714	var out []byte
2715	out = append(out, '{')
2716	if preserve {
2717		// Preserve duplicate keys.
2718		var idx int
2719		res.ForEach(func(_, value Result) bool {
2720			if !value.IsObject() {
2721				return true
2722			}
2723			if idx > 0 {
2724				out = append(out, ',')
2725			}
2726			out = append(out, unwrap(value.Raw)...)
2727			idx++
2728			return true
2729		})
2730	} else {
2731		// Deduplicate keys and generate an object with stable ordering.
2732		var keys []Result
2733		kvals := make(map[string]Result)
2734		res.ForEach(func(_, value Result) bool {
2735			if !value.IsObject() {
2736				return true
2737			}
2738			value.ForEach(func(key, value Result) bool {
2739				k := key.String()
2740				if _, ok := kvals[k]; !ok {
2741					keys = append(keys, key)
2742				}
2743				kvals[k] = value
2744				return true
2745			})
2746			return true
2747		})
2748		for i := 0; i < len(keys); i++ {
2749			if i > 0 {
2750				out = append(out, ',')
2751			}
2752			out = append(out, keys[i].Raw...)
2753			out = append(out, ':')
2754			out = append(out, kvals[keys[i].String()].Raw...)
2755		}
2756	}
2757	out = append(out, '}')
2758	return bytesString(out)
2759}
2760
2761// @valid ensures that the json is valid before moving on. An empty string is
2762// returned when the json is not valid, otherwise it returns the original json.
2763func modValid(json, arg string) string {
2764	if !Valid(json) {
2765		return ""
2766	}
2767	return json
2768}
2769
2770// stringHeader instead of reflect.StringHeader
2771type stringHeader struct {
2772	data unsafe.Pointer
2773	len  int
2774}
2775
2776// sliceHeader instead of reflect.SliceHeader
2777type sliceHeader struct {
2778	data unsafe.Pointer
2779	len  int
2780	cap  int
2781}
2782
2783// getBytes casts the input json bytes to a string and safely returns the
2784// results as uniquely allocated data. This operation is intended to minimize
2785// copies and allocations for the large json string->[]byte.
2786func getBytes(json []byte, path string) Result {
2787	var result Result
2788	if json != nil {
2789		// unsafe cast to string
2790		result = Get(*(*string)(unsafe.Pointer(&json)), path)
2791		// safely get the string headers
2792		rawhi := *(*stringHeader)(unsafe.Pointer(&result.Raw))
2793		strhi := *(*stringHeader)(unsafe.Pointer(&result.Str))
2794		// create byte slice headers
2795		rawh := sliceHeader{data: rawhi.data, len: rawhi.len, cap: rawhi.len}
2796		strh := sliceHeader{data: strhi.data, len: strhi.len, cap: rawhi.len}
2797		if strh.data == nil {
2798			// str is nil
2799			if rawh.data == nil {
2800				// raw is nil
2801				result.Raw = ""
2802			} else {
2803				// raw has data, safely copy the slice header to a string
2804				result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
2805			}
2806			result.Str = ""
2807		} else if rawh.data == nil {
2808			// raw is nil
2809			result.Raw = ""
2810			// str has data, safely copy the slice header to a string
2811			result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
2812		} else if uintptr(strh.data) >= uintptr(rawh.data) &&
2813			uintptr(strh.data)+uintptr(strh.len) <=
2814				uintptr(rawh.data)+uintptr(rawh.len) {
2815			// Str is a substring of Raw.
2816			start := uintptr(strh.data) - uintptr(rawh.data)
2817			// safely copy the raw slice header
2818			result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
2819			// substring the raw
2820			result.Str = result.Raw[start : start+uintptr(strh.len)]
2821		} else {
2822			// safely copy both the raw and str slice headers to strings
2823			result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
2824			result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
2825		}
2826	}
2827	return result
2828}
2829
2830// fillIndex finds the position of Raw data and assigns it to the Index field
2831// of the resulting value. If the position cannot be found then Index zero is
2832// used instead.
2833func fillIndex(json string, c *parseContext) {
2834	if len(c.value.Raw) > 0 && !c.calcd {
2835		jhdr := *(*stringHeader)(unsafe.Pointer(&json))
2836		rhdr := *(*stringHeader)(unsafe.Pointer(&(c.value.Raw)))
2837		c.value.Index = int(uintptr(rhdr.data) - uintptr(jhdr.data))
2838		if c.value.Index < 0 || c.value.Index >= len(json) {
2839			c.value.Index = 0
2840		}
2841	}
2842}
2843
2844func stringBytes(s string) []byte {
2845	return *(*[]byte)(unsafe.Pointer(&sliceHeader{
2846		data: (*stringHeader)(unsafe.Pointer(&s)).data,
2847		len:  len(s),
2848		cap:  len(s),
2849	}))
2850}
2851
2852func bytesString(b []byte) string {
2853	return *(*string)(unsafe.Pointer(&b))
2854}
2855