getStartNextLineAfter(Marker::STREAM, $startOffsetObject, $endOffsetObject) ?? throw new ParseFailureException(sprintf('Unable to locate marker %s', Marker::STREAM->value)); if ($dictionary->getTypeForKey(DictionaryKey::LENGTH) === IntegerValue::class && ($lengthInteger = $dictionary->getValueForKey(DictionaryKey::LENGTH, IntegerValue::class)) !== null) { $length = $lengthInteger->value; } else { $endStreamPos = $stream->lastPos(Marker::END_STREAM, $stream->getSizeInBytes() - $endOffsetObject) ?? throw new ParseFailureException(sprintf('Unable to locate marker %s', Marker::END_STREAM->value)); $eolPos = $stream->getEndOfCurrentLine($endStreamPos - 1, $endOffsetObject) ?? throw new ParseFailureException(sprintf('Unable to locate marker %s', WhitespaceCharacter::LINE_FEED->value)); $length = $eolPos - $startStreamPos; } $content = bin2hex(CompressedObjectContentParser::parseBinary($stream, $startStreamPos, $length, $dictionary)->toString()); $first = $dictionary->getValueForKey(DictionaryKey::FIRST, IntegerValue::class) ?? throw new RuntimeException('Expected a dictionary entry for "First", none found'); $buffer = new InfiniteBuffer(); $previousObjectNumber = null; $byteOffsets = []; foreach (str_split(substr($content, 0, $first->value * 2), 2) as $char) { $decodedChar = mb_chr((int) hexdec($char)); if (WhitespaceCharacter::tryFrom($decodedChar) !== null) { $numberInBuffer = $buffer->__toString(); if (trim($numberInBuffer) === '') { $buffer->flush(); continue; } if ($numberInBuffer !== (string)(int) $numberInBuffer) { throw new ParseFailureException(sprintf('Number "%s" in buffer is not a valid number', $numberInBuffer)); } $numberInBuffer = (int) $numberInBuffer; if ($previousObjectNumber !== null) { $byteOffsets[$previousObjectNumber] = $numberInBuffer; $previousObjectNumber = null; } else { $previousObjectNumber = $numberInBuffer; } $buffer->flush(); continue; } $buffer->addChar($decodedChar); } return new CompressedObjectByteOffsets($byteOffsets); } }