util/crc32.go

148 lines
2.7 KiB
Go

package util
import (
"encoding/hex"
"hash/crc32"
"io"
"os"
"path/filepath"
"strings"
)
type CRC32Result struct {
value uint32
err error
}
func (c *CRC32Result) Value() uint32 {
if c.err != nil {
return 0
}
return c.value
}
func (c *CRC32Result) Array() [4]byte {
if c.err != nil {
return [4]byte{}
}
return UInt32ToBytesArray(c.value)
}
func (c *CRC32Result) Slice() []byte {
if c.err != nil {
return []byte{}
}
return UInt32ToBytesSlice(c.value)
}
func (c *CRC32Result) Upper() string {
if c.err != nil {
return ""
}
return strings.ToUpper(hex.EncodeToString(c.Slice()))
}
func (c *CRC32Result) Lower() string {
if c.err != nil {
return ""
}
return strings.ToLower(hex.EncodeToString(c.Slice()))
}
func (c *CRC32Result) Error() error {
return c.err
}
func NewCRC32Result(result uint32, err error) *CRC32Result {
return &CRC32Result{
value: result,
err: err,
}
}
type CRC32 struct{}
func NewCRC32() *CRC32 {
return &CRC32{}
}
func (c *CRC32) FromReader(r io.Reader) *CRC32Result {
return c.FromReaderChunk(r, 1024*8)
}
func (c *CRC32) FromFile(filename string) *CRC32Result {
file, err := os.Open(filepath.Clean(filename))
if err != nil {
return NewCRC32Result(0, err)
}
defer func() {
_ = file.Close()
}()
return c.FromReader(file)
}
func (c *CRC32) FromReaderChunk(r io.Reader, chunksize int) *CRC32Result {
val := uint32(0)
buf := make([]byte, chunksize)
var n int
var err error
for {
n, err = r.Read(buf)
if err != nil {
if err != io.EOF {
return NewCRC32Result(0, err)
}
if n > 0 {
val = crc32.Update(val, crc32.IEEETable, buf[:n])
}
break
}
val = crc32.Update(val, crc32.IEEETable, buf[:n])
}
return NewCRC32Result(val, nil)
}
func (c *CRC32) FromFileChunk(filename string, chunksize int) *CRC32Result {
file, err := os.Open(filepath.Clean(filename))
if err != nil {
return NewCRC32Result(0, err)
}
defer func() {
_ = file.Close()
}()
return c.FromReaderChunk(file, chunksize)
}
func (c *CRC32) FromBytes(data []byte) *CRC32Result {
return NewCRC32Result(crc32.ChecksumIEEE(data), nil)
}
func (c *CRC32) FromString(data string) *CRC32Result {
return NewCRC32Result(crc32.ChecksumIEEE([]byte(data)), nil)
}
type CRC32Pip struct {
crc uint32
}
func NewCRC32Pip() *CRC32Pip {
return &CRC32Pip{crc: 0}
}
func (c *CRC32Pip) Write(data []byte) (n int, err error) {
c.crc = crc32.Update(c.crc, crc32.IEEETable, data)
return len(data), nil
}
func (c *CRC32Pip) WriteBytes(data []byte) {
c.crc = crc32.Update(c.crc, crc32.IEEETable, data)
}
func (c *CRC32Pip) WriteString(data string) {
c.crc = crc32.Update(c.crc, crc32.IEEETable, []byte(data))
}
func (c *CRC32Pip) Result() *CRC32Result {
return NewCRC32Result(c.crc, nil)
}