func parseVx()

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
}