9fans.net/go@v0.0.7/cmd/acme/internal/disk/buff.go (about) 1 package disk 2 3 import "9fans.net/go/cmd/acme/internal/util" 4 5 type Buffer struct { 6 nc int 7 c []rune // cnc was len(c), cmax was cap(c) 8 cq int 9 cdirty bool 10 cbi int 11 bl []*block // nbl was len(bl) == cap(bl) 12 } 13 14 var blist *block 15 16 func (b *Buffer) Len() int { return b.nc } 17 18 func (b *Buffer) resizeCache(n int) { 19 for cap(b.c) < n { 20 b.c = append(b.c[:cap(b.c)], 0) 21 } 22 b.c = b.c[:n] 23 } 24 25 func (b *Buffer) insertBlock(i, n int) { 26 if i > len(b.bl) { 27 util.Fatal("internal error: addblock") 28 } 29 b.bl = append(b.bl, nil) 30 copy(b.bl[i+1:], b.bl[i:]) 31 b.bl[i] = disk.allocBlock(n) 32 } 33 34 func (b *Buffer) deleteBlock(i int) { 35 if i >= len(b.bl) { 36 util.Fatal("internal error: delblock") 37 } 38 39 disk.freeBlock(b.bl[i]) 40 copy(b.bl[i:], b.bl[i+1:]) 41 b.bl = b.bl[:len(b.bl)-1] 42 } 43 44 /* 45 * Move cache so b->cq <= q0 < b->cq+b->cnc. 46 * If at very end, q0 will fall on end of cache block. 47 */ 48 49 func (b *Buffer) flushCache() { 50 if b.cdirty || len(b.c) == 0 { 51 if len(b.c) == 0 { 52 b.deleteBlock(b.cbi) 53 } else { 54 disk.write(&b.bl[b.cbi], b.c) 55 } 56 b.cdirty = false 57 } 58 } 59 60 func (b *Buffer) setCache(q0 int) { 61 if q0 > b.Len() { 62 util.Fatal("internal error: setcache") 63 } 64 /* 65 * flush and reload if q0 is not in cache. 66 */ 67 if b.Len() == 0 || (b.cq <= q0 && q0 < b.cq+len(b.c)) { 68 return 69 } 70 /* 71 * if q0 is at end of file and end of cache, continue to grow this block 72 */ 73 if q0 == b.Len() && q0 == b.cq+len(b.c) && len(b.c) < maxblock { // TODO(rsc): sam says <= Maxblock; which is right? 74 return 75 } 76 b.flushCache() 77 var q, i int 78 /* find block */ 79 if q0 < b.cq { 80 q = 0 81 i = 0 82 } else { 83 q = b.cq 84 i = b.cbi 85 } 86 blp := &b.bl[i] 87 for q+(*blp).u.n <= q0 && q+(*blp).u.n < b.Len() { 88 q += (*blp).u.n 89 i++ 90 if i >= len(b.bl) { 91 util.Fatal("block not found") 92 } 93 blp = &b.bl[i] 94 } 95 bl := *blp 96 /* remember position */ 97 b.cbi = i 98 b.cq = q 99 b.resizeCache(bl.u.n) 100 /*read block*/ 101 disk.read(bl, b.c) 102 } 103 104 func (b *Buffer) Read(q0 int, s []rune) { 105 n := len(s) 106 if !(q0 <= b.Len()) || !(q0+n <= b.Len()) { 107 util.Fatal("bufread: internal error") 108 } 109 110 for n > 0 { 111 b.setCache(q0) 112 m := util.Min(n, len(b.c)-(q0-b.cq)) 113 copy(s[:m], b.c[q0-b.cq:]) 114 q0 += m 115 s = s[m:] 116 n -= m 117 } 118 } 119 120 func (b *Buffer) Insert(q0 int, s []rune) { 121 n := len(s) 122 if q0 > b.Len() { 123 util.Fatal("internal error: bufinsert") 124 } 125 126 for n > 0 { 127 b.setCache(q0) 128 off := q0 - b.cq 129 var m int 130 if len(b.c)+n <= maxblock { 131 /* Everything fits in one block. */ 132 t := len(b.c) + n 133 m = n 134 if b.bl == nil { /* allocate */ 135 if len(b.c) != 0 { 136 util.Fatal("internal error: bufinsert1 cnc!=0") 137 } 138 b.insertBlock(0, t) 139 b.cbi = 0 140 } 141 b.resizeCache(t) 142 copy(b.c[off+m:], b.c[off:]) 143 copy(b.c[off:], s[:m]) 144 } else if q0 == b.cq || q0 == b.cq+len(b.c) { 145 /* 146 * We must make a new block. If q0 is at 147 * the very beginning or end of this block, 148 * just make a new block and fill it. 149 */ 150 if b.cdirty { 151 b.flushCache() 152 } 153 m = util.Min(n, maxblock) 154 var i int 155 if b.bl == nil { /* allocate */ 156 if len(b.c) != 0 { 157 util.Fatal("internal error: bufinsert2 cnc!=0") 158 } 159 i = 0 160 } else { 161 i = b.cbi 162 if q0 > b.cq { 163 i++ 164 } 165 } 166 b.insertBlock(i, m) 167 b.resizeCache(m) 168 copy(b.c, s[:m]) 169 b.cq = q0 170 b.cbi = i 171 } else { 172 /* 173 * Split the block; cut off the right side and 174 * let go of it. 175 */ 176 m = len(b.c) - off 177 if m > 0 { 178 i := b.cbi + 1 179 b.insertBlock(i, m) 180 disk.write(&b.bl[i], b.c[off:]) 181 b.c = b.c[:off] 182 } 183 /* 184 * Now at end of block. Take as much input 185 * as possible and tack it on end of block. 186 */ 187 m = util.Min(n, maxblock-len(b.c)) 188 n := len(b.c) 189 b.resizeCache(n + m) 190 copy(b.c[n:], s) 191 } 192 193 b.nc += m 194 q0 += m 195 s = s[m:] 196 n -= m 197 b.cdirty = true 198 } 199 } 200 201 func (b *Buffer) Delete(q0, q1 int) { 202 if !(q0 <= q1 && q0 <= b.Len()) || !(q1 <= b.Len()) { 203 util.Fatal("internal error: bufdelete") 204 } 205 for q1 > q0 { 206 b.setCache(q0) 207 off := q0 - b.cq 208 var n int 209 if q1 > b.cq+len(b.c) { 210 n = len(b.c) - off 211 } else { 212 n = q1 - q0 213 } 214 m := len(b.c) - (off + n) 215 if m > 0 { 216 copy(b.c[off:], b.c[off+n:]) 217 } 218 b.c = b.c[:len(b.c)-n] 219 b.cdirty = true 220 q1 -= n 221 b.nc -= n 222 } 223 } 224 225 func (b *Buffer) Reset() { 226 b.nc = 0 227 b.c = b.c[:0] 228 b.cq = 0 229 b.cdirty = false 230 b.cbi = 0 231 /* delete backwards to avoid n² behavior */ 232 // TODO(rsc): Is there a reason we leave one b.bl entry behind? 233 for i := len(b.bl) - 1; ; { 234 i-- 235 if i < 0 { 236 break 237 } 238 b.deleteBlock(i) 239 } 240 } 241 242 func (b *Buffer) Close() { 243 b.Reset() 244 // free(b.c) 245 b.c = nil 246 // free(b.bl) 247 b.bl = nil 248 }