Seek will search for uid in a packed block using the specified whence position. The value of whence must be one of the predefined values SeekStart or SeekCurrent. SeekStart searches uid and includes it as part of the results. SeekCurrent searches uid but only as offset, it won't be included with res
(uid uint64, whence seekPos)
| 277 | // |
| 278 | // Returns a slice of all uids whence the position, or an empty slice if none found. |
| 279 | func (d *Decoder) Seek(uid uint64, whence seekPos) []uint64 { |
| 280 | if d.Pack == nil { |
| 281 | return []uint64{} |
| 282 | } |
| 283 | d.blockIdx = 0 |
| 284 | if uid == 0 { |
| 285 | return d.UnpackBlock() |
| 286 | } |
| 287 | |
| 288 | pack := d.Pack |
| 289 | blocksFunc := func() searchFunc { |
| 290 | var f searchFunc |
| 291 | switch whence { |
| 292 | case SeekStart: |
| 293 | f = func(i int) bool { return pack.Blocks[i].Base >= uid } |
| 294 | case SeekCurrent: |
| 295 | f = func(i int) bool { return pack.Blocks[i].Base > uid } |
| 296 | } |
| 297 | return f |
| 298 | } |
| 299 | |
| 300 | idx := sort.Search(len(pack.Blocks), blocksFunc()) |
| 301 | // The first block.Base >= uid. |
| 302 | if idx == 0 { |
| 303 | return d.UnpackBlock() |
| 304 | } |
| 305 | // The uid is the first entry in the block. |
| 306 | if idx < len(pack.Blocks) && pack.Blocks[idx].Base == uid { |
| 307 | d.blockIdx = idx |
| 308 | return d.UnpackBlock() |
| 309 | } |
| 310 | |
| 311 | // Either the idx = len(pack.Blocks) that means it wasn't found in any of the block's base. Or, |
| 312 | // we found the first block index whose base is greater than uid. In these cases, go to the |
| 313 | // previous block and search there. |
| 314 | d.blockIdx = idx - 1 // Move to the previous block. If blockIdx<0, unpack will deal with it. |
| 315 | d.UnpackBlock() // And get all their uids. |
| 316 | |
| 317 | uidsFunc := func() searchFunc { |
| 318 | var f searchFunc |
| 319 | switch whence { |
| 320 | case SeekStart: |
| 321 | f = func(i int) bool { return d.uids[i] >= uid } |
| 322 | case SeekCurrent: |
| 323 | f = func(i int) bool { return d.uids[i] > uid } |
| 324 | } |
| 325 | return f |
| 326 | } |
| 327 | |
| 328 | // uidx points to the first uid in the uid list, which is >= uid. |
| 329 | uidx := sort.Search(len(d.uids), uidsFunc()) |
| 330 | if uidx < len(d.uids) { // Found an entry in uids, which >= uid. |
| 331 | d.uids = d.uids[uidx:] |
| 332 | return d.uids |
| 333 | } |
| 334 | // Could not find any uid in the block, which is >= uid. The next block might still have valid |
| 335 | // entries > uid. |
| 336 | return d.Next() |