gjson.go raw

   1  // Package gjson provides searching for json strings.
   2  package gjson
   3  
   4  import (
   5  	"strconv"
   6  	"strings"
   7  	"time"
   8  	"unicode/utf16"
   9  	"unicode/utf8"
  10  	"unsafe"
  11  
  12  	"github.com/tidwall/match"
  13  	"github.com/tidwall/pretty"
  14  )
  15  
  16  // Type is Result type
  17  type Type int
  18  
  19  const (
  20  	// Null is a null json value
  21  	Null Type = iota
  22  	// False is a json false boolean
  23  	False
  24  	// Number is json number
  25  	Number
  26  	// String is a json string
  27  	String
  28  	// True is a json true boolean
  29  	True
  30  	// JSON is a raw block of JSON
  31  	JSON
  32  )
  33  
  34  // String returns a string representation of the type.
  35  func (t Type) String() string {
  36  	switch t {
  37  	default:
  38  		return ""
  39  	case Null:
  40  		return "Null"
  41  	case False:
  42  		return "False"
  43  	case Number:
  44  		return "Number"
  45  	case String:
  46  		return "String"
  47  	case True:
  48  		return "True"
  49  	case JSON:
  50  		return "JSON"
  51  	}
  52  }
  53  
  54  // Result represents a json value that is returned from Get().
  55  type Result struct {
  56  	// Type is the json type
  57  	Type Type
  58  	// Raw is the raw json
  59  	Raw string
  60  	// Str is the json string
  61  	Str string
  62  	// Num is the json number
  63  	Num float64
  64  	// Index of raw value in original json, zero means index unknown
  65  	Index int
  66  	// Indexes of all the elements that match on a path containing the '#'
  67  	// query character.
  68  	Indexes []int
  69  }
  70  
  71  // String returns a string representation of the value.
  72  func (t Result) String() string {
  73  	switch t.Type {
  74  	default:
  75  		return ""
  76  	case False:
  77  		return "false"
  78  	case Number:
  79  		if len(t.Raw) == 0 {
  80  			// calculated result
  81  			return strconv.FormatFloat(t.Num, 'f', -1, 64)
  82  		}
  83  		var i int
  84  		if t.Raw[0] == '-' {
  85  			i++
  86  		}
  87  		for ; i < len(t.Raw); i++ {
  88  			if t.Raw[i] < '0' || t.Raw[i] > '9' {
  89  				return strconv.FormatFloat(t.Num, 'f', -1, 64)
  90  			}
  91  		}
  92  		return t.Raw
  93  	case String:
  94  		return t.Str
  95  	case JSON:
  96  		return t.Raw
  97  	case True:
  98  		return "true"
  99  	}
 100  }
 101  
 102  // Bool returns an boolean representation.
 103  func (t Result) Bool() bool {
 104  	switch t.Type {
 105  	default:
 106  		return false
 107  	case True:
 108  		return true
 109  	case String:
 110  		b, _ := strconv.ParseBool(strings.ToLower(t.Str))
 111  		return b
 112  	case Number:
 113  		return t.Num != 0
 114  	}
 115  }
 116  
 117  // Int returns an integer representation.
 118  func (t Result) Int() int64 {
 119  	switch t.Type {
 120  	default:
 121  		return 0
 122  	case True:
 123  		return 1
 124  	case String:
 125  		n, _ := parseInt(t.Str)
 126  		return n
 127  	case Number:
 128  		// try to directly convert the float64 to int64
 129  		i, ok := safeInt(t.Num)
 130  		if ok {
 131  			return i
 132  		}
 133  		// now try to parse the raw string
 134  		i, ok = parseInt(t.Raw)
 135  		if ok {
 136  			return i
 137  		}
 138  		// fallback to a standard conversion
 139  		return int64(t.Num)
 140  	}
 141  }
 142  
 143  // Uint returns an unsigned integer representation.
 144  func (t Result) Uint() uint64 {
 145  	switch t.Type {
 146  	default:
 147  		return 0
 148  	case True:
 149  		return 1
 150  	case String:
 151  		n, _ := parseUint(t.Str)
 152  		return n
 153  	case Number:
 154  		// try to directly convert the float64 to uint64
 155  		i, ok := safeInt(t.Num)
 156  		if ok && i >= 0 {
 157  			return uint64(i)
 158  		}
 159  		// now try to parse the raw string
 160  		u, ok := parseUint(t.Raw)
 161  		if ok {
 162  			return u
 163  		}
 164  		// fallback to a standard conversion
 165  		return uint64(t.Num)
 166  	}
 167  }
 168  
 169  // Float returns an float64 representation.
 170  func (t Result) Float() float64 {
 171  	switch t.Type {
 172  	default:
 173  		return 0
 174  	case True:
 175  		return 1
 176  	case String:
 177  		n, _ := strconv.ParseFloat(t.Str, 64)
 178  		return n
 179  	case Number:
 180  		return t.Num
 181  	}
 182  }
 183  
 184  // Time returns a time.Time representation.
 185  func (t Result) Time() time.Time {
 186  	res, _ := time.Parse(time.RFC3339, t.String())
 187  	return res
 188  }
 189  
 190  // Array returns back an array of values.
 191  // If the result represents a null value or is non-existent, then an empty
 192  // array will be returned.
 193  // If the result is not a JSON array, the return value will be an
 194  // array containing one result.
 195  func (t Result) Array() []Result {
 196  	if t.Type == Null {
 197  		return []Result{}
 198  	}
 199  	if !t.IsArray() {
 200  		return []Result{t}
 201  	}
 202  	r := t.arrayOrMap('[', false)
 203  	return r.a
 204  }
 205  
 206  // IsObject returns true if the result value is a JSON object.
 207  func (t Result) IsObject() bool {
 208  	return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '{'
 209  }
 210  
 211  // IsArray returns true if the result value is a JSON array.
 212  func (t Result) IsArray() bool {
 213  	return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '['
 214  }
 215  
 216  // IsBool returns true if the result value is a JSON boolean.
 217  func (t Result) IsBool() bool {
 218  	return t.Type == True || t.Type == False
 219  }
 220  
 221  // ForEach iterates through values.
 222  // If the result represents a non-existent value, then no values will be
 223  // iterated. If the result is an Object, the iterator will pass the key and
 224  // value of each item. If the result is an Array, the iterator will only pass
 225  // the value of each item. If the result is not a JSON array or object, the
 226  // iterator will pass back one value equal to the result.
 227  func (t Result) ForEach(iterator func(key, value Result) bool) {
 228  	if !t.Exists() {
 229  		return
 230  	}
 231  	if t.Type != JSON {
 232  		iterator(Result{}, t)
 233  		return
 234  	}
 235  	json := t.Raw
 236  	var obj bool
 237  	var i int
 238  	var key, value Result
 239  	for ; i < len(json); i++ {
 240  		if json[i] == '{' {
 241  			i++
 242  			key.Type = String
 243  			obj = true
 244  			break
 245  		} else if json[i] == '[' {
 246  			i++
 247  			key.Type = Number
 248  			key.Num = -1
 249  			break
 250  		}
 251  		if json[i] > ' ' {
 252  			return
 253  		}
 254  	}
 255  	var str string
 256  	var vesc bool
 257  	var ok bool
 258  	var idx int
 259  	for ; i < len(json); i++ {
 260  		if obj {
 261  			if json[i] != '"' {
 262  				continue
 263  			}
 264  			s := i
 265  			i, str, vesc, ok = parseString(json, i+1)
 266  			if !ok {
 267  				return
 268  			}
 269  			if vesc {
 270  				key.Str = unescape(str[1 : len(str)-1])
 271  			} else {
 272  				key.Str = str[1 : len(str)-1]
 273  			}
 274  			key.Raw = str
 275  			key.Index = s + t.Index
 276  		} else {
 277  			key.Num += 1
 278  		}
 279  		for ; i < len(json); i++ {
 280  			if json[i] <= ' ' || json[i] == ',' || json[i] == ':' {
 281  				continue
 282  			}
 283  			break
 284  		}
 285  		s := i
 286  		i, value, ok = parseAny(json, i, true)
 287  		if !ok {
 288  			return
 289  		}
 290  		if t.Indexes != nil {
 291  			if idx < len(t.Indexes) {
 292  				value.Index = t.Indexes[idx]
 293  			}
 294  		} else {
 295  			value.Index = s + t.Index
 296  		}
 297  		if !iterator(key, value) {
 298  			return
 299  		}
 300  		idx++
 301  	}
 302  }
 303  
 304  // Map returns back a map of values. The result should be a JSON object.
 305  // If the result is not a JSON object, the return value will be an empty map.
 306  func (t Result) Map() map[string]Result {
 307  	if t.Type != JSON {
 308  		return map[string]Result{}
 309  	}
 310  	r := t.arrayOrMap('{', false)
 311  	return r.o
 312  }
 313  
 314  // Get searches result for the specified path.
 315  // The result should be a JSON array or object.
 316  func (t Result) Get(path string) Result {
 317  	r := Get(t.Raw, path)
 318  	if r.Indexes != nil {
 319  		for i := 0; i < len(r.Indexes); i++ {
 320  			r.Indexes[i] += t.Index
 321  		}
 322  	} else {
 323  		r.Index += t.Index
 324  	}
 325  	return r
 326  }
 327  
 328  type arrayOrMapResult struct {
 329  	a  []Result
 330  	ai []interface{}
 331  	o  map[string]Result
 332  	oi map[string]interface{}
 333  	vc byte
 334  }
 335  
 336  func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) {
 337  	var json = t.Raw
 338  	var i int
 339  	var value Result
 340  	var count int
 341  	var key Result
 342  	if vc == 0 {
 343  		for ; i < len(json); i++ {
 344  			if json[i] == '{' || json[i] == '[' {
 345  				r.vc = json[i]
 346  				i++
 347  				break
 348  			}
 349  			if json[i] > ' ' {
 350  				goto end
 351  			}
 352  		}
 353  	} else {
 354  		for ; i < len(json); i++ {
 355  			if json[i] == vc {
 356  				i++
 357  				break
 358  			}
 359  			if json[i] > ' ' {
 360  				goto end
 361  			}
 362  		}
 363  		r.vc = vc
 364  	}
 365  	if r.vc == '{' {
 366  		if valueize {
 367  			r.oi = make(map[string]interface{})
 368  		} else {
 369  			r.o = make(map[string]Result)
 370  		}
 371  	} else {
 372  		if valueize {
 373  			r.ai = make([]interface{}, 0)
 374  		} else {
 375  			r.a = make([]Result, 0)
 376  		}
 377  	}
 378  	for ; i < len(json); i++ {
 379  		if json[i] <= ' ' {
 380  			continue
 381  		}
 382  		// get next value
 383  		if json[i] == ']' || json[i] == '}' {
 384  			break
 385  		}
 386  		switch json[i] {
 387  		default:
 388  			if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {
 389  				value.Type = Number
 390  				value.Raw, value.Num = tonum(json[i:])
 391  				value.Str = ""
 392  			} else {
 393  				continue
 394  			}
 395  		case '{', '[':
 396  			value.Type = JSON
 397  			value.Raw = squash(json[i:])
 398  			value.Str, value.Num = "", 0
 399  		case 'n':
 400  			value.Type = Null
 401  			value.Raw = tolit(json[i:])
 402  			value.Str, value.Num = "", 0
 403  		case 't':
 404  			value.Type = True
 405  			value.Raw = tolit(json[i:])
 406  			value.Str, value.Num = "", 0
 407  		case 'f':
 408  			value.Type = False
 409  			value.Raw = tolit(json[i:])
 410  			value.Str, value.Num = "", 0
 411  		case '"':
 412  			value.Type = String
 413  			value.Raw, value.Str = tostr(json[i:])
 414  			value.Num = 0
 415  		}
 416  		value.Index = i + t.Index
 417  
 418  		i += len(value.Raw) - 1
 419  
 420  		if r.vc == '{' {
 421  			if count%2 == 0 {
 422  				key = value
 423  			} else {
 424  				if valueize {
 425  					if _, ok := r.oi[key.Str]; !ok {
 426  						r.oi[key.Str] = value.Value()
 427  					}
 428  				} else {
 429  					if _, ok := r.o[key.Str]; !ok {
 430  						r.o[key.Str] = value
 431  					}
 432  				}
 433  			}
 434  			count++
 435  		} else {
 436  			if valueize {
 437  				r.ai = append(r.ai, value.Value())
 438  			} else {
 439  				r.a = append(r.a, value)
 440  			}
 441  		}
 442  	}
 443  end:
 444  	if t.Indexes != nil {
 445  		if len(t.Indexes) != len(r.a) {
 446  			for i := 0; i < len(r.a); i++ {
 447  				r.a[i].Index = 0
 448  			}
 449  		} else {
 450  			for i := 0; i < len(r.a); i++ {
 451  				r.a[i].Index = t.Indexes[i]
 452  			}
 453  		}
 454  	}
 455  	return
 456  }
 457  
 458  // Parse parses the json and returns a result.
 459  //
 460  // This function expects that the json is well-formed, and does not validate.
 461  // Invalid json will not panic, but it may return back unexpected results.
 462  // If you are consuming JSON from an unpredictable source then you may want to
 463  // use the Valid function first.
 464  func Parse(json string) Result {
 465  	var value Result
 466  	i := 0
 467  	for ; i < len(json); i++ {
 468  		if json[i] == '{' || json[i] == '[' {
 469  			value.Type = JSON
 470  			value.Raw = json[i:] // just take the entire raw
 471  			break
 472  		}
 473  		if json[i] <= ' ' {
 474  			continue
 475  		}
 476  		switch json[i] {
 477  		case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 478  			'i', 'I', 'N':
 479  			value.Type = Number
 480  			value.Raw, value.Num = tonum(json[i:])
 481  		case 'n':
 482  			if i+1 < len(json) && json[i+1] != 'u' {
 483  				// nan
 484  				value.Type = Number
 485  				value.Raw, value.Num = tonum(json[i:])
 486  			} else {
 487  				// null
 488  				value.Type = Null
 489  				value.Raw = tolit(json[i:])
 490  			}
 491  		case 't':
 492  			value.Type = True
 493  			value.Raw = tolit(json[i:])
 494  		case 'f':
 495  			value.Type = False
 496  			value.Raw = tolit(json[i:])
 497  		case '"':
 498  			value.Type = String
 499  			value.Raw, value.Str = tostr(json[i:])
 500  		default:
 501  			return Result{}
 502  		}
 503  		break
 504  	}
 505  	if value.Exists() {
 506  		value.Index = i
 507  	}
 508  	return value
 509  }
 510  
 511  // ParseBytes parses the json and returns a result.
 512  // If working with bytes, this method preferred over Parse(string(data))
 513  func ParseBytes(json []byte) Result {
 514  	return Parse(string(json))
 515  }
 516  
 517  func squash(json string) string {
 518  	// expects that the lead character is a '[' or '{' or '(' or '"'
 519  	// squash the value, ignoring all nested arrays and objects.
 520  	var i, depth int
 521  	if json[0] != '"' {
 522  		i, depth = 1, 1
 523  	}
 524  	for ; i < len(json); i++ {
 525  		if json[i] >= '"' && json[i] <= '}' {
 526  			switch json[i] {
 527  			case '"':
 528  				i++
 529  				s2 := i
 530  				for ; i < len(json); i++ {
 531  					if json[i] > '\\' {
 532  						continue
 533  					}
 534  					if json[i] == '"' {
 535  						// look for an escaped slash
 536  						if json[i-1] == '\\' {
 537  							n := 0
 538  							for j := i - 2; j > s2-1; j-- {
 539  								if json[j] != '\\' {
 540  									break
 541  								}
 542  								n++
 543  							}
 544  							if n%2 == 0 {
 545  								continue
 546  							}
 547  						}
 548  						break
 549  					}
 550  				}
 551  				if depth == 0 {
 552  					if i >= len(json) {
 553  						return json
 554  					}
 555  					return json[:i+1]
 556  				}
 557  			case '{', '[', '(':
 558  				depth++
 559  			case '}', ']', ')':
 560  				depth--
 561  				if depth == 0 {
 562  					return json[:i+1]
 563  				}
 564  			}
 565  		}
 566  	}
 567  	return json
 568  }
 569  
 570  func tonum(json string) (raw string, num float64) {
 571  	for i := 1; i < len(json); i++ {
 572  		// less than dash might have valid characters
 573  		if json[i] <= '-' {
 574  			if json[i] <= ' ' || json[i] == ',' {
 575  				// break on whitespace and comma
 576  				raw = json[:i]
 577  				num, _ = strconv.ParseFloat(raw, 64)
 578  				return
 579  			}
 580  			// could be a '+' or '-'. let's assume so.
 581  		} else if json[i] == ']' || json[i] == '}' {
 582  			// break on ']' or '}'
 583  			raw = json[:i]
 584  			num, _ = strconv.ParseFloat(raw, 64)
 585  			return
 586  		}
 587  	}
 588  	raw = json
 589  	num, _ = strconv.ParseFloat(raw, 64)
 590  	return
 591  }
 592  
 593  func tolit(json string) (raw string) {
 594  	for i := 1; i < len(json); i++ {
 595  		if json[i] < 'a' || json[i] > 'z' {
 596  			return json[:i]
 597  		}
 598  	}
 599  	return json
 600  }
 601  
 602  func tostr(json string) (raw string, str string) {
 603  	// expects that the lead character is a '"'
 604  	for i := 1; i < len(json); i++ {
 605  		if json[i] > '\\' {
 606  			continue
 607  		}
 608  		if json[i] == '"' {
 609  			return json[:i+1], json[1:i]
 610  		}
 611  		if json[i] == '\\' {
 612  			i++
 613  			for ; i < len(json); i++ {
 614  				if json[i] > '\\' {
 615  					continue
 616  				}
 617  				if json[i] == '"' {
 618  					// look for an escaped slash
 619  					if json[i-1] == '\\' {
 620  						n := 0
 621  						for j := i - 2; j > 0; j-- {
 622  							if json[j] != '\\' {
 623  								break
 624  							}
 625  							n++
 626  						}
 627  						if n%2 == 0 {
 628  							continue
 629  						}
 630  					}
 631  					return json[:i+1], unescape(json[1:i])
 632  				}
 633  			}
 634  			var ret string
 635  			if i+1 < len(json) {
 636  				ret = json[:i+1]
 637  			} else {
 638  				ret = json[:i]
 639  			}
 640  			return ret, unescape(json[1:i])
 641  		}
 642  	}
 643  	return json, json[1:]
 644  }
 645  
 646  // Exists returns true if value exists.
 647  //
 648  //	 if gjson.Get(json, "name.last").Exists(){
 649  //			println("value exists")
 650  //	 }
 651  func (t Result) Exists() bool {
 652  	return t.Type != Null || len(t.Raw) != 0
 653  }
 654  
 655  // Value returns one of these types:
 656  //
 657  //	bool, for JSON booleans
 658  //	float64, for JSON numbers
 659  //	Number, for JSON numbers
 660  //	string, for JSON string literals
 661  //	nil, for JSON null
 662  //	map[string]interface{}, for JSON objects
 663  //	[]interface{}, for JSON arrays
 664  func (t Result) Value() interface{} {
 665  	if t.Type == String {
 666  		return t.Str
 667  	}
 668  	switch t.Type {
 669  	default:
 670  		return nil
 671  	case False:
 672  		return false
 673  	case Number:
 674  		return t.Num
 675  	case JSON:
 676  		r := t.arrayOrMap(0, true)
 677  		if r.vc == '{' {
 678  			return r.oi
 679  		} else if r.vc == '[' {
 680  			return r.ai
 681  		}
 682  		return nil
 683  	case True:
 684  		return true
 685  	}
 686  }
 687  
 688  func parseString(json string, i int) (int, string, bool, bool) {
 689  	var s = i
 690  	for ; i < len(json); i++ {
 691  		if json[i] > '\\' {
 692  			continue
 693  		}
 694  		if json[i] == '"' {
 695  			return i + 1, json[s-1 : i+1], false, true
 696  		}
 697  		if json[i] == '\\' {
 698  			i++
 699  			for ; i < len(json); i++ {
 700  				if json[i] > '\\' {
 701  					continue
 702  				}
 703  				if json[i] == '"' {
 704  					// look for an escaped slash
 705  					if json[i-1] == '\\' {
 706  						n := 0
 707  						for j := i - 2; j > 0; j-- {
 708  							if json[j] != '\\' {
 709  								break
 710  							}
 711  							n++
 712  						}
 713  						if n%2 == 0 {
 714  							continue
 715  						}
 716  					}
 717  					return i + 1, json[s-1 : i+1], true, true
 718  				}
 719  			}
 720  			break
 721  		}
 722  	}
 723  	return i, json[s-1:], false, false
 724  }
 725  
 726  func parseNumber(json string, i int) (int, string) {
 727  	var s = i
 728  	i++
 729  	for ; i < len(json); i++ {
 730  		if json[i] <= ' ' || json[i] == ',' || json[i] == ']' ||
 731  			json[i] == '}' {
 732  			return i, json[s:i]
 733  		}
 734  	}
 735  	return i, json[s:]
 736  }
 737  
 738  func parseLiteral(json string, i int) (int, string) {
 739  	var s = i
 740  	i++
 741  	for ; i < len(json); i++ {
 742  		if json[i] < 'a' || json[i] > 'z' {
 743  			return i, json[s:i]
 744  		}
 745  	}
 746  	return i, json[s:]
 747  }
 748  
 749  type arrayPathResult struct {
 750  	part    string
 751  	path    string
 752  	pipe    string
 753  	piped   bool
 754  	more    bool
 755  	alogok  bool
 756  	arrch   bool
 757  	alogkey string
 758  	query   struct {
 759  		on    bool
 760  		all   bool
 761  		path  string
 762  		op    string
 763  		value string
 764  	}
 765  }
 766  
 767  func parseArrayPath(path string) (r arrayPathResult) {
 768  	for i := 0; i < len(path); i++ {
 769  		if path[i] == '|' {
 770  			r.part = path[:i]
 771  			r.pipe = path[i+1:]
 772  			r.piped = true
 773  			return
 774  		}
 775  		if path[i] == '.' {
 776  			r.part = path[:i]
 777  			if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1:]) {
 778  				r.pipe = path[i+1:]
 779  				r.piped = true
 780  			} else {
 781  				r.path = path[i+1:]
 782  				r.more = true
 783  			}
 784  			return
 785  		}
 786  		if path[i] == '#' {
 787  			r.arrch = true
 788  			if i == 0 && len(path) > 1 {
 789  				if path[1] == '.' {
 790  					r.alogok = true
 791  					r.alogkey = path[2:]
 792  					r.path = path[:1]
 793  				} else if path[1] == '[' || path[1] == '(' {
 794  					// query
 795  					r.query.on = true
 796  					qpath, op, value, _, fi, vesc, ok :=
 797  						parseQuery(path[i:])
 798  					if !ok {
 799  						// bad query, end now
 800  						break
 801  					}
 802  					if len(value) >= 2 && value[0] == '"' &&
 803  						value[len(value)-1] == '"' {
 804  						value = value[1 : len(value)-1]
 805  						if vesc {
 806  							value = unescape(value)
 807  						}
 808  					}
 809  					r.query.path = qpath
 810  					r.query.op = op
 811  					r.query.value = value
 812  
 813  					i = fi - 1
 814  					if i+1 < len(path) && path[i+1] == '#' {
 815  						r.query.all = true
 816  					}
 817  				}
 818  			}
 819  			continue
 820  		}
 821  	}
 822  	r.part = path
 823  	r.path = ""
 824  	return
 825  }
 826  
 827  // splitQuery takes a query and splits it into three parts:
 828  //
 829  //	path, op, middle, and right.
 830  //
 831  // So for this query:
 832  //
 833  //	#(first_name=="Murphy").last
 834  //
 835  // Becomes
 836  //
 837  //	first_name   # path
 838  //	=="Murphy"   # middle
 839  //	.last        # right
 840  //
 841  // Or,
 842  //
 843  //	#(service_roles.#(=="one")).cap
 844  //
 845  // Becomes
 846  //
 847  //	service_roles.#(=="one")   # path
 848  //	                           # middle
 849  //	.cap                       # right
 850  func parseQuery(query string) (
 851  	path, op, value, remain string, i int, vesc, ok bool,
 852  ) {
 853  	if len(query) < 2 || query[0] != '#' ||
 854  		(query[1] != '(' && query[1] != '[') {
 855  		return "", "", "", "", i, false, false
 856  	}
 857  	i = 2
 858  	j := 0 // start of value part
 859  	depth := 1
 860  	for ; i < len(query); i++ {
 861  		if depth == 1 && j == 0 {
 862  			switch query[i] {
 863  			case '!', '=', '<', '>', '%':
 864  				// start of the value part
 865  				j = i
 866  				continue
 867  			}
 868  		}
 869  		if query[i] == '\\' {
 870  			i++
 871  		} else if query[i] == '[' || query[i] == '(' {
 872  			depth++
 873  		} else if query[i] == ']' || query[i] == ')' {
 874  			depth--
 875  			if depth == 0 {
 876  				break
 877  			}
 878  		} else if query[i] == '"' {
 879  			// inside selector string, balance quotes
 880  			i++
 881  			for ; i < len(query); i++ {
 882  				if query[i] == '\\' {
 883  					vesc = true
 884  					i++
 885  				} else if query[i] == '"' {
 886  					break
 887  				}
 888  			}
 889  		}
 890  	}
 891  	if depth > 0 {
 892  		return "", "", "", "", i, false, false
 893  	}
 894  	if j > 0 {
 895  		path = trim(query[2:j])
 896  		value = trim(query[j:i])
 897  		remain = query[i+1:]
 898  		// parse the compare op from the value
 899  		var opsz int
 900  		switch {
 901  		case len(value) == 1:
 902  			opsz = 1
 903  		case value[0] == '!' && value[1] == '=':
 904  			opsz = 2
 905  		case value[0] == '!' && value[1] == '%':
 906  			opsz = 2
 907  		case value[0] == '<' && value[1] == '=':
 908  			opsz = 2
 909  		case value[0] == '>' && value[1] == '=':
 910  			opsz = 2
 911  		case value[0] == '=' && value[1] == '=':
 912  			value = value[1:]
 913  			opsz = 1
 914  		case value[0] == '<':
 915  			opsz = 1
 916  		case value[0] == '>':
 917  			opsz = 1
 918  		case value[0] == '=':
 919  			opsz = 1
 920  		case value[0] == '%':
 921  			opsz = 1
 922  		}
 923  		op = value[:opsz]
 924  		value = trim(value[opsz:])
 925  	} else {
 926  		path = trim(query[2:i])
 927  		remain = query[i+1:]
 928  	}
 929  	return path, op, value, remain, i + 1, vesc, true
 930  }
 931  
 932  func trim(s string) string {
 933  left:
 934  	if len(s) > 0 && s[0] <= ' ' {
 935  		s = s[1:]
 936  		goto left
 937  	}
 938  right:
 939  	if len(s) > 0 && s[len(s)-1] <= ' ' {
 940  		s = s[:len(s)-1]
 941  		goto right
 942  	}
 943  	return s
 944  }
 945  
 946  // peek at the next byte and see if it's a '@', '[', or '{'.
 947  func isDotPiperChar(s string) bool {
 948  	if DisableModifiers {
 949  		return false
 950  	}
 951  	c := s[0]
 952  	if c == '@' {
 953  		// check that the next component is *not* a modifier.
 954  		i := 1
 955  		for ; i < len(s); i++ {
 956  			if s[i] == '.' || s[i] == '|' || s[i] == ':' {
 957  				break
 958  			}
 959  		}
 960  		_, ok := modifiers[s[1:i]]
 961  		return ok
 962  	}
 963  	return c == '[' || c == '{'
 964  }
 965  
 966  type objectPathResult struct {
 967  	part  string
 968  	path  string
 969  	pipe  string
 970  	piped bool
 971  	wild  bool
 972  	more  bool
 973  }
 974  
 975  func parseObjectPath(path string) (r objectPathResult) {
 976  	for i := 0; i < len(path); i++ {
 977  		if path[i] == '|' {
 978  			r.part = path[:i]
 979  			r.pipe = path[i+1:]
 980  			r.piped = true
 981  			return
 982  		}
 983  		if path[i] == '.' {
 984  			r.part = path[:i]
 985  			if i < len(path)-1 && isDotPiperChar(path[i+1:]) {
 986  				r.pipe = path[i+1:]
 987  				r.piped = true
 988  			} else {
 989  				r.path = path[i+1:]
 990  				r.more = true
 991  			}
 992  			return
 993  		}
 994  		if path[i] == '*' || path[i] == '?' {
 995  			r.wild = true
 996  			continue
 997  		}
 998  		if path[i] == '\\' {
 999  			// go into escape mode. this is a slower path that
1000  			// strips off the escape character from the part.
1001  			epart := []byte(path[:i])
1002  			i++
1003  			if i < len(path) {
1004  				epart = append(epart, path[i])
1005  				i++
1006  				for ; i < len(path); i++ {
1007  					if path[i] == '\\' {
1008  						i++
1009  						if i < len(path) {
1010  							epart = append(epart, path[i])
1011  						}
1012  						continue
1013  					} else if path[i] == '.' {
1014  						r.part = string(epart)
1015  						if i < len(path)-1 && isDotPiperChar(path[i+1:]) {
1016  							r.pipe = path[i+1:]
1017  							r.piped = true
1018  						} else {
1019  							r.path = path[i+1:]
1020  							r.more = true
1021  						}
1022  						return
1023  					} else if path[i] == '|' {
1024  						r.part = string(epart)
1025  						r.pipe = path[i+1:]
1026  						r.piped = true
1027  						return
1028  					} else if path[i] == '*' || path[i] == '?' {
1029  						r.wild = true
1030  					}
1031  					epart = append(epart, path[i])
1032  				}
1033  			}
1034  			// append the last part
1035  			r.part = string(epart)
1036  			return
1037  		}
1038  	}
1039  	r.part = path
1040  	return
1041  }
1042  
1043  var vchars = [256]byte{
1044  	'"': 2, '{': 3, '(': 3, '[': 3, '}': 1, ')': 1, ']': 1,
1045  }
1046  
1047  func parseSquash(json string, i int) (int, string) {
1048  	// expects that the lead character is a '[' or '{' or '('
1049  	// squash the value, ignoring all nested arrays and objects.
1050  	// the first '[' or '{' or '(' has already been read
1051  	s := i
1052  	i++
1053  	depth := 1
1054  	var c byte
1055  	for i < len(json) {
1056  		for i < len(json)-8 {
1057  			jslice := json[i : i+8]
1058  			c = vchars[jslice[0]]
1059  			if c != 0 {
1060  				i += 0
1061  				goto token
1062  			}
1063  			c = vchars[jslice[1]]
1064  			if c != 0 {
1065  				i += 1
1066  				goto token
1067  			}
1068  			c = vchars[jslice[2]]
1069  			if c != 0 {
1070  				i += 2
1071  				goto token
1072  			}
1073  			c = vchars[jslice[3]]
1074  			if c != 0 {
1075  				i += 3
1076  				goto token
1077  			}
1078  			c = vchars[jslice[4]]
1079  			if c != 0 {
1080  				i += 4
1081  				goto token
1082  			}
1083  			c = vchars[jslice[5]]
1084  			if c != 0 {
1085  				i += 5
1086  				goto token
1087  			}
1088  			c = vchars[jslice[6]]
1089  			if c != 0 {
1090  				i += 6
1091  				goto token
1092  			}
1093  			c = vchars[jslice[7]]
1094  			if c != 0 {
1095  				i += 7
1096  				goto token
1097  			}
1098  			i += 8
1099  		}
1100  		c = vchars[json[i]]
1101  		if c == 0 {
1102  			i++
1103  			continue
1104  		}
1105  	token:
1106  		if c == 2 {
1107  			// '"' string
1108  			i++
1109  			s2 := i
1110  		nextquote:
1111  			for i < len(json)-8 {
1112  				jslice := json[i : i+8]
1113  				if jslice[0] == '"' {
1114  					i += 0
1115  					goto strchkesc
1116  				}
1117  				if jslice[1] == '"' {
1118  					i += 1
1119  					goto strchkesc
1120  				}
1121  				if jslice[2] == '"' {
1122  					i += 2
1123  					goto strchkesc
1124  				}
1125  				if jslice[3] == '"' {
1126  					i += 3
1127  					goto strchkesc
1128  				}
1129  				if jslice[4] == '"' {
1130  					i += 4
1131  					goto strchkesc
1132  				}
1133  				if jslice[5] == '"' {
1134  					i += 5
1135  					goto strchkesc
1136  				}
1137  				if jslice[6] == '"' {
1138  					i += 6
1139  					goto strchkesc
1140  				}
1141  				if jslice[7] == '"' {
1142  					i += 7
1143  					goto strchkesc
1144  				}
1145  				i += 8
1146  			}
1147  			goto strchkstd
1148  		strchkesc:
1149  			if json[i-1] != '\\' {
1150  				i++
1151  				continue
1152  			}
1153  		strchkstd:
1154  			for i < len(json) {
1155  				if json[i] > '\\' || json[i] != '"' {
1156  					i++
1157  					continue
1158  				}
1159  				// look for an escaped slash
1160  				if json[i-1] == '\\' {
1161  					n := 0
1162  					for j := i - 2; j > s2-1; j-- {
1163  						if json[j] != '\\' {
1164  							break
1165  						}
1166  						n++
1167  					}
1168  					if n%2 == 0 {
1169  						i++
1170  						goto nextquote
1171  					}
1172  				}
1173  				break
1174  			}
1175  		} else {
1176  			// '{', '[', '(', '}', ']', ')'
1177  			// open close tokens
1178  			depth += int(c) - 2
1179  			if depth == 0 {
1180  				i++
1181  				return i, json[s:i]
1182  			}
1183  		}
1184  		i++
1185  	}
1186  	return i, json[s:]
1187  }
1188  
1189  func parseObject(c *parseContext, i int, path string) (int, bool) {
1190  	var pmatch, kesc, vesc, ok, hit bool
1191  	var key, val string
1192  	rp := parseObjectPath(path)
1193  	if !rp.more && rp.piped {
1194  		c.pipe = rp.pipe
1195  		c.piped = true
1196  	}
1197  	for i < len(c.json) {
1198  		for ; i < len(c.json); i++ {
1199  			if c.json[i] == '"' {
1200  				// parse_key_string
1201  				// this is slightly different from getting s string value
1202  				// because we don't need the outer quotes.
1203  				i++
1204  				var s = i
1205  				for ; i < len(c.json); i++ {
1206  					if c.json[i] > '\\' {
1207  						continue
1208  					}
1209  					if c.json[i] == '"' {
1210  						i, key, kesc, ok = i+1, c.json[s:i], false, true
1211  						goto parse_key_string_done
1212  					}
1213  					if c.json[i] == '\\' {
1214  						i++
1215  						for ; i < len(c.json); i++ {
1216  							if c.json[i] > '\\' {
1217  								continue
1218  							}
1219  							if c.json[i] == '"' {
1220  								// look for an escaped slash
1221  								if c.json[i-1] == '\\' {
1222  									n := 0
1223  									for j := i - 2; j > 0; j-- {
1224  										if c.json[j] != '\\' {
1225  											break
1226  										}
1227  										n++
1228  									}
1229  									if n%2 == 0 {
1230  										continue
1231  									}
1232  								}
1233  								i, key, kesc, ok = i+1, c.json[s:i], true, true
1234  								goto parse_key_string_done
1235  							}
1236  						}
1237  						break
1238  					}
1239  				}
1240  				key, kesc, ok = c.json[s:], false, false
1241  			parse_key_string_done:
1242  				break
1243  			}
1244  			if c.json[i] == '}' {
1245  				return i + 1, false
1246  			}
1247  		}
1248  		if !ok {
1249  			return i, false
1250  		}
1251  		if rp.wild {
1252  			if kesc {
1253  				pmatch = matchLimit(unescape(key), rp.part)
1254  			} else {
1255  				pmatch = matchLimit(key, rp.part)
1256  			}
1257  		} else {
1258  			if kesc {
1259  				pmatch = rp.part == unescape(key)
1260  			} else {
1261  				pmatch = rp.part == key
1262  			}
1263  		}
1264  		hit = pmatch && !rp.more
1265  		for ; i < len(c.json); i++ {
1266  			var num bool
1267  			switch c.json[i] {
1268  			default:
1269  				continue
1270  			case '"':
1271  				i++
1272  				i, val, vesc, ok = parseString(c.json, i)
1273  				if !ok {
1274  					return i, false
1275  				}
1276  				if hit {
1277  					if vesc {
1278  						c.value.Str = unescape(val[1 : len(val)-1])
1279  					} else {
1280  						c.value.Str = val[1 : len(val)-1]
1281  					}
1282  					c.value.Raw = val
1283  					c.value.Type = String
1284  					return i, true
1285  				}
1286  			case '{':
1287  				if pmatch && !hit {
1288  					i, hit = parseObject(c, i+1, rp.path)
1289  					if hit {
1290  						return i, true
1291  					}
1292  				} else {
1293  					i, val = parseSquash(c.json, i)
1294  					if hit {
1295  						c.value.Raw = val
1296  						c.value.Type = JSON
1297  						return i, true
1298  					}
1299  				}
1300  			case '[':
1301  				if pmatch && !hit {
1302  					i, hit = parseArray(c, i+1, rp.path)
1303  					if hit {
1304  						return i, true
1305  					}
1306  				} else {
1307  					i, val = parseSquash(c.json, i)
1308  					if hit {
1309  						c.value.Raw = val
1310  						c.value.Type = JSON
1311  						return i, true
1312  					}
1313  				}
1314  			case 'n':
1315  				if i+1 < len(c.json) && c.json[i+1] != 'u' {
1316  					num = true
1317  					break
1318  				}
1319  				fallthrough
1320  			case 't', 'f':
1321  				vc := c.json[i]
1322  				i, val = parseLiteral(c.json, i)
1323  				if hit {
1324  					c.value.Raw = val
1325  					switch vc {
1326  					case 't':
1327  						c.value.Type = True
1328  					case 'f':
1329  						c.value.Type = False
1330  					}
1331  					return i, true
1332  				}
1333  			case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1334  				'i', 'I', 'N':
1335  				num = true
1336  			}
1337  			if num {
1338  				i, val = parseNumber(c.json, i)
1339  				if hit {
1340  					c.value.Raw = val
1341  					c.value.Type = Number
1342  					c.value.Num, _ = strconv.ParseFloat(val, 64)
1343  					return i, true
1344  				}
1345  			}
1346  			break
1347  		}
1348  	}
1349  	return i, false
1350  }
1351  
1352  // matchLimit will limit the complexity of the match operation to avoid ReDos
1353  // attacks from arbitrary inputs.
1354  // See the github.com/tidwall/match.MatchLimit function for more information.
1355  func matchLimit(str, pattern string) bool {
1356  	matched, _ := match.MatchLimit(str, pattern, 10000)
1357  	return matched
1358  }
1359  
1360  func falseish(t Result) bool {
1361  	switch t.Type {
1362  	case Null:
1363  		return true
1364  	case False:
1365  		return true
1366  	case String:
1367  		b, err := strconv.ParseBool(strings.ToLower(t.Str))
1368  		if err != nil {
1369  			return false
1370  		}
1371  		return !b
1372  	case Number:
1373  		return t.Num == 0
1374  	default:
1375  		return false
1376  	}
1377  }
1378  
1379  func trueish(t Result) bool {
1380  	switch t.Type {
1381  	case True:
1382  		return true
1383  	case String:
1384  		b, err := strconv.ParseBool(strings.ToLower(t.Str))
1385  		if err != nil {
1386  			return false
1387  		}
1388  		return b
1389  	case Number:
1390  		return t.Num != 0
1391  	default:
1392  		return false
1393  	}
1394  }
1395  
1396  func nullish(t Result) bool {
1397  	return t.Type == Null
1398  }
1399  
1400  func queryMatches(rp *arrayPathResult, value Result) bool {
1401  	rpv := rp.query.value
1402  	if len(rpv) > 0 {
1403  		if rpv[0] == '~' {
1404  			// convert to bool
1405  			rpv = rpv[1:]
1406  			var ish, ok bool
1407  			switch rpv {
1408  			case "*":
1409  				ish, ok = value.Exists(), true
1410  			case "null":
1411  				ish, ok = nullish(value), true
1412  			case "true":
1413  				ish, ok = trueish(value), true
1414  			case "false":
1415  				ish, ok = falseish(value), true
1416  			}
1417  			if ok {
1418  				rpv = "true"
1419  				if ish {
1420  					value = Result{Type: True}
1421  				} else {
1422  					value = Result{Type: False}
1423  				}
1424  			} else {
1425  				rpv = ""
1426  				value = Result{}
1427  			}
1428  		}
1429  	}
1430  	if !value.Exists() {
1431  		return false
1432  	}
1433  	if rp.query.op == "" {
1434  		// the query is only looking for existence, such as:
1435  		//   friends.#(name)
1436  		// which makes sure that the array "friends" has an element of
1437  		// "name" that exists
1438  		return true
1439  	}
1440  	switch value.Type {
1441  	case String:
1442  		switch rp.query.op {
1443  		case "=":
1444  			return value.Str == rpv
1445  		case "!=":
1446  			return value.Str != rpv
1447  		case "<":
1448  			return value.Str < rpv
1449  		case "<=":
1450  			return value.Str <= rpv
1451  		case ">":
1452  			return value.Str > rpv
1453  		case ">=":
1454  			return value.Str >= rpv
1455  		case "%":
1456  			return matchLimit(value.Str, rpv)
1457  		case "!%":
1458  			return !matchLimit(value.Str, rpv)
1459  		}
1460  	case Number:
1461  		rpvn, _ := strconv.ParseFloat(rpv, 64)
1462  		switch rp.query.op {
1463  		case "=":
1464  			return value.Num == rpvn
1465  		case "!=":
1466  			return value.Num != rpvn
1467  		case "<":
1468  			return value.Num < rpvn
1469  		case "<=":
1470  			return value.Num <= rpvn
1471  		case ">":
1472  			return value.Num > rpvn
1473  		case ">=":
1474  			return value.Num >= rpvn
1475  		}
1476  	case True:
1477  		switch rp.query.op {
1478  		case "=":
1479  			return rpv == "true"
1480  		case "!=":
1481  			return rpv != "true"
1482  		case ">":
1483  			return rpv == "false"
1484  		case ">=":
1485  			return true
1486  		}
1487  	case False:
1488  		switch rp.query.op {
1489  		case "=":
1490  			return rpv == "false"
1491  		case "!=":
1492  			return rpv != "false"
1493  		case "<":
1494  			return rpv == "true"
1495  		case "<=":
1496  			return true
1497  		}
1498  	}
1499  	return false
1500  }
1501  func parseArray(c *parseContext, i int, path string) (int, bool) {
1502  	var pmatch, vesc, ok, hit bool
1503  	var val string
1504  	var h int
1505  	var alog []int
1506  	var partidx int
1507  	var multires []byte
1508  	var queryIndexes []int
1509  	rp := parseArrayPath(path)
1510  	if !rp.arrch {
1511  		n, ok := parseUint(rp.part)
1512  		if !ok {
1513  			partidx = -1
1514  		} else {
1515  			partidx = int(n)
1516  		}
1517  	}
1518  	if !rp.more && rp.piped {
1519  		c.pipe = rp.pipe
1520  		c.piped = true
1521  	}
1522  
1523  	procQuery := func(qval Result) bool {
1524  		if rp.query.all {
1525  			if len(multires) == 0 {
1526  				multires = append(multires, '[')
1527  			}
1528  		}
1529  		var tmp parseContext
1530  		tmp.value = qval
1531  		fillIndex(c.json, &tmp)
1532  		parentIndex := tmp.value.Index
1533  		var res Result
1534  		if qval.Type == JSON {
1535  			res = qval.Get(rp.query.path)
1536  		} else {
1537  			if rp.query.path != "" {
1538  				return false
1539  			}
1540  			res = qval
1541  		}
1542  		if queryMatches(&rp, res) {
1543  			if rp.more {
1544  				left, right, ok := splitPossiblePipe(rp.path)
1545  				if ok {
1546  					rp.path = left
1547  					c.pipe = right
1548  					c.piped = true
1549  				}
1550  				res = qval.Get(rp.path)
1551  			} else {
1552  				res = qval
1553  			}
1554  			if rp.query.all {
1555  				raw := res.Raw
1556  				if len(raw) == 0 {
1557  					raw = res.String()
1558  				}
1559  				if raw != "" {
1560  					if len(multires) > 1 {
1561  						multires = append(multires, ',')
1562  					}
1563  					multires = append(multires, raw...)
1564  					queryIndexes = append(queryIndexes, res.Index+parentIndex)
1565  				}
1566  			} else {
1567  				c.value = res
1568  				return true
1569  			}
1570  		}
1571  		return false
1572  	}
1573  	for i < len(c.json)+1 {
1574  		if !rp.arrch {
1575  			pmatch = partidx == h
1576  			hit = pmatch && !rp.more
1577  		}
1578  		h++
1579  		if rp.alogok {
1580  			alog = append(alog, i)
1581  		}
1582  		for ; ; i++ {
1583  			var ch byte
1584  			if i > len(c.json) {
1585  				break
1586  			} else if i == len(c.json) {
1587  				ch = ']'
1588  			} else {
1589  				ch = c.json[i]
1590  			}
1591  			var num bool
1592  			switch ch {
1593  			default:
1594  				continue
1595  			case '"':
1596  				i++
1597  				i, val, vesc, ok = parseString(c.json, i)
1598  				if !ok {
1599  					return i, false
1600  				}
1601  				if rp.query.on {
1602  					var qval Result
1603  					if vesc {
1604  						qval.Str = unescape(val[1 : len(val)-1])
1605  					} else {
1606  						qval.Str = val[1 : len(val)-1]
1607  					}
1608  					qval.Raw = val
1609  					qval.Type = String
1610  					if procQuery(qval) {
1611  						return i, true
1612  					}
1613  				} else if hit {
1614  					if rp.alogok {
1615  						break
1616  					}
1617  					if vesc {
1618  						c.value.Str = unescape(val[1 : len(val)-1])
1619  					} else {
1620  						c.value.Str = val[1 : len(val)-1]
1621  					}
1622  					c.value.Raw = val
1623  					c.value.Type = String
1624  					return i, true
1625  				}
1626  			case '{':
1627  				if pmatch && !hit {
1628  					i, hit = parseObject(c, i+1, rp.path)
1629  					if hit {
1630  						if rp.alogok {
1631  							break
1632  						}
1633  						return i, true
1634  					}
1635  				} else {
1636  					i, val = parseSquash(c.json, i)
1637  					if rp.query.on {
1638  						if procQuery(Result{Raw: val, Type: JSON}) {
1639  							return i, true
1640  						}
1641  					} else if hit {
1642  						if rp.alogok {
1643  							break
1644  						}
1645  						c.value.Raw = val
1646  						c.value.Type = JSON
1647  						return i, true
1648  					}
1649  				}
1650  			case '[':
1651  				if pmatch && !hit {
1652  					i, hit = parseArray(c, i+1, rp.path)
1653  					if hit {
1654  						if rp.alogok {
1655  							break
1656  						}
1657  						return i, true
1658  					}
1659  				} else {
1660  					i, val = parseSquash(c.json, i)
1661  					if rp.query.on {
1662  						if procQuery(Result{Raw: val, Type: JSON}) {
1663  							return i, true
1664  						}
1665  					} else if hit {
1666  						if rp.alogok {
1667  							break
1668  						}
1669  						c.value.Raw = val
1670  						c.value.Type = JSON
1671  						return i, true
1672  					}
1673  				}
1674  			case 'n':
1675  				if i+1 < len(c.json) && c.json[i+1] != 'u' {
1676  					num = true
1677  					break
1678  				}
1679  				fallthrough
1680  			case 't', 'f':
1681  				vc := c.json[i]
1682  				i, val = parseLiteral(c.json, i)
1683  				if rp.query.on {
1684  					var qval Result
1685  					qval.Raw = val
1686  					switch vc {
1687  					case 't':
1688  						qval.Type = True
1689  					case 'f':
1690  						qval.Type = False
1691  					}
1692  					if procQuery(qval) {
1693  						return i, true
1694  					}
1695  				} else if hit {
1696  					if rp.alogok {
1697  						break
1698  					}
1699  					c.value.Raw = val
1700  					switch vc {
1701  					case 't':
1702  						c.value.Type = True
1703  					case 'f':
1704  						c.value.Type = False
1705  					}
1706  					return i, true
1707  				}
1708  			case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1709  				'i', 'I', 'N':
1710  				num = true
1711  			case ']':
1712  				if rp.arrch && rp.part == "#" {
1713  					if rp.alogok {
1714  						left, right, ok := splitPossiblePipe(rp.alogkey)
1715  						if ok {
1716  							rp.alogkey = left
1717  							c.pipe = right
1718  							c.piped = true
1719  						}
1720  						var indexes = make([]int, 0, 64)
1721  						var jsons = make([]byte, 0, 64)
1722  						jsons = append(jsons, '[')
1723  						for j, k := 0, 0; j < len(alog); j++ {
1724  							idx := alog[j]
1725  							for idx < len(c.json) {
1726  								switch c.json[idx] {
1727  								case ' ', '\t', '\r', '\n':
1728  									idx++
1729  									continue
1730  								}
1731  								break
1732  							}
1733  							if idx < len(c.json) && c.json[idx] != ']' {
1734  								_, res, ok := parseAny(c.json, idx, true)
1735  								if ok {
1736  									res := res.Get(rp.alogkey)
1737  									if res.Exists() {
1738  										if k > 0 {
1739  											jsons = append(jsons, ',')
1740  										}
1741  										raw := res.Raw
1742  										if len(raw) == 0 {
1743  											raw = res.String()
1744  										}
1745  										jsons = append(jsons, []byte(raw)...)
1746  										indexes = append(indexes, res.Index)
1747  										k++
1748  									}
1749  								}
1750  							}
1751  						}
1752  						jsons = append(jsons, ']')
1753  						c.value.Type = JSON
1754  						c.value.Raw = string(jsons)
1755  						c.value.Indexes = indexes
1756  						return i + 1, true
1757  					}
1758  					if rp.alogok {
1759  						break
1760  					}
1761  
1762  					c.value.Type = Number
1763  					c.value.Num = float64(h - 1)
1764  					c.value.Raw = strconv.Itoa(h - 1)
1765  					c.calcd = true
1766  					return i + 1, true
1767  				}
1768  				if !c.value.Exists() {
1769  					if len(multires) > 0 {
1770  						c.value = Result{
1771  							Raw:     string(append(multires, ']')),
1772  							Type:    JSON,
1773  							Indexes: queryIndexes,
1774  						}
1775  					} else if rp.query.all {
1776  						c.value = Result{
1777  							Raw:  "[]",
1778  							Type: JSON,
1779  						}
1780  					}
1781  				}
1782  				return i + 1, false
1783  			}
1784  			if num {
1785  				i, val = parseNumber(c.json, i)
1786  				if rp.query.on {
1787  					var qval Result
1788  					qval.Raw = val
1789  					qval.Type = Number
1790  					qval.Num, _ = strconv.ParseFloat(val, 64)
1791  					if procQuery(qval) {
1792  						return i, true
1793  					}
1794  				} else if hit {
1795  					if rp.alogok {
1796  						break
1797  					}
1798  					c.value.Raw = val
1799  					c.value.Type = Number
1800  					c.value.Num, _ = strconv.ParseFloat(val, 64)
1801  					return i, true
1802  				}
1803  			}
1804  			break
1805  		}
1806  	}
1807  	return i, false
1808  }
1809  
1810  func splitPossiblePipe(path string) (left, right string, ok bool) {
1811  	// take a quick peek for the pipe character. If found we'll split the piped
1812  	// part of the path into the c.pipe field and shorten the rp.
1813  	var possible bool
1814  	for i := 0; i < len(path); i++ {
1815  		if path[i] == '|' {
1816  			possible = true
1817  			break
1818  		}
1819  	}
1820  	if !possible {
1821  		return
1822  	}
1823  
1824  	if len(path) > 0 && path[0] == '{' {
1825  		squashed := squash(path[1:])
1826  		if len(squashed) < len(path)-1 {
1827  			squashed = path[:len(squashed)+1]
1828  			remain := path[len(squashed):]
1829  			if remain[0] == '|' {
1830  				return squashed, remain[1:], true
1831  			}
1832  		}
1833  		return
1834  	}
1835  
1836  	// split the left and right side of the path with the pipe character as
1837  	// the delimiter. This is a little tricky because we'll need to basically
1838  	// parse the entire path.
1839  	for i := 0; i < len(path); i++ {
1840  		if path[i] == '\\' {
1841  			i++
1842  		} else if path[i] == '.' {
1843  			if i == len(path)-1 {
1844  				return
1845  			}
1846  			if path[i+1] == '#' {
1847  				i += 2
1848  				if i == len(path) {
1849  					return
1850  				}
1851  				if path[i] == '[' || path[i] == '(' {
1852  					var start, end byte
1853  					if path[i] == '[' {
1854  						start, end = '[', ']'
1855  					} else {
1856  						start, end = '(', ')'
1857  					}
1858  					// inside selector, balance brackets
1859  					i++
1860  					depth := 1
1861  					for ; i < len(path); i++ {
1862  						if path[i] == '\\' {
1863  							i++
1864  						} else if path[i] == start {
1865  							depth++
1866  						} else if path[i] == end {
1867  							depth--
1868  							if depth == 0 {
1869  								break
1870  							}
1871  						} else if path[i] == '"' {
1872  							// inside selector string, balance quotes
1873  							i++
1874  							for ; i < len(path); i++ {
1875  								if path[i] == '\\' {
1876  									i++
1877  								} else if path[i] == '"' {
1878  									break
1879  								}
1880  							}
1881  						}
1882  					}
1883  				}
1884  			}
1885  		} else if path[i] == '|' {
1886  			return path[:i], path[i+1:], true
1887  		}
1888  	}
1889  	return
1890  }
1891  
1892  // ForEachLine iterates through lines of JSON as specified by the JSON Lines
1893  // format (http://jsonlines.org/).
1894  // Each line is returned as a GJSON Result.
1895  func ForEachLine(json string, iterator func(line Result) bool) {
1896  	var res Result
1897  	var i int
1898  	for {
1899  		i, res, _ = parseAny(json, i, true)
1900  		if !res.Exists() {
1901  			break
1902  		}
1903  		if !iterator(res) {
1904  			return
1905  		}
1906  	}
1907  }
1908  
1909  type subSelector struct {
1910  	name string
1911  	path string
1912  }
1913  
1914  // parseSubSelectors returns the subselectors belonging to a '[path1,path2]' or
1915  // '{"field1":path1,"field2":path2}' type subSelection. It's expected that the
1916  // first character in path is either '[' or '{', and has already been checked
1917  // prior to calling this function.
1918  func parseSubSelectors(path string) (sels []subSelector, out string, ok bool) {
1919  	modifier := 0
1920  	depth := 1
1921  	colon := 0
1922  	start := 1
1923  	i := 1
1924  	pushSel := func() {
1925  		var sel subSelector
1926  		if colon == 0 {
1927  			sel.path = path[start:i]
1928  		} else {
1929  			sel.name = path[start:colon]
1930  			sel.path = path[colon+1 : i]
1931  		}
1932  		sels = append(sels, sel)
1933  		colon = 0
1934  		modifier = 0
1935  		start = i + 1
1936  	}
1937  	for ; i < len(path); i++ {
1938  		switch path[i] {
1939  		case '\\':
1940  			i++
1941  		case '@':
1942  			if modifier == 0 && i > 0 && (path[i-1] == '.' || path[i-1] == '|') {
1943  				modifier = i
1944  			}
1945  		case ':':
1946  			if modifier == 0 && colon == 0 && depth == 1 {
1947  				colon = i
1948  			}
1949  		case ',':
1950  			if depth == 1 {
1951  				pushSel()
1952  			}
1953  		case '"':
1954  			i++
1955  		loop:
1956  			for ; i < len(path); i++ {
1957  				switch path[i] {
1958  				case '\\':
1959  					i++
1960  				case '"':
1961  					break loop
1962  				}
1963  			}
1964  		case '[', '(', '{':
1965  			depth++
1966  		case ']', ')', '}':
1967  			depth--
1968  			if depth == 0 {
1969  				pushSel()
1970  				path = path[i+1:]
1971  				return sels, path, true
1972  			}
1973  		}
1974  	}
1975  	return
1976  }
1977  
1978  // nameOfLast returns the name of the last component
1979  func nameOfLast(path string) string {
1980  	for i := len(path) - 1; i >= 0; i-- {
1981  		if path[i] == '|' || path[i] == '.' {
1982  			if i > 0 {
1983  				if path[i-1] == '\\' {
1984  					continue
1985  				}
1986  			}
1987  			return path[i+1:]
1988  		}
1989  	}
1990  	return path
1991  }
1992  
1993  func isSimpleName(component string) bool {
1994  	for i := 0; i < len(component); i++ {
1995  		if component[i] < ' ' {
1996  			return false
1997  		}
1998  		switch component[i] {
1999  		case '[', ']', '{', '}', '(', ')', '#', '|', '!':
2000  			return false
2001  		}
2002  	}
2003  	return true
2004  }
2005  
2006  var hexchars = [...]byte{
2007  	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2008  	'a', 'b', 'c', 'd', 'e', 'f',
2009  }
2010  
2011  func appendHex16(dst []byte, x uint16) []byte {
2012  	return append(dst,
2013  		hexchars[x>>12&0xF], hexchars[x>>8&0xF],
2014  		hexchars[x>>4&0xF], hexchars[x>>0&0xF],
2015  	)
2016  }
2017  
2018  // DisableEscapeHTML will disable the automatic escaping of certain
2019  // "problamatic" HTML characters when encoding to JSON.
2020  // These character include '>', '<' and '&', which get escaped to \u003e,
2021  // \u0026, and \u003c respectively.
2022  //
2023  // This is a global flag and will affect all further gjson operations.
2024  // Ideally, if used, it should be set one time before other gjson functions
2025  // are called.
2026  var DisableEscapeHTML = false
2027  
2028  // AppendJSONString is a convenience function that converts the provided string
2029  // to a valid JSON string and appends it to dst.
2030  func AppendJSONString(dst []byte, s string) []byte {
2031  	dst = append(dst, make([]byte, len(s)+2)...)
2032  	dst = append(dst[:len(dst)-len(s)-2], '"')
2033  	for i := 0; i < len(s); i++ {
2034  		if s[i] < ' ' {
2035  			dst = append(dst, '\\')
2036  			switch s[i] {
2037  			case '\b':
2038  				dst = append(dst, 'b')
2039  			case '\f':
2040  				dst = append(dst, 'f')
2041  			case '\n':
2042  				dst = append(dst, 'n')
2043  			case '\r':
2044  				dst = append(dst, 'r')
2045  			case '\t':
2046  				dst = append(dst, 't')
2047  			default:
2048  				dst = append(dst, 'u')
2049  				dst = appendHex16(dst, uint16(s[i]))
2050  			}
2051  		} else if !DisableEscapeHTML &&
2052  			(s[i] == '>' || s[i] == '<' || s[i] == '&') {
2053  			dst = append(dst, '\\', 'u')
2054  			dst = appendHex16(dst, uint16(s[i]))
2055  		} else if s[i] == '\\' {
2056  			dst = append(dst, '\\', '\\')
2057  		} else if s[i] == '"' {
2058  			dst = append(dst, '\\', '"')
2059  		} else if s[i] > 127 {
2060  			// read utf8 character
2061  			r, n := utf8.DecodeRuneInString(s[i:])
2062  			if n == 0 {
2063  				break
2064  			}
2065  			if r == utf8.RuneError && n == 1 {
2066  				dst = append(dst, `\ufffd`...)
2067  			} else if r == '\u2028' || r == '\u2029' {
2068  				dst = append(dst, `\u202`...)
2069  				dst = append(dst, hexchars[r&0xF])
2070  			} else {
2071  				dst = append(dst, s[i:i+n]...)
2072  			}
2073  			i = i + n - 1
2074  		} else {
2075  			dst = append(dst, s[i])
2076  		}
2077  	}
2078  	return append(dst, '"')
2079  }
2080  
2081  type parseContext struct {
2082  	json  string
2083  	value Result
2084  	pipe  string
2085  	piped bool
2086  	calcd bool
2087  	lines bool
2088  }
2089  
2090  // Get searches json for the specified path.
2091  // A path is in dot syntax, such as "name.last" or "age".
2092  // When the value is found it's returned immediately.
2093  //
2094  // A path is a series of keys separated by a dot.
2095  // A key may contain special wildcard characters '*' and '?'.
2096  // To access an array value use the index as the key.
2097  // To get the number of elements in an array or to access a child path, use
2098  // the '#' character.
2099  // The dot and wildcard character can be escaped with '\'.
2100  //
2101  //	{
2102  //	  "name": {"first": "Tom", "last": "Anderson"},
2103  //	  "age":37,
2104  //	  "children": ["Sara","Alex","Jack"],
2105  //	  "friends": [
2106  //	    {"first": "James", "last": "Murphy"},
2107  //	    {"first": "Roger", "last": "Craig"}
2108  //	  ]
2109  //	}
2110  //	"name.last"          >> "Anderson"
2111  //	"age"                >> 37
2112  //	"children"           >> ["Sara","Alex","Jack"]
2113  //	"children.#"         >> 3
2114  //	"children.1"         >> "Alex"
2115  //	"child*.2"           >> "Jack"
2116  //	"c?ildren.0"         >> "Sara"
2117  //	"friends.#.first"    >> ["James","Roger"]
2118  //
2119  // This function expects that the json is well-formed, and does not validate.
2120  // Invalid json will not panic, but it may return back unexpected results.
2121  // If you are consuming JSON from an unpredictable source then you may want to
2122  // use the Valid function first.
2123  func Get(json, path string) Result {
2124  	if len(path) > 1 {
2125  		if (path[0] == '@' && !DisableModifiers) || path[0] == '!' {
2126  			// possible modifier
2127  			var ok bool
2128  			var npath string
2129  			var rjson string
2130  			if path[0] == '@' && !DisableModifiers {
2131  				npath, rjson, ok = execModifier(json, path)
2132  			} else if path[0] == '!' {
2133  				npath, rjson, ok = execStatic(json, path)
2134  			}
2135  			if ok {
2136  				path = npath
2137  				if len(path) > 0 && (path[0] == '|' || path[0] == '.') {
2138  					res := Get(rjson, path[1:])
2139  					res.Index = 0
2140  					res.Indexes = nil
2141  					return res
2142  				}
2143  				return Parse(rjson)
2144  			}
2145  		}
2146  		if path[0] == '[' || path[0] == '{' {
2147  			// using a subselector path
2148  			kind := path[0]
2149  			var ok bool
2150  			var subs []subSelector
2151  			subs, path, ok = parseSubSelectors(path)
2152  			if ok {
2153  				if len(path) == 0 || (path[0] == '|' || path[0] == '.') {
2154  					var b []byte
2155  					b = append(b, kind)
2156  					var i int
2157  					for _, sub := range subs {
2158  						res := Get(json, sub.path)
2159  						if res.Exists() {
2160  							if i > 0 {
2161  								b = append(b, ',')
2162  							}
2163  							if kind == '{' {
2164  								if len(sub.name) > 0 {
2165  									if sub.name[0] == '"' && Valid(sub.name) {
2166  										b = append(b, sub.name...)
2167  									} else {
2168  										b = AppendJSONString(b, sub.name)
2169  									}
2170  								} else {
2171  									last := nameOfLast(sub.path)
2172  									if isSimpleName(last) {
2173  										b = AppendJSONString(b, last)
2174  									} else {
2175  										b = AppendJSONString(b, "_")
2176  									}
2177  								}
2178  								b = append(b, ':')
2179  							}
2180  							var raw string
2181  							if len(res.Raw) == 0 {
2182  								raw = res.String()
2183  								if len(raw) == 0 {
2184  									raw = "null"
2185  								}
2186  							} else {
2187  								raw = res.Raw
2188  							}
2189  							b = append(b, raw...)
2190  							i++
2191  						}
2192  					}
2193  					b = append(b, kind+2)
2194  					var res Result
2195  					res.Raw = string(b)
2196  					res.Type = JSON
2197  					if len(path) > 0 {
2198  						res = res.Get(path[1:])
2199  					}
2200  					res.Index = 0
2201  					return res
2202  				}
2203  			}
2204  		}
2205  	}
2206  	var i int
2207  	var c = &parseContext{json: json}
2208  	if len(path) >= 2 && path[0] == '.' && path[1] == '.' {
2209  		c.lines = true
2210  		parseArray(c, 0, path[2:])
2211  	} else {
2212  		for ; i < len(c.json); i++ {
2213  			if c.json[i] == '{' {
2214  				i++
2215  				parseObject(c, i, path)
2216  				break
2217  			}
2218  			if c.json[i] == '[' {
2219  				i++
2220  				parseArray(c, i, path)
2221  				break
2222  			}
2223  		}
2224  	}
2225  	if c.piped {
2226  		res := c.value.Get(c.pipe)
2227  		res.Index = 0
2228  		return res
2229  	}
2230  	fillIndex(json, c)
2231  	return c.value
2232  }
2233  
2234  // GetBytes searches json for the specified path.
2235  // If working with bytes, this method preferred over Get(string(data), path)
2236  func GetBytes(json []byte, path string) Result {
2237  	return getBytes(json, path)
2238  }
2239  
2240  // runeit returns the rune from the the \uXXXX
2241  func runeit(json string) rune {
2242  	n, _ := strconv.ParseUint(json[:4], 16, 64)
2243  	return rune(n)
2244  }
2245  
2246  // unescape unescapes a string
2247  func unescape(json string) string {
2248  	var str = make([]byte, 0, len(json))
2249  	for i := 0; i < len(json); i++ {
2250  		switch {
2251  		default:
2252  			str = append(str, json[i])
2253  		case json[i] < ' ':
2254  			return string(str)
2255  		case json[i] == '\\':
2256  			i++
2257  			if i >= len(json) {
2258  				return string(str)
2259  			}
2260  			switch json[i] {
2261  			default:
2262  				return string(str)
2263  			case '\\':
2264  				str = append(str, '\\')
2265  			case '/':
2266  				str = append(str, '/')
2267  			case 'b':
2268  				str = append(str, '\b')
2269  			case 'f':
2270  				str = append(str, '\f')
2271  			case 'n':
2272  				str = append(str, '\n')
2273  			case 'r':
2274  				str = append(str, '\r')
2275  			case 't':
2276  				str = append(str, '\t')
2277  			case '"':
2278  				str = append(str, '"')
2279  			case 'u':
2280  				if i+5 > len(json) {
2281  					return string(str)
2282  				}
2283  				r := runeit(json[i+1:])
2284  				i += 5
2285  				if utf16.IsSurrogate(r) {
2286  					// need another code
2287  					if len(json[i:]) >= 6 && json[i] == '\\' &&
2288  						json[i+1] == 'u' {
2289  						// we expect it to be correct so just consume it
2290  						r = utf16.DecodeRune(r, runeit(json[i+2:]))
2291  						i += 6
2292  					}
2293  				}
2294  				// provide enough space to encode the largest utf8 possible
2295  				str = append(str, 0, 0, 0, 0, 0, 0, 0, 0)
2296  				n := utf8.EncodeRune(str[len(str)-8:], r)
2297  				str = str[:len(str)-8+n]
2298  				i-- // backtrack index by one
2299  			}
2300  		}
2301  	}
2302  	return string(str)
2303  }
2304  
2305  // Less return true if a token is less than another token.
2306  // The caseSensitive parameter is used when the tokens are Strings.
2307  // The order when comparing two different type is:
2308  //
2309  //	Null < False < Number < String < True < JSON
2310  func (t Result) Less(token Result, caseSensitive bool) bool {
2311  	if t.Type < token.Type {
2312  		return true
2313  	}
2314  	if t.Type > token.Type {
2315  		return false
2316  	}
2317  	if t.Type == String {
2318  		if caseSensitive {
2319  			return t.Str < token.Str
2320  		}
2321  		return stringLessInsensitive(t.Str, token.Str)
2322  	}
2323  	if t.Type == Number {
2324  		return t.Num < token.Num
2325  	}
2326  	return t.Raw < token.Raw
2327  }
2328  
2329  func stringLessInsensitive(a, b string) bool {
2330  	for i := 0; i < len(a) && i < len(b); i++ {
2331  		if a[i] >= 'A' && a[i] <= 'Z' {
2332  			if b[i] >= 'A' && b[i] <= 'Z' {
2333  				// both are uppercase, do nothing
2334  				if a[i] < b[i] {
2335  					return true
2336  				} else if a[i] > b[i] {
2337  					return false
2338  				}
2339  			} else {
2340  				// a is uppercase, convert a to lowercase
2341  				if a[i]+32 < b[i] {
2342  					return true
2343  				} else if a[i]+32 > b[i] {
2344  					return false
2345  				}
2346  			}
2347  		} else if b[i] >= 'A' && b[i] <= 'Z' {
2348  			// b is uppercase, convert b to lowercase
2349  			if a[i] < b[i]+32 {
2350  				return true
2351  			} else if a[i] > b[i]+32 {
2352  				return false
2353  			}
2354  		} else {
2355  			// neither are uppercase
2356  			if a[i] < b[i] {
2357  				return true
2358  			} else if a[i] > b[i] {
2359  				return false
2360  			}
2361  		}
2362  	}
2363  	return len(a) < len(b)
2364  }
2365  
2366  // parseAny parses the next value from a json string.
2367  // A Result is returned when the hit param is set.
2368  // The return values are (i int, res Result, ok bool)
2369  func parseAny(json string, i int, hit bool) (int, Result, bool) {
2370  	var res Result
2371  	var val string
2372  	for ; i < len(json); i++ {
2373  		if json[i] == '{' || json[i] == '[' {
2374  			i, val = parseSquash(json, i)
2375  			if hit {
2376  				res.Raw = val
2377  				res.Type = JSON
2378  			}
2379  			var tmp parseContext
2380  			tmp.value = res
2381  			fillIndex(json, &tmp)
2382  			return i, tmp.value, true
2383  		}
2384  		if json[i] <= ' ' {
2385  			continue
2386  		}
2387  		var num bool
2388  		switch json[i] {
2389  		case '"':
2390  			i++
2391  			var vesc bool
2392  			var ok bool
2393  			i, val, vesc, ok = parseString(json, i)
2394  			if !ok {
2395  				return i, res, false
2396  			}
2397  			if hit {
2398  				res.Type = String
2399  				res.Raw = val
2400  				if vesc {
2401  					res.Str = unescape(val[1 : len(val)-1])
2402  				} else {
2403  					res.Str = val[1 : len(val)-1]
2404  				}
2405  			}
2406  			return i, res, true
2407  		case 'n':
2408  			if i+1 < len(json) && json[i+1] != 'u' {
2409  				num = true
2410  				break
2411  			}
2412  			fallthrough
2413  		case 't', 'f':
2414  			vc := json[i]
2415  			i, val = parseLiteral(json, i)
2416  			if hit {
2417  				res.Raw = val
2418  				switch vc {
2419  				case 't':
2420  					res.Type = True
2421  				case 'f':
2422  					res.Type = False
2423  				}
2424  				return i, res, true
2425  			}
2426  		case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2427  			'i', 'I', 'N':
2428  			num = true
2429  		}
2430  		if num {
2431  			i, val = parseNumber(json, i)
2432  			if hit {
2433  				res.Raw = val
2434  				res.Type = Number
2435  				res.Num, _ = strconv.ParseFloat(val, 64)
2436  			}
2437  			return i, res, true
2438  		}
2439  
2440  	}
2441  	return i, res, false
2442  }
2443  
2444  // GetMany searches json for the multiple paths.
2445  // The return value is a Result array where the number of items
2446  // will be equal to the number of input paths.
2447  func GetMany(json string, path ...string) []Result {
2448  	res := make([]Result, len(path))
2449  	for i, path := range path {
2450  		res[i] = Get(json, path)
2451  	}
2452  	return res
2453  }
2454  
2455  // GetManyBytes searches json for the multiple paths.
2456  // The return value is a Result array where the number of items
2457  // will be equal to the number of input paths.
2458  func GetManyBytes(json []byte, path ...string) []Result {
2459  	res := make([]Result, len(path))
2460  	for i, path := range path {
2461  		res[i] = GetBytes(json, path)
2462  	}
2463  	return res
2464  }
2465  
2466  func validpayload(data []byte, i int) (outi int, ok bool) {
2467  	for ; i < len(data); i++ {
2468  		switch data[i] {
2469  		default:
2470  			i, ok = validany(data, i)
2471  			if !ok {
2472  				return i, false
2473  			}
2474  			for ; i < len(data); i++ {
2475  				switch data[i] {
2476  				default:
2477  					return i, false
2478  				case ' ', '\t', '\n', '\r':
2479  					continue
2480  				}
2481  			}
2482  			return i, true
2483  		case ' ', '\t', '\n', '\r':
2484  			continue
2485  		}
2486  	}
2487  	return i, false
2488  }
2489  func validany(data []byte, i int) (outi int, ok bool) {
2490  	for ; i < len(data); i++ {
2491  		switch data[i] {
2492  		default:
2493  			return i, false
2494  		case ' ', '\t', '\n', '\r':
2495  			continue
2496  		case '{':
2497  			return validobject(data, i+1)
2498  		case '[':
2499  			return validarray(data, i+1)
2500  		case '"':
2501  			return validstring(data, i+1)
2502  		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
2503  			return validnumber(data, i+1)
2504  		case 't':
2505  			return validtrue(data, i+1)
2506  		case 'f':
2507  			return validfalse(data, i+1)
2508  		case 'n':
2509  			return validnull(data, i+1)
2510  		}
2511  	}
2512  	return i, false
2513  }
2514  func validobject(data []byte, i int) (outi int, ok bool) {
2515  	for ; i < len(data); i++ {
2516  		switch data[i] {
2517  		default:
2518  			return i, false
2519  		case ' ', '\t', '\n', '\r':
2520  			continue
2521  		case '}':
2522  			return i + 1, true
2523  		case '"':
2524  		key:
2525  			if i, ok = validstring(data, i+1); !ok {
2526  				return i, false
2527  			}
2528  			if i, ok = validcolon(data, i); !ok {
2529  				return i, false
2530  			}
2531  			if i, ok = validany(data, i); !ok {
2532  				return i, false
2533  			}
2534  			if i, ok = validcomma(data, i, '}'); !ok {
2535  				return i, false
2536  			}
2537  			if data[i] == '}' {
2538  				return i + 1, true
2539  			}
2540  			i++
2541  			for ; i < len(data); i++ {
2542  				switch data[i] {
2543  				default:
2544  					return i, false
2545  				case ' ', '\t', '\n', '\r':
2546  					continue
2547  				case '"':
2548  					goto key
2549  				}
2550  			}
2551  			return i, false
2552  		}
2553  	}
2554  	return i, false
2555  }
2556  func validcolon(data []byte, i int) (outi int, ok bool) {
2557  	for ; i < len(data); i++ {
2558  		switch data[i] {
2559  		default:
2560  			return i, false
2561  		case ' ', '\t', '\n', '\r':
2562  			continue
2563  		case ':':
2564  			return i + 1, true
2565  		}
2566  	}
2567  	return i, false
2568  }
2569  func validcomma(data []byte, i int, end byte) (outi int, ok bool) {
2570  	for ; i < len(data); i++ {
2571  		switch data[i] {
2572  		default:
2573  			return i, false
2574  		case ' ', '\t', '\n', '\r':
2575  			continue
2576  		case ',':
2577  			return i, true
2578  		case end:
2579  			return i, true
2580  		}
2581  	}
2582  	return i, false
2583  }
2584  func validarray(data []byte, i int) (outi int, ok bool) {
2585  	for ; i < len(data); i++ {
2586  		switch data[i] {
2587  		default:
2588  			for ; i < len(data); i++ {
2589  				if i, ok = validany(data, i); !ok {
2590  					return i, false
2591  				}
2592  				if i, ok = validcomma(data, i, ']'); !ok {
2593  					return i, false
2594  				}
2595  				if data[i] == ']' {
2596  					return i + 1, true
2597  				}
2598  			}
2599  		case ' ', '\t', '\n', '\r':
2600  			continue
2601  		case ']':
2602  			return i + 1, true
2603  		}
2604  	}
2605  	return i, false
2606  }
2607  func validstring(data []byte, i int) (outi int, ok bool) {
2608  	for ; i < len(data); i++ {
2609  		if data[i] < ' ' {
2610  			return i, false
2611  		} else if data[i] == '\\' {
2612  			i++
2613  			if i == len(data) {
2614  				return i, false
2615  			}
2616  			switch data[i] {
2617  			default:
2618  				return i, false
2619  			case '"', '\\', '/', 'b', 'f', 'n', 'r', 't':
2620  			case 'u':
2621  				for j := 0; j < 4; j++ {
2622  					i++
2623  					if i >= len(data) {
2624  						return i, false
2625  					}
2626  					if !((data[i] >= '0' && data[i] <= '9') ||
2627  						(data[i] >= 'a' && data[i] <= 'f') ||
2628  						(data[i] >= 'A' && data[i] <= 'F')) {
2629  						return i, false
2630  					}
2631  				}
2632  			}
2633  		} else if data[i] == '"' {
2634  			return i + 1, true
2635  		}
2636  	}
2637  	return i, false
2638  }
2639  func validnumber(data []byte, i int) (outi int, ok bool) {
2640  	i--
2641  	// sign
2642  	if data[i] == '-' {
2643  		i++
2644  		if i == len(data) {
2645  			return i, false
2646  		}
2647  		if data[i] < '0' || data[i] > '9' {
2648  			return i, false
2649  		}
2650  	}
2651  	// int
2652  	if i == len(data) {
2653  		return i, false
2654  	}
2655  	if data[i] == '0' {
2656  		i++
2657  	} else {
2658  		for ; i < len(data); i++ {
2659  			if data[i] >= '0' && data[i] <= '9' {
2660  				continue
2661  			}
2662  			break
2663  		}
2664  	}
2665  	// frac
2666  	if i == len(data) {
2667  		return i, true
2668  	}
2669  	if data[i] == '.' {
2670  		i++
2671  		if i == len(data) {
2672  			return i, false
2673  		}
2674  		if data[i] < '0' || data[i] > '9' {
2675  			return i, false
2676  		}
2677  		i++
2678  		for ; i < len(data); i++ {
2679  			if data[i] >= '0' && data[i] <= '9' {
2680  				continue
2681  			}
2682  			break
2683  		}
2684  	}
2685  	// exp
2686  	if i == len(data) {
2687  		return i, true
2688  	}
2689  	if data[i] == 'e' || data[i] == 'E' {
2690  		i++
2691  		if i == len(data) {
2692  			return i, false
2693  		}
2694  		if data[i] == '+' || data[i] == '-' {
2695  			i++
2696  		}
2697  		if i == len(data) {
2698  			return i, false
2699  		}
2700  		if data[i] < '0' || data[i] > '9' {
2701  			return i, false
2702  		}
2703  		i++
2704  		for ; i < len(data); i++ {
2705  			if data[i] >= '0' && data[i] <= '9' {
2706  				continue
2707  			}
2708  			break
2709  		}
2710  	}
2711  	return i, true
2712  }
2713  
2714  func validtrue(data []byte, i int) (outi int, ok bool) {
2715  	if i+3 <= len(data) && data[i] == 'r' && data[i+1] == 'u' &&
2716  		data[i+2] == 'e' {
2717  		return i + 3, true
2718  	}
2719  	return i, false
2720  }
2721  func validfalse(data []byte, i int) (outi int, ok bool) {
2722  	if i+4 <= len(data) && data[i] == 'a' && data[i+1] == 'l' &&
2723  		data[i+2] == 's' && data[i+3] == 'e' {
2724  		return i + 4, true
2725  	}
2726  	return i, false
2727  }
2728  func validnull(data []byte, i int) (outi int, ok bool) {
2729  	if i+3 <= len(data) && data[i] == 'u' && data[i+1] == 'l' &&
2730  		data[i+2] == 'l' {
2731  		return i + 3, true
2732  	}
2733  	return i, false
2734  }
2735  
2736  // Valid returns true if the input is valid json.
2737  //
2738  //	if !gjson.Valid(json) {
2739  //		return errors.New("invalid json")
2740  //	}
2741  //	value := gjson.Get(json, "name.last")
2742  func Valid(json string) bool {
2743  	_, ok := validpayload(stringBytes(json), 0)
2744  	return ok
2745  }
2746  
2747  // ValidBytes returns true if the input is valid json.
2748  //
2749  //	if !gjson.Valid(json) {
2750  //		return errors.New("invalid json")
2751  //	}
2752  //	value := gjson.Get(json, "name.last")
2753  //
2754  // If working with bytes, this method preferred over ValidBytes(string(data))
2755  func ValidBytes(json []byte) bool {
2756  	_, ok := validpayload(json, 0)
2757  	return ok
2758  }
2759  
2760  func parseUint(s string) (n uint64, ok bool) {
2761  	var i int
2762  	if i == len(s) {
2763  		return 0, false
2764  	}
2765  	for ; i < len(s); i++ {
2766  		if s[i] >= '0' && s[i] <= '9' {
2767  			n = n*10 + uint64(s[i]-'0')
2768  		} else {
2769  			return 0, false
2770  		}
2771  	}
2772  	return n, true
2773  }
2774  
2775  func parseInt(s string) (n int64, ok bool) {
2776  	var i int
2777  	var sign bool
2778  	if len(s) > 0 && s[0] == '-' {
2779  		sign = true
2780  		i++
2781  	}
2782  	if i == len(s) {
2783  		return 0, false
2784  	}
2785  	for ; i < len(s); i++ {
2786  		if s[i] >= '0' && s[i] <= '9' {
2787  			n = n*10 + int64(s[i]-'0')
2788  		} else {
2789  			return 0, false
2790  		}
2791  	}
2792  	if sign {
2793  		return n * -1, true
2794  	}
2795  	return n, true
2796  }
2797  
2798  // safeInt validates a given JSON number
2799  // ensures it lies within the minimum and maximum representable JSON numbers
2800  func safeInt(f float64) (n int64, ok bool) {
2801  	// https://tc39.es/ecma262/#sec-number.min_safe_integer
2802  	// https://tc39.es/ecma262/#sec-number.max_safe_integer
2803  	if f < -9007199254740991 || f > 9007199254740991 {
2804  		return 0, false
2805  	}
2806  	return int64(f), true
2807  }
2808  
2809  // execStatic parses the path to find a static value.
2810  // The input expects that the path already starts with a '!'
2811  func execStatic(json, path string) (pathOut, res string, ok bool) {
2812  	name := path[1:]
2813  	if len(name) > 0 {
2814  		switch name[0] {
2815  		case '{', '[', '"', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7',
2816  			'8', '9':
2817  			_, res = parseSquash(name, 0)
2818  			pathOut = name[len(res):]
2819  			return pathOut, res, true
2820  		}
2821  	}
2822  	for i := 1; i < len(path); i++ {
2823  		if path[i] == '|' {
2824  			pathOut = path[i:]
2825  			name = path[1:i]
2826  			break
2827  		}
2828  		if path[i] == '.' {
2829  			pathOut = path[i:]
2830  			name = path[1:i]
2831  			break
2832  		}
2833  	}
2834  	switch strings.ToLower(name) {
2835  	case "true", "false", "null", "nan", "inf":
2836  		return pathOut, name, true
2837  	}
2838  	return pathOut, res, false
2839  }
2840  
2841  // execModifier parses the path to find a matching modifier function.
2842  // The input expects that the path already starts with a '@'
2843  func execModifier(json, path string) (pathOut, res string, ok bool) {
2844  	name := path[1:]
2845  	var hasArgs bool
2846  	for i := 1; i < len(path); i++ {
2847  		if path[i] == ':' {
2848  			pathOut = path[i+1:]
2849  			name = path[1:i]
2850  			hasArgs = len(pathOut) > 0
2851  			break
2852  		}
2853  		if path[i] == '|' {
2854  			pathOut = path[i:]
2855  			name = path[1:i]
2856  			break
2857  		}
2858  		if path[i] == '.' {
2859  			pathOut = path[i:]
2860  			name = path[1:i]
2861  			break
2862  		}
2863  	}
2864  	if fn, ok := modifiers[name]; ok {
2865  		var args string
2866  		if hasArgs {
2867  			var parsedArgs bool
2868  			switch pathOut[0] {
2869  			case '{', '[', '"':
2870  				// json arg
2871  				res := Parse(pathOut)
2872  				if res.Exists() {
2873  					args = squash(pathOut)
2874  					pathOut = pathOut[len(args):]
2875  					parsedArgs = true
2876  				}
2877  			}
2878  			if !parsedArgs {
2879  				// simple arg
2880  				i := 0
2881  				for ; i < len(pathOut); i++ {
2882  					if pathOut[i] == '|' {
2883  						break
2884  					}
2885  					switch pathOut[i] {
2886  					case '{', '[', '"', '(':
2887  						s := squash(pathOut[i:])
2888  						i += len(s) - 1
2889  					}
2890  				}
2891  				args = pathOut[:i]
2892  				pathOut = pathOut[i:]
2893  			}
2894  		}
2895  		return pathOut, fn(json, args), true
2896  	}
2897  	return pathOut, res, false
2898  }
2899  
2900  // unwrap removes the '[]' or '{}' characters around json
2901  func unwrap(json string) string {
2902  	json = trim(json)
2903  	if len(json) >= 2 && (json[0] == '[' || json[0] == '{') {
2904  		json = json[1 : len(json)-1]
2905  	}
2906  	return json
2907  }
2908  
2909  // DisableModifiers will disable the modifier syntax
2910  var DisableModifiers = false
2911  
2912  var modifiers map[string]func(json, arg string) string
2913  
2914  func init() {
2915  	modifiers = map[string]func(json, arg string) string{
2916  		"pretty":  modPretty,
2917  		"ugly":    modUgly,
2918  		"reverse": modReverse,
2919  		"this":    modThis,
2920  		"flatten": modFlatten,
2921  		"join":    modJoin,
2922  		"valid":   modValid,
2923  		"keys":    modKeys,
2924  		"values":  modValues,
2925  		"tostr":   modToStr,
2926  		"fromstr": modFromStr,
2927  		"group":   modGroup,
2928  		"dig":     modDig,
2929  	}
2930  }
2931  
2932  // AddModifier binds a custom modifier command to the GJSON syntax.
2933  // This operation is not thread safe and should be executed prior to
2934  // using all other gjson function.
2935  func AddModifier(name string, fn func(json, arg string) string) {
2936  	modifiers[name] = fn
2937  }
2938  
2939  // ModifierExists returns true when the specified modifier exists.
2940  func ModifierExists(name string, fn func(json, arg string) string) bool {
2941  	_, ok := modifiers[name]
2942  	return ok
2943  }
2944  
2945  // cleanWS remove any non-whitespace from string
2946  func cleanWS(s string) string {
2947  	for i := 0; i < len(s); i++ {
2948  		switch s[i] {
2949  		case ' ', '\t', '\n', '\r':
2950  			continue
2951  		default:
2952  			var s2 []byte
2953  			for i := 0; i < len(s); i++ {
2954  				switch s[i] {
2955  				case ' ', '\t', '\n', '\r':
2956  					s2 = append(s2, s[i])
2957  				}
2958  			}
2959  			return string(s2)
2960  		}
2961  	}
2962  	return s
2963  }
2964  
2965  // @pretty modifier makes the json look nice.
2966  func modPretty(json, arg string) string {
2967  	if len(arg) > 0 {
2968  		opts := *pretty.DefaultOptions
2969  		Parse(arg).ForEach(func(key, value Result) bool {
2970  			switch key.String() {
2971  			case "sortKeys":
2972  				opts.SortKeys = value.Bool()
2973  			case "indent":
2974  				opts.Indent = cleanWS(value.String())
2975  			case "prefix":
2976  				opts.Prefix = cleanWS(value.String())
2977  			case "width":
2978  				opts.Width = int(value.Int())
2979  			}
2980  			return true
2981  		})
2982  		return bytesString(pretty.PrettyOptions(stringBytes(json), &opts))
2983  	}
2984  	return bytesString(pretty.Pretty(stringBytes(json)))
2985  }
2986  
2987  // @this returns the current element. Can be used to retrieve the root element.
2988  func modThis(json, arg string) string {
2989  	return json
2990  }
2991  
2992  // @ugly modifier removes all whitespace.
2993  func modUgly(json, arg string) string {
2994  	return bytesString(pretty.Ugly(stringBytes(json)))
2995  }
2996  
2997  // @reverse reverses array elements or root object members.
2998  func modReverse(json, arg string) string {
2999  	res := Parse(json)
3000  	if res.IsArray() {
3001  		var values []Result
3002  		res.ForEach(func(_, value Result) bool {
3003  			values = append(values, value)
3004  			return true
3005  		})
3006  		out := make([]byte, 0, len(json))
3007  		out = append(out, '[')
3008  		for i, j := len(values)-1, 0; i >= 0; i, j = i-1, j+1 {
3009  			if j > 0 {
3010  				out = append(out, ',')
3011  			}
3012  			out = append(out, values[i].Raw...)
3013  		}
3014  		out = append(out, ']')
3015  		return bytesString(out)
3016  	}
3017  	if res.IsObject() {
3018  		var keyValues []Result
3019  		res.ForEach(func(key, value Result) bool {
3020  			keyValues = append(keyValues, key, value)
3021  			return true
3022  		})
3023  		out := make([]byte, 0, len(json))
3024  		out = append(out, '{')
3025  		for i, j := len(keyValues)-2, 0; i >= 0; i, j = i-2, j+1 {
3026  			if j > 0 {
3027  				out = append(out, ',')
3028  			}
3029  			out = append(out, keyValues[i+0].Raw...)
3030  			out = append(out, ':')
3031  			out = append(out, keyValues[i+1].Raw...)
3032  		}
3033  		out = append(out, '}')
3034  		return bytesString(out)
3035  	}
3036  	return json
3037  }
3038  
3039  // @flatten an array with child arrays.
3040  //
3041  //	[1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,[6,7]]
3042  //
3043  // The {"deep":true} arg can be provide for deep flattening.
3044  //
3045  //	[1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,6,7]
3046  //
3047  // The original json is returned when the json is not an array.
3048  func modFlatten(json, arg string) string {
3049  	res := Parse(json)
3050  	if !res.IsArray() {
3051  		return json
3052  	}
3053  	var deep bool
3054  	if arg != "" {
3055  		Parse(arg).ForEach(func(key, value Result) bool {
3056  			if key.String() == "deep" {
3057  				deep = value.Bool()
3058  			}
3059  			return true
3060  		})
3061  	}
3062  	var out []byte
3063  	out = append(out, '[')
3064  	var idx int
3065  	res.ForEach(func(_, value Result) bool {
3066  		var raw string
3067  		if value.IsArray() {
3068  			if deep {
3069  				raw = unwrap(modFlatten(value.Raw, arg))
3070  			} else {
3071  				raw = unwrap(value.Raw)
3072  			}
3073  		} else {
3074  			raw = value.Raw
3075  		}
3076  		raw = strings.TrimSpace(raw)
3077  		if len(raw) > 0 {
3078  			if idx > 0 {
3079  				out = append(out, ',')
3080  			}
3081  			out = append(out, raw...)
3082  			idx++
3083  		}
3084  		return true
3085  	})
3086  	out = append(out, ']')
3087  	return bytesString(out)
3088  }
3089  
3090  // @keys extracts the keys from an object.
3091  //
3092  //	{"first":"Tom","last":"Smith"} -> ["first","last"]
3093  func modKeys(json, arg string) string {
3094  	v := Parse(json)
3095  	if !v.Exists() {
3096  		return "[]"
3097  	}
3098  	obj := v.IsObject()
3099  	var out strings.Builder
3100  	out.WriteByte('[')
3101  	var i int
3102  	v.ForEach(func(key, _ Result) bool {
3103  		if i > 0 {
3104  			out.WriteByte(',')
3105  		}
3106  		if obj {
3107  			out.WriteString(key.Raw)
3108  		} else {
3109  			out.WriteString("null")
3110  		}
3111  		i++
3112  		return true
3113  	})
3114  	out.WriteByte(']')
3115  	return out.String()
3116  }
3117  
3118  // @values extracts the values from an object.
3119  //
3120  //	{"first":"Tom","last":"Smith"} -> ["Tom","Smith"]
3121  func modValues(json, arg string) string {
3122  	v := Parse(json)
3123  	if !v.Exists() {
3124  		return "[]"
3125  	}
3126  	if v.IsArray() {
3127  		return json
3128  	}
3129  	var out strings.Builder
3130  	out.WriteByte('[')
3131  	var i int
3132  	v.ForEach(func(_, value Result) bool {
3133  		if i > 0 {
3134  			out.WriteByte(',')
3135  		}
3136  		out.WriteString(value.Raw)
3137  		i++
3138  		return true
3139  	})
3140  	out.WriteByte(']')
3141  	return out.String()
3142  }
3143  
3144  // @join multiple objects into a single object.
3145  //
3146  //	[{"first":"Tom"},{"last":"Smith"}] -> {"first","Tom","last":"Smith"}
3147  //
3148  // The arg can be "true" to specify that duplicate keys should be preserved.
3149  //
3150  //	[{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":37,"age":41}
3151  //
3152  // Without preserved keys:
3153  //
3154  //	[{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":41}
3155  //
3156  // The original json is returned when the json is not an object.
3157  func modJoin(json, arg string) string {
3158  	res := Parse(json)
3159  	if !res.IsArray() {
3160  		return json
3161  	}
3162  	var preserve bool
3163  	if arg != "" {
3164  		Parse(arg).ForEach(func(key, value Result) bool {
3165  			if key.String() == "preserve" {
3166  				preserve = value.Bool()
3167  			}
3168  			return true
3169  		})
3170  	}
3171  	var out []byte
3172  	out = append(out, '{')
3173  	if preserve {
3174  		// Preserve duplicate keys.
3175  		var idx int
3176  		res.ForEach(func(_, value Result) bool {
3177  			if !value.IsObject() {
3178  				return true
3179  			}
3180  			if idx > 0 {
3181  				out = append(out, ',')
3182  			}
3183  			out = append(out, unwrap(value.Raw)...)
3184  			idx++
3185  			return true
3186  		})
3187  	} else {
3188  		// Deduplicate keys and generate an object with stable ordering.
3189  		var keys []Result
3190  		kvals := make(map[string]Result)
3191  		res.ForEach(func(_, value Result) bool {
3192  			if !value.IsObject() {
3193  				return true
3194  			}
3195  			value.ForEach(func(key, value Result) bool {
3196  				k := key.String()
3197  				if _, ok := kvals[k]; !ok {
3198  					keys = append(keys, key)
3199  				}
3200  				kvals[k] = value
3201  				return true
3202  			})
3203  			return true
3204  		})
3205  		for i := 0; i < len(keys); i++ {
3206  			if i > 0 {
3207  				out = append(out, ',')
3208  			}
3209  			out = append(out, keys[i].Raw...)
3210  			out = append(out, ':')
3211  			out = append(out, kvals[keys[i].String()].Raw...)
3212  		}
3213  	}
3214  	out = append(out, '}')
3215  	return bytesString(out)
3216  }
3217  
3218  // @valid ensures that the json is valid before moving on. An empty string is
3219  // returned when the json is not valid, otherwise it returns the original json.
3220  func modValid(json, arg string) string {
3221  	if !Valid(json) {
3222  		return ""
3223  	}
3224  	return json
3225  }
3226  
3227  // @fromstr converts a string to json
3228  //
3229  //	"{\"id\":1023,\"name\":\"alert\"}" -> {"id":1023,"name":"alert"}
3230  func modFromStr(json, arg string) string {
3231  	if !Valid(json) {
3232  		return ""
3233  	}
3234  	return Parse(json).String()
3235  }
3236  
3237  // @tostr converts a string to json
3238  //
3239  //	{"id":1023,"name":"alert"} -> "{\"id\":1023,\"name\":\"alert\"}"
3240  func modToStr(str, arg string) string {
3241  	return string(AppendJSONString(nil, str))
3242  }
3243  
3244  func modGroup(json, arg string) string {
3245  	res := Parse(json)
3246  	if !res.IsObject() {
3247  		return ""
3248  	}
3249  	var all [][]byte
3250  	res.ForEach(func(key, value Result) bool {
3251  		if !value.IsArray() {
3252  			return true
3253  		}
3254  		var idx int
3255  		value.ForEach(func(_, value Result) bool {
3256  			if idx == len(all) {
3257  				all = append(all, []byte{})
3258  			}
3259  			all[idx] = append(all[idx], ("," + key.Raw + ":" + value.Raw)...)
3260  			idx++
3261  			return true
3262  		})
3263  		return true
3264  	})
3265  	var data []byte
3266  	data = append(data, '[')
3267  	for i, item := range all {
3268  		if i > 0 {
3269  			data = append(data, ',')
3270  		}
3271  		data = append(data, '{')
3272  		data = append(data, item[1:]...)
3273  		data = append(data, '}')
3274  	}
3275  	data = append(data, ']')
3276  	return string(data)
3277  }
3278  
3279  // stringHeader instead of reflect.StringHeader
3280  type stringHeader struct {
3281  	data unsafe.Pointer
3282  	len  int
3283  }
3284  
3285  // sliceHeader instead of reflect.SliceHeader
3286  type sliceHeader struct {
3287  	data unsafe.Pointer
3288  	len  int
3289  	cap  int
3290  }
3291  
3292  // getBytes casts the input json bytes to a string and safely returns the
3293  // results as uniquely allocated data. This operation is intended to minimize
3294  // copies and allocations for the large json string->[]byte.
3295  func getBytes(json []byte, path string) Result {
3296  	var result Result
3297  	if json != nil {
3298  		// unsafe cast to string
3299  		result = Get(*(*string)(unsafe.Pointer(&json)), path)
3300  		// safely get the string headers
3301  		rawhi := *(*stringHeader)(unsafe.Pointer(&result.Raw))
3302  		strhi := *(*stringHeader)(unsafe.Pointer(&result.Str))
3303  		// create byte slice headers
3304  		rawh := sliceHeader{data: rawhi.data, len: rawhi.len, cap: rawhi.len}
3305  		strh := sliceHeader{data: strhi.data, len: strhi.len, cap: rawhi.len}
3306  		if strh.data == nil {
3307  			// str is nil
3308  			if rawh.data == nil {
3309  				// raw is nil
3310  				result.Raw = ""
3311  			} else {
3312  				// raw has data, safely copy the slice header to a string
3313  				result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
3314  			}
3315  			result.Str = ""
3316  		} else if rawh.data == nil {
3317  			// raw is nil
3318  			result.Raw = ""
3319  			// str has data, safely copy the slice header to a string
3320  			result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
3321  		} else if uintptr(strh.data) >= uintptr(rawh.data) &&
3322  			uintptr(strh.data)+uintptr(strh.len) <=
3323  				uintptr(rawh.data)+uintptr(rawh.len) {
3324  			// Str is a substring of Raw.
3325  			start := uintptr(strh.data) - uintptr(rawh.data)
3326  			// safely copy the raw slice header
3327  			result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
3328  			// substring the raw
3329  			result.Str = result.Raw[start : start+uintptr(strh.len)]
3330  		} else {
3331  			// safely copy both the raw and str slice headers to strings
3332  			result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
3333  			result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
3334  		}
3335  	}
3336  	return result
3337  }
3338  
3339  // fillIndex finds the position of Raw data and assigns it to the Index field
3340  // of the resulting value. If the position cannot be found then Index zero is
3341  // used instead.
3342  func fillIndex(json string, c *parseContext) {
3343  	if len(c.value.Raw) > 0 && !c.calcd {
3344  		jhdr := *(*stringHeader)(unsafe.Pointer(&json))
3345  		rhdr := *(*stringHeader)(unsafe.Pointer(&(c.value.Raw)))
3346  		c.value.Index = int(uintptr(rhdr.data) - uintptr(jhdr.data))
3347  		if c.value.Index < 0 || c.value.Index >= len(json) {
3348  			c.value.Index = 0
3349  		}
3350  	}
3351  }
3352  
3353  func stringBytes(s string) []byte {
3354  	return *(*[]byte)(unsafe.Pointer(&sliceHeader{
3355  		data: (*stringHeader)(unsafe.Pointer(&s)).data,
3356  		len:  len(s),
3357  		cap:  len(s),
3358  	}))
3359  }
3360  
3361  func bytesString(b []byte) string {
3362  	return *(*string)(unsafe.Pointer(&b))
3363  }
3364  
3365  func revSquash(json string) string {
3366  	// reverse squash
3367  	// expects that the tail character is a ']' or '}' or ')' or '"'
3368  	// squash the value, ignoring all nested arrays and objects.
3369  	i := len(json) - 1
3370  	var depth int
3371  	if json[i] != '"' {
3372  		depth++
3373  	}
3374  	if json[i] == '}' || json[i] == ']' || json[i] == ')' {
3375  		i--
3376  	}
3377  	for ; i >= 0; i-- {
3378  		switch json[i] {
3379  		case '"':
3380  			i--
3381  			for ; i >= 0; i-- {
3382  				if json[i] == '"' {
3383  					esc := 0
3384  					for i > 0 && json[i-1] == '\\' {
3385  						i--
3386  						esc++
3387  					}
3388  					if esc%2 == 1 {
3389  						continue
3390  					}
3391  					i += esc
3392  					break
3393  				}
3394  			}
3395  			if depth == 0 {
3396  				if i < 0 {
3397  					i = 0
3398  				}
3399  				return json[i:]
3400  			}
3401  		case '}', ']', ')':
3402  			depth++
3403  		case '{', '[', '(':
3404  			depth--
3405  			if depth == 0 {
3406  				return json[i:]
3407  			}
3408  		}
3409  	}
3410  	return json
3411  }
3412  
3413  // Paths returns the original GJSON paths for a Result where the Result came
3414  // from a simple query path that returns an array, like:
3415  //
3416  //	gjson.Get(json, "friends.#.first")
3417  //
3418  // The returned value will be in the form of a JSON array:
3419  //
3420  //	["friends.0.first","friends.1.first","friends.2.first"]
3421  //
3422  // The param 'json' must be the original JSON used when calling Get.
3423  //
3424  // Returns an empty string if the paths cannot be determined, which can happen
3425  // when the Result came from a path that contained a multipath, modifier,
3426  // or a nested query.
3427  func (t Result) Paths(json string) []string {
3428  	if t.Indexes == nil {
3429  		return nil
3430  	}
3431  	paths := make([]string, 0, len(t.Indexes))
3432  	t.ForEach(func(_, value Result) bool {
3433  		paths = append(paths, value.Path(json))
3434  		return true
3435  	})
3436  	if len(paths) != len(t.Indexes) {
3437  		return nil
3438  	}
3439  	return paths
3440  }
3441  
3442  // Path returns the original GJSON path for a Result where the Result came
3443  // from a simple path that returns a single value, like:
3444  //
3445  //	gjson.Get(json, "friends.#(last=Murphy)")
3446  //
3447  // The returned value will be in the form of a JSON string:
3448  //
3449  //	"friends.0"
3450  //
3451  // The param 'json' must be the original JSON used when calling Get.
3452  //
3453  // Returns an empty string if the paths cannot be determined, which can happen
3454  // when the Result came from a path that contained a multipath, modifier,
3455  // or a nested query.
3456  func (t Result) Path(json string) string {
3457  	var path []byte
3458  	var comps []string // raw components
3459  	i := t.Index - 1
3460  	if t.Index+len(t.Raw) > len(json) {
3461  		// JSON cannot safely contain Result.
3462  		goto fail
3463  	}
3464  	if !strings.HasPrefix(json[t.Index:], t.Raw) {
3465  		// Result is not at the JSON index as expected.
3466  		goto fail
3467  	}
3468  	for ; i >= 0; i-- {
3469  		if json[i] <= ' ' {
3470  			continue
3471  		}
3472  		if json[i] == ':' {
3473  			// inside of object, get the key
3474  			for ; i >= 0; i-- {
3475  				if json[i] != '"' {
3476  					continue
3477  				}
3478  				break
3479  			}
3480  			raw := revSquash(json[:i+1])
3481  			i = i - len(raw)
3482  			comps = append(comps, raw)
3483  			// key gotten, now squash the rest
3484  			raw = revSquash(json[:i+1])
3485  			i = i - len(raw)
3486  			i++ // increment the index for next loop step
3487  		} else if json[i] == '{' {
3488  			// Encountered an open object. The original result was probably an
3489  			// object key.
3490  			goto fail
3491  		} else if json[i] == ',' || json[i] == '[' {
3492  			// inside of an array, count the position
3493  			var arrIdx int
3494  			if json[i] == ',' {
3495  				arrIdx++
3496  				i--
3497  			}
3498  			for ; i >= 0; i-- {
3499  				if json[i] == ':' {
3500  					// Encountered an unexpected colon. The original result was
3501  					// probably an object key.
3502  					goto fail
3503  				} else if json[i] == ',' {
3504  					arrIdx++
3505  				} else if json[i] == '[' {
3506  					comps = append(comps, strconv.Itoa(arrIdx))
3507  					break
3508  				} else if json[i] == ']' || json[i] == '}' || json[i] == '"' {
3509  					raw := revSquash(json[:i+1])
3510  					i = i - len(raw) + 1
3511  				}
3512  			}
3513  		}
3514  	}
3515  	if len(comps) == 0 {
3516  		if DisableModifiers {
3517  			goto fail
3518  		}
3519  		return "@this"
3520  	}
3521  	for i := len(comps) - 1; i >= 0; i-- {
3522  		rcomp := Parse(comps[i])
3523  		if !rcomp.Exists() {
3524  			goto fail
3525  		}
3526  		comp := Escape(rcomp.String())
3527  		path = append(path, '.')
3528  		path = append(path, comp...)
3529  	}
3530  	if len(path) > 0 {
3531  		path = path[1:]
3532  	}
3533  	return string(path)
3534  fail:
3535  	return ""
3536  }
3537  
3538  // isSafePathKeyChar returns true if the input character is safe for not
3539  // needing escaping.
3540  func isSafePathKeyChar(c byte) bool {
3541  	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
3542  		(c >= '0' && c <= '9') || c <= ' ' || c > '~' || c == '_' ||
3543  		c == '-' || c == ':'
3544  }
3545  
3546  // Escape returns an escaped path component.
3547  //
3548  //	json := `{
3549  //	  "user":{
3550  //	     "first.name": "Janet",
3551  //	     "last.name": "Prichard"
3552  //	   }
3553  //	}`
3554  //	user := gjson.Get(json, "user")
3555  //	println(user.Get(gjson.Escape("first.name"))
3556  //	println(user.Get(gjson.Escape("last.name"))
3557  //	// Output:
3558  //	// Janet
3559  //	// Prichard
3560  func Escape(comp string) string {
3561  	for i := 0; i < len(comp); i++ {
3562  		if !isSafePathKeyChar(comp[i]) {
3563  			ncomp := make([]byte, len(comp)+1)
3564  			copy(ncomp, comp[:i])
3565  			ncomp = ncomp[:i]
3566  			for ; i < len(comp); i++ {
3567  				if !isSafePathKeyChar(comp[i]) {
3568  					ncomp = append(ncomp, '\\')
3569  				}
3570  				ncomp = append(ncomp, comp[i])
3571  			}
3572  			return string(ncomp)
3573  		}
3574  	}
3575  	return comp
3576  }
3577  
3578  func parseRecursiveDescent(all []Result, parent Result, path string) []Result {
3579  	if res := parent.Get(path); res.Exists() {
3580  		all = append(all, res)
3581  	}
3582  	if parent.IsArray() || parent.IsObject() {
3583  		parent.ForEach(func(_, val Result) bool {
3584  			all = parseRecursiveDescent(all, val, path)
3585  			return true
3586  		})
3587  	}
3588  	return all
3589  }
3590  
3591  func modDig(json, arg string) string {
3592  	all := parseRecursiveDescent(nil, Parse(json), arg)
3593  	var out []byte
3594  	out = append(out, '[')
3595  	for i, res := range all {
3596  		if i > 0 {
3597  			out = append(out, ',')
3598  		}
3599  		out = append(out, res.Raw...)
3600  	}
3601  	out = append(out, ']')
3602  	return string(out)
3603  }
3604