Skip to content

Commit

Permalink
Issue work (#113)
Browse files Browse the repository at this point in the history
* Add web support (Fixes #108)
* Support badly formatted PDF files (Fixes #36)
* Analysis updates
* Add test for the ByteStream warning
  • Loading branch information
NicolaVerbeeck authored Jun 3, 2024
1 parent 836871b commit 48ce78b
Show file tree
Hide file tree
Showing 35 changed files with 276 additions and 152 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 2.0.0

- Add web support
- Support badly formatted PDFs that have only 19 byte long xref sections
- **Breaking** FileStream has moved to dart_pdf_reader_io library

## 1.0.1

- Added funding to pubspec.yaml
Expand All @@ -17,7 +23,8 @@
## 0.5.0

- Add support for web by using the archive package. (#48)
- **Breaking**: EOFException and ParseException now no longer implement dart:io's IOException, just base Exception. (#48)
- **Breaking**: EOFException and ParseException now no longer implement dart:io's IOException, just base Exception. (
#48)

## 0.4.3

Expand Down
13 changes: 13 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,16 @@ linter:
- prefer_const_constructors
- prefer_final_locals
- omit_local_variable_types
- prefer_relative_imports
- avoid_print
- avoid_unnecessary_containers
- avoid_web_libraries_in_flutter
- no_logic_in_create_state
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
- sized_box_for_whitespace
- sort_child_properties_last
- use_build_context_synchronously
- use_full_hex_values_for_flutter_colors
- use_key_in_widget_constructors
2 changes: 2 additions & 0 deletions example/example.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: avoid_print

import 'dart:io';

import 'package:dart_pdf_reader/dart_pdf_reader.dart';
Expand Down
1 change: 0 additions & 1 deletion lib/dart_pdf_reader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ export 'src/parser/object_resolver.dart';
export 'src/parser/pdf_parser.dart' show PDFParser;
export 'src/utils/byte_stream.dart';
export 'src/utils/cache/buffered_random_access_stream.dart';
export 'src/utils/file_stream.dart';
export 'src/utils/random_access_stream.dart';
4 changes: 4 additions & 0 deletions lib/dart_pdf_reader_io.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
library dart_pdf_reader_io;

export 'dart_pdf_reader.dart';
export 'src/utils/file_stream.dart';
4 changes: 2 additions & 2 deletions lib/src/model/indirect_object_table.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:dart_pdf_reader/src/model/pdf_types.dart';
import 'package:dart_pdf_reader/src/parser/xref_reader.dart';
import 'pdf_types.dart';
import '../parser/xref_reader.dart';

class IndirectObjectTable {
final XRefTable _xrefTable;
Expand Down
4 changes: 2 additions & 2 deletions lib/src/model/pdf_constants.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'package:dart_pdf_reader/src/model/pdf_types.dart';
import 'pdf_types.dart';
import 'package:meta/meta.dart';

/// Collection of names used in PDF files
@immutable
final class PDFNames {
// coverage:ignore-start
PDFNames._();
const PDFNames._();

// coverage:ignore-end

Expand Down
8 changes: 4 additions & 4 deletions lib/src/model/pdf_document.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:dart_pdf_reader/src/model/pdf_constants.dart';
import 'package:dart_pdf_reader/src/model/pdf_document_catalog.dart';
import 'package:dart_pdf_reader/src/model/pdf_types.dart';
import 'package:dart_pdf_reader/src/parser/object_resolver.dart';
import 'pdf_constants.dart';
import 'pdf_document_catalog.dart';
import 'pdf_types.dart';
import '../parser/object_resolver.dart';

/// Holds the data for the PDF document.
class PDFDocument {
Expand Down
12 changes: 6 additions & 6 deletions lib/src/model/pdf_document_catalog.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'package:dart_pdf_reader/src/model/pdf_constants.dart';
import 'package:dart_pdf_reader/src/model/pdf_document.dart';
import 'package:dart_pdf_reader/src/model/pdf_outline.dart';
import 'package:dart_pdf_reader/src/model/pdf_page.dart';
import 'package:dart_pdf_reader/src/model/pdf_types.dart';
import 'package:dart_pdf_reader/src/parser/object_resolver.dart';
import 'pdf_constants.dart';
import 'pdf_document.dart';
import 'pdf_outline.dart';
import 'pdf_page.dart';
import 'pdf_types.dart';
import '../parser/object_resolver.dart';

/// The document catalog describing the document
class PDFDocumentCatalog {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/model/pdf_outline.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:dart_pdf_reader/dart_pdf_reader.dart';
import '../../dart_pdf_reader.dart';
import 'package:meta/meta.dart';

/// Action types for pdf outlines
Expand Down
10 changes: 5 additions & 5 deletions lib/src/model/pdf_page.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'dart:math';

import 'package:dart_pdf_reader/src/error/exceptions.dart';
import 'package:dart_pdf_reader/src/model/pdf_constants.dart';
import 'package:dart_pdf_reader/src/model/pdf_document.dart';
import 'package:dart_pdf_reader/src/model/pdf_types.dart';
import 'package:dart_pdf_reader/src/parser/object_resolver.dart';
import '../error/exceptions.dart';
import 'pdf_constants.dart';
import 'pdf_document.dart';
import 'pdf_types.dart';
import '../parser/object_resolver.dart';

/// Pages tree root of the document
class PDFPages {
Expand Down
10 changes: 5 additions & 5 deletions lib/src/model/pdf_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import 'dart:typed_data';

import 'package:charset/charset.dart';
import 'package:collection/collection.dart';
import 'package:dart_pdf_reader/src/error/exceptions.dart';
import 'package:dart_pdf_reader/src/model/pdf_constants.dart';
import 'package:dart_pdf_reader/src/parser/object_resolver.dart';
import 'package:dart_pdf_reader/src/utils/filter/stream_filter.dart';
import 'package:dart_pdf_reader/src/utils/random_access_stream.dart';
import '../error/exceptions.dart';
import 'pdf_constants.dart';
import '../parser/object_resolver.dart';
import '../utils/filter/stream_filter.dart';
import '../utils/random_access_stream.dart';
import 'package:meta/meta.dart';

/// Base class for all PDF objects.
Expand Down
22 changes: 11 additions & 11 deletions lib/src/parser/indirect_object_parser.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import 'package:dart_pdf_reader/src/error/exceptions.dart';
import 'package:dart_pdf_reader/src/model/indirect_object_table.dart';
import 'package:dart_pdf_reader/src/model/pdf_constants.dart';
import 'package:dart_pdf_reader/src/model/pdf_types.dart';
import 'package:dart_pdf_reader/src/parser/object_resolver.dart';
import 'package:dart_pdf_reader/src/parser/pdf_object_parser.dart';
import 'package:dart_pdf_reader/src/parser/token_stream.dart';
import 'package:dart_pdf_reader/src/parser/xref_reader.dart';
import 'package:dart_pdf_reader/src/utils/byte_stream.dart';
import 'package:dart_pdf_reader/src/utils/random_access_stream.dart';
import 'package:dart_pdf_reader/src/utils/reader_helper.dart';
import '../error/exceptions.dart';
import '../model/indirect_object_table.dart';
import '../model/pdf_constants.dart';
import '../model/pdf_types.dart';
import 'object_resolver.dart';
import 'pdf_object_parser.dart';
import 'token_stream.dart';
import 'xref_reader.dart';
import '../utils/byte_stream.dart';
import '../utils/random_access_stream.dart';
import '../utils/reader_helper.dart';

class IndirectObjectParser {
final RandomAccessStream _buffer;
Expand Down
6 changes: 3 additions & 3 deletions lib/src/parser/object_resolver.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:dart_pdf_reader/src/model/indirect_object_table.dart';
import 'package:dart_pdf_reader/src/model/pdf_types.dart';
import 'package:dart_pdf_reader/src/parser/indirect_object_parser.dart';
import '../model/indirect_object_table.dart';
import '../model/pdf_types.dart';
import 'indirect_object_parser.dart';

class ObjectResolver {
final IndirectObjectParser _indirectObjectParser;
Expand Down
10 changes: 5 additions & 5 deletions lib/src/parser/pdf_object_parser.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:dart_pdf_reader/dart_pdf_reader.dart';
import 'package:dart_pdf_reader/src/parser/indirect_object_parser.dart';
import 'package:dart_pdf_reader/src/parser/token_stream.dart';
import 'package:dart_pdf_reader/src/utils/list_extensions.dart';
import 'package:dart_pdf_reader/src/utils/reader_helper.dart';
import '../../dart_pdf_reader.dart';
import 'indirect_object_parser.dart';
import 'token_stream.dart';
import '../utils/list_extensions.dart';
import '../utils/reader_helper.dart';

class PDFObjectParser {
final RandomAccessStream _buffer;
Expand Down
23 changes: 12 additions & 11 deletions lib/src/parser/pdf_parser.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import 'package:dart_pdf_reader/src/model/indirect_object_table.dart';
import 'package:dart_pdf_reader/src/model/pdf_constants.dart';
import 'package:dart_pdf_reader/src/model/pdf_document.dart';
import 'package:dart_pdf_reader/src/model/pdf_types.dart';
import 'package:dart_pdf_reader/src/parser/indirect_object_parser.dart';
import 'package:dart_pdf_reader/src/parser/object_resolver.dart';
import 'package:dart_pdf_reader/src/parser/pdf_object_parser.dart';
import 'package:dart_pdf_reader/src/parser/xref_reader.dart';
import 'package:dart_pdf_reader/src/utils/random_access_stream.dart';
import 'package:dart_pdf_reader/src/utils/reader_helper.dart';
import '../model/indirect_object_table.dart';
import '../model/pdf_constants.dart';
import '../model/pdf_document.dart';
import '../model/pdf_types.dart';
import 'indirect_object_parser.dart';
import 'object_resolver.dart';
import 'pdf_object_parser.dart';
import 'xref_reader.dart';
import '../utils/random_access_stream.dart';
import '../utils/reader_helper.dart';
import 'package:meta/meta.dart';

/// Parses a PDF document from a [RandomAccessStream].
Expand All @@ -30,11 +30,12 @@ class PDFParser {
final objectParser = IndirectObjectParser(_buffer, table);

PDFDictionary? mainTrailer;
final first = true;
var first = true;
while (true) {
final trailer = (first && parsedXRefTrailer != null)
? parsedXRefTrailer
: await parseTrailer(objectParser, _buffer);
first = false;
mainTrailer ??= trailer;
final prev = trailer[PDFNames.prev] as PDFNumber?;
if (prev == null) break;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/parser/token_stream.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:dart_pdf_reader/src/utils/random_access_stream.dart';
import '../utils/random_access_stream.dart';

typedef CharCode = int;

Expand Down
38 changes: 25 additions & 13 deletions lib/src/parser/xref_reader.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import 'dart:math';
import 'dart:typed_data';

import 'package:dart_pdf_reader/src/error/exceptions.dart';
import 'package:dart_pdf_reader/src/model/indirect_object_table.dart';
import 'package:dart_pdf_reader/src/model/pdf_constants.dart';
import 'package:dart_pdf_reader/src/model/pdf_types.dart';
import 'package:dart_pdf_reader/src/parser/indirect_object_parser.dart';
import 'package:dart_pdf_reader/src/parser/object_resolver.dart';
import 'package:dart_pdf_reader/src/parser/pdf_object_parser.dart';
import 'package:dart_pdf_reader/src/parser/token_stream.dart';
import 'package:dart_pdf_reader/src/utils/filter/direct_byte_stream.dart';
import 'package:dart_pdf_reader/src/utils/random_access_stream.dart';
import 'package:dart_pdf_reader/src/utils/reader_helper.dart';
import '../error/exceptions.dart';
import '../model/indirect_object_table.dart';
import '../model/pdf_constants.dart';
import '../model/pdf_types.dart';
import 'indirect_object_parser.dart';
import 'object_resolver.dart';
import 'pdf_object_parser.dart';
import 'token_stream.dart';
import '../utils/filter/direct_byte_stream.dart';
import '../utils/random_access_stream.dart';
import '../utils/reader_helper.dart';
import 'package:meta/meta.dart';

@immutable
Expand Down Expand Up @@ -244,10 +244,22 @@ class _XRefSubsectionReader {
final numEntries = int.parse(parts[1]);

final entries = <XRefEntry>[];
final lineBytes = Uint8List(20);
var readSize = 20;
final lineBytes = Uint8List(readSize);
var id = startIndex;
for (var i = 0; i < numEntries; ++i) {
await stream.readBuffer(20, lineBytes);
await stream.readBuffer(readSize, lineBytes);

if (i == 0) {
final last = lineBytes.last;
if (last >= 0x30 && last <= 0x39) {
// Some lines 19 bytes long even though that is not the standard
// To support this, start using 19 by tes and step 1 back
await stream.seek((await stream.position) - 1);
// Read 19 bytes from now on
readSize = 19;
}
}

final offset = int.parse(String.fromCharCodes(lineBytes.getRange(0, 10)));
final generation =
Expand Down
2 changes: 1 addition & 1 deletion lib/src/utils/byte_stream.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:math';
import 'dart:typed_data';

import 'package:dart_pdf_reader/src/utils/random_access_stream.dart';
import 'random_access_stream.dart';

/// Implementation of [RandomAccessStream] which reads from a list of bytes
class ByteStream extends RandomAccessStream {
Expand Down
20 changes: 12 additions & 8 deletions lib/src/utils/cache/buffered_random_access_stream.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:math';
import 'dart:typed_data';

import 'package:dart_pdf_reader/src/utils/byte_stream.dart';
import 'package:dart_pdf_reader/src/utils/cache/lru_map.dart';
import 'package:dart_pdf_reader/src/utils/random_access_stream.dart';
import '../byte_stream.dart';
import '../random_access_stream.dart';
import 'lru_map.dart';

/// Implementation of [RandomAccessStream] which buffers reads from another stream
/// This is useful for improving performance when reading from a slow stream
Expand All @@ -30,11 +30,15 @@ class BufferedRandomAccessStream extends RandomAccessStream {
int maxNumBlocks = 10,
}) : _blockSize = blockSize,
_cache = LRUMap(maxNumBlocks) {
if (_stream is ByteStream) {
print(
'Warning: BufferedRandomAccessStream is not recommended for ByteStream',
);
}
assert(() {
if (_stream is ByteStream) {
// ignore: avoid_print
print(
'Warning: BufferedRandomAccessStream is not recommended for ByteStream',
);
}
return true;
}());
}

@override
Expand Down
2 changes: 1 addition & 1 deletion lib/src/utils/file_stream.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:io';
import 'dart:typed_data';

import 'package:dart_pdf_reader/src/utils/random_access_stream.dart';
import 'random_access_stream.dart';

/// Implementation of [RandomAccessStream] which reads from a file
/// Currently this does not perform smart buffering and can be quite slow
Expand Down
6 changes: 3 additions & 3 deletions lib/src/utils/filter/stream_filter.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:typed_data';

import 'package:dart_pdf_reader/dart_pdf_reader.dart';
import 'package:dart_pdf_reader/src/utils/filter/direct_byte_stream.dart';
import '../../../dart_pdf_reader.dart';
import 'direct_byte_stream.dart';
import 'package:archive/archive.dart';
import 'package:dart_pdf_reader/src/utils/list_extensions.dart';
import '../list_extensions.dart';

part 'ascii_85_decode_filter.dart';
part 'ascii_hex_decode_filter.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/src/utils/random_access_stream.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'dart:typed_data';

import 'package:dart_pdf_reader/src/error/exceptions.dart';
import '../error/exceptions.dart';

/// An abstraction of a stream of bytes that can be read from.
abstract class RandomAccessStream {
Expand Down
4 changes: 2 additions & 2 deletions lib/src/utils/reader_helper.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:typed_data';

import 'package:dart_pdf_reader/dart_pdf_reader.dart';
import 'package:dart_pdf_reader/src/parser/token_stream.dart';
import '../../dart_pdf_reader.dart';
import '../parser/token_stream.dart';

abstract class ReaderHelper {
/// Try to read the first non-empty line from the buffer, stripping comments
Expand Down
6 changes: 3 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: dart_pdf_reader
description: Small pure-dart library for parsing PDF files. Supports reading all pdf structures
version: 1.0.1
version: 2.0.0
repository: https://github.com/NicolaVerbeeck/dart_pdf_reader
issue_tracker: https://github.com/NicolaVerbeeck/dart_pdf_reader/issues
topics: [pdf, parser]
topics: [ pdf, parser ]

environment:
sdk: '>=3.0.0 <4.0.0'
Expand All @@ -15,7 +15,7 @@ dependencies:
meta: '>=1.9.1 < 2.0.0'

dev_dependencies:
lints: ">=2.0.0 <5.0.0"
lints: ^4.0.0
test: ^1.21.0
mocktail: ^1.0.0
convert: ^3.1.1
Expand Down
Loading

0 comments on commit 48ce78b

Please sign in to comment.