# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: kinkie@squid-cache.org-20080813154513-scid8h9og9nxbc84
# target_branch: http://www.squid-cache.org/bzr/squid3/trunk
# testament_sha1: 5fe2ebc86a5040d49d862d3f50256c1547ce4b29
# timestamp: 2008-08-13 17:54:29 +0200
# source_branch: ../repo/squid-trunk
# base_revision_id: squid3@treenet.co.nz-20080813102225-\
#   5eq6cy876h2qb39f
# 
# Begin patch
=== modified file 'src/ACLARP.cc'
--- src/ACLARP.cc	2008-04-06 12:37:53 +0000
+++ src/ACLARP.cc	2008-08-09 16:13:04 +0000
@@ -631,13 +631,13 @@
              arp->eth[0] & 0xff, arp->eth[1] & 0xff,
              arp->eth[2] & 0xff, arp->eth[3] & 0xff,
              arp->eth[4] & 0xff, arp->eth[5] & 0xff);
-    wordlistAdd((wordlist **)state, buf);
+    (*static_cast<wordlist **> (state))->add(buf);
 }
 
 wordlist *
 ACLARP::dump() const
 {
-    wordlist *w = NULL;
+    wordlist *w = new wordlist;
     data->walk(aclDumpArpListWalkee, &w);
     return w;
 }

=== modified file 'src/ACLCertificateData.cc'
--- src/ACLCertificateData.cc	2006-04-23 20:28:06 +0000
+++ src/ACLCertificateData.cc	2008-08-07 16:03:51 +0000
@@ -86,14 +86,14 @@
 aclDumpAttributeListWalkee(char * const & node_data, void *outlist)
 {
     /* outlist is really a wordlist ** */
-    wordlistAdd((wordlist **)outlist, node_data);
+    (*static_cast<wordlist **>(outlist))->add(node_data);
 }
 
 wordlist *
 ACLCertificateData::dump()
 {
-    wordlist *wl = NULL;
-    wordlistAdd(&wl, attribute);
+    wordlist *wl = new wordlist;
+    wl->add(attribute);
     /* damn this is VERY inefficient for long ACL lists... filling
      * a wordlist this way costs Sum(1,N) iterations. For instance
      * a 1000-elements list will be filled in 499500 iterations.

=== modified file 'src/ACLDomainData.cc'
--- src/ACLDomainData.cc	2007-04-29 04:26:37 +0000
+++ src/ACLDomainData.cc	2008-08-09 16:13:04 +0000
@@ -127,13 +127,13 @@
 aclDumpDomainListWalkee(char * const & node_data, void *outlist)
 {
     /* outlist is really a wordlist ** */
-    wordlistAdd((wordlist **)outlist, (char const *)node_data);
+    (*static_cast<wordlist **>(outlist))->add((char const *) node_data);
 }
 
 wordlist *
 ACLDomainData::dump()
 {
-    wordlist *wl = NULL;
+    wordlist *wl = new wordlist;
     /* damn this is VERY inefficient for long ACL lists... filling
      * a wordlist this way costs Sum(1,N) iterations. For instance
      * a 1000-elements list will be filled in 499500 iterations.

=== modified file 'src/ACLHTTPHeaderData.cc'
--- src/ACLHTTPHeaderData.cc	2007-05-29 19:31:36 +0000
+++ src/ACLHTTPHeaderData.cc	2008-08-13 07:05:45 +0000
@@ -73,11 +73,8 @@
 wordlist *
 ACLHTTPHeaderData::dump()
 {
-    wordlist *W = NULL;
-    wordlistAdd(&W, hdrName.buf());
-    wordlist * regex_dump = regex_rule->dump();
-    wordlistAddWl(&W, regex_dump);
-    wordlistDestroy(&regex_dump);
+    wordlist *W = new wordlist(hdrName.buf());
+    W->append(regex_rule->dump());
     return W;
 }
 

=== modified file 'src/ACLHTTPStatus.cc'
--- src/ACLHTTPStatus.cc	2007-04-29 04:26:37 +0000
+++ src/ACLHTTPStatus.cc	2008-08-09 16:13:04 +0000
@@ -193,13 +193,13 @@
 {
     static char buf[8];
     node->toStr(buf, sizeof(buf));
-    wordlistAdd((wordlist **)state, buf);
+    (*static_cast<wordlist **>(state))->add(buf);
 }
 
 wordlist *
 ACLHTTPStatus::dump() const
 {
-    wordlist *w = NULL;
+    wordlist *w = new wordlist;
     data->walk(aclDumpHTTPStatusListWalkee, &w);
     return w;
 }

=== modified file 'src/ACLIP.cc'
--- src/ACLIP.cc	2008-08-13 03:22:54 +0000
+++ src/ACLIP.cc	2008-08-13 06:16:53 +0000
@@ -73,7 +73,7 @@
     assert(mb.max_capacity > 0 && 2==2 );
     mb.append(tmpbuf, strlen(tmpbuf) );
     assert(mb.max_capacity > 0 && 3==3);
-    wordlistAdd(W, mb.buf);
+    (*W)->add(mb.buf);
     mb.clean();
 }
 
@@ -433,7 +433,7 @@
 wordlist *
 ACLIP::dump() const
 {
-    wordlist *w = NULL;
+    wordlist *w = new wordlist;
     data->walk (DumpIpListWalkee, &w);
     return w;
 }

=== modified file 'src/ACLIntRange.cc'
--- src/ACLIntRange.cc	2008-07-09 11:55:41 +0000
+++ src/ACLIntRange.cc	2008-08-07 16:03:51 +0000
@@ -111,7 +111,7 @@
 wordlist *
 ACLIntRange::dump ()
 {
-    wordlist *W = NULL;
+    wordlist *W = new wordlist;
     char buf[32];
     CbDataListIterator<RangeType> iter(ranges);
 
@@ -123,7 +123,7 @@
         else
             snprintf(buf, sizeof(buf), "%d-%d", element.start, element.end-1);
 
-        wordlistAdd(&W, buf);
+        W->add(buf);
     }
 
     return W;

=== modified file 'src/ACLMaxConnection.cc'
--- src/ACLMaxConnection.cc	2007-04-29 04:26:37 +0000
+++ src/ACLMaxConnection.cc	2008-08-07 16:03:51 +0000
@@ -104,13 +104,13 @@
     if (!limit)
         return NULL;
 
-    wordlist *W = NULL;
+    wordlist *W = new wordlist;
 
     char buf[32];
 
     snprintf(buf, sizeof(buf), "%d", limit);
 
-    wordlistAdd(&W, buf);
+    W->add(buf);
 
     return W;
 }

=== modified file 'src/ACLMaxUserIP.cc'
--- src/ACLMaxUserIP.cc	2008-06-13 13:36:53 +0000
+++ src/ACLMaxUserIP.cc	2008-08-07 16:03:51 +0000
@@ -174,16 +174,16 @@
     if (!maximum)
         return NULL;
 
-    wordlist *W = NULL;
+    wordlist *W = new wordlist;
 
     if (flags.strict)
-        wordlistAdd(&W, "-s");
+        W->add("-s");
 
     char buf[128];
 
     snprintf(buf, sizeof(buf), "%lu", (unsigned long int) maximum);
 
-    wordlistAdd(&W, buf);
+    W->add(buf);
 
     return W;
 }

=== modified file 'src/ACLMethodData.cc'
--- src/ACLMethodData.cc	2008-07-09 11:55:41 +0000
+++ src/ACLMethodData.cc	2008-08-07 16:03:51 +0000
@@ -70,11 +70,11 @@
 wordlist *
 ACLMethodData::dump()
 {
-    wordlist *W = NULL;
+    wordlist *W=new wordlist;
     CbDataList<HttpRequestMethod> *data = values;
 
     while (data != NULL) {
-        wordlistAdd(&W, RequestMethodStr(data->element));
+        W->add(RequestMethodStr(data->element));
         data = data->next;
     }
 

=== modified file 'src/ACLProtocolData.cc'
--- src/ACLProtocolData.cc	2008-07-09 11:55:41 +0000
+++ src/ACLProtocolData.cc	2008-08-07 16:03:51 +0000
@@ -69,11 +69,11 @@
 wordlist *
 ACLProtocolData::dump()
 {
-    wordlist *W = NULL;
+    wordlist *W = new wordlist;
     CbDataList<protocol_t> *data = values;
 
     while (data != NULL) {
-        wordlistAdd(&W, ProtocolStr[data->element]);
+        W->add(ProtocolStr[data->element]);
         data = data->next;
     }
 

=== modified file 'src/ACLRegexData.cc'
--- src/ACLRegexData.cc	2008-03-16 21:48:45 +0000
+++ src/ACLRegexData.cc	2008-08-07 16:03:51 +0000
@@ -103,11 +103,11 @@
 wordlist *
 ACLRegexData::dump()
 {
-    wordlist *W = NULL;
+    wordlist *W = new wordlist;
     relist *temp = data;
 
     while (temp != NULL) {
-        wordlistAdd(&W, temp->pattern);
+        W->add(temp->pattern);
         temp = temp->next;
     }
 

=== modified file 'src/ACLSslErrorData.cc'
--- src/ACLSslErrorData.cc	2008-07-09 11:55:41 +0000
+++ src/ACLSslErrorData.cc	2008-08-07 16:03:51 +0000
@@ -34,11 +34,11 @@
 wordlist *
 ACLSslErrorData::dump()
 {
-    wordlist *W = NULL;
+    wordlist *W = new wordlist;
     CbDataList<ssl_error_t> *data = values;
 
     while (data != NULL) {
-        wordlistAdd(&W, sslFindErrorString(data->element));
+        W->add(sslFindErrorString(data->element));
         data = data->next;
     }
 

=== modified file 'src/ACLStringData.cc'
--- src/ACLStringData.cc	2007-04-29 04:26:37 +0000
+++ src/ACLStringData.cc	2008-08-09 16:13:04 +0000
@@ -86,13 +86,13 @@
 aclDumpStringWalkee(char * const & node_data, void *outlist)
 {
     /* outlist is really a wordlist ** */
-    wordlistAdd((wordlist **)outlist, node_data);
+    (*static_cast<wordlist **>(outlist))->add(node_data);
 }
 
 wordlist *
 ACLStringData::dump()
 {
-    wordlist *wl = NULL;
+    wordlist *wl = new wordlist;
     /* damn this is VERY inefficient for long ACL lists... filling
      * a wordlist this way costs Sum(1,N) iterations. For instance
      * a 1000-elements list will be filled in 499500 iterations.

=== modified file 'src/ACLTimeData.cc'
--- src/ACLTimeData.cc	2008-03-16 21:48:45 +0000
+++ src/ACLTimeData.cc	2008-08-07 16:03:51 +0000
@@ -102,7 +102,7 @@
 wordlist *
 ACLTimeData::dump()
 {
-    wordlist *W = NULL;
+    wordlist *W = new wordlist;
     char buf[128];
     ACLTimeData *t = this;
 
@@ -116,7 +116,7 @@
                  t->weekbits & ACL_FRIDAY ? 'F' : '-',
                  t->weekbits & ACL_SATURDAY ? 'A' : '-',
                  t->start / 60, t->start % 60, t->stop / 60, t->stop % 60);
-        wordlistAdd(&W, buf);
+        W->add(buf);
         t = t->next;
     }
 

=== modified file 'src/ACLUserData.cc'
--- src/ACLUserData.cc	2007-04-29 04:26:37 +0000
+++ src/ACLUserData.cc	2008-08-07 16:03:51 +0000
@@ -100,23 +100,23 @@
 aclDumpUserListWalkee(char * const & node_data, void *outlist)
 {
     /* outlist is really a wordlist ** */
-    wordlistAdd((wordlist **)outlist, (char const *)node_data);
+    (*static_cast<wordlist **>(outlist))->add(node_data);
 }
 
 wordlist *
 ACLUserData::dump()
 {
-    wordlist *wl = NULL;
+    wordlist *wl = new wordlist;
 
     if (flags.case_insensitive)
-        wordlistAdd(&wl, "-i");
+        wl->add("-i");
 
     /* damn this is VERY inefficient for long ACL lists... filling
      * a wordlist this way costs Sum(1,N) iterations. For instance
      * a 1000-elements list will be filled in 499500 iterations.
      */
     if (flags.required)
-        wordlistAdd(&wl, "REQUIRED");
+        wl->add("REQUIRED");
     else if (names)
         names->walk(aclDumpUserListWalkee, &wl);
 

=== modified file 'src/ICAP/ICAPConfig.cc'
--- src/ICAP/ICAPConfig.cc	2008-04-03 05:31:29 +0000
+++ src/ICAP/ICAPConfig.cc	2008-08-09 16:13:04 +0000
@@ -43,7 +43,6 @@
 #include "HttpRequest.h"
 #include "HttpReply.h"
 #include "ACLChecklist.h"
-#include "wordlist.h"
 
 ICAPConfig TheICAPConfig;
 

=== modified file 'src/ICAP/ICAPOptions.cc'
--- src/ICAP/ICAPOptions.cc	2007-05-29 19:31:36 +0000
+++ src/ICAP/ICAPOptions.cc	2008-08-10 22:19:32 +0000
@@ -155,11 +155,11 @@
 };
 
 ICAPOptions::TransferList::~TransferList() {
-    wordlistDestroy(&extensions);
+    delete extensions;
 };
 
 void ICAPOptions::TransferList::add(const char *extension) {
-    wordlistAdd(&extensions, extension);
+    extensions->add(extension);
 };
 
 bool ICAPOptions::TransferList::matches(const String &urlPath) const {

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2008-08-09 05:59:55 +0000
+++ src/Makefile.am	2008-08-13 14:28:09 +0000
@@ -1188,6 +1188,7 @@
 	tests/testStore \
 	tests/testString \
 	tests/testURL \
+	tests/testWordlist \
 	@STORE_TESTS@
 
 ## Special Universal .h dependency test script
@@ -2513,3 +2514,28 @@
 	@REPL_OBJS@ \
 	@SQUID_CPPUNIT_LA@ \
 	${ADAPTATION_LIBS}
+
+tests_testWordlist_SOURCES = \
+    tests/testWordlist.h tests/testWordlist.cc \
+	wordlist.cc \
+	tests/testMain.cc \
+	time.cc \
+	mem.cc \
+	MemBuf.cc \
+	tests/stub_cache_manager.cc \
+	tests/stub_event.cc \
+	tests/stub_tools.cc \
+	$(TESTSOURCES)
+
+
+tests_testWordlist_LDADD = \
+	@SQUID_CPPUNIT_LIBS@ \
+	@SQUID_CPPUNIT_LA@ \
+	@XTRA_LIBS@ \
+	libsquid.la \
+	-L../lib -lmiscutil
+tests_testWordlist_LDFLAGS = $(LIBADD_DL)
+tests_testWordlist_DEPENDENCIES =  \
+    $(top_builddir)/lib/libmiscutil.a \
+	@SQUID_CPPUNIT_LA@ \
+	$(top_builddir)/lib/libmiscutil.a

=== modified file 'src/RemovalPolicy.h'
--- src/RemovalPolicy.h	2006-08-21 06:50:40 +0000
+++ src/RemovalPolicy.h	2008-08-09 16:13:04 +0000
@@ -45,7 +45,8 @@
 {
 
 public:
-    RemovalPolicySettings() : type(NULL), args(NULL) {};
+    RemovalPolicySettings() : type(NULL), args(new wordlist) {};
+    ~RemovalPolicySettings() { if (args) delete args; }
 
     char *type;
     wordlist *args;

=== modified file 'src/URLScheme.cc'
--- src/URLScheme.cc	2006-05-09 05:38:33 +0000
+++ src/URLScheme.cc	2008-08-13 14:28:09 +0000
@@ -35,7 +35,6 @@
 
 #include "squid.h"
 #include "URLScheme.h"
-#include "wordlist.h"
 
 const char *ProtocolStr[] =
     {

=== modified file 'src/adaptation/ServiceGroups.cc'
--- src/adaptation/ServiceGroups.cc	2008-04-03 23:11:40 +0000
+++ src/adaptation/ServiceGroups.cc	2008-08-12 19:57:38 +0000
@@ -21,11 +21,11 @@
 {
     ConfigParser::ParseString(&id);
 
-    wordlist *names = NULL;
+    wordlist *names = new wordlist;
     ConfigParser::ParseWordList(&names);
     for (wordlist *i = names; i; i = i->next)
         services.push_back(i->key);
-    wordlistDestroy(&names);
+    delete names;
 }
 
 void

=== modified file 'src/asn.cc'
--- src/asn.cc	2008-07-12 15:51:24 +0000
+++ src/asn.cc	2008-08-07 16:03:51 +0000
@@ -551,13 +551,13 @@
 wordlist *
 ACLASN::dump()
 {
-    wordlist *W = NULL;
+    wordlist *W = new wordlist;
     char buf[32];
     CbDataList<int> *ldata = data;
 
     while (ldata != NULL) {
         snprintf(buf, sizeof(buf), "%d", ldata->element);
-        wordlistAdd(&W, buf);
+        W->add(buf);
         ldata = ldata->next;
     }
 

=== modified file 'src/auth/basic/auth_basic.cc'
--- src/auth/basic/auth_basic.cc	2008-07-09 14:38:11 +0000
+++ src/auth/basic/auth_basic.cc	2008-08-12 19:57:38 +0000
@@ -223,8 +223,10 @@
 void
 AuthBasicConfig::done()
 {
-    if (authenticate)
-        wordlistDestroy(&authenticate);
+    if (authenticate) {
+        delete authenticate;
+        authenticate = NULL;
+    }
 
     if (basicAuthRealm)
         safe_free(basicAuthRealm);
@@ -326,9 +328,12 @@
 AuthBasicConfig::parse(AuthConfig * scheme, int n_configured, char *param_str)
 {
     if (strcasecmp(param_str, "program") == 0) {
-        if (authenticate)
-            wordlistDestroy(&authenticate);
+        if (authenticate) {
+            delete authenticate;
+            authenticate = NULL;
+        }
 
+        authenticate = new wordlist;
         parse_wordlist(&authenticate);
 
         requirePathnameExists("authparam basic program", authenticate->key);

=== modified file 'src/auth/digest/auth_digest.cc'
--- src/auth/digest/auth_digest.cc	2008-07-09 14:38:11 +0000
+++ src/auth/digest/auth_digest.cc	2008-08-12 19:57:38 +0000
@@ -900,8 +900,10 @@
 void
 AuthDigestConfig::done()
 {
-    if (authenticate)
-        wordlistDestroy(&authenticate);
+    if (authenticate) {
+        delete authenticate;
+        authenticate = NULL;
+    }
 
     safe_free(digestAuthRealm);
 }
@@ -927,9 +929,12 @@
 AuthDigestConfig::parse(AuthConfig * scheme, int n_configured, char *param_str)
 {
     if (strcasecmp(param_str, "program") == 0) {
-        if (authenticate)
-            wordlistDestroy(&authenticate);
+        if (authenticate) {
+            delete authenticate;
+            authenticate = NULL;
+        }
 
+        authenticate = new wordlist; //wordlist MUST be a valid object
         parse_wordlist(&authenticate);
 
         requirePathnameExists("authparam digest program", authenticate->key);

=== modified file 'src/auth/negotiate/auth_negotiate.cc'
--- src/auth/negotiate/auth_negotiate.cc	2008-08-06 12:51:15 +0000
+++ src/auth/negotiate/auth_negotiate.cc	2008-08-12 19:57:38 +0000
@@ -126,8 +126,10 @@
 void
 AuthNegotiateConfig::done()
 {
-    if (authenticate)
-        wordlistDestroy(&authenticate);
+    if (authenticate) {
+        delete authenticate;
+        authenticate = NULL;
+    }
 }
 
 void
@@ -154,9 +156,12 @@
 AuthNegotiateConfig::parse(AuthConfig * scheme, int n_configured, char *param_str)
 {
     if (strcasecmp(param_str, "program") == 0) {
-        if (authenticate)
-            wordlistDestroy(&authenticate);
+        if (authenticate) {
+            delete authenticate;
+            authenticate = NULL;
+        }
 
+        authenticate = new wordlist;
         parse_wordlist(&authenticate);
 
         requirePathnameExists("authparam negotiate program", authenticate->key);

=== modified file 'src/auth/ntlm/auth_ntlm.cc'
--- src/auth/ntlm/auth_ntlm.cc	2008-07-09 14:28:16 +0000
+++ src/auth/ntlm/auth_ntlm.cc	2008-08-12 19:57:38 +0000
@@ -108,8 +108,10 @@
 void
 AuthNTLMConfig::done()
 {
-    if (authenticate)
-        wordlistDestroy(&authenticate);
+    if (authenticate) {
+        delete authenticate;
+        authenticate = NULL;
+    }
 }
 
 void
@@ -136,9 +138,12 @@
 AuthNTLMConfig::parse(AuthConfig * scheme, int n_configured, char *param_str)
 {
     if (strcasecmp(param_str, "program") == 0) {
-        if (authenticate)
-            wordlistDestroy(&authenticate);
+        if (authenticate) {
+            delete authenticate;
+            authenticate = NULL;
+        }
 
+        authenticate = new wordlist;
         parse_wordlist(&authenticate);
 
         requirePathnameExists("authparam ntlm program", authenticate->key);

=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc	2008-08-10 05:05:45 +0000
+++ src/cache_cf.cc	2008-08-12 19:57:38 +0000
@@ -463,7 +463,8 @@
     if (Config.Program.redirect) {
         if (Config.redirectChildren < 1) {
             Config.redirectChildren = 0;
-            wordlistDestroy(&Config.Program.redirect);
+            delete Config.Program.redirect;
+            Config.Program.redirect = NULL;
         }
     }
 
@@ -928,7 +929,7 @@
         }
 
         storeAppendPrintf(entry, "\n");
-        wordlistDestroy(&w);
+        delete w;
         ae = ae->next;
     }
 }
@@ -1951,7 +1952,7 @@
     while ((p = *head) != NULL) {
         *head = p->next;
         xfree(p->passwd);
-        wordlistDestroy(&p->actions);
+        delete p->actions;
         xfree(p);
     }
 }
@@ -2606,8 +2607,11 @@
     char *token;
     char *t = strtok(NULL, "");
 
+    if (*list == NULL)
+    	*list = new wordlist;
+
     while ((token = strwordtok(NULL, &t)))
-        wordlistAdd(list, token);
+        (*list)->add(token);
 }
 
 #if 0 /* now unused */
@@ -2624,7 +2628,6 @@
     return a == NULL;
 }
 
-#define free_wordlist wordlistDestroy
 
 #define free_uri_whitespace free_int
 
@@ -2677,7 +2680,7 @@
 
     free_string(&(*settings)->type);
 
-    free_wordlist(&(*settings)->args);
+    delete (*settings)->args;
 
     delete *settings;
 

=== modified file 'src/client_side_request.cc'
--- src/client_side_request.cc	2008-08-13 03:24:57 +0000
+++ src/client_side_request.cc	2008-08-13 06:16:53 +0000
@@ -667,7 +667,7 @@
     const char *url = http->uri;
     HttpRequest *request = http->request;
     HttpRequestMethod method = request->method;
-    const wordlist *p = NULL;
+    const wordlist *p;
 
     /*
      * IMS needs a private key, so we can use the hierarchy for IMS only if our

=== modified file 'src/dns.cc'
--- src/dns.cc	2008-07-13 08:37:43 +0000
+++ src/dns.cc	2008-08-12 19:57:38 +0000
@@ -81,14 +81,14 @@
 
     assert(dnsservers->cmdline == NULL);
 
-    wordlistAdd(&dnsservers->cmdline, Config.Program.dnsserver);
+    dnsservers->cmdline->add(Config.Program.dnsserver);
 
     if (Config.onoff.res_defnames)
-        wordlistAdd(&dnsservers->cmdline, "-D");
+        dnsservers->cmdline->add("-D");
 
     for (w = Config.dns_nameservers; w != NULL; w = w->next) {
-        wordlistAdd(&dnsservers->cmdline, "-s");
-        wordlistAdd(&dnsservers->cmdline, w->key);
+        dnsservers->cmdline->add("-s");
+        dnsservers->cmdline->add(w->key);
     }
 
     helperOpenServers(dnsservers);
@@ -102,7 +102,8 @@
 
     helperShutdown(dnsservers);
 
-    wordlistDestroy(&dnsservers->cmdline);
+    delete dnsservers->cmdline;
+    dnsservers->cmdline = NULL;
 
     if (!shutting_down)
         return;

=== modified file 'src/errorpage.cc'
--- src/errorpage.cc	2008-08-09 05:59:55 +0000
+++ src/errorpage.cc	2008-08-12 19:57:38 +0000
@@ -482,7 +482,8 @@
     safe_free(err->url);
     safe_free(err->dnsserver_msg);
     safe_free(err->request_hdrs);
-    wordlistDestroy(&err->ftp.server_msg);
+    delete err->ftp.server_msg;
+    err->ftp.server_msg = NULL;
     safe_free(err->ftp.request);
     safe_free(err->ftp.reply);
     AUTHUSERREQUESTUNLOCK(err->auth_user_request, "errstate");
@@ -556,7 +557,7 @@
         str.Printf("FTP Request: %s\r\n", ftp.request);
         str.Printf("FTP Reply: %s\r\n", ftp.reply);
         str.Printf("FTP Msg: ");
-        wordlistCat(ftp.server_msg, &str);
+        ftp.server_msg->cat(&str);
         str.Printf("\r\n");
     }
 
@@ -635,7 +636,7 @@
 
     case 'g':
         /* FTP SERVER MESSAGE */
-        wordlistCat(ftp.server_msg, &mb);
+        ftp.server_msg->cat(&mb);
 
         break;
 

=== modified file 'src/external_acl.cc'
--- src/external_acl.cc	2008-07-13 08:37:43 +0000
+++ src/external_acl.cc	2008-08-12 19:57:38 +0000
@@ -194,7 +194,8 @@
         cbdataFree(f);
     }
 
-    wordlistDestroy(&p->cmdline);
+    delete p->cmdline;
+    p->cmdline = NULL;
 
     if (p->theHelper) {
         helperShutdown(p->theHelper);
@@ -403,7 +404,7 @@
     if (!token)
         self_destruct();
 
-    wordlistAdd(&a->cmdline, token);
+    a->cmdline->add(token);
 
     /* arguments */
     parse_wordlist(&a->cmdline);
@@ -578,7 +579,8 @@
 free_external_acl_data(void *data)
 {
     external_acl_data *p = static_cast<external_acl_data *>(data);
-    wordlistDestroy(&p->arguments);
+    delete p->arguments;
+     p->arguments = NULL;
     cbdataReferenceDone(p->def);
 }
 
@@ -605,7 +607,7 @@
         self_destruct();
 
     while ((token = strtokFile())) {
-        wordlistAdd(&data->arguments, token);
+        data->arguments->add(token);
     }
 }
 
@@ -747,7 +749,7 @@
 ACLExternal::dump() const
 {
     external_acl_data const *acl = data;
-    wordlist *result = NULL;
+    wordlist *result = new wordlist;
     wordlist *arg;
     MemBuf mb;
     mb.init();
@@ -757,7 +759,7 @@
         mb.Printf(" %s", arg->key);
     }
 
-    wordlistAdd(&result, mb.buf);
+    result->add(mb.buf);
     mb.clean();
     return result;
 }

=== modified file 'src/fqdncache.cc'
--- src/fqdncache.cc	2008-07-12 15:40:56 +0000
+++ src/fqdncache.cc	2008-08-09 16:13:04 +0000
@@ -857,13 +857,15 @@
 
     fce = fqdncacheCreateEntry(addr);
 
-    while (hostnames) {
-        fce->names[j] = xstrdup(hostnames->key);
-        j++;
-        hostnames = hostnames->next;
+    if (!hostnames->isEmpty()) {
+        while (hostnames) {
+            fce->names[j] = xstrdup(hostnames->key);
+            j++;
+            hostnames = hostnames->next;
 
-        if (j >= FQDN_MAX_NAMES)
-            break;
+            if (j >= FQDN_MAX_NAMES)
+                break;
+        }
     }
 
     fce->name_count = j;

=== modified file 'src/ftp.cc'
--- src/ftp.cc	2008-07-22 12:33:41 +0000
+++ src/ftp.cc	2008-08-12 19:57:38 +0000
@@ -455,13 +455,13 @@
     }
 
     if (pathcomps)
-        wordlistDestroy(&pathcomps);
+        delete pathcomps;
 
     if (ctrl.message)
-        wordlistDestroy(&ctrl.message);
+        delete ctrl.message;
 
     if (cwd_message)
-        wordlistDestroy(&cwd_message);
+        delete cwd_message;
 
     safe_free(ctrl.last_reply);
 
@@ -570,7 +570,8 @@
 
         printfReplyBody("<HR noshade size=\"1px\">\n");
 
-        wordlistDestroy(&cwd_message);
+        delete cwd_message;
+        cwd_message = NULL;
     }
 
     printfReplyBody("<H2>\n");
@@ -1727,8 +1728,10 @@
     *used = (size_t) (s - sbuf);
     safe_free(sbuf);
 
-    if (!complete)
-        wordlistDestroy(&head);
+    if (!complete) {
+        delete head;
+        head = NULL;
+    }
 
     if (codep)
         *codep = code;
@@ -1834,7 +1837,7 @@
 {
     wordlist **W;
     size_t bytes_used = 0;
-    wordlistDestroy(&ctrl.message);
+    delete ctrl.message;
     ctrl.message = ftpParseControlReply(ctrl.buf,
                                         ctrl.offset, &ctrl.replycode, &bytes_used);
 
@@ -1864,12 +1867,12 @@
 
     ctrl.last_reply = xstrdup((*W)->key);
 
-    wordlistDestroy(W);
+    delete *W;
 
     /* Copy the rest of the message to cwd_message to be printed in
      * error messages
      */
-    wordlistAddWl(&cwd_message, ctrl.message);
+    *cwd_message += *ctrl.message;
 
     debugs(9, 3, HERE << "state=" << state << ", code=" << ctrl.replycode);
 
@@ -2049,7 +2052,7 @@
             rfc1738_unescape(d);
 
             if (*d)
-                wordlistAdd(&ftpState->pathcomps, d);
+                ftpState->pathcomps->add(d);
         }
 
         xfree(path);
@@ -2140,8 +2143,10 @@
         ftpState->unhack();
         /* Reset cwd_message to only include the last message */
 
-        if (ftpState->cwd_message)
-            wordlistDestroy(&ftpState->cwd_message);
+        if (ftpState->cwd_message) {
+            delete ftpState->cwd_message;
+            ftpState->cwd_message = NULL;
+        }
 
         ftpState->cwd_message = ftpState->ctrl.message;
 
@@ -3396,8 +3401,10 @@
 
     debugs(9, 3, HERE);
 
-    if (ftpState->pathcomps)
-        wordlistDestroy(&ftpState->pathcomps);
+    if (ftpState->pathcomps) {
+        delete ftpState->pathcomps;
+        ftpState->pathcomps = NULL;
+    }
 
     safe_free(ftpState->filepath);
 

=== modified file 'src/net_db.cc'
--- src/net_db.cc	2008-07-19 10:16:48 +0000
+++ src/net_db.cc	2008-08-12 19:57:38 +0000
@@ -656,7 +656,7 @@
             return w->key;
     }
 
-    return wordlistAdd(&peer_names, name);
+    return peer_names->add(name);
 }
 
 static void
@@ -902,6 +902,8 @@
 #if USE_ICMP
     int n;
 
+    peer_names = new wordlist;
+
     netdbRegisterWithCacheManager();
 
     if (addr_table)
@@ -919,6 +921,7 @@
 
     netdbReloadState();
 
+
 #endif
 }
 
@@ -978,7 +981,7 @@
     hashFreeItems(host_table, netdbFreeNameEntry);
     hashFreeMemory(host_table);
     host_table = NULL;
-    wordlistDestroy(&peer_names);
+    delete peer_names;
     peer_names = NULL;
 #endif
 }

=== modified file 'src/protos.h'
--- src/protos.h	2008-07-17 12:38:06 +0000
+++ src/protos.h	2008-08-08 12:23:50 +0000
@@ -61,7 +61,6 @@
  */
 SQUIDCEXTERN void configFreeMemory(void);
 class MemBuf;
-SQUIDCEXTERN void wordlistCat(const wordlist *, MemBuf * mb);
 SQUIDCEXTERN void self_destruct(void);
 SQUIDCEXTERN void add_http_port(char *portspec);
 extern int xatoi(const char *token);

=== modified file 'src/repl/lru/store_repl_lru.cc'
--- src/repl/lru/store_repl_lru.cc	2007-04-25 17:30:14 +0000
+++ src/repl/lru/store_repl_lru.cc	2008-08-09 16:13:04 +0000
@@ -329,7 +329,7 @@
     RemovalPolicy *policy;
     LruPolicyData *lru_data;
     /* no arguments expected or understood */
-    assert(!args);
+    assert(args==NULL || args->isEmpty());
     /* Initialize */
 
     if (!lru_node_pool) {

=== modified file 'src/tests/stub_cache_cf.cc'
--- src/tests/stub_cache_cf.cc	2007-04-06 18:15:45 +0000
+++ src/tests/stub_cache_cf.cc	2008-08-07 16:03:51 +0000
@@ -80,8 +80,10 @@
     char *token;
     char *t = strtok(NULL, "");
 
+    assert(*list != NULL); //wordlist myst be defined here
+
     while ((token = strwordtok(NULL, &t)))
-        wordlistAdd(list, token);
+        (*list)->add(token);
 }
 
 void

=== added file 'src/tests/stub_debug.cc'
--- src/tests/stub_debug.cc	1970-01-01 00:00:00 +0000
+++ src/tests/stub_debug.cc	2008-08-11 14:54:43 +0000
@@ -0,0 +1,40 @@
+/*
+ * stub_debug.cc
+ *
+ * AUTHOR: Francesco Chemolli
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+#include "Debug.h"
+#include <iostream>
+
+void
+Debug::parseOptions(char const *options) { }
+

=== added file 'src/tests/stub_event.cc'
--- src/tests/stub_event.cc	1970-01-01 00:00:00 +0000
+++ src/tests/stub_event.cc	2008-08-10 22:19:32 +0000
@@ -0,0 +1,41 @@
+/*
+ * stub_event.cc
+ *
+ * AUTHOR: Francesco Chemolli
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+#include "event.h"
+
+void
+eventAdd(const char *name, EVH * func, void *arg, double when, int weight, bool
+cbdata)
+{
+}

=== added file 'src/tests/testWordlist.cc'
--- src/tests/testWordlist.cc	1970-01-01 00:00:00 +0000
+++ src/tests/testWordlist.cc	2008-08-13 07:05:45 +0000
@@ -0,0 +1,195 @@
+#define SQUID_UNIT_TEST 1 
+
+#include "squid.h"
+#include <stdexcept>
+
+#include "Mem.h"
+#include "MemBuf.h"
+#include "wordlist.h"
+#include "testWordlist.h"
+#include <iostream>
+
+CPPUNIT_TEST_SUITE_REGISTRATION( testWordlist );
+
+const char *words[] = {
+    "foo", "bar", "gazonk", "baz", "squid", "cache", "test", NULL
+    };
+
+std::ostream&
+operator << (std::ostream & str, wordlist & wl)
+{
+    wordlist *w= &wl;
+    while (w != NULL) {
+        if (w->key!=NULL)
+            str << w->key << ", ";
+        w = w->next;
+    }
+    return str;
+}
+
+void
+testWordlist::setUp()
+{
+    Mem::Init();
+    /* std::cerr << "testWordlist::setUp()" << std::endl; */
+}
+
+void
+testWordlist::testWordlistCreation()
+{
+    wordlist w1;
+    wordlist *w2 = new wordlist;
+    wordlist *w3 = new wordlist("foo");
+
+    CPPUNIT_ASSERT(w2 != NULL);
+    CPPUNIT_ASSERT(w3 != NULL);
+
+    /*
+    std::cerr << "testWordlistCreation: w1 = {" << w1 << "}, w2 = {" << *w2 <<
+        "}, w3 = {" << *w3 << "}" << std::endl;
+    */
+
+    delete w2;
+    delete w3;
+}
+
+void
+testWordlist::testEqualityTest()
+{
+    wordlist *w1=new wordlist;
+    wordlist *w2=new wordlist;
+    int j=0;
+
+    while (words[j] != NULL) {
+        //std::cerr << "adding: " << words[j] << std::endl;
+        w1->add(words[j]);
+        w2->add(words[j]);
+        ++j;
+    }
+    /*
+    std::cerr << "testWordlist::testEqualityTest: w1 = {" << *w1 <<
+        "}, w2 = {" << *w2 << "}" << std::endl;
+    */
+
+    CPPUNIT_ASSERT(*w1 == *w2); //test equality
+    delete w2;
+
+    w2 = new wordlist(words[0]);
+    CPPUNIT_ASSERT(! (*w1 == *w2)); //inequality due to different lengths
+    delete w2;
+
+    w2 = new wordlist("differentstring");;
+    j=1;
+    while (words[j] != NULL) {
+        w2->add(words[j]);
+        ++j;
+    }
+    CPPUNIT_ASSERT(! (*w1 == *w2)); //inequality due to different contents
+
+    delete w1;
+    delete w2;
+}
+
+void
+testWordlist::testConstructors()
+{
+    wordlist *w1 = new wordlist(words[0]);
+    wordlist *w2 = new wordlist;
+    w2->add(words[0]);
+
+    CPPUNIT_ASSERT(*w1 == *w2);
+    delete w1;
+    delete w2;
+}
+
+void
+testWordlist::testConcatenation()
+{
+    wordlist w1, w2;
+
+    int j=0;
+
+    while (words[j] != NULL) {
+        w1.add(words[j]);
+        w2.add(words[j]);
+        ++j;
+    }
+
+    j=0;
+    w2 += w1;
+    while (words[j] != NULL) {
+        w1.add(words[j]);
+        ++j;
+    }
+
+    /*
+    std::cerr << "testWordlist::testConcatenation: w1 = {" << w1 <<
+        "}, w2 = {" << w2 << "}" << std::endl;
+    */
+
+    CPPUNIT_ASSERT(w1 == w2);
+}
+
+void
+testWordlist::testCat()
+{
+    MemBuf mb;
+    wordlist wl;
+    int j=0;
+    char *benchmark = new char[4096];
+
+    mb.init(1024,4096);
+
+    while (words[j] != NULL) {
+        wl.add(words[j]);
+        ++j;
+    }
+    j=0;
+    while (words[j] != NULL) {
+        strcat(benchmark,words[j]);
+        strcat(benchmark,"\n");
+        j++;
+    }
+    wl.cat(&mb);
+    //std::cerr << "mb: {" <<mb.content() << "}" << std::endl;
+    CPPUNIT_ASSERT(!strcmp(mb.content(),benchmark));
+    delete benchmark;
+}
+
+void
+testWordlist::testAppend()
+{
+    wordlist *w1 = new wordlist(), *w2 = new wordlist(), *w3 = new wordlist();
+    int j=0;
+
+    while (words[j] != NULL) {
+        w1->add(words[j]);
+        w2->add(words[j]);
+        ++j;
+    }
+
+    w1->append(w2);
+    w2 = new wordlist(); //not a leak, will be managed by w1 now
+    j=0;
+    while (words[j] != NULL) {
+        w2->add(words[j]);
+        ++j;
+    }
+    j=0;
+    while (words[j] != NULL) {
+        w2->add(words[j]);
+        ++j;
+    }
+
+    w3->append(w2);
+
+    std::cerr << "testWordlist::testAppend: w1 = {" << *w1 <<"}, w2 = {"
+        << *w2 << "}, w3 = {" << *w3 << "}" <<std::endl;
+
+    CPPUNIT_ASSERT( *w1 == *w2 );
+    CPPUNIT_ASSERT( *w1 == *w3 );
+
+    delete w1;
+    delete w3; //will also delete w2
+
+}

=== added file 'src/tests/testWordlist.h'
--- src/tests/testWordlist.h	1970-01-01 00:00:00 +0000
+++ src/tests/testWordlist.h	2008-08-13 07:05:45 +0000
@@ -0,0 +1,34 @@
+
+#ifndef SQUID_SRC_TESTWORDLIST_H
+#define SQUID_SRC_TESTWORDLIST_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+/*
+ * test the wordlist functionality
+ */
+
+class testWordlist : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( testWordlist );
+    CPPUNIT_TEST( testWordlistCreation );
+    CPPUNIT_TEST( testEqualityTest );
+    CPPUNIT_TEST( testConstructors );
+    CPPUNIT_TEST( testConcatenation );
+    CPPUNIT_TEST( testAppend );
+    CPPUNIT_TEST_SUITE_END();
+
+public:
+    void setUp();
+
+protected:
+    void testWordlistCreation();
+    void testEqualityTest();
+    void testConstructors();
+    void testConcatenation();
+    void testCat();
+    void testAppend();
+};
+
+#endif
+

=== modified file 'src/tools.cc'
--- src/tools.cc	2008-07-17 12:27:10 +0000
+++ src/tools.cc	2008-08-12 19:57:38 +0000
@@ -1105,7 +1105,7 @@
 #endif
 
     while (fgets(buf, 1024, fp)) {	/* for each line */
-        wordlist *hosts = NULL;
+        wordlist *hosts = new wordlist;
         char *addr;
 
         if (buf[0] == '#')	/* MS-windows likes to add comments */
@@ -1154,7 +1154,7 @@
             if (ipcacheAddEntryFromHosts(host, addr) != 0)
                 goto skip;	/* invalid address, continuing is useless */
 
-            wordlistAdd(&hosts, host);
+            hosts->add(host);
 
             lt = nt + 1;
         }
@@ -1162,7 +1162,8 @@
         fqdncacheAddEntryFromHosts(addr, hosts);
 
 skip:
-        wordlistDestroy(&hosts);
+        delete hosts;
+        hosts = NULL;
     }
 
     fclose (fp);

=== modified file 'src/wordlist.cc'
--- src/wordlist.cc	2006-04-23 17:10:29 +0000
+++ src/wordlist.cc	2008-08-13 15:45:13 +0000
@@ -35,78 +35,178 @@
 
 #include "wordlist.h"
 #include "MemBuf.h"
-
-void
-wordlistDestroy(wordlist ** list)
-{
-    wordlist *w = NULL;
-
-    while ((w = *list) != NULL) {
-        *list = w->next;
-        safe_free(w->key);
-        delete w;
-    }
-
-    *list = NULL;
-}
-
+#include "Store.h"
+
+/**
+ \defgroup wordlist Word List 
+ \par
+ * A wordlist is an ordered list of copied C-style strings, copied
+ * upon adding to the list.
+ */
+
+/**
+ * wordlist destructor. Frees all associated storage.
+ */
+wordlist::~wordlist()
+{
+    empty();
+}
+
+/**
+ * creates a wordlist already containing the first element.
+ \param word a NULL-terminated string to add
+ */
+wordlist::wordlist(const char * word): next(NULL)
+{
+    key = xstrdup(word);
+}
+
+/**
+ * add a word to the wordlist.
+ \param word a NULL-terminated string to add
+ \retval the original added string
+ */
 const char *
-wordlistAdd(wordlist ** list, const char *key)
-{
-    while (*list)
-        list = &(*list)->next;
-
-    *list = new wordlist;
-
-    (*list)->key = xstrdup(key);
-
-    (*list)->next = NULL;
-
-    return (*list)->key;
-}
-
-void
-wordlistJoin(wordlist ** list, wordlist ** wl)
-{
-    while (*list)
-        list = &(*list)->next;
-
-    *list = *wl;
-
+wordlist::add(const char *word)
+{
+    wordlist *cur=this;
+
+    if (key==NULL) { //special case empty wordlist
+        key = xstrdup(word);
+        return word;
+    }
+
+    while (cur->next != NULL)
+        cur = cur->next;
+
+    cur->next = new wordlist(word);
+
+    return word;
+}
+
+/**
+ \param word a NULL-terminated string to add
+ * syntactically-sugar-coated version of wordlist::add(word)
+ */
+wordlist &
+wordlist::operator += (const char * word ) {
+    add(word);
+    return *this;
+}
+
+/**
+ \param otherwl wordlist to concatenate to this
+ * appends (copies) all elements of the supplied list to this.
+ */
+void
+wordlist::add_wordlist(wordlist & otherwl)
+{
+    wordlist *list=this, *wl=&otherwl;
+
+    if (key == NULL) { //special-case: empty list. Consume one word
+        list->key=xstrdup(wl->key);
+        wl=wl->next;
+    } else { //walk till the last element of the list
+        while (list->next != NULL)
+            list = list->next;
+    }
+
+    while (wl!=NULL) {
+        list->next = new wordlist(wl->key);
+        list = list->next;
+        wl = wl->next;
+    }
+}
+
+/**
+ \param otherwl wordlist to concatenate to this
+ * syntactically-sugar-coated version of wordlist::add_wordlist.
+ */
+wordlist &
+wordlist::operator += (wordlist & otherwl)
+{
+    add_wordlist(otherwl);
+    return *this;
+}
+
+/**
+ * Appends all words in the wordlist to the supplied membuf, newline-separated.
+ */
+void
+wordlist::cat(MemBuf * mb)
+{
+    wordlist *w=this;
+    if (key!=NULL) //special case: empty list
+        while (NULL != w) {
+            mb->Printf("%s\n", w->key);
+            w = w->next;
+        }
+}
+
+// this is needed for the config parser
+void free_wordlist (wordlist ** wl) {
+    delete *wl;
     *wl = NULL;
 }
 
-void
-wordlistAddWl(wordlist ** list, wordlist * wl)
-{
-    while (*list)
-        list = &(*list)->next;
-
-    for (; wl; wl = wl->next, list = &(*list)->next) {
-        *list = new wordlist();
-        (*list)->key = xstrdup(wl->key);
-        (*list)->next = NULL;
-    }
-}
-
-void
-wordlistCat(const wordlist * w, MemBuf * mb)
-{
-    while (NULL != w) {
-        mb->Printf("%s\n", w->key);
-        w = w->next;
-    }
-}
-
-wordlist *
-wordlistDup(const wordlist * w)
-{
-    wordlist *D = NULL;
-
-    while (NULL != w) {
-        wordlistAdd(&D, w->key);
-        w = w->next;
-    }
-
-    return D;
+/**
+ * Convenience function, returns true if the wordlist is empty
+ */
+bool wordlist::isEmpty(void) {
+    return (key==NULL);
+}
+
+/**
+ * Tests equality of two wordlists by checking their contents.
+ * It's only needed for the unit-tests really...
+ */
+bool
+wordlist::operator == (const wordlist &wl) const
+{
+    const wordlist *k2 = &wl;
+    const wordlist *k1 = this;
+
+    while (k1 != NULL && k2 != NULL) {
+        if (0!=strcmp(k1->key,k2->key))
+            return false;
+        k1=k1->next;
+        k2=k2->next;
+    }
+    if (k1==NULL && k2==NULL) //all keys were equal and length is equal
+        return true;
+    return false;
+}
+
+/**
+ * appends the supplied wordlist to the current one. DOES NOT copy the values,
+ * thus the caller should forget about the argument supplied as it will
+ * be freed when the current object gets deleted
+ */
+void
+wordlist::append (wordlist *wl) {
+   wordlist *W=this;
+   if (key == NULL) { //empty wordlist
+       key = wl->key;
+       wl=wl->next;
+   }
+   while (W->next != NULL) //reach the end of the wordlist
+       W=W->next;
+   W->next=wl; //append the other wordlist
+}
+
+/**
+ * empties a wordlist's contents, resetting it.
+ */
+void wordlist::empty(void)
+{
+    wordlist *w = this->next, *e;
+
+    while (w != NULL) {
+        e=w;
+        w = w->next;
+        safe_free(e->key);
+    }
+    safe_free(key); //already set to NULL by safe_free
+    next=NULL;
+
 }

=== modified file 'src/wordlist.h'
--- src/wordlist.h	2008-03-20 11:30:19 +0000
+++ src/wordlist.h	2008-08-13 14:28:09 +0000
@@ -35,6 +35,8 @@
 #include "squid.h"
 #include "MemPool.h"
 
+class MemBuf; //stub declaration
+
 class wordlist
 {
 
@@ -42,14 +44,26 @@
     MEMPROXY_CLASS(wordlist);
     char *key;
     wordlist *next;
+
+    wordlist(const char * initial_key);
+    wordlist() : key(NULL), next(NULL) { }
+    ~wordlist();
+    const char * add(const char * word);
+    wordlist & operator += (const char * word );
+    void add_wordlist(wordlist & otherwl);
+    wordlist & operator += (wordlist & otherwl);
+    bool isEmpty(void);
+
+    void cat (MemBuf *mb);
+    void append (wordlist *W);
+
+    void empty(void);
+
+    bool operator == (const wordlist &wl) const;
 };
 
 MEMPROXY_CLASS_INLINE(wordlist);
 
-SQUIDCEXTERN const char *wordlistAdd(wordlist **, const char *);
-SQUIDCEXTERN void wordlistAddWl(wordlist **, wordlist *);
-SQUIDCEXTERN void wordlistJoin(wordlist **, wordlist **);
-SQUIDCEXTERN wordlist *wordlistDup(const wordlist *);
-SQUIDCEXTERN void wordlistDestroy(wordlist **);
+SQUIDCEXTERN void free_wordlist(wordlist **); //for cf_parser.h
 
 #endif /* SQUID_WORDLIST_H */

# Begin bundle
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
