go-hep.org/x/hep@v0.38.1/groot/rbytes/wbuffer.go (about) 1 // Copyright ©2018 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package rbytes 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "encoding/hex" 11 "fmt" 12 "io" 13 "math" 14 "reflect" 15 16 "go-hep.org/x/hep/groot/root" 17 "go-hep.org/x/hep/groot/rvers" 18 ) 19 20 type wbuff struct { 21 p []byte // buffer of data to write on 22 c int // current position in buffer of data 23 } 24 25 func (w *wbuff) Write(p []byte) (int, error) { 26 if w.c >= len(w.p) { 27 return 0, io.EOF 28 } 29 n := copy(w.p[w.c:], p) 30 w.c += n 31 return n, nil 32 } 33 34 // grow grows the buffer's capacity, if necessary, to guarantee space foranother n bytes. 35 // After grow(n), at least n bytes can be written to the buffer without 36 // another allocation. 37 // If n is negative, grow will panic. 38 func (w *wbuff) grow(n int) { 39 if n < 0 { 40 panic(fmt.Errorf("rbytes: negative count")) 41 } 42 if n == 0 { 43 return 44 } 45 var ( 46 plen = len(w.p) 47 pcap = cap(w.p) 48 nlen = plen + n 49 ) 50 if nlen < pcap { 51 w.p = w.p[:nlen] 52 return 53 } 54 if pcap < nlen { 55 const sz = 4 * 1024 56 pcap = ((nlen / sz) + 1) * sz 57 } 58 w.p = append(w.p[:cap(w.p)], make([]byte, 2*pcap)...) 59 w.p = w.p[:nlen:cap(w.p)] 60 } 61 62 // WBuffer is a write-only ROOT buffer for streaming. 63 type WBuffer struct { 64 w wbuff 65 err error 66 offset uint32 67 refs map[any]int64 68 sictx StreamerInfoContext 69 } 70 71 func NewWBuffer(data []byte, refs map[any]int64, offset uint32, ctx StreamerInfoContext) *WBuffer { 72 if refs == nil { 73 refs = make(map[any]int64) 74 } 75 76 return &WBuffer{ 77 w: wbuff{p: data, c: 0}, 78 refs: refs, 79 offset: offset, 80 sictx: ctx, 81 } 82 } 83 84 // StreamerInfo returns the named StreamerInfo. 85 // If version is negative, the latest version should be returned. 86 func (w *WBuffer) StreamerInfo(name string, version int) (StreamerInfo, error) { 87 if w.sictx == nil { 88 return nil, fmt.Errorf("rbytes: no streamers") 89 } 90 return w.sictx.StreamerInfo(name, version) 91 } 92 93 func (w *WBuffer) Grow(n int) { w.w.grow(n) } 94 func (w *WBuffer) buffer() []byte { return w.w.p[:w.w.c] } 95 func (w *WBuffer) Bytes() []byte { return w.w.p[:w.w.c] } 96 97 func (w *WBuffer) Err() error { return w.err } 98 func (w *WBuffer) SetErr(err error) { w.err = err } 99 100 func (w *WBuffer) Pos() int64 { 101 return int64(w.w.c) + int64(w.offset) 102 } 103 104 func (w *WBuffer) Len() int64 { 105 return int64(w.w.c) 106 } 107 108 func (w *WBuffer) SetPos(pos int64) { w.setPos(pos) } 109 func (w *WBuffer) setPos(pos int64) { 110 pos -= int64(w.offset) 111 w.w.c = int(pos) 112 } 113 114 func (w *WBuffer) DumpHex(n int) { 115 buf := w.buffer() 116 if len(buf) > n { 117 buf = buf[:n] 118 } 119 fmt.Printf("--- hex --- (pos=%d len=%d end=%d)\n%s\n", w.Pos(), n, w.Len(), string(hex.Dump(buf))) 120 } 121 122 func (w *WBuffer) Write(p []byte) (int, error) { 123 if w.err != nil { 124 return 0, w.err 125 } 126 w.w.grow(len(p)) 127 n, err := w.w.Write(p) 128 w.err = err 129 return n, w.err 130 } 131 132 func (w *WBuffer) WriteHeader(typename string, vers int16) Header { 133 hdr := Header{ 134 Name: typename, 135 Pos: w.Pos(), 136 Vers: vers, 137 } 138 if w.err != nil { 139 return hdr 140 } 141 142 w.w.grow(6) 143 w.writeU32(0) // byte-count placeholder 144 w.writeU16(uint16(vers)) 145 146 return hdr 147 } 148 149 func (w *WBuffer) SetHeader(hdr Header) (int, error) { 150 if w.err != nil { 151 return 0, w.err 152 } 153 154 cur := w.Pos() 155 cnt := cur - hdr.Pos - 4 156 w.setPos(hdr.Pos) 157 w.WriteU32(uint32(cnt | kByteCountMask)) 158 w.setPos(cur) 159 160 return int(cnt + 4), w.err 161 } 162 163 func (w *WBuffer) WriteObject(obj Marshaler) { 164 if w.err != nil { 165 return 166 } 167 168 if v := reflect.ValueOf(obj); (v == reflect.Value{}) || v.IsNil() { 169 w.WriteU32(0) // NULL pointer 170 return 171 } 172 173 _, w.err = obj.MarshalROOT(w) 174 } 175 176 func (w *WBuffer) WriteObjectAny(obj root.Object) { 177 if w.err != nil { 178 return 179 } 180 181 if v := reflect.ValueOf(obj); (v == reflect.Value{}) || v.IsNil() { 182 w.WriteU32(0) // NULL pointer 183 return 184 } 185 186 pos := w.Pos() 187 w.WriteU32(0) // placeholder for bytecount. 188 189 bcnt := w.WriteClass(pos, obj) 190 if w.err != nil { 191 return 192 } 193 end := w.Pos() 194 w.setPos(pos) 195 w.writeU32(bcnt) 196 w.setPos(end) 197 } 198 199 func (w *WBuffer) WriteClass(beg int64, obj root.Object) uint32 { 200 if w.err != nil { 201 return 0 202 } 203 204 start := w.Pos() 205 if ref64, dup := w.refs[obj]; dup { 206 // we've already seen this value. 207 w.WriteU32(uint32(ref64)) 208 bcnt := w.Pos() - start 209 return uint32(bcnt | kByteCountMask) 210 } 211 212 class := obj.Class() 213 ref64, ok := w.refs[class] 214 if !ok { 215 // first time we see this type 216 w.WriteU32(uint32(kNewClassTag)) 217 w.WriteCString(class) 218 w.refs[class] = (start + kMapOffset) | kClassMask 219 220 // add to refs before writing value, to handle self reference 221 w.refs[obj] = beg + kMapOffset 222 223 mobj := obj.(Marshaler) 224 if _, err := mobj.MarshalROOT(w); err != nil { 225 return 0 226 } 227 228 bcnt := w.Pos() - start 229 return uint32(bcnt | kByteCountMask) 230 } 231 232 // first time we see this value 233 w.WriteU32(uint32(ref64) | kClassMask) 234 if _, err := obj.(Marshaler).MarshalROOT(w); err != nil { 235 return 0 236 } 237 238 w.refs[obj] = beg + kMapOffset 239 bcnt := w.Pos() - start 240 return uint32(bcnt | kByteCountMask) 241 } 242 243 func (w *WBuffer) write(v []byte) { 244 if w.err != nil { 245 return 246 } 247 w.w.grow(len(v)) 248 _, w.err = w.w.Write(v) 249 } 250 251 func (w *WBuffer) WriteI8(v int8) { 252 if w.err != nil { 253 return 254 } 255 w.w.grow(1) 256 w.writeI8(v) 257 } 258 259 func (w *WBuffer) writeI8(v int8) { 260 w.w.p[w.w.c] = byte(v) 261 w.w.c++ 262 } 263 264 func (w *WBuffer) writeI32(v int32) { 265 const sz = 4 266 beg := w.w.c 267 end := w.w.c + sz 268 binary.BigEndian.PutUint32(w.w.p[beg:end], uint32(v)) 269 w.w.c += sz 270 } 271 272 func (w *WBuffer) WriteU8(v uint8) { 273 if w.err != nil { 274 return 275 } 276 w.w.grow(1) 277 w.writeU8(v) 278 } 279 280 func (w *WBuffer) writeU8(v uint8) { 281 w.w.p[w.w.c] = v 282 w.w.c++ 283 } 284 285 func (w *WBuffer) writeU16(v uint16) { 286 const sz = 2 287 beg := w.w.c 288 end := w.w.c + sz 289 binary.BigEndian.PutUint16(w.w.p[beg:end], uint16(v)) 290 w.w.c += sz 291 } 292 293 func (w *WBuffer) writeU32(v uint32) { 294 const sz = 4 295 beg := w.w.c 296 end := w.w.c + sz 297 binary.BigEndian.PutUint32(w.w.p[beg:end], v) 298 w.w.c += sz 299 } 300 301 func (w *WBuffer) writeF32(v float32) { 302 const sz = 4 303 beg := w.w.c 304 end := w.w.c + sz 305 binary.BigEndian.PutUint32(w.w.p[beg:end], math.Float32bits(v)) 306 w.w.c += sz 307 } 308 309 func (w *WBuffer) WriteF16(v root.Float16, elm StreamerElement) { 310 if w.err != nil { 311 return 312 } 313 switch { 314 case elm != nil && elm.Factor() != 0: 315 // range specified. 316 // normalize the float64 to the range and convert to an integer, 317 // according to the provided scaling factor. 318 var ( 319 x = float64(v) 320 min = float64(elm.XMin()) 321 max = float64(elm.XMax()) 322 ) 323 if x < min { 324 x = min 325 } 326 if x > max { 327 x = max 328 } 329 u32 := uint32(0.5 + elm.Factor()*(x-min)) 330 w.w.grow(4) 331 w.writeU32(u32) 332 default: 333 var nbits uint32 334 if elm != nil { 335 nbits = uint32(elm.XMin()) 336 } 337 if nbits == 0 { 338 nbits = 12 339 } 340 // no range, but nbits. 341 // truncate mantissa to nbits. 342 u32 := math.Float32bits(float32(v)) 343 exp := uint8(0x000000ff & ((u32 << 1) >> 24)) 344 man := uint16(((1 << (nbits + 1)) - 1) & (u32 >> (23 - nbits - 1))) 345 man++ 346 man = man >> 1 347 if man&1<<nbits != 0 { 348 man = (1 << nbits) - 1 349 } 350 if v < 0 { 351 man |= 1 << (nbits + 1) 352 } 353 w.w.grow(3) 354 w.writeU8(exp) 355 w.writeU16(man) 356 } 357 } 358 359 func (w *WBuffer) WriteD32(v root.Double32, elm StreamerElement) { 360 if w.err != nil { 361 return 362 } 363 switch { 364 case elm != nil && elm.Factor() != 0: 365 // range specified. 366 // normalize the float64 to the range and convert to an integer, 367 // according to the provided scaling factor. 368 var ( 369 min = root.Double32(elm.XMin()) 370 max = root.Double32(elm.XMax()) 371 ) 372 if v < min { 373 v = min 374 } 375 if v > max { 376 v = max 377 } 378 u32 := uint32(0.5 + elm.Factor()*float64(v-min)) 379 w.w.grow(4) 380 w.writeU32(u32) 381 default: 382 var nbits uint32 383 if elm != nil { 384 nbits = uint32(elm.XMin()) 385 } 386 switch { 387 case nbits == 0: 388 // no range, no bits: convert to float32 389 w.w.grow(4) 390 w.writeF32(float32(v)) 391 default: 392 // no range, but nbits. 393 // truncate mantissa to nbits. 394 u32 := math.Float32bits(float32(v)) 395 exp := uint8(0x000000ff & ((u32 << 1) >> 24)) 396 man := uint16(((1 << (nbits + 1)) - 1) & (u32 >> (23 - nbits - 1))) 397 man++ 398 man = man >> 1 399 if man&1<<nbits != 0 { 400 man = (1 << nbits) - 1 401 } 402 if v < 0 { 403 man |= 1 << (nbits + 1) 404 } 405 w.w.grow(3) 406 w.writeU8(exp) 407 w.writeU16(man) 408 } 409 } 410 } 411 412 func (w *WBuffer) WriteBool(v bool) { 413 var o uint8 414 if v { 415 o = 1 416 } 417 w.w.grow(1) 418 w.writeU8(o) 419 } 420 421 func (w *WBuffer) WriteStdString(v string) { 422 if w.err != nil { 423 return 424 } 425 426 hdr := w.WriteHeader("string", rvers.StreamerBaseSTL) 427 w.WriteString(v) 428 _, err := w.SetHeader(hdr) 429 if err != nil { 430 w.SetErr(err) 431 } 432 } 433 434 func (w *WBuffer) WriteString(v string) { 435 if w.err != nil { 436 return 437 } 438 l := len(v) 439 if l < 255 { 440 w.w.grow(1 + l) 441 w.writeU8(uint8(l)) 442 if l > 0 { 443 w.write([]byte(v)) 444 } 445 return 446 } 447 w.w.grow(1 + 4 + l) 448 w.writeU8(255) 449 w.writeU32(uint32(l)) 450 w.write([]byte(v)) 451 } 452 453 func (w *WBuffer) writeString(v string) { 454 if w.err != nil { 455 return 456 } 457 l := len(v) 458 if l < 255 { 459 w.writeU8(uint8(l)) 460 w.write([]byte(v)) 461 return 462 } 463 w.writeU8(255) 464 w.writeU32(uint32(l)) 465 w.write([]byte(v)) 466 } 467 468 func (w *WBuffer) WriteCString(v string) { 469 if w.err != nil { 470 return 471 } 472 b := []byte(v) 473 i := bytes.Index(b, []byte{0}) 474 switch { 475 case i < 0: 476 b = append(b, 0) 477 w.write(b) 478 default: 479 b = b[:i+1] 480 w.write(b) 481 } 482 } 483 484 func (w *WBuffer) WriteStaticArrayI32(v []int32) { 485 if w.err != nil { 486 return 487 } 488 w.w.grow(4 + 4*len(v)) 489 w.writeI32(int32(len(v))) 490 for _, v := range v { 491 w.writeI32(v) 492 } 493 } 494 495 func (w *WBuffer) WriteArrayBool(v []bool) { 496 if w.err != nil { 497 return 498 } 499 w.w.grow(len(v)) 500 for _, v := range v { 501 var b byte = 0 502 if v { 503 b = 1 504 } 505 w.writeU8(b) 506 } 507 } 508 509 func (w *WBuffer) WriteArrayI8(v []int8) { 510 if w.err != nil { 511 return 512 } 513 w.w.grow(len(v)) 514 for _, v := range v { 515 w.writeI8(v) 516 } 517 } 518 519 func (w *WBuffer) WriteArrayU8(v []uint8) { 520 if w.err != nil { 521 return 522 } 523 w.w.grow(len(v)) 524 for _, v := range v { 525 w.writeU8(v) 526 } 527 } 528 529 func (w *WBuffer) WriteArrayF16(v []root.Float16, elm StreamerElement) { 530 for _, v := range v { 531 w.WriteF16(v, elm) 532 } 533 } 534 535 func (w *WBuffer) WriteArrayD32(v []root.Double32, elm StreamerElement) { 536 for _, v := range v { 537 w.WriteD32(v, elm) 538 } 539 } 540 541 func (w *WBuffer) strlen(v string) int { 542 l := len(v) 543 if l < 255 { 544 return 1 + l 545 } 546 return 1 + 4 + l 547 } 548 549 func (w *WBuffer) WriteArrayString(v []string) { 550 if w.err != nil { 551 return 552 } 553 n := 0 554 for _, v := range v { 555 n += w.strlen(v) 556 } 557 w.w.grow(n) 558 559 for _, v := range v { 560 w.writeString(v) 561 } 562 } 563 564 func (w *WBuffer) WriteStdVectorStrs(v []string) { 565 if w.err != nil { 566 return 567 } 568 569 hdr := w.WriteHeader("vector<string>", rvers.StreamerBaseSTL) 570 w.WriteI32(int32(len(v))) 571 572 n := 0 573 for _, v := range v { 574 n += w.strlen(v) 575 } 576 w.w.grow(n) 577 578 for _, v := range v { 579 w.writeString(v) 580 } 581 _, _ = w.SetHeader(hdr) 582 } 583 584 func (w *WBuffer) WriteStdBitset(v []uint8) { 585 n := len(v) 586 w.w.grow(n) 587 for i := range v { 588 w.writeU8(v[n-1-i]) 589 } 590 } 591 592 var ( 593 _ StreamerInfoContext = (*WBuffer)(nil) 594 )