]> git.ipfire.org Git - thirdparty/squid.git/blame - src/Packer.cc
Boilerplate: update copyright blurbs on src/
[thirdparty/squid.git] / src / Packer.cc
CommitLineData
cb69b4c7 1/*
bbc27441 2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
e25c139f 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
cb69b4c7 7 */
8
bbc27441
AJ
9/* DEBUG: section 60 Packer: A uniform interface to store-like modules */
10
adba4a64 11/*
2ac76861 12 * Rationale:
13 * ----------
26ac0430 14 *
bbc27441 15 * OK, we have two major interfaces comm.c and store.c.
26ac0430 16 *
2ac76861 17 * Store.c has a nice storeAppend[Printf] capability which makes "storing"
26ac0430
AJ
18 * things easy and painless.
19 *
2ac76861 20 * Comm.c lacks commAppend[Printf] because comm does not handle its own
21 * buffers (no mem_obj equivalent for comm.c).
26ac0430 22 *
ec41b64c 23 * Thus, if one wants to be able to store _and_ Comm::Write an object, s/he
2ac76861 24 * has to implement two almost identical functions.
26ac0430 25 *
2ac76861 26 * Packer
27 * ------
26ac0430 28 *
2ac76861 29 * Packer provides for a more uniform interface to store and comm modules.
30 * Packer has its own append and printf routines that "know" where to send
31 * incoming data. In case of store interface, Packer sends data to
32 * storeAppend. Otherwise, Packer uses a MemBuf that can be flushed later to
ec41b64c 33 * Comm::Write.
26ac0430 34 *
2ac76861 35 * Thus, one can write just one function that will either "pack" things for
ec41b64c 36 * Comm::Write or "append" things to store, depending on actual packer
2ac76861 37 * supplied.
26ac0430 38 *
eb139d08 39 * It is amazing how much work a tiny object can save. :)
cb69b4c7 40 */
41
582c2af2 42#include "squid.h"
0eb49b6d 43#include "MemBuf.h"
602d9612 44#include "Store.h"
cb69b4c7 45
cb69b4c7 46/*
47 * We do have one potential problem here. Both append_f and vprintf_f types
48 * cannot match real functions precisely (at least because of the difference in
49 * the type of the first parameter). Thus, we have to use type cast. If somebody
50 * changes the prototypes of real functions, Packer will not notice that because
51 * of the type cast.
52 *
53 * Solution: we use the constants below to *hard code* current prototypes of
54 * real functions. If real prototypes change, these constants will produce a
55 * warning (e.g., "warning: assignment from incompatible pointer type").
56 */
57
2fe7eff9 58static void
59memBufAppend(MemBuf *mb, const char *buf, mb_size_t len)
60{
61 mb->append(buf, len);
62}
63
64static void
65memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs)
66{
67 mb->vPrintf(fmt, vargs);
68}
69
3900307b 70static void
71storeEntryAppend(StoreEntry *e, const char *buf, int len)
72{
73 e->append(buf, len);
74}
75
cb69b4c7 76/* append()'s */
3900307b 77static void (*const store_append) (StoreEntry *, const char *, int) = &storeEntryAppend;
2ac76861 78static void (*const memBuf_append) (MemBuf *, const char *, mb_size_t) = &memBufAppend;
cb69b4c7 79
80/* vprintf()'s */
2ac76861 81static void (*const store_vprintf) (StoreEntry *, const char *, va_list ap) = &storeAppendVPrintf;
82static void (*const memBuf_vprintf) (MemBuf *, const char *, va_list ap) = &memBufVPrintf;
cb69b4c7 83
adba4a64 84/* init/clean */
85
86/* init with this to forward data to StoreEntry */
cb69b4c7 87void
2ac76861 88packerToStoreInit(Packer * p, StoreEntry * e)
cb69b4c7 89{
90 assert(p && e);
2ac76861 91 p->append = (append_f) store_append;
866be921 92 p->packer_vprintf = (vprintf_f) store_vprintf;
cb69b4c7 93 p->real_handler = e;
3900307b 94 e->buffer();
cb69b4c7 95}
96
adba4a64 97/* init with this to accumulate data in MemBuf */
cb69b4c7 98void
2ac76861 99packerToMemInit(Packer * p, MemBuf * mb)
cb69b4c7 100{
101 assert(p && mb);
2ac76861 102 p->append = (append_f) memBuf_append;
866be921 103 p->packer_vprintf = (vprintf_f) memBuf_vprintf;
cb69b4c7 104 p->real_handler = mb;
105}
106
adba4a64 107/* call this when you are done */
cb69b4c7 108void
2ac76861 109packerClean(Packer * p)
cb69b4c7 110{
2ac76861 111 assert(p);
b89401f3 112
113 if (p->append == (append_f) store_append && p->real_handler)
3900307b 114 static_cast<StoreEntry*>(p->real_handler)->flush();
b89401f3 115
2ac76861 116 /* it is not really necessary to do this, but, just in case... */
117 p->append = NULL;
866be921 118 p->packer_vprintf = NULL;
2ac76861 119 p->real_handler = NULL;
cb69b4c7 120}
121
122void
2ac76861 123packerAppend(Packer * p, const char *buf, int sz)
cb69b4c7 124{
125 assert(p);
126 assert(p->real_handler && p->append);
127 p->append(p->real_handler, buf, sz);
128}
129
cb69b4c7 130void
2ac76861 131packerPrintf(Packer * p, const char *fmt,...)
cb69b4c7 132{
133 va_list args;
134 va_start(args, fmt);
62e76326 135
cb69b4c7 136 assert(p);
866be921 137 assert(p->real_handler && p->packer_vprintf);
138 p->packer_vprintf(p->real_handler, fmt, args);
cb69b4c7 139 va_end(args);
140}