in leapsectz/leapsectz.go [97:188]
func parseVx(r io.Reader) ([]LeapSecond, error) {
var ret []LeapSecond
var v byte
for v = 0; v < 2; v++ {
// 4-byte magic "TZif"
magic := make([]byte, 4)
if _, _ = r.Read(magic); string(magic) != "TZif" {
return nil, errBadData
}
// 1-byte version, then 15 bytes of padding
var version byte
p := make([]byte, 16)
if n, _ := r.Read(p); n != 16 {
return nil, errBadData
}
version = p[0]
if version != 0 && version != '2' && version != '3' {
return nil, errUnsupportedVersion
}
if v > version {
return nil, errBadData
}
var hdr Header
err := binary.Read(r, binary.BigEndian, &hdr)
if err != nil {
return nil, err
}
// skip uninteresting data:
// tzh_timecnt (char [4] or char [8] for ver 2)s coded transition times a la time(2)
// tzh_timecnt (unsigned char)s types of local time starting at above
// tzh_typecnt repetitions of
// one (char [4]) coded UT offset in seconds
// one (unsigned char) used to set tm_isdst
// one (unsigned char) that's an abbreviation list index
// tzh_charcnt (char)s '\0'-terminated zone abbreviations
var skip int
if v == 0 {
skip = int(hdr.TimeCnt)*5 + int(hdr.TypeCnt)*6 + int(hdr.CharCnt)
} else {
skip = int(hdr.TimeCnt)*9 + int(hdr.TypeCnt)*6 + int(hdr.CharCnt)
}
// if it's first part of two parts file (version 2 or 3)
// then skip it completely
if v == 0 && version > 0 {
skip += int(hdr.LeapCnt)*8 + int(hdr.IsUtcCnt) + int(hdr.IsStdCnt)
}
if n, _ := io.CopyN(ioutil.Discard, r, int64(skip)); n != int64(skip) {
return nil, errBadData
}
if v == 0 && version > 0 {
continue
}
// calculate the amount of bytes to skip after reading leap seconds array
skip = int(hdr.IsUtcCnt) + int(hdr.IsStdCnt)
for i := 0; i < int(hdr.LeapCnt); i++ {
var l LeapSecond
if version == 0 {
lsv0 := []uint32{0, 0}
err := binary.Read(r, binary.BigEndian, &lsv0)
if err != nil {
return nil, err
}
l.Tleap = uint64(lsv0[0])
l.Nleap = int32(lsv0[1])
} else {
err := binary.Read(r, binary.BigEndian, &l)
if err != nil {
return nil, err
}
}
ret = append(ret, l)
}
// we need to skip the rest of the data
_, _ = io.CopyN(ioutil.Discard, r, int64(skip))
break
}
if len(ret) == 0 {
return nil, errNoLeapSeconds
}
return ret, nil
}