]> git.ipfire.org Git - thirdparty/squid.git/blob - src/Packer.cc
541ef04b11b43f5aef387b0396f0bd612ef1e50f
[thirdparty/squid.git] / src / Packer.cc
1
2 /*
3 * DEBUG: section 60 Packer: A uniform interface to store-like modules
4 * AUTHOR: Alex Rousskov
5 *
6 * SQUID Web Proxy Cache http://www.squid-cache.org/
7 * ----------------------------------------------------------
8 *
9 * Squid is the result of efforts by numerous individuals from
10 * the Internet community; see the CONTRIBUTORS file for full
11 * details. Many organizations have provided support for Squid's
12 * development; see the SPONSORS file for full details. Squid is
13 * Copyrighted (C) 2001 by the Regents of the University of
14 * California; see the COPYRIGHT file for full details. Squid
15 * incorporates software developed and/or copyrighted by other
16 * sources; see the CREDITS file for full details.
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
31 *
32 */
33
34 /*
35 * Rationale:
36 * ----------
37 *
38 * OK, we have to major interfaces comm.c and store.c.
39 *
40 * Store.c has a nice storeAppend[Printf] capability which makes "storing"
41 * things easy and painless.
42 *
43 * Comm.c lacks commAppend[Printf] because comm does not handle its own
44 * buffers (no mem_obj equivalent for comm.c).
45 *
46 * Thus, if one wants to be able to store _and_ Comm::Write an object, s/he
47 * has to implement two almost identical functions.
48 *
49 * Packer
50 * ------
51 *
52 * Packer provides for a more uniform interface to store and comm modules.
53 * Packer has its own append and printf routines that "know" where to send
54 * incoming data. In case of store interface, Packer sends data to
55 * storeAppend. Otherwise, Packer uses a MemBuf that can be flushed later to
56 * Comm::Write.
57 *
58 * Thus, one can write just one function that will either "pack" things for
59 * Comm::Write or "append" things to store, depending on actual packer
60 * supplied.
61 *
62 * It is amazing how much work a tiny object can save. :)
63 *
64 */
65
66 /*
67 * To-Do:
68 */
69
70 #include "squid.h"
71 #include "MemBuf.h"
72 #include "Store.h"
73
74 /* local types */
75
76 /* local routines */
77
78 /* local constants and vars */
79
80 /*
81 * We do have one potential problem here. Both append_f and vprintf_f types
82 * cannot match real functions precisely (at least because of the difference in
83 * the type of the first parameter). Thus, we have to use type cast. If somebody
84 * changes the prototypes of real functions, Packer will not notice that because
85 * of the type cast.
86 *
87 * Solution: we use the constants below to *hard code* current prototypes of
88 * real functions. If real prototypes change, these constants will produce a
89 * warning (e.g., "warning: assignment from incompatible pointer type").
90 */
91
92 static void
93 memBufAppend(MemBuf *mb, const char *buf, mb_size_t len)
94 {
95 mb->append(buf, len);
96 }
97
98 static void
99 memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs)
100 {
101 mb->vPrintf(fmt, vargs);
102 }
103
104 static void
105 storeEntryAppend(StoreEntry *e, const char *buf, int len)
106 {
107 e->append(buf, len);
108 }
109
110 /* append()'s */
111 static void (*const store_append) (StoreEntry *, const char *, int) = &storeEntryAppend;
112 static void (*const memBuf_append) (MemBuf *, const char *, mb_size_t) = &memBufAppend;
113
114 /* vprintf()'s */
115 static void (*const store_vprintf) (StoreEntry *, const char *, va_list ap) = &storeAppendVPrintf;
116 static void (*const memBuf_vprintf) (MemBuf *, const char *, va_list ap) = &memBufVPrintf;
117
118 /* init/clean */
119
120 /* init with this to forward data to StoreEntry */
121 void
122 packerToStoreInit(Packer * p, StoreEntry * e)
123 {
124 assert(p && e);
125 p->append = (append_f) store_append;
126 p->packer_vprintf = (vprintf_f) store_vprintf;
127 p->real_handler = e;
128 e->buffer();
129 }
130
131 /* init with this to accumulate data in MemBuf */
132 void
133 packerToMemInit(Packer * p, MemBuf * mb)
134 {
135 assert(p && mb);
136 p->append = (append_f) memBuf_append;
137 p->packer_vprintf = (vprintf_f) memBuf_vprintf;
138 p->real_handler = mb;
139 }
140
141 /* call this when you are done */
142 void
143 packerClean(Packer * p)
144 {
145 assert(p);
146
147 if (p->append == (append_f) store_append && p->real_handler)
148 static_cast<StoreEntry*>(p->real_handler)->flush();
149
150 /* it is not really necessary to do this, but, just in case... */
151 p->append = NULL;
152 p->packer_vprintf = NULL;
153 p->real_handler = NULL;
154 }
155
156 void
157 packerAppend(Packer * p, const char *buf, int sz)
158 {
159 assert(p);
160 assert(p->real_handler && p->append);
161 p->append(p->real_handler, buf, sz);
162 }
163
164 void
165 packerPrintf(Packer * p, const char *fmt,...)
166 {
167 va_list args;
168 va_start(args, fmt);
169
170 assert(p);
171 assert(p->real_handler && p->packer_vprintf);
172 p->packer_vprintf(p->real_handler, fmt, args);
173 va_end(args);
174 }