--------------------- PatchSet 5302 Date: 2002/10/08 12:27:48 Author: rbcollins Branch: rbcollins_cxxtest Tag: (none) Log: and more Members: src/Makefile.am:1.29.2.13->1.29.2.14 src/MemBuf.c:1.8->1.8.16.1(DEAD) src/MemBuf.cc:1.1->1.1.2.1 src/Packer.c:1.4.96.1->1.4.96.2(DEAD) src/Packer.cc:1.1->1.1.2.1 Index: squid/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Makefile.am,v retrieving revision 1.29.2.13 retrieving revision 1.29.2.14 diff -u -r1.29.2.13 -r1.29.2.14 --- squid/src/Makefile.am 8 Oct 2002 11:11:34 -0000 1.29.2.13 +++ squid/src/Makefile.am 8 Oct 2002 12:27:48 -0000 1.29.2.14 @@ -179,12 +179,12 @@ logfile.cc \ main.cc \ mem.cc \ - MemBuf.c \ + MemBuf.cc \ mime.cc \ multicast.c \ neighbors.c \ net_db.c \ - Packer.c \ + Packer.cc \ $(XPROF_STATS_SOURCE) \ pconn.c \ peer_digest.c \ --- squid/src/MemBuf.c Wed Feb 14 01:07:36 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,322 +0,0 @@ - -/* - * $Id: MemBuf.c,v 1.8 2002/04/16 01:12:41 squidadm Exp $ - * - * DEBUG: section 59 auto-growing Memory Buffer with printf - * AUTHOR: Alex Rousskov - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -/* - * To-Do: use memory pools for .buf recycling @?@ @?@ - */ - -/* - * Rationale: - * ---------- - * - * Here is how one would comm_write an object without MemBuffer: - * - * { - * -- allocate: - * buf = malloc(big_enough); - * - * -- "pack": - * snprintf object(s) piece-by-piece constantly checking for overflows - * and maintaining (buf+offset); - * ... - * - * -- write - * comm_write(buf, free, ...); - * } - * - * The whole "packing" idea is quite messy: We are given a buffer of fixed - * size and we have to check all the time that we still fit. Sounds logical. - * - * However, what happens if we have more data? If we are lucky to stop before - * we overrun any buffers, we still may have garbage (e.g. half of ETag) in - * the buffer. - * - * MemBuffer: - * ---------- - * - * MemBuffer is a memory-resident buffer with printf()-like interface. It - * hides all offest handling and overflow checking. Moreover, it has a - * build-in control that no partial data has been written. - * - * MemBuffer is designed to handle relatively small data. It starts with a - * small buffer of configurable size to avoid allocating huge buffers all the - * time. MemBuffer doubles the buffer when needed. It assert()s that it will - * not grow larger than a configurable limit. MemBuffer has virtually no - * overhead (and can even reduce memory consumption) compared to old - * "packing" approach. - * - * MemBuffer eliminates both "packing" mess and truncated data: - * - * { - * -- setup - * MemBuf buf; - * - * -- required init with optional size tuning (see #defines for defaults) - * memBufInit(&buf, initial-size, absolute-maximum); - * - * -- "pack" (no need to handle offsets or check for overflows) - * memBufPrintf(&buf, ...); - * ... - * - * -- write - * comm_write_mbuf(fd, buf, handler, data); - * - * -- *iff* you did not give the buffer away, free it yourself - * -- memBufClean(&buf); - * } - */ - - -#include "squid.h" - -/* local constants */ - -/* default values for buffer sizes, used by memBufDefInit */ -#define MEM_BUF_INIT_SIZE (2*1024) -#define MEM_BUF_MAX_SIZE (2*1000*1024*1024) - - -/* local routines */ -static void memBufGrow(MemBuf * mb, mb_size_t min_cap); - - -/* init with defaults */ -void -memBufDefInit(MemBuf * mb) -{ - memBufInit(mb, MEM_BUF_INIT_SIZE, MEM_BUF_MAX_SIZE); -} - - -/* init with specific sizes */ -void -memBufInit(MemBuf * mb, mb_size_t szInit, mb_size_t szMax) -{ - assert(mb); - assert(szInit > 0 && szMax > 0); - - mb->buf = NULL; - mb->size = 0; - mb->max_capacity = szMax; - mb->capacity = 0; - mb->stolen = 0; - - memBufGrow(mb, szInit); -} - -/* - * cleans the mb; last function to call if you do not give .buf away with - * memBufFreeFunc - */ -void -memBufClean(MemBuf * mb) -{ - assert(mb); - assert(mb->buf); - assert(!mb->stolen); /* not frozen */ - - memFreeBuf(mb->capacity, mb->buf); - mb->buf = NULL; - mb->size = mb->capacity = 0; -} - -/* cleans the buffer without changing its capacity - * if called with a Null buffer, calls memBufDefInit() */ -void -memBufReset(MemBuf * mb) -{ - assert(mb); - - if (memBufIsNull(mb)) { - memBufDefInit(mb); - } else { - assert(!mb->stolen); /* not frozen */ - /* reset */ - memset(mb->buf, 0, mb->capacity); - mb->size = 0; - } -} - -/* unfortunate hack to test if the buffer has been Init()ialized */ -int -memBufIsNull(MemBuf * mb) -{ - assert(mb); - if (!mb->buf && !mb->max_capacity && !mb->capacity && !mb->size) - return 1; /* is null (not initialized) */ - assert(mb->buf && mb->max_capacity && mb->capacity); /* paranoid */ - return 0; -} - - -/* calls memcpy, appends exactly size bytes, extends buffer if needed */ -void -memBufAppend(MemBuf * mb, const char *buf, mb_size_t sz) -{ - assert(mb && buf && sz >= 0); - assert(mb->buf); - assert(!mb->stolen); /* not frozen */ - - if (sz > 0) { - if (mb->size + sz + 1 > mb->capacity) - memBufGrow(mb, mb->size + sz + 1); - assert(mb->size + sz <= mb->capacity); /* paranoid */ - xmemcpy(mb->buf + mb->size, buf, sz); - mb->size += sz; - mb->buf[mb->size] = '\0'; /* \0 terminate in case we are used as a string. Not counted in the size */ - } -} - -/* calls memBufVPrintf */ -#if STDC_HEADERS -void -memBufPrintf(MemBuf * mb, const char *fmt,...) -{ - va_list args; - va_start(args, fmt); -#else -void -memBufPrintf(va_alist) - va_dcl -{ - va_list args; - MemBuf *mb = NULL; - const char *fmt = NULL; - mb_size_t sz = 0; - va_start(args); - mb = va_arg(args, MemBuf *); - fmt = va_arg(args, char *); -#endif - memBufVPrintf(mb, fmt, args); - va_end(args); -} - - -/* vprintf for other printf()'s to use; calls vsnprintf, extends buf if needed */ -void -memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs) -{ - int sz = 0; - assert(mb && fmt); - assert(mb->buf); - assert(!mb->stolen); /* not frozen */ - /* assert in Grow should quit first, but we do not want to have a scary infinite loop */ - while (mb->capacity <= mb->max_capacity) { - mb_size_t free_space = mb->capacity - mb->size; - /* put as much as we can */ - sz = vsnprintf(mb->buf + mb->size, free_space, fmt, vargs); - /* check for possible overflow */ - /* snprintf on Linuz returns -1 on overflows */ - /* snprintf on FreeBSD returns at least free_space on overflows */ - if (sz < 0 || sz >= free_space) - memBufGrow(mb, mb->capacity + 1); - else - break; - } - mb->size += sz; - /* on Linux and FreeBSD, '\0' is not counted in return value */ - /* on XXX it might be counted */ - /* check that '\0' is appended and not counted */ - if (!mb->size || mb->buf[mb->size - 1]) { - assert(!mb->buf[mb->size]); - } else { - mb->size--; - } -} - -/* - * returns free() function to be used. - * Important: - * calling this function "freezes" mb, - * do not _update_ mb after that in any way - * (you still can read-access .buf and .size) - */ -FREE * -memBufFreeFunc(MemBuf * mb) -{ - FREE *ff; - assert(mb); - assert(mb->buf); - assert(!mb->stolen); /* not frozen */ - - ff = memFreeBufFunc((size_t) mb->capacity); - mb->stolen = 1; /* freeze */ - return ff; -} - -/* grows (doubles) internal buffer to satisfy required minimal capacity */ -static void -memBufGrow(MemBuf * mb, mb_size_t min_cap) -{ - size_t new_cap; - size_t buf_cap; - - assert(mb); - assert(!mb->stolen); - assert(mb->capacity < min_cap); - - /* determine next capacity */ - if (min_cap > 64 * 1024) { - new_cap = 64 * 1024; - while (new_cap < (size_t) min_cap) - new_cap += 64 * 1024; /* increase in reasonable steps */ - } else { - new_cap = (size_t) min_cap; - } - - /* last chance to fit before we assert(!overflow) */ - if (new_cap > (size_t) mb->max_capacity) - new_cap = (size_t) mb->max_capacity; - - assert(new_cap <= (size_t) mb->max_capacity); /* no overflow */ - assert(new_cap > (size_t) mb->capacity); /* progress */ - - buf_cap = (size_t) mb->capacity; - mb->buf = memReallocBuf(mb->buf, new_cap, &buf_cap); - - /* done */ - mb->capacity = (mb_size_t) buf_cap; -} - - -/* Reports */ - -/* puts report on MemBuf _module_ usage into mb */ -void -memBufReport(MemBuf * mb) -{ - assert(mb); - memBufPrintf(mb, "memBufReport is not yet implemented @?@\n"); -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/MemBuf.cc Wed Feb 14 01:07:36 2007 @@ -0,0 +1,322 @@ + +/* + * $Id: MemBuf.cc,v 1.1.2.1 2002/10/08 12:27:49 rbcollins Exp $ + * + * DEBUG: section 59 auto-growing Memory Buffer with printf + * AUTHOR: Alex Rousskov + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +/* + * To-Do: use memory pools for .buf recycling @?@ @?@ + */ + +/* + * Rationale: + * ---------- + * + * Here is how one would comm_write an object without MemBuffer: + * + * { + * -- allocate: + * buf = malloc(big_enough); + * + * -- "pack": + * snprintf object(s) piece-by-piece constantly checking for overflows + * and maintaining (buf+offset); + * ... + * + * -- write + * comm_write(buf, free, ...); + * } + * + * The whole "packing" idea is quite messy: We are given a buffer of fixed + * size and we have to check all the time that we still fit. Sounds logical. + * + * However, what happens if we have more data? If we are lucky to stop before + * we overrun any buffers, we still may have garbage (e.g. half of ETag) in + * the buffer. + * + * MemBuffer: + * ---------- + * + * MemBuffer is a memory-resident buffer with printf()-like interface. It + * hides all offest handling and overflow checking. Moreover, it has a + * build-in control that no partial data has been written. + * + * MemBuffer is designed to handle relatively small data. It starts with a + * small buffer of configurable size to avoid allocating huge buffers all the + * time. MemBuffer doubles the buffer when needed. It assert()s that it will + * not grow larger than a configurable limit. MemBuffer has virtually no + * overhead (and can even reduce memory consumption) compared to old + * "packing" approach. + * + * MemBuffer eliminates both "packing" mess and truncated data: + * + * { + * -- setup + * MemBuf buf; + * + * -- required init with optional size tuning (see #defines for defaults) + * memBufInit(&buf, initial-size, absolute-maximum); + * + * -- "pack" (no need to handle offsets or check for overflows) + * memBufPrintf(&buf, ...); + * ... + * + * -- write + * comm_write_mbuf(fd, buf, handler, data); + * + * -- *iff* you did not give the buffer away, free it yourself + * -- memBufClean(&buf); + * } + */ + + +#include "squid.h" + +/* local constants */ + +/* default values for buffer sizes, used by memBufDefInit */ +#define MEM_BUF_INIT_SIZE (2*1024) +#define MEM_BUF_MAX_SIZE (2*1000*1024*1024) + + +/* local routines */ +static void memBufGrow(MemBuf * mb, mb_size_t min_cap); + + +/* init with defaults */ +void +memBufDefInit(MemBuf * mb) +{ + memBufInit(mb, MEM_BUF_INIT_SIZE, MEM_BUF_MAX_SIZE); +} + + +/* init with specific sizes */ +void +memBufInit(MemBuf * mb, mb_size_t szInit, mb_size_t szMax) +{ + assert(mb); + assert(szInit > 0 && szMax > 0); + + mb->buf = NULL; + mb->size = 0; + mb->max_capacity = szMax; + mb->capacity = 0; + mb->stolen = 0; + + memBufGrow(mb, szInit); +} + +/* + * cleans the mb; last function to call if you do not give .buf away with + * memBufFreeFunc + */ +void +memBufClean(MemBuf * mb) +{ + assert(mb); + assert(mb->buf); + assert(!mb->stolen); /* not frozen */ + + memFreeBuf(mb->capacity, mb->buf); + mb->buf = NULL; + mb->size = mb->capacity = 0; +} + +/* cleans the buffer without changing its capacity + * if called with a Null buffer, calls memBufDefInit() */ +void +memBufReset(MemBuf * mb) +{ + assert(mb); + + if (memBufIsNull(mb)) { + memBufDefInit(mb); + } else { + assert(!mb->stolen); /* not frozen */ + /* reset */ + memset(mb->buf, 0, mb->capacity); + mb->size = 0; + } +} + +/* unfortunate hack to test if the buffer has been Init()ialized */ +int +memBufIsNull(MemBuf * mb) +{ + assert(mb); + if (!mb->buf && !mb->max_capacity && !mb->capacity && !mb->size) + return 1; /* is null (not initialized) */ + assert(mb->buf && mb->max_capacity && mb->capacity); /* paranoid */ + return 0; +} + + +/* calls memcpy, appends exactly size bytes, extends buffer if needed */ +void +memBufAppend(MemBuf * mb, const char *buf, mb_size_t sz) +{ + assert(mb && buf && sz >= 0); + assert(mb->buf); + assert(!mb->stolen); /* not frozen */ + + if (sz > 0) { + if (mb->size + sz + 1 > mb->capacity) + memBufGrow(mb, mb->size + sz + 1); + assert(mb->size + sz <= mb->capacity); /* paranoid */ + xmemcpy(mb->buf + mb->size, buf, sz); + mb->size += sz; + mb->buf[mb->size] = '\0'; /* \0 terminate in case we are used as a string. Not counted in the size */ + } +} + +/* calls memBufVPrintf */ +#if STDC_HEADERS +void +memBufPrintf(MemBuf * mb, const char *fmt,...) +{ + va_list args; + va_start(args, fmt); +#else +void +memBufPrintf(va_alist) + va_dcl +{ + va_list args; + MemBuf *mb = NULL; + const char *fmt = NULL; + mb_size_t sz = 0; + va_start(args); + mb = va_arg(args, MemBuf *); + fmt = va_arg(args, char *); +#endif + memBufVPrintf(mb, fmt, args); + va_end(args); +} + + +/* vprintf for other printf()'s to use; calls vsnprintf, extends buf if needed */ +void +memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs) +{ + int sz = 0; + assert(mb && fmt); + assert(mb->buf); + assert(!mb->stolen); /* not frozen */ + /* assert in Grow should quit first, but we do not want to have a scary infinite loop */ + while (mb->capacity <= mb->max_capacity) { + mb_size_t free_space = mb->capacity - mb->size; + /* put as much as we can */ + sz = vsnprintf(mb->buf + mb->size, free_space, fmt, vargs); + /* check for possible overflow */ + /* snprintf on Linuz returns -1 on overflows */ + /* snprintf on FreeBSD returns at least free_space on overflows */ + if (sz < 0 || sz >= free_space) + memBufGrow(mb, mb->capacity + 1); + else + break; + } + mb->size += sz; + /* on Linux and FreeBSD, '\0' is not counted in return value */ + /* on XXX it might be counted */ + /* check that '\0' is appended and not counted */ + if (!mb->size || mb->buf[mb->size - 1]) { + assert(!mb->buf[mb->size]); + } else { + mb->size--; + } +} + +/* + * returns free() function to be used. + * Important: + * calling this function "freezes" mb, + * do not _update_ mb after that in any way + * (you still can read-access .buf and .size) + */ +FREE * +memBufFreeFunc(MemBuf * mb) +{ + FREE *ff; + assert(mb); + assert(mb->buf); + assert(!mb->stolen); /* not frozen */ + + ff = memFreeBufFunc((size_t) mb->capacity); + mb->stolen = 1; /* freeze */ + return ff; +} + +/* grows (doubles) internal buffer to satisfy required minimal capacity */ +static void +memBufGrow(MemBuf * mb, mb_size_t min_cap) +{ + size_t new_cap; + size_t buf_cap; + + assert(mb); + assert(!mb->stolen); + assert(mb->capacity < min_cap); + + /* determine next capacity */ + if (min_cap > 64 * 1024) { + new_cap = 64 * 1024; + while (new_cap < (size_t) min_cap) + new_cap += 64 * 1024; /* increase in reasonable steps */ + } else { + new_cap = (size_t) min_cap; + } + + /* last chance to fit before we assert(!overflow) */ + if (new_cap > (size_t) mb->max_capacity) + new_cap = (size_t) mb->max_capacity; + + assert(new_cap <= (size_t) mb->max_capacity); /* no overflow */ + assert(new_cap > (size_t) mb->capacity); /* progress */ + + buf_cap = (size_t) mb->capacity; + mb->buf = (char *)memReallocBuf(mb->buf, new_cap, &buf_cap); + + /* done */ + mb->capacity = (mb_size_t) buf_cap; +} + + +/* Reports */ + +/* puts report on MemBuf _module_ usage into mb */ +void +memBufReport(MemBuf * mb) +{ + assert(mb); + memBufPrintf(mb, "memBufReport is not yet implemented @?@\n"); +} --- squid/src/Packer.c Wed Feb 14 01:07:36 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,168 +0,0 @@ - -/* - * $Id: Packer.c,v 1.4.96.1 2002/10/04 07:07:19 rbcollins Exp $ - * - * DEBUG: section 60 Packer: A uniform interface to store-like modules - * AUTHOR: Alex Rousskov - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -/* - * Rationale: - * ---------- - * - * OK, we have to major interfaces comm.c and store.c. - * - * Store.c has a nice storeAppend[Printf] capability which makes "storing" - * things easy and painless. - * - * Comm.c lacks commAppend[Printf] because comm does not handle its own - * buffers (no mem_obj equivalent for comm.c). - * - * Thus, if one wants to be able to store _and_ comm_write an object, s/he - * has to implement two almost identical functions. - * - * Packer - * ------ - * - * Packer provides for a more uniform interface to store and comm modules. - * Packer has its own append and printf routines that "know" where to send - * incoming data. In case of store interface, Packer sends data to - * storeAppend. Otherwise, Packer uses a MemBuf that can be flushed later to - * comm_write. - * - * Thus, one can write just one function that will either "pack" things for - * comm_write or "append" things to store, depending on actual packer - * supplied. - * - * It is amazing how much work a tiny object can save. :) - * - */ - - -/* - * To-Do: - */ - - -#include "squid.h" -#include "Store.h" - -/* local types */ - -/* local routines */ - -/* local constants and vars */ - -/* - * We do have one potential problem here. Both append_f and vprintf_f types - * cannot match real functions precisely (at least because of the difference in - * the type of the first parameter). Thus, we have to use type cast. If somebody - * changes the prototypes of real functions, Packer will not notice that because - * of the type cast. - * - * Solution: we use the constants below to *hard code* current prototypes of - * real functions. If real prototypes change, these constants will produce a - * warning (e.g., "warning: assignment from incompatible pointer type"). - */ - -/* append()'s */ -static void (*const store_append) (StoreEntry *, const char *, int) = &storeAppend; -static void (*const memBuf_append) (MemBuf *, const char *, mb_size_t) = &memBufAppend; - -/* vprintf()'s */ -static void (*const store_vprintf) (StoreEntry *, const char *, va_list ap) = &storeAppendVPrintf; -static void (*const memBuf_vprintf) (MemBuf *, const char *, va_list ap) = &memBufVPrintf; - - -/* init/clean */ - -/* init with this to forward data to StoreEntry */ -void -packerToStoreInit(Packer * p, StoreEntry * e) -{ - assert(p && e); - p->append = (append_f) store_append; - p->vprintf = (vprintf_f) store_vprintf; - p->real_handler = e; -} - -/* init with this to accumulate data in MemBuf */ -void -packerToMemInit(Packer * p, MemBuf * mb) -{ - assert(p && mb); - p->append = (append_f) memBuf_append; - p->vprintf = (vprintf_f) memBuf_vprintf; - p->real_handler = mb; -} - -/* call this when you are done */ -void -packerClean(Packer * p) -{ - assert(p); - /* it is not really necessary to do this, but, just in case... */ - p->append = NULL; - p->vprintf = NULL; - p->real_handler = NULL; -} - -void -packerAppend(Packer * p, const char *buf, int sz) -{ - assert(p); - assert(p->real_handler && p->append); - p->append(p->real_handler, buf, sz); -} - -#if STDC_HEADERS -void -packerPrintf(Packer * p, const char *fmt,...) -{ - va_list args; - va_start(args, fmt); -#else -void -packerPrintf(va_alist) - va_dcl -{ - va_list args; - Packer *p = NULL; - const char *fmt = NULL; - int sz = 0; - va_start(args); - p = va_arg(args, Packer *); - fmt = va_arg(args, char *); -#endif - assert(p); - assert(p->real_handler && p->vprintf); - p->vprintf(p->real_handler, fmt, args); - va_end(args); -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/Packer.cc Wed Feb 14 01:07:36 2007 @@ -0,0 +1,168 @@ + +/* + * $Id: Packer.cc,v 1.1.2.1 2002/10/08 12:27:49 rbcollins Exp $ + * + * DEBUG: section 60 Packer: A uniform interface to store-like modules + * AUTHOR: Alex Rousskov + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +/* + * Rationale: + * ---------- + * + * OK, we have to major interfaces comm.c and store.c. + * + * Store.c has a nice storeAppend[Printf] capability which makes "storing" + * things easy and painless. + * + * Comm.c lacks commAppend[Printf] because comm does not handle its own + * buffers (no mem_obj equivalent for comm.c). + * + * Thus, if one wants to be able to store _and_ comm_write an object, s/he + * has to implement two almost identical functions. + * + * Packer + * ------ + * + * Packer provides for a more uniform interface to store and comm modules. + * Packer has its own append and printf routines that "know" where to send + * incoming data. In case of store interface, Packer sends data to + * storeAppend. Otherwise, Packer uses a MemBuf that can be flushed later to + * comm_write. + * + * Thus, one can write just one function that will either "pack" things for + * comm_write or "append" things to store, depending on actual packer + * supplied. + * + * It is amazing how much work a tiny object can save. :) + * + */ + + +/* + * To-Do: + */ + + +#include "squid.h" +#include "Store.h" + +/* local types */ + +/* local routines */ + +/* local constants and vars */ + +/* + * We do have one potential problem here. Both append_f and vprintf_f types + * cannot match real functions precisely (at least because of the difference in + * the type of the first parameter). Thus, we have to use type cast. If somebody + * changes the prototypes of real functions, Packer will not notice that because + * of the type cast. + * + * Solution: we use the constants below to *hard code* current prototypes of + * real functions. If real prototypes change, these constants will produce a + * warning (e.g., "warning: assignment from incompatible pointer type"). + */ + +/* append()'s */ +static void (*const store_append) (StoreEntry *, const char *, int) = &storeAppend; +static void (*const memBuf_append) (MemBuf *, const char *, mb_size_t) = &memBufAppend; + +/* vprintf()'s */ +static void (*const store_vprintf) (StoreEntry *, const char *, va_list ap) = &storeAppendVPrintf; +static void (*const memBuf_vprintf) (MemBuf *, const char *, va_list ap) = &memBufVPrintf; + + +/* init/clean */ + +/* init with this to forward data to StoreEntry */ +void +packerToStoreInit(Packer * p, StoreEntry * e) +{ + assert(p && e); + p->append = (append_f) store_append; + p->vprintf = (vprintf_f) store_vprintf; + p->real_handler = e; +} + +/* init with this to accumulate data in MemBuf */ +void +packerToMemInit(Packer * p, MemBuf * mb) +{ + assert(p && mb); + p->append = (append_f) memBuf_append; + p->vprintf = (vprintf_f) memBuf_vprintf; + p->real_handler = mb; +} + +/* call this when you are done */ +void +packerClean(Packer * p) +{ + assert(p); + /* it is not really necessary to do this, but, just in case... */ + p->append = NULL; + p->vprintf = NULL; + p->real_handler = NULL; +} + +void +packerAppend(Packer * p, const char *buf, int sz) +{ + assert(p); + assert(p->real_handler && p->append); + p->append(p->real_handler, buf, sz); +} + +#if STDC_HEADERS +void +packerPrintf(Packer * p, const char *fmt,...) +{ + va_list args; + va_start(args, fmt); +#else +void +packerPrintf(va_alist) + va_dcl +{ + va_list args; + Packer *p = NULL; + const char *fmt = NULL; + int sz = 0; + va_start(args); + p = va_arg(args, Packer *); + fmt = va_arg(args, char *); +#endif + assert(p); + assert(p->real_handler && p->vprintf); + p->vprintf(p->real_handler, fmt, args); + va_end(args); +}