github.com/nikandfor/tlog@v0.21.3/tlz/decoder.go (about) 1 package tlz 2 3 import ( 4 "bytes" 5 "io" 6 7 "github.com/nikandfor/errors" 8 "github.com/nikandfor/hacked/hfmt" 9 10 "github.com/nikandfor/tlog/low" 11 ) 12 13 type ( 14 Decoder struct { 15 io.Reader 16 17 // output 18 block []byte 19 mask int 20 pos int64 // output stream pos 21 22 // current tag 23 state byte 24 off, len int 25 26 // input 27 b []byte 28 i int 29 boff int64 // input stream offset to b[0] 30 } 31 32 Dumper struct { 33 io.Writer 34 35 d Decoder 36 37 GlobalOffset int64 38 39 b low.Buf 40 } 41 ) 42 43 var eUnexpectedEOF = errors.NewNoCaller("need more") 44 45 func NewDecoder(r io.Reader) *Decoder { 46 return &Decoder{ 47 Reader: r, 48 } 49 } 50 51 func NewDecoderBytes(b []byte) *Decoder { 52 return &Decoder{ 53 b: b, 54 } 55 } 56 57 func (d *Decoder) Reset(rd io.Reader) { 58 d.ResetBytes(nil) 59 d.Reader = rd 60 } 61 62 func (d *Decoder) ResetBytes(b []byte) { 63 d.Reader = nil 64 65 if b != nil { 66 d.b = b 67 } 68 69 d.i = 0 70 d.b = d.b[:len(b)] 71 d.boff = 0 72 73 d.state = 0 74 } 75 76 func (d *Decoder) Read(p []byte) (n int, err error) { 77 var m, i int 78 79 for n < len(p) && err == nil { 80 m, i, err = d.read(p[n:], d.i) 81 82 n += m 83 d.i = i 84 85 if n == len(p) { 86 err = nil 87 break 88 } 89 90 if err != eUnexpectedEOF { //nolint:errorlint 91 continue 92 } 93 94 err = d.more() 95 if errors.Is(err, io.EOF) && (d.state != 0 || d.i < len(d.b)) { 96 err = io.ErrUnexpectedEOF 97 } 98 } 99 100 return n, err 101 } 102 103 func (d *Decoder) read(p []byte, st int) (n, i int, err error) { 104 if d.state != 0 && len(d.block) == 0 { 105 return 0, st, errors.New("missed meta") 106 } 107 108 i = st 109 110 if d.state == 0 { 111 i, err = d.readTag(i) 112 if err != nil { 113 return 114 } 115 } 116 117 if d.state == 'l' && i == len(d.b) { 118 return 0, i, eUnexpectedEOF 119 } 120 121 end := d.len 122 if end > len(p) { 123 end = len(p) 124 } 125 126 if d.state == 'l' { 127 end = copy(p[:end], d.b[i:]) 128 i += end 129 } else { 130 end = copy(p[:end], d.block[d.off&d.mask:]) 131 d.off += end 132 } 133 134 d.len -= end 135 136 for n < end { 137 m := copy(d.block[int(d.pos)&d.mask:], p[n:end]) 138 n += m 139 d.pos += int64(m) 140 } 141 142 if d.len == 0 { 143 d.state = 0 144 } 145 146 return 147 } 148 149 func (d *Decoder) readTag(st int) (i int, err error) { 150 tag, l, i, err := d.tag(d.b, st) 151 if err != nil { 152 return st, err 153 } 154 155 if tag == Literal && l == Meta { 156 return d.readMetaTag(st) 157 } 158 159 switch tag { 160 case Literal: 161 d.state = 'l' 162 d.len = l 163 case Copy: 164 d.off, i, err = d.roff(d.b, i) 165 if err != nil { 166 return st, err 167 } 168 169 d.off = int(d.pos) - d.off - l 170 171 d.state = 'c' 172 d.len = l 173 default: 174 return st, errors.New("unsupported tag: %x", tag) 175 } 176 177 return i, nil 178 } 179 180 func (d *Decoder) readMetaTag(st int) (i int, err error) { 181 _, meta, i, err := d.tag(d.b, st) 182 if err != nil { 183 return st, err 184 } 185 186 if meta != Meta { 187 panic("bad usage") 188 } 189 190 meta, i, err = d.roff(d.b, i) 191 if err != nil { 192 return st, err 193 } 194 195 switch meta & MetaTagMask { 196 case MetaMagic: 197 meta &^= MetaTagMask 198 199 if i+meta > len(d.b) { 200 return st, eUnexpectedEOF 201 } 202 203 if !bytes.Equal(d.b[i:i+meta], []byte("tlz")) { 204 return st, errors.New("bad magic") 205 } 206 207 i += meta 208 case MetaVer: 209 meta &^= MetaTagMask 210 211 if i+meta > len(d.b) { 212 return st, eUnexpectedEOF 213 } 214 215 if string(d.b[i:i+meta]) != Version { 216 return st, errors.New("incompatible version") 217 } 218 219 i += meta 220 case MetaReset: 221 meta, i, err = d.roff(d.b, i) // block size log 222 if err != nil { 223 return st, err 224 } 225 226 bs := 1 << meta 227 228 if bs > len(d.block) { 229 d.block = make([]byte, bs) 230 } else { 231 d.block = d.block[:bs] 232 233 for i := 0; i < bs; { 234 i += copy(d.block[i:], zeros) 235 } 236 } 237 238 d.pos = 0 239 d.mask = bs - 1 240 241 d.state = 0 242 default: 243 return st, errors.New("unsupported meta: %x", meta) 244 } 245 246 return i, nil 247 } 248 249 func (d *Decoder) roff(b []byte, st int) (off, i int, err error) { 250 if st >= len(b) { 251 return 0, st, eUnexpectedEOF 252 } 253 254 i = st 255 256 off = int(b[i]) 257 i++ 258 259 switch off { 260 case Off1: 261 if i+1 > len(b) { 262 return off, st, eUnexpectedEOF 263 } 264 265 off = int(b[i]) 266 i++ 267 case Off2: 268 if i+2 > len(b) { 269 return off, st, eUnexpectedEOF 270 } 271 272 off = int(b[i])<<8 | int(b[i+1]) 273 i += 2 274 case Off4: 275 if i+4 > len(b) { 276 return off, st, eUnexpectedEOF 277 } 278 279 off = int(b[i])<<24 | int(b[i+1])<<16 | int(b[i+2])<<8 | int(b[i+3]) 280 i += 4 281 case Off8: 282 if i+8 > len(b) { 283 return off, st, eUnexpectedEOF 284 } 285 286 off = int(b[i])<<56 | int(b[i+1])<<48 | int(b[i+2])<<40 | int(b[i+3])<<32 | 287 int(b[i+4])<<24 | int(b[i+5])<<16 | int(b[i+6])<<8 | int(b[i+7]) 288 i += 8 289 default: 290 // off is embedded 291 } 292 293 return off, i, nil 294 } 295 296 func (d *Decoder) tag(b []byte, st int) (tag, l, i int, err error) { 297 if st >= len(b) { 298 return 0, 0, st, eUnexpectedEOF 299 } 300 301 i = st 302 303 tag = int(b[i]) & TagMask 304 l = int(b[i]) & TagLenMask 305 i++ 306 307 switch l { 308 case Len1: 309 if i+1 > len(b) { 310 return tag, l, st, eUnexpectedEOF 311 } 312 313 l = int(b[i]) 314 i++ 315 case Len2: 316 if i+2 > len(b) { 317 return tag, l, st, eUnexpectedEOF 318 } 319 320 l = int(b[i])<<8 | int(b[i+1]) 321 i += 2 322 case Len4: 323 if i+4 > len(b) { 324 return tag, l, st, eUnexpectedEOF 325 } 326 327 l = int(b[i])<<24 | int(b[i+1])<<16 | int(b[i+2])<<8 | int(b[i+3]) 328 i += 4 329 case Len8: 330 if i+8 > len(b) { 331 return tag, l, st, eUnexpectedEOF 332 } 333 334 l = int(b[i])<<56 | int(b[i+1])<<48 | int(b[i+2])<<40 | int(b[i+3])<<32 | 335 int(b[i+4])<<24 | int(b[i+5])<<16 | int(b[i+6])<<8 | int(b[i+7]) 336 i += 8 337 default: 338 // l is embedded 339 } 340 341 return tag, l, i, nil 342 } 343 344 func (d *Decoder) more() (err error) { 345 if d.Reader == nil { 346 return io.EOF 347 } 348 349 copy(d.b, d.b[d.i:]) 350 d.b = d.b[:len(d.b)-d.i] 351 d.boff += int64(d.i) 352 d.i = 0 353 354 end := len(d.b) 355 356 if len(d.b) == 0 { 357 d.b = make([]byte, 1024) 358 } else { 359 d.b = append(d.b, 0, 0, 0, 0, 0, 0, 0, 0) 360 } 361 362 d.b = d.b[:cap(d.b)] 363 364 n, err := d.Reader.Read(d.b[end:]) 365 // println("more", d.i, end, end+n, n, len(d.b)) 366 d.b = d.b[:end+n] 367 368 if n != 0 && errors.Is(err, io.EOF) { 369 err = nil 370 } 371 372 return err 373 } 374 375 func Dump(p []byte) string { 376 var d Dumper 377 378 _, err := d.Write(p) 379 if err != nil { 380 return err.Error() 381 } 382 383 return string(d.b) 384 } 385 386 func NewDumper(w io.Writer) *Dumper { 387 return &Dumper{ 388 Writer: w, 389 } 390 } 391 392 func (w *Dumper) Write(p []byte) (i int, err error) { 393 w.b = w.b[:0] 394 395 var tag, l int 396 for i < len(p) { 397 if w.GlobalOffset >= 0 { 398 w.b = hfmt.Appendf(w.b, "%6x ", int(w.GlobalOffset)+i) 399 } 400 401 w.b = hfmt.Appendf(w.b, "%4x ", i) 402 403 w.b = hfmt.Appendf(w.b, "%6x ", w.d.pos) 404 405 tag, l, i, err = w.d.tag(p, i) 406 if err != nil { 407 return 408 } 409 410 // println("loop", i, tag>>6, l) 411 412 switch { 413 case l == Meta: 414 tag, i, err = w.d.roff(p, i) 415 if err != nil { 416 return 417 } 418 419 switch tag & MetaTagMask { 420 case MetaMagic, MetaVer: 421 l = tag &^ MetaTagMask 422 423 w.b = hfmt.Appendf(w.b, "meta %4x %q\n", tag, p[i:i+l]) 424 425 i += l 426 case MetaReset: 427 l, i, err = w.d.roff(p, i) 428 429 w.b = hfmt.Appendf(w.b, "meta %4x %x\n", tag, l) 430 default: 431 return i, errors.New("unsupported meta tag: %x", tag) 432 } 433 case tag == Literal: 434 w.b = hfmt.Appendf(w.b, "lit %4x %q\n", l, p[i:i+l]) 435 436 i += l 437 w.d.pos += int64(l) 438 case tag == Copy: 439 var off int 440 441 off, i, err = w.d.roff(p, i) 442 if err != nil { 443 return 444 } 445 446 w.d.pos += int64(l) 447 448 w.b = hfmt.Appendf(w.b, "copy %4x off %4x (%4x)\n", l, off, off+l) 449 450 // off += l 451 default: 452 panic(tag) 453 } 454 } 455 456 w.GlobalOffset += int64(i) 457 458 if w.Writer != nil { 459 _, err = w.Writer.Write(w.b) 460 } 461 462 return i, err 463 }