SYS-REQ-008, SYS-REQ-085
(data []byte, cb func(int, []byte, ValueType, error), paths ...[]string)
| 397 | |
| 398 | // SYS-REQ-008, SYS-REQ-085 |
| 399 | func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]string) int { |
| 400 | var x struct{} |
| 401 | var level, pathsMatched, i int |
| 402 | ln := len(data) |
| 403 | |
| 404 | pathFlags := make([]bool, stackArraySize)[:] |
| 405 | if len(paths) > cap(pathFlags) { |
| 406 | pathFlags = make([]bool, len(paths))[:] |
| 407 | } |
| 408 | pathFlags = pathFlags[0:len(paths)] |
| 409 | |
| 410 | var maxPath int |
| 411 | for _, p := range paths { |
| 412 | if len(p) > maxPath { |
| 413 | maxPath = len(p) |
| 414 | } |
| 415 | } |
| 416 | |
| 417 | pathsBuf := make([]string, stackArraySize)[:] |
| 418 | if maxPath > cap(pathsBuf) { |
| 419 | pathsBuf = make([]string, maxPath)[:] |
| 420 | } |
| 421 | pathsBuf = pathsBuf[0:maxPath] |
| 422 | |
| 423 | for i < ln { |
| 424 | switch data[i] { |
| 425 | case '"': |
| 426 | i++ |
| 427 | keyBegin := i |
| 428 | |
| 429 | strEnd, keyEscaped := stringEnd(data[i:]) |
| 430 | if strEnd == -1 { |
| 431 | return -1 |
| 432 | } |
| 433 | i += strEnd |
| 434 | |
| 435 | keyEnd := i - 1 |
| 436 | |
| 437 | valueOffset := nextToken(data[i:]) |
| 438 | if valueOffset == -1 { |
| 439 | return -1 |
| 440 | } |
| 441 | |
| 442 | i += valueOffset |
| 443 | |
| 444 | // if string is a key, and key level match |
| 445 | if data[i] == ':' { |
| 446 | match := -1 |
| 447 | key := data[keyBegin:keyEnd] |
| 448 | |
| 449 | // for unescape: if there are no escape sequences, this is cheap; if there are, it is a |
| 450 | // bit more expensive, but causes no allocations unless len(key) > unescapeStackBufSize |
| 451 | var keyUnesc []byte |
| 452 | if !keyEscaped { |
| 453 | keyUnesc = key |
| 454 | } else { |
| 455 | var stackbuf [unescapeStackBufSize]byte |
| 456 | if ku, err := Unescape(key, stackbuf[:]); err != nil { |
searching dependent graphs…