5
5
from . import ffi
6
6
from .ffi import (
7
7
ARCHIVE_EOF , OPEN_CALLBACK , READ_CALLBACK , CLOSE_CALLBACK , SEEK_CALLBACK ,
8
- VOID_CB , page_size ,
8
+ NO_OPEN_CB , NO_CLOSE_CB , page_size ,
9
9
)
10
10
from .entry import ArchiveEntry , new_archive_entry
11
11
@@ -57,15 +57,17 @@ def new_archive_read(format_name='all', filter_name='all', passphrase=None):
57
57
@contextmanager
58
58
def custom_reader (
59
59
read_func , format_name = 'all' , filter_name = 'all' ,
60
- open_func = VOID_CB , close_func = VOID_CB , block_size = page_size ,
61
- archive_read_class = ArchiveRead , passphrase = None ,
60
+ open_func = None , seek_func = None , close_func = None ,
61
+ block_size = page_size , archive_read_class = ArchiveRead , passphrase = None ,
62
62
):
63
63
"""Read an archive using a custom function.
64
64
"""
65
- open_cb = OPEN_CALLBACK (open_func )
65
+ open_cb = OPEN_CALLBACK (open_func ) if open_func else NO_OPEN_CB
66
66
read_cb = READ_CALLBACK (read_func )
67
- close_cb = CLOSE_CALLBACK (close_func )
67
+ close_cb = CLOSE_CALLBACK (close_func ) if close_func else NO_CLOSE_CB
68
68
with new_archive_read (format_name , filter_name , passphrase ) as archive_p :
69
+ if seek_func :
70
+ ffi .read_set_seek_callback (archive_p , SEEK_CALLBACK (seek_func ))
69
71
ffi .read_open (archive_p , None , open_cb , read_cb , close_cb )
70
72
yield archive_read_class (archive_p )
71
73
@@ -117,36 +119,9 @@ def stream_reader(
117
119
"""Read an archive from a stream.
118
120
119
121
The `stream` object must support the standard `readinto` method.
120
- """
121
- buf = create_string_buffer (block_size )
122
- buf_p = cast (buf , c_void_p )
123
122
124
- def read_func (archive_p , context , ptrptr ):
125
- # readinto the buffer, returns number of bytes read
126
- length = stream .readinto (buf )
127
- # write the address of the buffer into the pointer
128
- ptrptr = cast (ptrptr , POINTER (c_void_p ))
129
- ptrptr [0 ] = buf_p
130
- # tell libarchive how much data was written into the buffer
131
- return length
132
-
133
- open_cb = OPEN_CALLBACK (VOID_CB )
134
- read_cb = READ_CALLBACK (read_func )
135
- close_cb = CLOSE_CALLBACK (VOID_CB )
136
- with new_archive_read (format_name , filter_name , passphrase ) as archive_p :
137
- ffi .read_open (archive_p , None , open_cb , read_cb , close_cb )
138
- yield ArchiveRead (archive_p )
139
-
140
-
141
- @contextmanager
142
- def seekable_stream_reader (
143
- stream , format_name = 'all' , filter_name = 'all' , block_size = page_size ,
144
- passphrase = None ,
145
- ):
146
- """Read an archive from a seekable stream.
147
-
148
- The `stream` object must support the standard `readinto`, 'seek' and
149
- 'tell' methods.
123
+ If `stream.seekable()` returns `True`, then an appropriate seek callback is
124
+ passed to libarchive.
150
125
"""
151
126
buf = create_string_buffer (block_size )
152
127
buf_p = cast (buf , c_void_p )
@@ -165,11 +140,14 @@ def seek_func(archive_p, context, offset, whence):
165
140
# tell libarchive the current position
166
141
return stream .tell ()
167
142
168
- open_cb = OPEN_CALLBACK ( VOID_CB )
143
+ open_cb = NO_OPEN_CB
169
144
read_cb = READ_CALLBACK (read_func )
170
- seek_cb = SEEK_CALLBACK (seek_func )
171
- close_cb = CLOSE_CALLBACK (VOID_CB )
145
+ close_cb = NO_CLOSE_CB
172
146
with new_archive_read (format_name , filter_name , passphrase ) as archive_p :
173
- ffi .read_set_seek_callback (archive_p , seek_cb )
147
+ if stream .seekable ():
148
+ ffi .read_set_seek_callback (archive_p , SEEK_CALLBACK (seek_func ))
174
149
ffi .read_open (archive_p , None , open_cb , read_cb , close_cb )
175
150
yield ArchiveRead (archive_p )
151
+
152
+
153
+ seekable_stream_reader = stream_reader
0 commit comments