///|
/// Parse object-number and offset pairs from an object-stream header.
pub fn pdf_object_stream_number_offsets(
data : BytesView,
first : Int,
count : Int,
) -> Array[(Int, Int)] raise @core.PdfError {
if first < 0 || first > data.length() || count < 0 {
raise StreamDataExpected
}
let values = @syntax.pdf_parse_lexemes(@syntax.pdf_lex_view(data[0:first]))
// Guard without `count * 2`, which overflows Int for huge declared `/N`
// counts and would bypass the check (and the allocation bound below).
if count > values.length() / 2 {
raise XRefEntryExpected
}
let pairs : Array[(Int, Int)] = Array(capacity=count)
for i in 0.. 0 &&
offset >= 0 => pairs.push((object_number, offset))
_ => raise XRefEntryExpected
}
}
pairs
}
///|
/// Compute per-object content end offsets for object-stream members.
pub fn pdf_object_stream_end_offsets(
pairs : ArrayView[(Int, Int)],
data_length : Int,
first : Int,
) -> Array[Int] {
let default_end = data_length - first
let sorted : Array[(Int, Int)] = Array(capacity=pairs.length())
for index in 0.. (@hashmap.HashMap[Int, Int], Int) {
let counts : @hashmap.HashMap[Int, Int] = HashMap([])
let mut group_count = 0
for xref in xrefs {
match xref.object_stream {
Some(reference) =>
if xref.in_use && xref.object_number != 0 {
let object_stream_number = reference.object_stream_number
match counts.get(object_stream_number) {
Some(count) => counts[object_stream_number] = count + 1
None => {
counts[object_stream_number] = 1
group_count += 1
}
}
}
None => ()
}
}
(counts, group_count)
}
///|
/// Group active compressed xrefs by their containing object stream.
pub fn pdf_reader_object_stream_groups(
xrefs : ArrayView[PdfClassicXRefEntry],
) -> Array[
(Int, Array[(PdfClassicXRefEntry, @xref_model.ObjectStreamReference)]),
] {
let (counts, group_count) = pdf_reader_object_stream_group_counts(xrefs)
let groups : Array[
(Int, Array[(PdfClassicXRefEntry, @xref_model.ObjectStreamReference)]),
] = Array(capacity=group_count)
let indexes : @hashmap.HashMap[Int, Int] = HashMap([])
for xref in xrefs {
match xref.object_stream {
Some(reference) =>
if xref.in_use && xref.object_number != 0 {
match indexes.get(reference.object_stream_number) {
Some(index) => groups[index].1.push((xref, reference))
None => {
indexes[reference.object_stream_number] = groups.length()
let entries : Array[
(PdfClassicXRefEntry, @xref_model.ObjectStreamReference),
] = Array(
capacity=match counts.get(reference.object_stream_number) {
Some(count) => count
None => 1
},
)
entries.push((xref, reference))
groups.push((reference.object_stream_number, entries))
}
}
}
None => ()
}
}
groups
}