func (this *PdfReader) readXref() error {
	var err error
	r := bufio.NewReader(this.f)
	_, err = this.f.Seek(int64(this.xrefPos), 0)
	if err != nil {
		return errors.Wrap(err, "Failed to set position of file")
	}
	t, err := this.readToken(r)
	if err != nil {
		return errors.Wrap(err, "Failed to read token")
	}
	if t != "xref" {
		v, err := this.readValue(r, t)
		if err != nil {
			return errors.Wrap(err, "Failed to read XRef stream")
		}
		if v.Type == PDF_TYPE_OBJDEC {
			t, err = this.readToken(r)
			if err != nil {
				return errors.Wrap(err, "Failed to read token")
			}
			v, err := this.readValue(r, t)
			if err != nil {
				return errors.Wrap(err, "Failed to read value for token: "+t)
			}
			if _, ok := v.Dictionary["/Type"]; ok {
				if v.Dictionary["/Type"].Token == "/XRef" {
					paethDecode := false
					if _, ok := v.Dictionary["/DecodeParms"]; ok {
						columns := 0
						predictor := 0
						if _, ok2 := v.Dictionary["/DecodeParms"].Dictionary["/Columns"]; ok2 {
							columns = v.Dictionary["/DecodeParms"].Dictionary["/Columns"].Int
						}
						if _, ok2 := v.Dictionary["/DecodeParms"].Dictionary["/Predictor"]; ok2 {
							predictor = v.Dictionary["/DecodeParms"].Dictionary["/Predictor"].Int
						}
						if columns > 4 || predictor > 12 {
							return errors.New("Unsupported /DecodeParms - only tested with /Columns <= 4 and /Predictor <= 12")
						}
						paethDecode = true
					}
					index := make([]int, 2)
					if _, ok := v.Dictionary["/Index"]; ok {
						if len(v.Dictionary["/Index"].Array) < 2 {
							return errors.Wrap(err, "Index array does not contain 2 elements")
						}
						index[0] = v.Dictionary["/Index"].Array[0].Int
						index[1] = v.Dictionary["/Index"].Array[1].Int
					} else {
						index[0] = 0
					}
					prevXref := 0
					if _, ok := v.Dictionary["/Prev"]; ok {
						prevXref = v.Dictionary["/Prev"].Int
					}
					if _, ok := v.Dictionary["/Root"]; ok {
						this.trailer = v
					} else {
					}
					startObject := index[0]
					err = this.skipWhitespace(r)
					if err != nil {
						return errors.Wrap(err, "Failed to skip whitespace")
					}
					lengthDict := v.Dictionary["/Length"]
					length := lengthDict.Int
					if lengthDict.Type == PDF_TYPE_OBJREF {
						lengthDict, err = this.resolveObject(lengthDict)
						if err != nil {
							return errors.Wrap(err, "Failed to resolve length object of stream")
						}
						length = lengthDict.Value.Int
					}
					t, err = this.readToken(r)
					if err != nil {
						return errors.Wrap(err, "Failed to read token")
					}
					if t != "stream" {
						return errors.New("Expected next token to be: stream, got: " + t)
					}
					err = this.skipWhitespace(r)
					if err != nil {
						return errors.Wrap(err, "Failed to skip whitespace")
					}
					data := make([]byte, length)
					_, err := io.ReadFull(r, data)
					if err != nil {
						return errors.Wrap(err, "Failed to read bytes from buffer")
					}
					t, err = this.readToken(r)
					if err != nil {
						return errors.Wrap(err, "Failed to read token")
					}
					if t != "endstream" {
						return errors.New("Expected next token to be: endstream, got: " + t)
					}
					t, err = this.readToken(r)
					if err != nil {
						return errors.Wrap(err, "Failed to read token")
					}
					if t != "endobj" {
						return errors.New("Expected next token to be: endobj, got: " + t)
					}
					b := bytes.NewReader(data)
					z, err := zlib.NewReader(b)
					if err != nil {
						return errors.Wrap(err, "zlib.NewReader error")
					}
					defer z.Close()
					p, err := ioutil.ReadAll(z)
					if err != nil {
						return errors.Wrap(err, "ioutil.ReadAll error")
					}
					objPos := 0
					objGen := 0
					i := startObject
					var result []byte
					b = bytes.NewReader(p)
					firstFieldSize := v.Dictionary["/W"].Array[0].Int
					middleFieldSize := v.Dictionary["/W"].Array[1].Int
					lastFieldSize := v.Dictionary["/W"].Array[2].Int
					fieldSize := firstFieldSize + middleFieldSize + lastFieldSize
					if paethDecode {
						fieldSize++
					}
					prevRow := make([]byte, fieldSize)
					for {
						result = make([]byte, fieldSize)
						_, err := io.ReadFull(b, result)
						if err != nil {
							if err == io.EOF {
								break
							} else {
								return errors.Wrap(err, "io.ReadFull error")
							}
						}
						if paethDecode {
							filterPaeth(result, prevRow, fieldSize)
							copy(prevRow, result)
						}
						objectData := make([]byte, fieldSize)
						if paethDecode {
							copy(objectData, result[1:fieldSize])
						} else {
							copy(objectData, result[0:fieldSize])
						}
						if objectData[0] == 1 {
							b := make([]byte, 4)
							copy(b[4-middleFieldSize:], objectData[1:1+middleFieldSize])
							objPos = int(binary.BigEndian.Uint32(b))
							objGen = int(objectData[firstFieldSize+middleFieldSize])
							this.xref[i] = make(map[int]int, 1)
							this.xref[i][objGen] = objPos
						} else if objectData[0] == 2 {
							b := make([]byte, 4)
							copy(b[4-middleFieldSize:], objectData[1:1+middleFieldSize])
							objId := int(binary.BigEndian.Uint32(b))
							objIdx := int(objectData[firstFieldSize+middleFieldSize])
							this.xrefStream[i] = [2]int{objId, objIdx}
						}
						i++
					}
					if prevXref > 0 {
						this.xrefPos = prevXref
						xrefErr := this.readXref()
						if xrefErr != nil {
							return errors.Wrap(xrefErr, "Failed to read prev xref")
						}
					}
				}
			}
			return nil
		}
		return errors.New("Expected xref to start with 'xref'.  Got: " + t)
	}
	for {
		t, err = this.readToken(r)
		if err != nil {
			return errors.Wrap(err, "Failed to read token")
		}
		if t == "trailer" {
			break
		}
		startObject, err := strconv.Atoi(t)
		if err != nil {
			return errors.Wrap(err, "Failed to convert start object to integer: "+t)
		}
		t, err = this.readToken(r)
		if err != nil {
			return errors.Wrap(err, "Failed to read token")
		}
		numObject, err := strconv.Atoi(t)
		if err != nil {
			return errors.Wrap(err, "Failed to convert num object to integer: "+t)
		}
		for i := startObject; i < startObject+numObject; i++ {
			t, err = this.readToken(r)
			if err != nil {
				return errors.Wrap(err, "Failed to read token")
			}
			objPos, err := strconv.Atoi(t)
			if err != nil {
				return errors.Wrap(err, "Failed to convert object position to integer: "+t)
			}
			t, err = this.readToken(r)
			if err != nil {
				return errors.Wrap(err, "Failed to read token")
			}
			objGen, err := strconv.Atoi(t)
			if err != nil {
				return errors.Wrap(err, "Failed to convert object generation to integer: "+t)
			}
			objStatus, err := this.readToken(r)
			if err != nil {
				return errors.Wrap(err, "Failed to read token")
			}
			if objStatus != "f" && objStatus != "n" {
				return errors.New("Expected objStatus to be 'n' or 'f', got: " + objStatus)
			}
			this.xref[i] = make(map[int]int, 1)
			this.xref[i][objGen] = objPos
		}
	}
	t, err = this.readToken(r)
	if err != nil {
		return errors.Wrap(err, "Failed to read token")
	}
	trailer, err := this.readValue(r, t)
	if err != nil {
		return errors.Wrap(err, "Failed to read value for token: "+t)
	}
	if _, ok := trailer.Dictionary["/Root"]; ok {
		this.trailer = trailer
	}
	if tr, ok := trailer.Dictionary["/Prev"]; ok {
		this.xrefPos = tr.Int
		return this.readXref()
	}
	return nil
}
Read and parse the xref table
package gofpdi
import (
	"bufio"
	"bytes"
	"compress/zlib"
	"encoding/binary"
	"fmt"
	"github.com/pkg/errors"
	"io"
	"io/ioutil"
	"math"
	"os"
	"strconv"
)
type PdfReader struct {
	availableBoxes []string
	stack          []string
	trailer        *PdfValue
	catalog        *PdfValue
	pages          []*PdfValue
	xrefPos        int
	xref           map[int]map[int]int
	xrefStream     map[int][2]int
	f              io.ReadSeeker
	nBytes         int64
	sourceFile     string
	curPage        int
	alreadyRead    bool
	pageCount      int
}
func NewPdfReaderFromStream(rs io.ReadSeeker) (*PdfReader, error) {
	length, err := rs.Seek(0, 2)
	if err != nil {
		return nil, errors.Wrapf(err, "Failed to determine stream length")
	}
	parser := &PdfReader{f: rs, nBytes: length}
	if err := parser.init(); err != nil {
		return nil, errors.Wrap(err, "Failed to initialize parser")
	}
	if err := parser.read(); err != nil {
		return nil, errors.Wrap(err, "Failed to read pdf from stream")
	}
	return parser, nil
}
func NewPdfReader(filename string) (*PdfReader, error) {
	var err error
	f, err := os.Open(filename)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to open file")
	}
	info, err := f.Stat()
	if err != nil {
		return nil, errors.Wrap(err, "Failed to obtain file information")
	}
	parser := &PdfReader{f: f, sourceFile: filename, nBytes: info.Size()}
	if err = parser.init(); err != nil {
		return nil, errors.Wrap(err, "Failed to initialize parser")
	}
	if err = parser.read(); err != nil {
		return nil, errors.Wrap(err, "Failed to read pdf")
	}
	return parser, nil
}
func (this *PdfReader) init() error {
	this.availableBoxes = []string{"/MediaBox", "/CropBox", "/BleedBox", "/TrimBox", "/ArtBox"}
	this.xref = make(map[int]map[int]int, 0)
	this.xrefStream = make(map[int][2]int, 0)
	err := this.read()
	if err != nil {
		return errors.Wrap(err, "Failed to read pdf")
	}
	return nil
}
type PdfValue struct {
	Type       int
	String     string
	Token      string
	Int        int
	Real       float64
	Bool       bool
	Dictionary map[string]*PdfValue
	Array      []*PdfValue
	Id         int
	NewId      int
	Gen        int
	Value      *PdfValue
	Stream     *PdfValue
	Bytes      []byte
}
func (this *PdfReader) skipComments(r *bufio.Reader) error {
	var err error
	var b byte
	for {
		b, err = r.ReadByte()
		if err != nil {
			return errors.Wrap(err, "Failed to ReadByte while skipping comments")
		}
		if b == '\n' || b == '\r' {
			if b == '\r' {
				b2, err := r.ReadByte()
				if err != nil {
					return errors.Wrap(err, "Failed to read byte")
				}
				if b2 != '\n' {
					r.UnreadByte()
				}
			}
			break
		}
	}
	return nil
}
func (this *PdfReader) skipWhitespace(r *bufio.Reader) error {
	var err error
	var b byte
	for {
		b, err = r.ReadByte()
		if err != nil {
			if err == io.EOF {
				break
			}
			return errors.Wrap(err, "Failed to read byte")
		}
		if b == ' ' || b == '\n' || b == '\r' || b == '\t' {
			continue
		} else {
			r.UnreadByte()
			break
		}
	}
	return nil
}
func (this *PdfReader) readToken(r *bufio.Reader) (string, error) {
	var err error
	if len(this.stack) > 0 {
		var popped string
		popped, this.stack = this.stack[len(this.stack)-1], this.stack[:len(this.stack)-1]
		return popped, nil
	}
	err = this.skipWhitespace(r)
	if err != nil {
		return "", errors.Wrap(err, "Failed to skip whitespace")
	}
	b, err := r.ReadByte()
	if err != nil {
		if err == io.EOF {
			return "", nil
		}
		return "", errors.Wrap(err, "Failed to read byte")
	}
	switch b {
	case '[', ']', '(', ')':
		return string(b), nil
	case '<', '>':
		nb, err := r.ReadByte()
		if err != nil {
			return "", errors.Wrap(err, "Failed to read byte")
		}
		if nb == b {
			return string(b) + string(nb), nil
		} else {
			r.UnreadByte()
			return string(b), nil
		}
	case '%':
		err = this.skipComments(r)
		if err != nil {
			return "", errors.Wrap(err, "Failed to skip comments")
		}
		return this.readToken(r)
	default:
		str := string(b)
	loop:
		for {
			b, err := r.ReadByte()
			if err != nil {
				return "", errors.Wrap(err, "Failed to read byte")
			}
			switch b {
			case ' ', '%', '[', ']', '<', '>', '(', ')', '\r', '\n', '\t', '/':
				r.UnreadByte()
				break loop
			default:
				str += string(b)
			}
		}
		return str, nil
	}
	return "", nil
}
func (this *PdfReader) readValue(r *bufio.Reader, t string) (*PdfValue, error) {
	var err error
	var b byte
	result := &PdfValue{}
	result.Type = -1
	result.Token = t
	result.Dictionary = make(map[string]*PdfValue, 0)
	result.Array = make([]*PdfValue, 0)
	switch t {
	case "<":
		var s string
		for {
			b, err = r.ReadByte()
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read byte")
			}
			if b != '>' {
				s += string(b)
			} else {
				break
			}
		}
		result.Type = PDF_TYPE_HEX
		result.String = s
	case "<<":
		for {
			key, err := this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			if key == "" {
				return nil, errors.New("Token is empty")
			}
			if key == ">>" {
				break
			}
			newKey, err := this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			value, err := this.readValue(r, newKey)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read value for token: "+newKey)
			}
			if value.Type == -1 {
				return result, nil
			}
			if value.Type == PDF_TYPE_TOKEN && value.String == ">>" {
				result.Type = PDF_TYPE_NULL
				result.Dictionary[key] = value
				break
			}
			result.Dictionary[key] = value
		}
		result.Type = PDF_TYPE_DICTIONARY
		return result, nil
	case "[":
		tmpResult := make([]*PdfValue, 0)
		for {
			key, err := this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			if key == "" {
				return nil, errors.New("Token is empty")
			}
			if key == "]" {
				break
			}
			value, err := this.readValue(r, key)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read value for token: "+key)
			}
			if value.Type == -1 {
				return result, nil
			}
			tmpResult = append(tmpResult, value)
		}
		result.Type = PDF_TYPE_ARRAY
		result.Array = tmpResult
	case "(":
		openBrackets := 1
		var buf bytes.Buffer
		for openBrackets > 0 {
			b, err := r.ReadByte()
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read byte")
			}
			switch b {
			case '(':
				openBrackets++
			case ')':
				openBrackets--
			case '\\':
				nb, err := r.ReadByte()
				if err != nil {
					return nil, errors.Wrap(err, "Failed to read byte")
				}
				buf.WriteByte(b)
				buf.WriteByte(nb)
				continue
			}
			if openBrackets > 0 {
				buf.WriteByte(b)
			}
		}
		result.Type = PDF_TYPE_STRING
		result.String = buf.String()
	case "stream":
		return nil, errors.New("Stream not implemented")
	default:
		result.Type = PDF_TYPE_TOKEN
		result.Token = t
		if is_numeric(t) {
			t2, err := this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			if t2 != "" {
				if is_numeric(t2) {
					t3, err := this.readToken(r)
					if err != nil {
						return nil, errors.Wrap(err, "Failed to read token")
					}
					if t3 != "" {
						switch t3 {
						case "obj":
							result.Type = PDF_TYPE_OBJDEC
							result.Id, _ = strconv.Atoi(t)
							result.Gen, _ = strconv.Atoi(t2)
							return result, nil
						case "R":
							result.Type = PDF_TYPE_OBJREF
							result.Id, _ = strconv.Atoi(t)
							result.Gen, _ = strconv.Atoi(t2)
							return result, nil
						}
						this.stack = append(this.stack, t3)
					}
				}
				this.stack = append(this.stack, t2)
			}
			if n, err := strconv.Atoi(t); err == nil {
				result.Type = PDF_TYPE_NUMERIC
				result.Int = n
				result.Real = float64(n)  
			} else {
				result.Type = PDF_TYPE_REAL
				result.Real, _ = strconv.ParseFloat(t, 64)
			}
		} else if t == "true" || t == "false" {
			result.Type = PDF_TYPE_BOOLEAN
			result.Bool = t == "true"
		} else if t == "null" {
			result.Type = PDF_TYPE_NULL
		} else {
			result.Type = PDF_TYPE_TOKEN
			result.Token = t
		}
	}
	return result, nil
}
func (this *PdfReader) resolveCompressedObject(objSpec *PdfValue) (*PdfValue, error) {
	var err error
	if _, ok := this.xrefStream[objSpec.Id]; !ok {
		return nil, errors.New(fmt.Sprintf("Could not find object ID %d in xref stream or xref table.", objSpec.Id))
	}
	objectId := this.xrefStream[objSpec.Id][0]
	objectIndex := this.xrefStream[objSpec.Id][1]
	compressedObjSpec := &PdfValue{Type: PDF_TYPE_OBJREF, Id: objectId, Gen: 0}
	compressedObj, err := this.resolveObject(compressedObjSpec)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to resolve compressed object")
	}
	if _, ok := compressedObj.Value.Dictionary["/Type"]; ok {
		if compressedObj.Value.Dictionary["/Type"].Token != "/ObjStm" {
			return nil, errors.New("Expected compressed object type to be /ObjStm")
		}
	} else {
		return nil, errors.New("Could not determine compressed object type.")
	}
	n := compressedObj.Value.Dictionary["/N"].Int
	if n <= 0 {
		return nil, errors.New("No sub objects in compressed object")
	}
	first := compressedObj.Value.Dictionary["/First"].Int
	filter := ""
	if _, ok := compressedObj.Value.Dictionary["/Filter"]; ok {
		filter = compressedObj.Value.Dictionary["/Filter"].Token
		if filter != "/FlateDecode" {
			return nil, errors.New("Unsupported filter - expected /FlateDecode, got: " + filter)
		}
	}
	if filter == "/FlateDecode" {
		var out bytes.Buffer
		zlibReader, _ := zlib.NewReader(bytes.NewBuffer(compressedObj.Stream.Bytes))
		defer zlibReader.Close()
		io.Copy(&out, zlibReader)
		compressedObj.Stream.Bytes = out.Bytes()
	}
	r := bufio.NewReader(bytes.NewBuffer(compressedObj.Stream.Bytes))
	subObjId := 0
	subObjPos := 0
	for i := 0; i < n; i++ {
		var token string
		var _objidx int
		var _objpos int
		token, err = this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}
		_objidx, err = strconv.Atoi(token)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to convert token into integer: "+token)
		}
		token, err = this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}
		_objpos, err = strconv.Atoi(token)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to convert token into integer: "+token)
		}
		if i == objectIndex {
			subObjId = _objidx
			subObjPos = _objpos
		}
	}
	rs := io.ReadSeeker(bytes.NewReader(compressedObj.Stream.Bytes))
	seekTo := int64(subObjPos + first)
	rs.Seek(seekTo, 0)
	r = bufio.NewReader(rs)
	token, err := this.readToken(r)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to read token")
	}
	obj, err := this.readValue(r, token)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to read value for token: "+token)
	}
	result := &PdfValue{}
	result.Id = subObjId
	result.Gen = 0
	result.Type = PDF_TYPE_OBJECT
	result.Value = obj
	return result, nil
}
func (this *PdfReader) resolveObject(objSpec *PdfValue) (*PdfValue, error) {
	var err error
	var old_pos int64
	r := bufio.NewReader(this.f)
	if objSpec.Type == PDF_TYPE_OBJREF {
		offset := this.xref[objSpec.Id][objSpec.Gen]
		if _, ok := this.xref[objSpec.Id]; !ok {
			return this.resolveCompressedObject(objSpec)
		}
		old_pos, err = this.f.Seek(0, os.SEEK_CUR)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to get current position of file")
		}
		_, err = this.f.Seek(int64(offset), 0)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to set position of file")
		}
		token, err := this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}
		obj, err := this.readValue(r, token)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read value for token: "+token)
		}
		if obj.Type != PDF_TYPE_OBJDEC {
			return nil, errors.New(fmt.Sprintf("Expected type to be PDF_TYPE_OBJDEC, got: %d", obj.Type))
		}
		if obj.Id != objSpec.Id {
			return nil, errors.New(fmt.Sprintf("Object ID (%d) does not match ObjSpec ID (%d)", obj.Id, objSpec.Id))
		}
		if obj.Gen != objSpec.Gen {
			return nil, errors.New("Object Gen does not match ObjSpec Gen")
		}
		token, err = this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}
		value, err := this.readValue(r, token)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read value for token: "+token)
		}
		token, err = this.readToken(r)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to read token")
		}
		result := &PdfValue{}
		result.Id = obj.Id
		result.Gen = obj.Gen
		result.Type = PDF_TYPE_OBJECT
		result.Value = value
		if token == "stream" {
			result.Type = PDF_TYPE_STREAM
			err = this.skipWhitespace(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to skip whitespace")
			}
			lengthDict := value.Dictionary["/Length"]
			length := lengthDict.Int
			if lengthDict.Type == PDF_TYPE_OBJREF {
				lengthDict, err = this.resolveObject(lengthDict)
				if err != nil {
					return nil, errors.Wrap(err, "Failed to resolve length object of stream")
				}
				length = lengthDict.Value.Int
			}
			bytes := make([]byte, length)
			_, err := io.ReadFull(r, bytes)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read bytes from buffer")
			}
			token, err = this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			if token != "endstream" {
				return nil, errors.New("Expected next token to be: endstream, got: " + token)
			}
			token, err = this.readToken(r)
			if err != nil {
				return nil, errors.Wrap(err, "Failed to read token")
			}
			streamObj := &PdfValue{}
			streamObj.Type = PDF_TYPE_STREAM
			streamObj.Bytes = bytes
			result.Stream = streamObj
		}
		if token != "endobj" {
			return nil, errors.New("Expected next token to be: endobj, got: " + token)
		}
		_, err = this.f.Seek(old_pos, 0)
		if err != nil {
			return nil, errors.Wrap(err, "Failed to set position of file")
		}
		return result, nil
	} else {
		return objSpec, nil
	}
	return &PdfValue{}, nil
}
func (this *PdfReader) findXref() error {
	var result int
	var err error
	var toRead int64
	toRead = 1500
	fileSize := this.nBytes
	if fileSize < toRead {
		toRead = fileSize
	}
	whence := 2
	_, err = this.f.Seek(-toRead, whence)
	if err != nil {
		return errors.Wrap(err, "Failed to set position of file")
	}
	r := bufio.NewReader(this.f)
	for {
		token, err := this.readToken(r)
		if err != nil {
			return errors.Wrap(err, "Failed to read token")
		}
		if token == "startxref" {
			token, err = this.readToken(r)
			if err != nil {
				return errors.Wrap(err, "Failed to find startxref token")
			}
			result, err = strconv.Atoi(token)
			if err != nil {
				return errors.Wrap(err, "Failed to convert xref position into integer: "+token)
			}
			this.xrefPos = result
			break
		}
	}
	whence = 0
	_, err = this.f.Seek(0, whence)
	if err != nil {
		return errors.Wrap(err, "Failed to set position of file")
	}
	this.xrefPos = result
	return nil
}