MCPcopy Create free account
hub / github.com/couchbase/sync_gateway / evalKeyPath

Function evalKeyPath

db/functions/function.go:356–416  ·  view source on GitHub ↗

Evaluates a "key path", like "points[3].x.y" on a JSON-based map.

(root map[string]any, keyPath string)

Source from the content-addressed store, hash-verified

354
355// Evaluates a "key path", like "points[3].x.y" on a JSON-based map.
356func evalKeyPath(root map[string]any, keyPath string) (reflect.Value, error) {
357 // Handle the first path component specially because we can access `root` without reflection:
358 var value reflect.Value
359 i := strings.IndexAny(keyPath, ".[")
360 if i < 0 {
361 i = len(keyPath)
362 }
363 key := keyPath[0:i]
364 keyPath = keyPath[i:]
365 firstVal := root[key]
366 if firstVal == nil {
367 return value, base.HTTPErrorf(http.StatusInternalServerError, "parameter %q is not declared in 'args'", key)
368 }
369
370 value = reflect.ValueOf(firstVal)
371 if len(keyPath) == 0 {
372 return value, nil
373 }
374
375 for len(keyPath) > 0 {
376 ch := keyPath[0]
377 keyPath = keyPath[1:]
378 if ch == '.' {
379 i = strings.IndexAny(keyPath, ".[")
380 if i < 0 {
381 i = len(keyPath)
382 }
383 key = keyPath[0:i]
384 keyPath = keyPath[i:]
385
386 if value.Kind() != reflect.Map {
387 return value, base.HTTPErrorf(http.StatusBadRequest, "value is not a map")
388 }
389 value = value.MapIndex(reflect.ValueOf(key))
390 } else if ch == '[' {
391 i = strings.IndexByte(keyPath, ']')
392 if i < 0 {
393 return value, base.HTTPErrorf(http.StatusInternalServerError, "missing ']")
394 }
395 key = keyPath[0:i]
396 keyPath = keyPath[i+1:]
397
398 index, err := strconv.ParseUint(key, 10, 8)
399 if err != nil {
400 return value, err
401 }
402 if value.Kind() != reflect.Array && value.Kind() != reflect.Slice {
403 return value, base.HTTPErrorf(http.StatusBadRequest, "value is a %v not an array", value.Type())
404 } else if uint64(value.Len()) <= index {
405 return value, base.HTTPErrorf(http.StatusBadRequest, "array index out of range")
406 }
407 value = value.Index(int(index))
408 } else {
409 return value, base.HTTPErrorf(http.StatusInternalServerError, "invalid character after a ']'")
410 }
411 for value.Kind() == reflect.Interface || value.Kind() == reflect.Pointer {
412 value = value.Elem()
413 }

Callers 2

expandPatternFunction · 0.85
TestKeyPathFunction · 0.85

Calls 3

HTTPErrorfFunction · 0.92
TypeMethod · 0.65
LenMethod · 0.65

Tested by 1

TestKeyPathFunction · 0.68