mirror of
https://github.com/UglyToad/PdfPig.git
synced 2026-03-10 00:23:29 +08:00
remove cos object key completely and test indirect reference
This commit is contained in:
@@ -0,0 +1,89 @@
|
|||||||
|
namespace UglyToad.PdfPig.Tests.ContentStream
|
||||||
|
{
|
||||||
|
using PdfPig.ContentStream;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class IndirectReferenceTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void SetsProperties()
|
||||||
|
{
|
||||||
|
var reference = new IndirectReference(129, 45);
|
||||||
|
|
||||||
|
Assert.Equal(129, reference.ObjectNumber);
|
||||||
|
Assert.Equal(45, reference.Generation);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToStringCorrect()
|
||||||
|
{
|
||||||
|
var reference = new IndirectReference(130, 70);
|
||||||
|
|
||||||
|
Assert.Equal("130 70", reference.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TwoIndirectReferenceEqual()
|
||||||
|
{
|
||||||
|
var reference1 = new IndirectReference(1574, 690);
|
||||||
|
var reference2 = new IndirectReference(1574, 690);
|
||||||
|
|
||||||
|
Assert.True(reference1.Equals(reference2));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TwoIndirectReferenceNotEqual()
|
||||||
|
{
|
||||||
|
var reference1 = new IndirectReference(1574, 690);
|
||||||
|
var reference2 = new IndirectReference(12, 0);
|
||||||
|
|
||||||
|
Assert.False(reference1.Equals(reference2));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TwoIndirectHashCodeEqual()
|
||||||
|
{
|
||||||
|
var reference1 = new IndirectReference(1267775544, 690);
|
||||||
|
var reference2 = new IndirectReference(1267775544, 690);
|
||||||
|
|
||||||
|
Assert.Equal(reference1.GetHashCode(), reference2.GetHashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TwoIndirectHashCodeNotEqual()
|
||||||
|
{
|
||||||
|
var reference1 = new IndirectReference(1267775544, 690);
|
||||||
|
var reference2 = new IndirectReference(1267775544, 12);
|
||||||
|
|
||||||
|
Assert.NotEqual(reference1.GetHashCode(), reference2.GetHashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TwoIndirectHashCodeSimilarValuesNotEqual()
|
||||||
|
{
|
||||||
|
var reference1 = new IndirectReference(12, 1);
|
||||||
|
var reference2 = new IndirectReference(1, 12);
|
||||||
|
|
||||||
|
Assert.NotEqual(reference1.GetHashCode(), reference2.GetHashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OtherObjectNotEqual()
|
||||||
|
{
|
||||||
|
var reference = new IndirectReference(1267775544, 690);
|
||||||
|
var obj = "test";
|
||||||
|
|
||||||
|
// ReSharper disable once SuspiciousTypeConversion.Global
|
||||||
|
Assert.False(reference.Equals(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NullNotEqual()
|
||||||
|
{
|
||||||
|
var reference = new IndirectReference(1267775544, 690);
|
||||||
|
|
||||||
|
// ReSharper disable once SuspiciousTypeConversion.Global
|
||||||
|
Assert.False(reference.Equals(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
// ReSharper disable ObjectCreationAsStatement
|
|
||||||
namespace UglyToad.PdfPig.Tests.Cos
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using PdfPig.Cos;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
public class CosObjectKeyTests
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public void NullObjectThrows()
|
|
||||||
{
|
|
||||||
Action action = () => new CosObjectKey(null);
|
|
||||||
|
|
||||||
Assert.Throws<ArgumentNullException>(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void CanLookupInDictionary()
|
|
||||||
{
|
|
||||||
var key1 = new CosObjectKey(3, 0);
|
|
||||||
var key2 = new CosObjectKey(3, 0);
|
|
||||||
|
|
||||||
var dictionary = new Dictionary<CosObjectKey, long>
|
|
||||||
{
|
|
||||||
{key1, 5}
|
|
||||||
};
|
|
||||||
|
|
||||||
var result = dictionary[key2];
|
|
||||||
|
|
||||||
Assert.Equal(5, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-12
@@ -140,18 +140,7 @@
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CanBeNull]
|
|
||||||
public static CosObjectKey GetObjectKey(this PdfDictionary dictionary, CosName key)
|
|
||||||
{
|
|
||||||
if (!dictionary.TryGetValue(key, out var value) || !(value is CosObject obj))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CosObjectKey(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
public static PdfDictionary GetDictionaryOrDefault(this PdfDictionary dictionary,
|
public static PdfDictionary GetDictionaryOrDefault(this PdfDictionary dictionary,
|
||||||
CosName key)
|
CosName key)
|
||||||
|
|||||||
@@ -19,11 +19,6 @@
|
|||||||
SetObject(obj);
|
SetObject(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CosObjectKey GetObjectKey()
|
|
||||||
{
|
|
||||||
return new CosObjectKey(objectNumber, generationNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will get the dictionary object in this object that has the name key and
|
* This will get the dictionary object in this object that has the name key and
|
||||||
* if it is a pdfobjref then it will dereference that and return it.
|
* if it is a pdfobjref then it will dereference that and return it.
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
namespace UglyToad.PdfPig.Cos
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
internal class CosObjectKey : IComparable<CosObjectKey>
|
|
||||||
{
|
|
||||||
public long Number { get; }
|
|
||||||
public long Generation { get; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PDFObjectKey constructor comment.
|
|
||||||
*
|
|
||||||
* @param object The object that this key will represent.
|
|
||||||
*/
|
|
||||||
public CosObjectKey(CosObject obj) : this(GetNumber(obj), obj.GetGenerationNumber())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long GetNumber(CosObject obj)
|
|
||||||
{
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj.GetObjectNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CosObjectKey(long num, int gen)
|
|
||||||
{
|
|
||||||
Number = num;
|
|
||||||
Generation = gen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
CosObjectKey objToBeCompared = obj is CosObjectKey ? (CosObjectKey)obj : null;
|
|
||||||
return objToBeCompared != null &&
|
|
||||||
objToBeCompared.Number == Number &&
|
|
||||||
objToBeCompared.Generation == Generation;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool Equals(CosObjectKey other)
|
|
||||||
{
|
|
||||||
return Number == other.Number && Generation == other.Generation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
unchecked
|
|
||||||
{
|
|
||||||
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
|
|
||||||
return (int)((Number.GetHashCode() * 397) ^ Generation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{Number} {Generation} R";
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareTo(CosObjectKey other)
|
|
||||||
{
|
|
||||||
if (Number < other.Number)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (Number > other.Number)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Generation < other.Generation)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (Generation > other.Generation)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -32,14 +32,7 @@
|
|||||||
arguments.IsLenientParsing,
|
arguments.IsLenientParsing,
|
||||||
requiresExistingObject);
|
requiresExistingObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CosBase Parse(ParsingArguments arguments, CosObjectKey key, bool requiresExistingObject)
|
|
||||||
{
|
|
||||||
return Parse(arguments.Reader, key.Number, (int)key.Generation, arguments.CachingProviders.ObjectPool,
|
|
||||||
arguments.CrossReferenceTable, arguments.CachingProviders.BruteForceSearcher,
|
|
||||||
arguments.IsLenientParsing, requiresExistingObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CosBase Parse(IRandomAccessRead reader, CosObject obj, CosObjectPool pool,
|
public CosBase Parse(IRandomAccessRead reader, CosObject obj, CosObjectPool pool,
|
||||||
CrossReferenceTable crossReferenceTable, BruteForceSearcher bruteForceSearcher, bool isLenient, bool requireExistingObject)
|
CrossReferenceTable crossReferenceTable, BruteForceSearcher bruteForceSearcher, bool isLenient, bool requireExistingObject)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,334 +0,0 @@
|
|||||||
namespace UglyToad.PdfPig.Parser
|
|
||||||
{
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Cos;
|
|
||||||
|
|
||||||
internal class XrefTrailerResolver
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class which represents a xref/trailer object.
|
|
||||||
*/
|
|
||||||
private class XrefTrailerObj
|
|
||||||
{
|
|
||||||
public CosDictionary trailer = null;
|
|
||||||
|
|
||||||
public XRefType xrefType;
|
|
||||||
|
|
||||||
public readonly Dictionary<CosObjectKey, long> xrefTable = new Dictionary<CosObjectKey, long>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor.
|
|
||||||
*/
|
|
||||||
public XrefTrailerObj()
|
|
||||||
{
|
|
||||||
xrefType = XRefType.TABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
xrefTable.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The XRefType of a trailer.
|
|
||||||
*/
|
|
||||||
public enum XRefType
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* XRef table type.
|
|
||||||
*/
|
|
||||||
TABLE,
|
|
||||||
/**
|
|
||||||
* XRef stream type.
|
|
||||||
*/
|
|
||||||
STREAM
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly Dictionary<long, XrefTrailerObj> bytePosToXrefMap = new Dictionary<long, XrefTrailerObj>();
|
|
||||||
private XrefTrailerObj curXrefTrailerObj = null;
|
|
||||||
private XrefTrailerObj resolvedXrefTrailer = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the first trailer if at least one exists.
|
|
||||||
*
|
|
||||||
* @return the first trailer or null
|
|
||||||
*/
|
|
||||||
public CosDictionary getFirstTrailer()
|
|
||||||
{
|
|
||||||
return getPositionalTrailer(Position.Last);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the last trailer if at least one exists.
|
|
||||||
*
|
|
||||||
* @return the last trailer ir null
|
|
||||||
*/
|
|
||||||
public CosDictionary getLastTrailer()
|
|
||||||
{
|
|
||||||
return getPositionalTrailer(Position.Last);
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Position
|
|
||||||
{
|
|
||||||
First,
|
|
||||||
Last
|
|
||||||
}
|
|
||||||
|
|
||||||
private CosDictionary getPositionalTrailer(Position position)
|
|
||||||
{
|
|
||||||
if (bytePosToXrefMap.Count == 0)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ordered = bytePosToXrefMap.Keys.OrderBy(x => x);
|
|
||||||
|
|
||||||
var key = position == Position.First ? ordered.First() : ordered.Last();
|
|
||||||
|
|
||||||
if (!bytePosToXrefMap.TryGetValue(key, out XrefTrailerObj result))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.trailer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the count of trailers.
|
|
||||||
*
|
|
||||||
* @return the count of trailers.
|
|
||||||
*/
|
|
||||||
public int getTrailerCount()
|
|
||||||
{
|
|
||||||
return bytePosToXrefMap.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signals that a new XRef object (table or stream) starts.
|
|
||||||
* @param startBytePos the offset to start at
|
|
||||||
* @param type the type of the Xref object
|
|
||||||
*/
|
|
||||||
public void nextXrefObj(long startBytePos, XRefType type)
|
|
||||||
{
|
|
||||||
bytePosToXrefMap[startBytePos] = curXrefTrailerObj = new XrefTrailerObj();
|
|
||||||
curXrefTrailerObj.xrefType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the XRefTxpe of the resolved trailer.
|
|
||||||
*
|
|
||||||
* @return the XRefType or null.
|
|
||||||
*/
|
|
||||||
public XRefType? getXrefType()
|
|
||||||
{
|
|
||||||
return resolvedXrefTrailer?.xrefType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populate XRef HashMap of current XRef object.
|
|
||||||
* Will add an Xreftable entry that maps ObjectKeys to byte offsets in the file.
|
|
||||||
* @param objKey The objkey, with id and gen numbers
|
|
||||||
* @param offset The byte offset in this file
|
|
||||||
*/
|
|
||||||
public void setXRef(CosObjectKey objKey, long offset)
|
|
||||||
{
|
|
||||||
if (curXrefTrailerObj == null)
|
|
||||||
{
|
|
||||||
// should not happen...
|
|
||||||
// LOG.warn("Cannot add XRef entry for '" + objKey.getNumber() + "' because XRef start was not signalled.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// PDFBOX-3506 check before adding to the map, to avoid entries from the table being
|
|
||||||
// overwritten by obsolete entries in hybrid files (/XRefStm entry)
|
|
||||||
if (!curXrefTrailerObj.xrefTable.ContainsKey(objKey))
|
|
||||||
{
|
|
||||||
curXrefTrailerObj.xrefTable[objKey] = offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds trailer information for current XRef object.
|
|
||||||
*
|
|
||||||
* @param trailer the current document trailer dictionary
|
|
||||||
*/
|
|
||||||
public void setTrailer(CosDictionary trailer)
|
|
||||||
{
|
|
||||||
if (curXrefTrailerObj == null)
|
|
||||||
{
|
|
||||||
// should not happen...
|
|
||||||
//LOG.warn("Cannot add trailer because XRef start was not signalled.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
curXrefTrailerObj.trailer = trailer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the trailer last set by {@link #setTrailer(COSDictionary)}.
|
|
||||||
*
|
|
||||||
* @return the current trailer.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public CosDictionary getCurrentTrailer()
|
|
||||||
{
|
|
||||||
return curXrefTrailerObj.trailer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the byte position of the first XRef
|
|
||||||
* (has to be called after very last startxref was read).
|
|
||||||
* This is used to resolve chain of active XRef/trailer.
|
|
||||||
*
|
|
||||||
* In case startxref position is not found we output a
|
|
||||||
* warning and use all XRef/trailer objects combined
|
|
||||||
* in byte position order.
|
|
||||||
* Thus for incomplete PDF documents with missing
|
|
||||||
* startxref one could call this method with parameter value -1.
|
|
||||||
*
|
|
||||||
* @param startxrefBytePosValue starting position of the first XRef
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void setStartxref(long startxrefBytePosValue)
|
|
||||||
{
|
|
||||||
if (resolvedXrefTrailer != null)
|
|
||||||
{
|
|
||||||
//LOG.warn("Method must be called only ones with last startxref value.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvedXrefTrailer = new XrefTrailerObj { trailer = new CosDictionary() };
|
|
||||||
|
|
||||||
bytePosToXrefMap.TryGetValue(startxrefBytePosValue, out XrefTrailerObj curObj);
|
|
||||||
|
|
||||||
List<long> xrefSeqBytePos = new List<long>();
|
|
||||||
|
|
||||||
if (curObj == null)
|
|
||||||
{
|
|
||||||
// no XRef at given position
|
|
||||||
//LOG.warn("Did not found XRef object at specified startxref position " + startxrefBytePosValue);
|
|
||||||
|
|
||||||
// use all objects in byte position order (last entries overwrite previous ones)
|
|
||||||
xrefSeqBytePos.AddRange(bytePosToXrefMap.Keys);
|
|
||||||
xrefSeqBytePos.Sort();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// copy xref type
|
|
||||||
resolvedXrefTrailer.xrefType = curObj.xrefType;
|
|
||||||
// found starting Xref object
|
|
||||||
// add this and follow chain defined by 'Prev' keys
|
|
||||||
xrefSeqBytePos.Add(startxrefBytePosValue);
|
|
||||||
while (curObj.trailer != null)
|
|
||||||
{
|
|
||||||
long prevBytePos = curObj.trailer.getLong(CosName.PREV, -1L);
|
|
||||||
if (prevBytePos == -1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytePosToXrefMap.TryGetValue(prevBytePos, out curObj);
|
|
||||||
if (curObj == null)
|
|
||||||
{
|
|
||||||
//LOG.warn("Did not found XRef object pointed to by 'Prev' key at position " + prevBytePos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
xrefSeqBytePos.Add(prevBytePos);
|
|
||||||
|
|
||||||
// sanity check to prevent infinite loops
|
|
||||||
if (xrefSeqBytePos.Count >= bytePosToXrefMap.Count)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// have to reverse order so that later XRefs will overwrite previous ones
|
|
||||||
xrefSeqBytePos.Reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
// merge used and sorted XRef/trailer
|
|
||||||
foreach (long bPos in xrefSeqBytePos)
|
|
||||||
{
|
|
||||||
bytePosToXrefMap.TryGetValue(bPos, out curObj);
|
|
||||||
if (curObj.trailer != null)
|
|
||||||
{
|
|
||||||
resolvedXrefTrailer.trailer.addAll(curObj.trailer);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var item in curObj.xrefTable)
|
|
||||||
{
|
|
||||||
resolvedXrefTrailer.xrefTable[item.Key] = item.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the resolved trailer. Might return <code>null</code> in case
|
|
||||||
* {@link #setStartxref(long)} was not called before.
|
|
||||||
*
|
|
||||||
* @return the trailer if available
|
|
||||||
*/
|
|
||||||
public CosDictionary getTrailer()
|
|
||||||
{
|
|
||||||
return (resolvedXrefTrailer == null) ? null : resolvedXrefTrailer.trailer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the resolved xref table. Might return <code>null</code> in case
|
|
||||||
* {@link #setStartxref(long)} was not called before.
|
|
||||||
*
|
|
||||||
* @return the xrefTable if available
|
|
||||||
*/
|
|
||||||
public Dictionary<CosObjectKey, long> getXrefTable()
|
|
||||||
{
|
|
||||||
return (resolvedXrefTrailer == null) ? null : resolvedXrefTrailer.xrefTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns object numbers which are referenced as contained
|
|
||||||
* in object stream with specified object number.
|
|
||||||
*
|
|
||||||
* This will scan resolved xref table for all entries having negated
|
|
||||||
* stream object number as value.
|
|
||||||
*
|
|
||||||
* @param objstmObjNr object number of object stream for which contained object numbers
|
|
||||||
* should be returned
|
|
||||||
*
|
|
||||||
* @return set of object numbers referenced for given object stream
|
|
||||||
* or <code>null</code> if {@link #setStartxref(long)} was not
|
|
||||||
* called before so that no resolved xref table exists
|
|
||||||
*/
|
|
||||||
public ISet<long> getContainedObjectNumbers(int objstmObjNr)
|
|
||||||
{
|
|
||||||
if (resolvedXrefTrailer == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ISet<long> refObjNrs = new HashSet<long>();
|
|
||||||
long cmpVal = -objstmObjNr;
|
|
||||||
|
|
||||||
foreach (var xrefEntry in resolvedXrefTrailer.xrefTable)
|
|
||||||
{
|
|
||||||
if (xrefEntry.Value == cmpVal)
|
|
||||||
{
|
|
||||||
refObjNrs.Add(xrefEntry.Key.Number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return refObjNrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset all data so that it can be used to rebuild the trailer.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
foreach (XrefTrailerObj trailerObj in bytePosToXrefMap.Values)
|
|
||||||
{
|
|
||||||
trailerObj.reset();
|
|
||||||
}
|
|
||||||
curXrefTrailerObj = null;
|
|
||||||
resolvedXrefTrailer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user