1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
#ifndef ARTIFEX_EXTRACT_BUFFER_H
#define ARTIFEX_EXTRACT_BUFFER_H
#include "extract_alloc.h"
#include <stddef.h>
/* Work around MSVS issues with our use of 'inline'. */
#ifdef _MSC_VER
#include "extract_compat_inline.h"
#endif
/* Reading and writing abstractions.
We use inline code in the common case where reading or writing can be satisfied
using a cache.
*/
typedef struct extract_buffer_t extract_buffer_t;
/* Abstract state for a buffer. */
static inline int extract_buffer_read(
extract_buffer_t* buffer,
void* data,
size_t numbytes,
size_t* o_actual
);
/* Reads specified number of bytes from buffer into data..+bytes, making multiple calls to
the underlying extract_buffer_fn_read function until we have read <numbytes> or reached
EOF. If we reach EOF, . Returns +1 if
short read due to EOF.
buffer:
As returned by earlier call to extract_buffer_open().
data:
Location of transferred data.
bytes:
Number of bytes transferred.
o_actual:
Optional out-param, set to actual number of bytes read. If we return zero
this will always be <numbytes>; otherwise will be less than <numbytes>.
For speed reasons, this is implemented in extract_buffer_impl.h and uses only
inline code if the requested data can be read from the cache.
*/
static inline int extract_buffer_write(
extract_buffer_t* buffer,
const void* data,
size_t numbytes,
size_t* o_actual
);
/* Writes specified data into buffer. Returns +1 if short write due to EOF.
buffer:
As returned by earlier call to extract_buffer_open().
data:
Location of source data.
bytes:
Number of bytes to copy.
out_actual:
Optional out-param, set to actual number of bytes written. If we return
zero this will always be <numbytes>; otherwise will be less than <numbytes>
and can even be negative if internal cache-flush using fn_write() fails or
returns EOF.
For speed reasons, this is implemented in extract_buffer_impl.h and uses only
inline code if there is space in the cache for the data.
*/
size_t extract_buffer_pos(extract_buffer_t* buffer);
/* Returns number of bytes read or number of bytes written so far. */
int extract_buffer_close(extract_buffer_t** io_buffer);
/* Closes down an extract_buffer_t and frees all internal resources.
Can return error or +1 for EOF if write buffer and fn_write() fails when
flushing cache.
Always sets *io_buffer to NULL. Does nothing if *io_buffer is already NULL.
*/
typedef int (*extract_buffer_fn_read)(void* handle, void* destination, size_t numbytes, size_t* o_actual);
/* Callback used by read buffer. Should read data from buffer into the supplied
destination. Short reads are not an error.
E.g. used to fill cache or to handle large reads.
Should returns 0 on success (including short read or EOF) or -1 with errno set.
handle:
As passed to extract_buffer_open().
destination:
Start of destination.
bytes:
Number of bytes in destination.
o_actual:
Out-param, set to zero if EOF. Otherwise set to the number of bytes
transferred in the range 1..<numbytes> inclusive.
*/
typedef int (*extract_buffer_fn_write)(void* handle, const void* source, size_t numbytes, size_t* o_actual);
/* Callback used by write buffer. Should write data from the supplied source
into the buffer; short writes are not an error.
E.g. used to flush cache or to handle large writes.
Should return 0 on success (including short write or EOF) or -1 with errno set.
handle:
As passed to extract_buffer_open().
source:
Start of source.
bytes:
Number of bytes in source.
o_actual:
Out-param, set to zero if EOF. Otherwise set to the number of bytes
transferred in the range 1..<numbytes> inclusive.
*/
typedef int (*extract_buffer_fn_cache)(void* handle, void** o_cache, size_t* o_numbytes);
/* Callback to flush/populate cache.
If the buffer is for writing:
Should return a memory region to which data can be written. Any data
written to a previous cache will have already been passed to fn_write() so
this can overlap or be the same as any previously-returned cache.
If the buffer is for reading:
Should return a memory region containing more data to be read. All data in
any previously-returned cache has been read so this can overlap or be the
same as any previous cache.
handle:
As passed to extract_buffer_open().
o_data:
Out-param, set to point to new cache.
o_numbytes:
Out-param, set to size of new cache.
If no data is available due to EOF, should return with *o_numbytes set to zero.
*/
typedef void (*extract_buffer_fn_close)(void* handle);
/* Called by extract_buffer_close().
handle:
As passed to extract_buffer_open().
*/
extract_alloc_t* extract_buffer_alloc(extract_buffer_t* buffer);
/* Returns the extract_alloc_t* originally passed to extract_buffer_open*(). */
int extract_buffer_open(
extract_alloc_t* alloc,
void* handle,
extract_buffer_fn_read fn_read,
extract_buffer_fn_write fn_write,
extract_buffer_fn_cache fn_cache,
extract_buffer_fn_close fn_close,
extract_buffer_t** o_buffer
);
/* Creates an extract_buffer_t that uses specified callbacks.
If fn_read is non-NULL the buffer is a read buffer, else if fn_write is
non-NULL the buffer is a write buffer. Passing non-NULL for both or neither is
not supported.
alloc:
NULL or from extract_alloc_create(). Is only used to allocate the
extract_buffer_t returned in *o_buffer.
handle:
Passed to fn_read, fn_write, fn_cache and fn_close callbacks.
fn_read:
Callback for reading data.
fn_write:
Callback for writing data.
fn_cache:
Optional cache callback.
fn_close:
Optional close callback.
o_buffer:
Out-param. Set to NULL on error.
*/
int extract_buffer_open_simple(
extract_alloc_t* alloc,
const void* data,
size_t numbytes,
void* handle,
extract_buffer_fn_close fn_close,
extract_buffer_t** o_buffer
);
/* Creates an extract_buffer_t that reads from or writes to a single fixed
block of memory.
The address region data..+data_length must exist for the lifetime of the
returned extract_buffer_t.
alloc:
NULL or from extract_alloc_create(). Is only used to allocate the
extract_buffer_t returned in *o_buffer.
data:
Start of memory region. Note that if the extract_buffer_t is used as a
write buffer then data[] will be written-to, despite the 'const'. [This
use of const avoids the need for the caller to use a cast when creating a
read-buffer.]
bytes:
Size of memory region.
handle:
Passed to fn_close.
fn_close:
Optional callback called by extract_buffer_close(). E.g. could copy the
memory region elsewhere if the buffer was used as a write buffer.
o_buffer:
Out-param.
*/
int extract_buffer_open_file(
extract_alloc_t* alloc,
const char* path,
int writable,
extract_buffer_t** o_buffer
);
/* Creates a buffer that reads from, or writes to, a file. For portability
uses an internal FILE* rather than an integer file descriptor, so doesn't use
extract_buffer's caching support because FILE* already provides caching.
path:
Path of file to read from.
writable:
We create read buffer if zero, else a write buffer.
o_buffer:
Out-param. Set to NULL on error.
*/
typedef struct
{
extract_buffer_t* buffer;
char* data;
size_t alloc_size;
size_t data_size;
} extract_buffer_expanding_t;
/* A write buffer that writes to an automatically-growing contiguous area of
memory. */
int extract_buffer_expanding_create(
extract_alloc_t* alloc,
extract_buffer_expanding_t* buffer_expanding
);
/* Creates a writable buffer that writes into an automatically-growing
contiguous area of memory.
alloc:
NULL or from extract_alloc_create().
buffer_expanding:
Out-param; *buffer_expanding is initialised.
Initialises buffer_expanding. buffer_expanding->buffer can be passed to
extract_buffer_*() functions. After buffer_close(), the written data is
available in buffer_expanding->data..+data_size, which will have been allocated
using <alloc>. */
/* Include implementations of inline-functions. */
#include "extract_buffer_impl.h"
#endif
|