summaryrefslogtreecommitdiff
path: root/serf_bucket_util.h
blob: 6ff3035dcfaf692d3b40230953642a1be4504d1e (plain)
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
279
280
281
282
283
284
285
286
/* Copyright 2002-2004 Justin Erenkrantz and Greg Stein
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SERF_BUCKET_UTIL_H
#define SERF_BUCKET_UTIL_H

/**
 * @file serf_bucket_util.h
 * @brief This header defines a set of functions and other utilities
 * for implementing buckets. It is not needed by users of the bucket
 * system.
 */

#include "serf.h"

#ifdef __cplusplus
extern "C" {
#endif


/**
 * Basic bucket creation function.
 *
 * This function will create a bucket of @a type, allocating the necessary
 * memory from @a allocator. The @a data bucket-private information will
 * be stored into the bucket.
 */
serf_bucket_t *serf_bucket_create(
    const serf_bucket_type_t *type,
    serf_bucket_alloc_t *allocator,
    void *data);

/**
 * Default implementation of the @see read_iovec functionality.
 *
 * This function will use the @see read function to get a block of memory,
 * then return it in the iovec.
 */
apr_status_t serf_default_read_iovec(
    serf_bucket_t *bucket,
    apr_size_t requested,
    int vecs_size,
    struct iovec *vecs,
    int *vecs_used);

/**
 * Default implementation of the @see read_for_sendfile functionality.
 *
 * This function will use the @see read function to get a block of memory,
 * then return it as a header. No file will be returned.
 */
apr_status_t serf_default_read_for_sendfile(
    serf_bucket_t *bucket,
    apr_size_t requested,
    apr_hdtr_t *hdtr,
    apr_file_t **file,
    apr_off_t *offset,
    apr_size_t *len);

/**
 * Default implementation of the @see read_bucket functionality.
 *
 * This function will always return NULL, indicating that the @a type
 * of bucket cannot be found within @a bucket.
 */
serf_bucket_t *serf_default_read_bucket(
    serf_bucket_t *bucket,
    const serf_bucket_type_t *type);

/**
 * Default implementation of the @see destroy functionality.
 *
 * This function will return the @a bucket to its allcoator.
 */
void serf_default_destroy(
    serf_bucket_t *bucket);


/**
 * Default implementation of the @see destroy functionality.
 *
 * This function will return the @a bucket, and the data member to its
 * allocator.
 */
void serf_default_destroy_and_data(
    serf_bucket_t *bucket);


/**
 * Allocate @a size bytes of memory using @a allocator.
 *
 * Returns NULL of the requested memory size could not be allocated.
 */
void *serf_bucket_mem_alloc(
    serf_bucket_alloc_t *allocator,
    apr_size_t size);

/**
 * Allocate @a size bytes of memory using @a allocator and set all of the
 * memory to 0.
 *
 * Returns NULL of the requested memory size could not be allocated.
 */
void *serf_bucket_mem_calloc(
    serf_bucket_alloc_t *allocator,
    apr_size_t size);

/**
 * Free the memory at @a block, returning it to @a allocator.
 */
void serf_bucket_mem_free(
    serf_bucket_alloc_t *allocator,
    void *block);


/**
 * Analogous to apr_pstrmemdup, using a bucket allocator instead.
 */
char *serf_bstrmemdup(
    serf_bucket_alloc_t *allocator,
    const char *str,
    apr_size_t size);

/**
 * Analogous to apr_pmemdup, using a bucket allocator instead.
 */
void * serf_bmemdup(
    serf_bucket_alloc_t *allocator,
    const void *mem,
    apr_size_t size);

/**
 * Analogous to apr_pstrdup, using a bucket allocator instead.
 */
char * serf_bstrdup(
    serf_bucket_alloc_t *allocator,
    const char *str);


/**
 * Read data up to a newline.
 *
 * @a acceptable contains the allowed forms of a newline, and @a found
 * will return the particular newline type that was found. If a newline
 * is not found, then SERF_NEWLINE_NONE will be placed in @a found.
 *
 * @a data should contain a pointer to the data to be scanned. @a len
 * should specify the length of that data buffer. On exit, @a data will
 * be advanced past the newline, and @a len will specify the remaining
 * amount of data in the buffer.
 *
 * Given this pattern of behavior, the caller should store the initial
 * value of @a data as the line start. The difference between the
 * returned value of @a data and the saved start is the length of the
 * line.
 *
 * Note that the newline character(s) will remain within the buffer.
 * This function scans at a byte level for the newline characters. Thus,
 * the data buffer may contain NUL characters. As a corollary, this
 * function only works on 8-bit character encodings.
 *
 * If the data is fully consumed (@a len gets set to zero) and a CR
 * character is found at the end and the CRLF sequence is allowed, then
 * this function may store SERF_NEWLINE_CRLF_SPLIT into @a found. The
 * caller should take particular consideration for the CRLF sequence
 * that may be split across data buffer boundaries.
 */
void serf_util_readline(
    const char **data,
    apr_size_t *len,
    int acceptable,
    int *found);


/** The buffer size used within @see serf_databuf_t. */
#define SERF_DATABUF_BUFSIZE 8000

/** Callback function which is used to refill the data buffer.
 *
 * The function takes @a baton, which is the @see read_baton value
 * from the serf_databuf_t structure. Data should be placed into
 * a buffer specified by @a buf, which is @a bufsize bytes long.
 * The amount of data read should be returned in @a len.
 *
 * APR_EOF should be returned if no more data is available. APR_EAGAIN
 * should be returned, rather than blocking. In both cases, @a buf
 * should be filled in and @a len set, as appropriate.
 */
typedef apr_status_t (*serf_databuf_reader_t)(
    void *baton,
    apr_size_t bufsize,
    char *buf,
    apr_size_t *len);

/**
 * This structure is used as an intermediate data buffer for some "external"
 * source of data. It works as a scratch pad area for incoming data to be
 * stored, and then returned as a ptr/len pair by the bucket read functions.
 *
 * This structure should be initialized by calling @see serf_databuf_init.
 * Users should not bother to zero the structure beforehand.
 */
typedef struct {
    /** The current data position within the buffer. */
    const char *current;

    /** Amount of data remaining in the buffer. */
    apr_size_t remaining;

    /** Callback function. */
    serf_databuf_reader_t read;

    /** A baton to hold context-specific data. */
    void *read_baton;

    /** Records the status from the last @see read operation. */
    apr_status_t status;

    /** Holds the data until it can be returned. */
    char buf[SERF_DATABUF_BUFSIZE];

} serf_databuf_t;

/**
 * Initialize the @see serf_databuf_t structure specified by @a databuf.
 */
void serf_databuf_init(
    serf_databuf_t *databuf);

/**
 * Implement a bucket-style read function from the @see serf_databuf_t
 * structure given by @a databuf.
 *
 * The @a requested, @a data, and @a len fields are interpreted and used
 * as in the read function of @see serf_bucket_t.
 */
apr_status_t serf_databuf_read(
    serf_databuf_t *databuf,
    apr_size_t requested,
    const char **data,
    apr_size_t *len);

/**
 * Implement a bucket-style readline function from the @see serf_databuf_t
 * structure given by @a databuf.
 *
 * The @a acceptable, @a found, @a data, and @a len fields are interpreted
 * and used as in the read function of @see serf_bucket_t.
 */
apr_status_t serf_databuf_readline(
    serf_databuf_t *databuf,
    int acceptable,
    int *found,
    const char **data,
    apr_size_t *len);

/**
 * Implement a bucket-style peek function from the @see serf_databuf_t
 * structure given by @a databuf.
 *
 * The @a data, and @a len fields are interpreted and used as in the
 * peek function of @see serf_bucket_t.
 */
apr_status_t serf_databuf_peek(
    serf_databuf_t *databuf,
    const char **data,
    apr_size_t *len);


#ifdef __cplusplus
}
#endif

#endif	/* !SERF_BUCKET_UTIL_H */