github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/bfs/file_reader.go (about)

     1  // Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
     2  
     3  package bfs
     4  
     5  import (
     6  	"errors"
     7  	"github.com/iwind/TeaGo/types"
     8  	"io"
     9  	"os"
    10  )
    11  
    12  type FileReader struct {
    13  	bFile *BlocksFile
    14  	fp    *os.File
    15  
    16  	fileHeader *FileHeader
    17  	pos        int64
    18  
    19  	isClosed bool
    20  }
    21  
    22  func NewFileReader(bFile *BlocksFile, fp *os.File, fileHeader *FileHeader) *FileReader {
    23  	return &FileReader{
    24  		bFile:      bFile,
    25  		fp:         fp,
    26  		fileHeader: fileHeader,
    27  	}
    28  }
    29  
    30  func (this *FileReader) FileHeader() *FileHeader {
    31  	return this.fileHeader
    32  }
    33  
    34  func (this *FileReader) Read(b []byte) (n int, err error) {
    35  	n, err = this.ReadAt(b, this.pos)
    36  	this.pos += int64(n)
    37  
    38  	return
    39  }
    40  
    41  func (this *FileReader) ReadAt(b []byte, offset int64) (n int, err error) {
    42  	if offset >= this.fileHeader.MaxOffset() {
    43  		err = io.EOF
    44  		return
    45  	}
    46  
    47  	blockInfo, ok := this.fileHeader.BlockAt(offset)
    48  	if !ok {
    49  		err = errors.New("could not find block at '" + types.String(offset) + "'")
    50  		return
    51  	}
    52  
    53  	var delta = offset - blockInfo.OriginOffsetFrom
    54  	var bFrom = blockInfo.BFileOffsetFrom + delta
    55  	var bTo = blockInfo.BFileOffsetTo
    56  	if bFrom > bTo {
    57  		err = errors.New("invalid block information")
    58  		return
    59  	}
    60  
    61  	var bufLen = len(b)
    62  	if int64(bufLen) > bTo-bFrom {
    63  		bufLen = int(bTo - bFrom)
    64  	}
    65  
    66  	AckReadThread()
    67  	n, err = this.fp.ReadAt(b[:bufLen], bFrom)
    68  	ReleaseReadThread()
    69  
    70  	return
    71  }
    72  
    73  func (this *FileReader) Reset(fileHeader *FileHeader) {
    74  	this.fileHeader = fileHeader
    75  	this.pos = 0
    76  }
    77  
    78  func (this *FileReader) Close() error {
    79  	if this.isClosed {
    80  		return nil
    81  	}
    82  	this.isClosed = true
    83  	return this.bFile.CloseFileReader(this)
    84  }
    85  
    86  func (this *FileReader) Free() error {
    87  	return this.fp.Close()
    88  }