edit.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. package msgp
  2. import (
  3. "math"
  4. )
  5. // Locate returns a []byte pointing to the field
  6. // in a messagepack map with the provided key. (The returned []byte
  7. // points to a sub-slice of 'raw'; Locate does no allocations.) If the
  8. // key doesn't exist in the map, a zero-length []byte will be returned.
  9. func Locate(key string, raw []byte) []byte {
  10. s, n := locate(raw, key)
  11. return raw[s:n]
  12. }
  13. // Replace takes a key ("key") in a messagepack map ("raw")
  14. // and replaces its value with the one provided and returns
  15. // the new []byte. The returned []byte may point to the same
  16. // memory as "raw". Replace makes no effort to evaluate the validity
  17. // of the contents of 'val'. It may use up to the full capacity of 'raw.'
  18. // Replace returns 'nil' if the field doesn't exist or if the object in 'raw'
  19. // is not a map.
  20. func Replace(key string, raw []byte, val []byte) []byte {
  21. start, end := locate(raw, key)
  22. if start == end {
  23. return nil
  24. }
  25. return replace(raw, start, end, val, true)
  26. }
  27. // CopyReplace works similarly to Replace except that the returned
  28. // byte slice does not point to the same memory as 'raw'. CopyReplace
  29. // returns 'nil' if the field doesn't exist or 'raw' isn't a map.
  30. func CopyReplace(key string, raw []byte, val []byte) []byte {
  31. start, end := locate(raw, key)
  32. if start == end {
  33. return nil
  34. }
  35. return replace(raw, start, end, val, false)
  36. }
  37. // Remove removes a key-value pair from 'raw'. It returns
  38. // 'raw' unchanged if the key didn't exist.
  39. func Remove(key string, raw []byte) []byte {
  40. start, end := locateKV(raw, key)
  41. if start == end {
  42. return raw
  43. }
  44. raw = raw[:start+copy(raw[start:], raw[end:])]
  45. return resizeMap(raw, -1)
  46. }
  47. // HasKey returns whether the map in 'raw' has
  48. // a field with key 'key'
  49. func HasKey(key string, raw []byte) bool {
  50. sz, bts, err := ReadMapHeaderBytes(raw)
  51. if err != nil {
  52. return false
  53. }
  54. var field []byte
  55. for i := uint32(0); i < sz; i++ {
  56. field, bts, err = ReadStringZC(bts)
  57. if err != nil {
  58. return false
  59. }
  60. if UnsafeString(field) == key {
  61. return true
  62. }
  63. }
  64. return false
  65. }
  66. func replace(raw []byte, start int, end int, val []byte, inplace bool) []byte {
  67. ll := end - start // length of segment to replace
  68. lv := len(val)
  69. if inplace {
  70. extra := lv - ll
  71. // fastest case: we're doing
  72. // a 1:1 replacement
  73. if extra == 0 {
  74. copy(raw[start:], val)
  75. return raw
  76. } else if extra < 0 {
  77. // 'val' smaller than replaced value
  78. // copy in place and shift back
  79. x := copy(raw[start:], val)
  80. y := copy(raw[start+x:], raw[end:])
  81. return raw[:start+x+y]
  82. } else if extra < cap(raw)-len(raw) {
  83. // 'val' less than (cap-len) extra bytes
  84. // copy in place and shift forward
  85. raw = raw[0 : len(raw)+extra]
  86. // shift end forward
  87. copy(raw[end+extra:], raw[end:])
  88. copy(raw[start:], val)
  89. return raw
  90. }
  91. }
  92. // we have to allocate new space
  93. out := make([]byte, len(raw)+len(val)-ll)
  94. x := copy(out, raw[:start])
  95. y := copy(out[x:], val)
  96. copy(out[x+y:], raw[end:])
  97. return out
  98. }
  99. // locate does a naive O(n) search for the map key; returns start, end
  100. // (returns 0,0 on error)
  101. func locate(raw []byte, key string) (start int, end int) {
  102. var (
  103. sz uint32
  104. bts []byte
  105. field []byte
  106. err error
  107. )
  108. sz, bts, err = ReadMapHeaderBytes(raw)
  109. if err != nil {
  110. return
  111. }
  112. // loop and locate field
  113. for i := uint32(0); i < sz; i++ {
  114. field, bts, err = ReadStringZC(bts)
  115. if err != nil {
  116. return 0, 0
  117. }
  118. if UnsafeString(field) == key {
  119. // start location
  120. l := len(raw)
  121. start = l - len(bts)
  122. bts, err = Skip(bts)
  123. if err != nil {
  124. return 0, 0
  125. }
  126. end = l - len(bts)
  127. return
  128. }
  129. bts, err = Skip(bts)
  130. if err != nil {
  131. return 0, 0
  132. }
  133. }
  134. return 0, 0
  135. }
  136. // locate key AND value
  137. func locateKV(raw []byte, key string) (start int, end int) {
  138. var (
  139. sz uint32
  140. bts []byte
  141. field []byte
  142. err error
  143. )
  144. sz, bts, err = ReadMapHeaderBytes(raw)
  145. if err != nil {
  146. return 0, 0
  147. }
  148. for i := uint32(0); i < sz; i++ {
  149. tmp := len(bts)
  150. field, bts, err = ReadStringZC(bts)
  151. if err != nil {
  152. return 0, 0
  153. }
  154. if UnsafeString(field) == key {
  155. start = len(raw) - tmp
  156. bts, err = Skip(bts)
  157. if err != nil {
  158. return 0, 0
  159. }
  160. end = len(raw) - len(bts)
  161. return
  162. }
  163. bts, err = Skip(bts)
  164. if err != nil {
  165. return 0, 0
  166. }
  167. }
  168. return 0, 0
  169. }
  170. // delta is delta on map size
  171. func resizeMap(raw []byte, delta int64) []byte {
  172. var sz int64
  173. switch raw[0] {
  174. case mmap16:
  175. sz = int64(big.Uint16(raw[1:]))
  176. if sz+delta <= math.MaxUint16 {
  177. big.PutUint16(raw[1:], uint16(sz+delta))
  178. return raw
  179. }
  180. if cap(raw)-len(raw) >= 2 {
  181. raw = raw[0 : len(raw)+2]
  182. copy(raw[5:], raw[3:])
  183. raw[0] = mmap32
  184. big.PutUint32(raw[1:], uint32(sz+delta))
  185. return raw
  186. }
  187. n := make([]byte, 0, len(raw)+5)
  188. n = AppendMapHeader(n, uint32(sz+delta))
  189. return append(n, raw[3:]...)
  190. case mmap32:
  191. sz = int64(big.Uint32(raw[1:]))
  192. big.PutUint32(raw[1:], uint32(sz+delta))
  193. return raw
  194. default:
  195. sz = int64(rfixmap(raw[0]))
  196. if sz+delta < 16 {
  197. raw[0] = wfixmap(uint8(sz + delta))
  198. return raw
  199. } else if sz+delta <= math.MaxUint16 {
  200. if cap(raw)-len(raw) >= 2 {
  201. raw = raw[0 : len(raw)+2]
  202. copy(raw[3:], raw[1:])
  203. raw[0] = mmap16
  204. big.PutUint16(raw[1:], uint16(sz+delta))
  205. return raw
  206. }
  207. n := make([]byte, 0, len(raw)+5)
  208. n = AppendMapHeader(n, uint32(sz+delta))
  209. return append(n, raw[1:]...)
  210. }
  211. if cap(raw)-len(raw) >= 4 {
  212. raw = raw[0 : len(raw)+4]
  213. copy(raw[5:], raw[1:])
  214. raw[0] = mmap32
  215. big.PutUint32(raw[1:], uint32(sz+delta))
  216. return raw
  217. }
  218. n := make([]byte, 0, len(raw)+5)
  219. n = AppendMapHeader(n, uint32(sz+delta))
  220. return append(n, raw[1:]...)
  221. }
  222. }