doc: make blooms docs match reality
[pgsql.git] / contrib / pgcrypto / mbuf.c
blobbc668a0e802ff64e2621b6d0f3bd3f498b766e5d
1 /*
2 * mbuf.c
3 * Memory buffer operations.
5 * Copyright (c) 2005 Marko Kreen
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * contrib/pgcrypto/mbuf.c
32 #include "postgres.h"
34 #include "mbuf.h"
35 #include "px.h"
37 #define STEP (16*1024)
39 struct MBuf
41 uint8 *data;
42 uint8 *data_end;
43 uint8 *read_pos;
44 uint8 *buf_end;
45 bool no_write;
46 bool own_data;
49 int
50 mbuf_avail(MBuf *mbuf)
52 return mbuf->data_end - mbuf->read_pos;
55 int
56 mbuf_size(MBuf *mbuf)
58 return mbuf->data_end - mbuf->data;
61 int
62 mbuf_tell(MBuf *mbuf)
64 return mbuf->read_pos - mbuf->data;
67 int
68 mbuf_free(MBuf *mbuf)
70 if (mbuf->own_data)
72 px_memset(mbuf->data, 0, mbuf->buf_end - mbuf->data);
73 pfree(mbuf->data);
75 pfree(mbuf);
76 return 0;
79 static void
80 prepare_room(MBuf *mbuf, int block_len)
82 uint8 *newbuf;
83 unsigned newlen;
85 if (mbuf->data_end + block_len <= mbuf->buf_end)
86 return;
88 newlen = (mbuf->buf_end - mbuf->data)
89 + ((block_len + STEP + STEP - 1) & -STEP);
91 newbuf = repalloc(mbuf->data, newlen);
93 mbuf->buf_end = newbuf + newlen;
94 mbuf->data_end = newbuf + (mbuf->data_end - mbuf->data);
95 mbuf->read_pos = newbuf + (mbuf->read_pos - mbuf->data);
96 mbuf->data = newbuf;
99 int
100 mbuf_append(MBuf *dst, const uint8 *buf, int len)
102 if (dst->no_write)
104 px_debug("mbuf_append: no_write");
105 return PXE_BUG;
108 prepare_room(dst, len);
110 memcpy(dst->data_end, buf, len);
111 dst->data_end += len;
113 return 0;
116 MBuf *
117 mbuf_create(int len)
119 MBuf *mbuf;
121 if (!len)
122 len = 8192;
124 mbuf = palloc(sizeof *mbuf);
125 mbuf->data = palloc(len);
126 mbuf->buf_end = mbuf->data + len;
127 mbuf->data_end = mbuf->data;
128 mbuf->read_pos = mbuf->data;
130 mbuf->no_write = false;
131 mbuf->own_data = true;
133 return mbuf;
136 MBuf *
137 mbuf_create_from_data(uint8 *data, int len)
139 MBuf *mbuf;
141 mbuf = palloc(sizeof *mbuf);
142 mbuf->data = (uint8 *) data;
143 mbuf->buf_end = mbuf->data + len;
144 mbuf->data_end = mbuf->data + len;
145 mbuf->read_pos = mbuf->data;
147 mbuf->no_write = true;
148 mbuf->own_data = false;
150 return mbuf;
155 mbuf_grab(MBuf *mbuf, int len, uint8 **data_p)
157 if (len > mbuf_avail(mbuf))
158 len = mbuf_avail(mbuf);
160 mbuf->no_write = true;
162 *data_p = mbuf->read_pos;
163 mbuf->read_pos += len;
164 return len;
168 mbuf_rewind(MBuf *mbuf)
170 mbuf->read_pos = mbuf->data;
171 return 0;
175 mbuf_steal_data(MBuf *mbuf, uint8 **data_p)
177 int len = mbuf_size(mbuf);
179 mbuf->no_write = true;
180 mbuf->own_data = false;
182 *data_p = mbuf->data;
184 mbuf->data = mbuf->data_end = mbuf->read_pos = mbuf->buf_end = NULL;
186 return len;
190 * PullFilter
193 struct PullFilter
195 PullFilter *src;
196 const PullFilterOps *op;
197 int buflen;
198 uint8 *buf;
199 int pos;
200 void *priv;
204 pullf_create(PullFilter **pf_p, const PullFilterOps *op, void *init_arg, PullFilter *src)
206 PullFilter *pf;
207 void *priv;
208 int res;
210 if (op->init != NULL)
212 res = op->init(&priv, init_arg, src);
213 if (res < 0)
214 return res;
216 else
218 priv = init_arg;
219 res = 0;
222 pf = palloc0(sizeof(*pf));
223 pf->buflen = res;
224 pf->op = op;
225 pf->priv = priv;
226 pf->src = src;
227 if (pf->buflen > 0)
229 pf->buf = palloc(pf->buflen);
230 pf->pos = 0;
232 else
234 pf->buf = NULL;
235 pf->pos = 0;
237 *pf_p = pf;
238 return 0;
241 void
242 pullf_free(PullFilter *pf)
244 if (pf->op->free)
245 pf->op->free(pf->priv);
247 if (pf->buf)
249 px_memset(pf->buf, 0, pf->buflen);
250 pfree(pf->buf);
253 px_memset(pf, 0, sizeof(*pf));
254 pfree(pf);
257 /* may return less data than asked, 0 means eof */
259 pullf_read(PullFilter *pf, int len, uint8 **data_p)
261 int res;
263 if (pf->op->pull)
265 if (pf->buflen && len > pf->buflen)
266 len = pf->buflen;
267 res = pf->op->pull(pf->priv, pf->src, len, data_p,
268 pf->buf, pf->buflen);
270 else
271 res = pullf_read(pf->src, len, data_p);
272 return res;
276 pullf_read_max(PullFilter *pf, int len, uint8 **data_p, uint8 *tmpbuf)
278 int res,
279 total;
280 uint8 *tmp;
282 res = pullf_read(pf, len, data_p);
283 if (res <= 0 || res == len)
284 return res;
286 /* read was shorter, use tmpbuf */
287 memcpy(tmpbuf, *data_p, res);
288 *data_p = tmpbuf;
289 len -= res;
290 total = res;
292 while (len > 0)
294 res = pullf_read(pf, len, &tmp);
295 if (res < 0)
297 /* so the caller must clear only on success */
298 px_memset(tmpbuf, 0, total);
299 return res;
301 if (res == 0)
302 break;
303 memcpy(tmpbuf + total, tmp, res);
304 total += res;
305 len -= res;
307 return total;
311 * caller wants exactly len bytes and don't bother with references
314 pullf_read_fixed(PullFilter *src, int len, uint8 *dst)
316 int res;
317 uint8 *p;
319 res = pullf_read_max(src, len, &p, dst);
320 if (res < 0)
321 return res;
322 if (res != len)
324 px_debug("pullf_read_fixed: need=%d got=%d", len, res);
325 return PXE_PGP_CORRUPT_DATA;
327 if (p != dst)
328 memcpy(dst, p, len);
329 return 0;
333 * read from MBuf
335 static int
336 pull_from_mbuf(void *arg, PullFilter *src, int len,
337 uint8 **data_p, uint8 *buf, int buflen)
339 MBuf *mbuf = arg;
341 return mbuf_grab(mbuf, len, data_p);
344 static const struct PullFilterOps mbuf_reader = {
345 NULL, pull_from_mbuf, NULL
349 pullf_create_mbuf_reader(PullFilter **mp_p, MBuf *src)
351 return pullf_create(mp_p, &mbuf_reader, src, NULL);
356 * PushFilter
359 struct PushFilter
361 PushFilter *next;
362 const PushFilterOps *op;
363 int block_size;
364 uint8 *buf;
365 int pos;
366 void *priv;
370 pushf_create(PushFilter **mp_p, const PushFilterOps *op, void *init_arg, PushFilter *next)
372 PushFilter *mp;
373 void *priv;
374 int res;
376 if (op->init != NULL)
378 res = op->init(next, init_arg, &priv);
379 if (res < 0)
380 return res;
382 else
384 priv = init_arg;
385 res = 0;
388 mp = palloc0(sizeof(*mp));
389 mp->block_size = res;
390 mp->op = op;
391 mp->priv = priv;
392 mp->next = next;
393 if (mp->block_size > 0)
395 mp->buf = palloc(mp->block_size);
396 mp->pos = 0;
398 else
400 mp->buf = NULL;
401 mp->pos = 0;
403 *mp_p = mp;
404 return 0;
407 void
408 pushf_free(PushFilter *mp)
410 if (mp->op->free)
411 mp->op->free(mp->priv);
413 if (mp->buf)
415 px_memset(mp->buf, 0, mp->block_size);
416 pfree(mp->buf);
419 px_memset(mp, 0, sizeof(*mp));
420 pfree(mp);
423 void
424 pushf_free_all(PushFilter *mp)
426 PushFilter *tmp;
428 while (mp)
430 tmp = mp->next;
431 pushf_free(mp);
432 mp = tmp;
436 static int
437 wrap_process(PushFilter *mp, const uint8 *data, int len)
439 int res;
441 if (mp->op->push != NULL)
442 res = mp->op->push(mp->next, mp->priv, data, len);
443 else
444 res = pushf_write(mp->next, data, len);
445 if (res > 0)
446 return PXE_BUG;
447 return res;
450 /* consumes all data, returns len on success */
452 pushf_write(PushFilter *mp, const uint8 *data, int len)
454 int need,
455 res;
458 * no buffering
460 if (mp->block_size <= 0)
461 return wrap_process(mp, data, len);
464 * try to empty buffer
466 need = mp->block_size - mp->pos;
467 if (need > 0)
469 if (len < need)
471 memcpy(mp->buf + mp->pos, data, len);
472 mp->pos += len;
473 return 0;
475 memcpy(mp->buf + mp->pos, data, need);
476 len -= need;
477 data += need;
481 * buffer full, process
483 res = wrap_process(mp, mp->buf, mp->block_size);
484 if (res < 0)
485 return res;
486 mp->pos = 0;
489 * now process directly from data
491 while (len > 0)
493 if (len > mp->block_size)
495 res = wrap_process(mp, data, mp->block_size);
496 if (res < 0)
497 return res;
498 data += mp->block_size;
499 len -= mp->block_size;
501 else
503 memcpy(mp->buf, data, len);
504 mp->pos += len;
505 break;
508 return 0;
512 pushf_flush(PushFilter *mp)
514 int res;
516 while (mp)
518 if (mp->block_size > 0)
520 res = wrap_process(mp, mp->buf, mp->pos);
521 if (res < 0)
522 return res;
525 if (mp->op->flush)
527 res = mp->op->flush(mp->next, mp->priv);
528 if (res < 0)
529 return res;
532 mp = mp->next;
534 return 0;
539 * write to MBuf
541 static int
542 push_into_mbuf(PushFilter *next, void *arg, const uint8 *data, int len)
544 int res = 0;
545 MBuf *mbuf = arg;
547 if (len > 0)
548 res = mbuf_append(mbuf, data, len);
549 return res < 0 ? res : 0;
552 static const struct PushFilterOps mbuf_filter = {
553 NULL, push_into_mbuf, NULL, NULL
557 pushf_create_mbuf_writer(PushFilter **res, MBuf *dst)
559 return pushf_create(res, &mbuf_filter, dst, NULL);