You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
goip/vendor/github.com/saracen/go7z/headers/streams_info.go

144 lines
3.1 KiB

package headers
import (
"io"
)
// StreamsInfo is a top-level structure of the 7z format.
type StreamsInfo struct {
PackInfo *PackInfo
UnpackInfo *UnpackInfo
SubStreamsInfo *SubStreamsInfo
}
// ReadStreamsInfo reads the streams info structure.
func ReadStreamsInfo(r io.Reader) (*StreamsInfo, error) {
streamsInfo := &StreamsInfo{}
for {
id, err := ReadByte(r)
if err != nil {
return nil, err
}
switch id {
case k7zPackInfo:
if streamsInfo.PackInfo, err = ReadPackInfo(r); err != nil {
return nil, err
}
case k7zUnpackInfo:
if streamsInfo.UnpackInfo, err = ReadUnpackInfo(r); err != nil {
return nil, err
}
case k7zSubStreamsInfo:
if streamsInfo.UnpackInfo == nil {
return nil, ErrUnexpectedPropertyID
}
if streamsInfo.SubStreamsInfo, err = ReadSubStreamsInfo(r, streamsInfo.UnpackInfo); err != nil {
return nil, err
}
case k7zEnd:
if streamsInfo.PackInfo == nil || streamsInfo.UnpackInfo == nil {
return nil, ErrUnexpectedPropertyID
}
return streamsInfo, nil
default:
return nil, ErrUnexpectedPropertyID
}
}
}
// SubStreamsInfo is a structure found within the StreamsInfo structure.
type SubStreamsInfo struct {
NumUnpackStreamsInFolders []int
UnpackSizes []uint64
Digests []uint32
}
// ReadSubStreamsInfo reads the substreams info structure.
func ReadSubStreamsInfo(r io.Reader, unpackInfo *UnpackInfo) (*SubStreamsInfo, error) {
id, err := ReadByte(r)
if err != nil {
return nil, err
}
subStreamInfo := &SubStreamsInfo{}
subStreamInfo.NumUnpackStreamsInFolders = make([]int, len(unpackInfo.Folders))
for i := range subStreamInfo.NumUnpackStreamsInFolders {
subStreamInfo.NumUnpackStreamsInFolders[i] = 1
}
if id == k7zNumUnpackStream {
for i := range subStreamInfo.NumUnpackStreamsInFolders {
if subStreamInfo.NumUnpackStreamsInFolders[i], err = ReadNumberInt(r); err != nil {
return nil, err
}
}
id, err = ReadByte(r)
if err != nil {
return nil, err
}
}
for i := range unpackInfo.Folders {
if subStreamInfo.NumUnpackStreamsInFolders[i] == 0 {
continue
}
var sum uint64
if id == k7zSize {
for j := 1; j < subStreamInfo.NumUnpackStreamsInFolders[i]; j++ {
size, err := ReadNumber(r)
if err != nil {
return nil, err
}
sum += size
subStreamInfo.UnpackSizes = append(subStreamInfo.UnpackSizes, size)
}
}
subStreamInfo.UnpackSizes = append(subStreamInfo.UnpackSizes, unpackInfo.Folders[i].UnpackSize()-uint64(sum))
}
if id == k7zSize {
id, err = ReadByte(r)
if err != nil {
return nil, err
}
}
numDigests := 0
for i := range unpackInfo.Folders {
numSubStreams := subStreamInfo.NumUnpackStreamsInFolders[i]
if numSubStreams > 1 || unpackInfo.Folders[i].UnpackCRC == 0 {
numDigests += int(numSubStreams)
}
}
if id == k7zCRC {
subStreamInfo.Digests, err = ReadDigests(r, numDigests)
if err != nil {
return nil, err
}
id, err = ReadByte(r)
if err != nil {
return nil, err
}
}
if id != k7zEnd {
return nil, ErrUnexpectedPropertyID
}
return subStreamInfo, nil
}