This repository was archived by the owner on Nov 22, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslist.go
141 lines (117 loc) · 3.3 KB
/
slist.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2017 The DB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package db
const (
oSListNext = 8 * iota // int64 0 8
oSListData // [dataSize]byte 8 dataSize
)
// SList is a node of a single linked list.
type SList struct {
*DB
Off int64
}
// NewSList returns a newly allocated SList or an error, if any. The datasize
// parameter is the fixed size of data associated with the list node. To
// get/set the node data, use the ReadAt/WriteAt methods of db, using
// SList.DataOff() as the offset. Reading or writing more than datasize data at
// DataOff() is undefined behavior and may irreparably corrupt the database.
//
// The result of NewSList is not a part of any list.
func (db *DB) NewSList(dataSize int64) (SList, error) {
off, err := db.Alloc(oSListData + dataSize)
if err != nil {
return SList{}, err
}
r, err := db.OpenSList(off)
if err != nil {
return SList{}, err
}
return r, r.setNext(0)
}
func (l SList) setNext(off int64) error { return l.w8(l.Off+oSListNext, off) }
// OpenSList returns an SList found at offset off.
func (db *DB) OpenSList(off int64) (SList, error) { return SList{db, off}, nil }
// DataOff returns the offset in db at which data of l are located.
func (l SList) DataOff() int64 { return l.Off + oSListData }
// Next returns the offset of the next node of l.
func (l SList) Next() (int64, error) { return l.r8(l.Off + oSListNext) }
// InsertAfter inserts l after the SList node at off. Node l must not be
// already a part of any list.
func (l SList) InsertAfter(off int64) error {
n, err := l.OpenSList(off)
if err != nil {
return err
}
afterNext, err := n.Next()
if err != nil {
return err
}
if err = n.setNext(l.Off); err != nil {
return err
}
return l.setNext(afterNext)
}
// InsertBefore inserts l before the SList node at off. If the SList node at
// off is linked to from an SList node at prev, the prev argument must reflect
// that, otherwise prev must be zero. Node l must not be already a part of any
// list.
func (l SList) InsertBefore(prev, off int64) error {
n, err := l.OpenSList(off)
if err != nil {
return err
}
if prev != 0 {
p, err := l.OpenSList(prev)
if err != nil {
return err
}
if err := p.setNext(l.Off); err != nil {
return err
}
}
return l.setNext(n.Off)
}
// Remove removes l from a list. If l is linked to from an SList node at prev,
// the prev argument must reflect that, otherwise prev must be zero.
func (l SList) Remove(prev int64) error {
if prev != 0 {
next, err := l.Next()
if err != nil {
return err
}
p, err := l.OpenSList(prev)
if err != nil {
return err
}
if err := p.setNext(next); err != nil {
return err
}
}
return l.Free(l.Off)
}
// RemoveToLast removes all nodes from a list starting at l to the end of the
// list. If l is linked to from an SList node at prev, the prev argument must
// reflect that, otherwise prev must be zero.
func (l SList) RemoveToLast(prev int64) error {
if prev != 0 {
p, err := l.OpenSList(prev)
if err != nil {
return err
}
if err := p.setNext(0); err != nil {
return err
}
}
for l.Off != 0 {
next, err := l.Next()
if err != nil {
return err
}
if err := l.Free(l.Off); err != nil {
return err
}
l.Off = next
}
return nil
}