You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
2.6 KiB

  1. package msgpack
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "github.com/vmihailenco/msgpack/codes"
  7. )
  8. type queryResult struct {
  9. query string
  10. key string
  11. hasAsterisk bool
  12. values []interface{}
  13. }
  14. func (q *queryResult) nextKey() {
  15. ind := strings.IndexByte(q.query, '.')
  16. if ind == -1 {
  17. q.key = q.query
  18. q.query = ""
  19. return
  20. }
  21. q.key = q.query[:ind]
  22. q.query = q.query[ind+1:]
  23. }
  24. // Query extracts data specified by the query from the msgpack stream skipping
  25. // any other data. Query consists of map keys and array indexes separated with dot,
  26. // e.g. key1.0.key2.
  27. func (d *Decoder) Query(query string) ([]interface{}, error) {
  28. res := queryResult{
  29. query: query,
  30. }
  31. if err := d.query(&res); err != nil {
  32. return nil, err
  33. }
  34. return res.values, nil
  35. }
  36. func (d *Decoder) query(q *queryResult) error {
  37. q.nextKey()
  38. if q.key == "" {
  39. v, err := d.DecodeInterface()
  40. if err != nil {
  41. return err
  42. }
  43. q.values = append(q.values, v)
  44. return nil
  45. }
  46. code, err := d.PeekCode()
  47. if err != nil {
  48. return err
  49. }
  50. switch {
  51. case code == codes.Map16 || code == codes.Map32 || codes.IsFixedMap(code):
  52. err = d.queryMapKey(q)
  53. case code == codes.Array16 || code == codes.Array32 || codes.IsFixedArray(code):
  54. err = d.queryArrayIndex(q)
  55. default:
  56. err = fmt.Errorf("msgpack: unsupported code=%x decoding key=%q", code, q.key)
  57. }
  58. return err
  59. }
  60. func (d *Decoder) queryMapKey(q *queryResult) error {
  61. n, err := d.DecodeMapLen()
  62. if err != nil {
  63. return err
  64. }
  65. if n == -1 {
  66. return nil
  67. }
  68. for i := 0; i < n; i++ {
  69. k, err := d.bytesNoCopy()
  70. if err != nil {
  71. return err
  72. }
  73. if string(k) == q.key {
  74. if err := d.query(q); err != nil {
  75. return err
  76. }
  77. if q.hasAsterisk {
  78. return d.skipNext((n - i - 1) * 2)
  79. }
  80. return nil
  81. }
  82. if err := d.Skip(); err != nil {
  83. return err
  84. }
  85. }
  86. return nil
  87. }
  88. func (d *Decoder) queryArrayIndex(q *queryResult) error {
  89. n, err := d.DecodeArrayLen()
  90. if err != nil {
  91. return err
  92. }
  93. if n == -1 {
  94. return nil
  95. }
  96. if q.key == "*" {
  97. q.hasAsterisk = true
  98. query := q.query
  99. for i := 0; i < n; i++ {
  100. q.query = query
  101. if err := d.query(q); err != nil {
  102. return err
  103. }
  104. }
  105. q.hasAsterisk = false
  106. return nil
  107. }
  108. ind, err := strconv.Atoi(q.key)
  109. if err != nil {
  110. return err
  111. }
  112. for i := 0; i < n; i++ {
  113. if i == ind {
  114. if err := d.query(q); err != nil {
  115. return err
  116. }
  117. if q.hasAsterisk {
  118. return d.skipNext(n - i - 1)
  119. }
  120. return nil
  121. }
  122. if err := d.Skip(); err != nil {
  123. return err
  124. }
  125. }
  126. return nil
  127. }
  128. func (d *Decoder) skipNext(n int) error {
  129. for i := 0; i < n; i++ {
  130. if err := d.Skip(); err != nil {
  131. return err
  132. }
  133. }
  134. return nil
  135. }