package encodemeta
import (
"bufio"
"crypto/md5"
"encoding/binary"
"fmt"
"internal/coverage"
"internal/coverage/stringtab"
"io"
"os"
"unsafe"
)
type CoverageMetaFileWriter struct {
stab stringtab .Writer
mfname string
w *bufio .Writer
tmp []byte
debug bool
}
func NewCoverageMetaFileWriter (mfname string , w io .Writer ) *CoverageMetaFileWriter {
r := &CoverageMetaFileWriter {
mfname : mfname ,
w : bufio .NewWriter (w ),
tmp : make ([]byte , 64 ),
}
r .stab .InitWriter ()
r .stab .Lookup ("" )
return r
}
func (m *CoverageMetaFileWriter ) Write (finalHash [16 ]byte , blobs [][]byte , mode coverage .CounterMode , granularity coverage .CounterGranularity ) error {
mhsz := uint64 (unsafe .Sizeof (coverage .MetaFileHeader {}))
stSize := m .stab .Size ()
stOffset := mhsz + uint64 (16 *len (blobs ))
preambleLength := stOffset + uint64 (stSize )
if m .debug {
fmt .Fprintf (os .Stderr , "=+= sizeof(MetaFileHeader)=%d\n" , mhsz )
fmt .Fprintf (os .Stderr , "=+= preambleLength=%d stSize=%d\n" , preambleLength , stSize )
}
tlen := preambleLength
for i := 0 ; i < len (blobs ); i ++ {
tlen += uint64 (len (blobs [i ]))
}
mh := coverage .MetaFileHeader {
Magic : coverage .CovMetaMagic ,
Version : coverage .MetaFileVersion ,
TotalLength : tlen ,
Entries : uint64 (len (blobs )),
MetaFileHash : finalHash ,
StrTabOffset : uint32 (stOffset ),
StrTabLength : stSize ,
CMode : mode ,
CGranularity : granularity ,
}
var err error
if err = binary .Write (m .w , binary .LittleEndian , mh ); err != nil {
return fmt .Errorf ("error writing %s: %v" , m .mfname , err )
}
if m .debug {
fmt .Fprintf (os .Stderr , "=+= len(blobs) is %d\n" , mh .Entries )
}
off := preambleLength
off2 := mhsz
buf := make ([]byte , 8 )
for _ , blob := range blobs {
binary .LittleEndian .PutUint64 (buf , off )
if _, err = m .w .Write (buf ); err != nil {
return fmt .Errorf ("error writing %s: %v" , m .mfname , err )
}
if m .debug {
fmt .Fprintf (os .Stderr , "=+= pkg offset %d 0x%x\n" , off , off )
}
off += uint64 (len (blob ))
off2 += 8
}
for _ , blob := range blobs {
bl := uint64 (len (blob ))
binary .LittleEndian .PutUint64 (buf , bl )
if _, err = m .w .Write (buf ); err != nil {
return fmt .Errorf ("error writing %s: %v" , m .mfname , err )
}
if m .debug {
fmt .Fprintf (os .Stderr , "=+= pkg len %d 0x%x\n" , bl , bl )
}
off2 += 8
}
if err = m .stab .Write (m .w ); err != nil {
return err
}
for k , blob := range blobs {
if m .debug {
fmt .Fprintf (os .Stderr , "=+= writing blob %d len %d at off=%d hash %s\n" , k , len (blob ), off2 , fmt .Sprintf ("%x" , md5 .Sum (blob )))
}
if _, err = m .w .Write (blob ); err != nil {
return fmt .Errorf ("error writing %s: %v" , m .mfname , err )
}
if m .debug {
fmt .Fprintf (os .Stderr , "=+= wrote package payload of %d bytes\n" ,
len (blob ))
}
off2 += uint64 (len (blob ))
}
if err = m .w .Flush (); err != nil {
return fmt .Errorf ("error writing %s: %v" , m .mfname , err )
}
return nil
}
The pages are generated with Golds v0.7.0-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .