Hi,
attaching v4, hand-unrolling SBufListJoin (as before, missing
Makefile.am changes), and marking wordlist as deprecated.
On Tue, Dec 3, 2013 at 5:35 PM, Kinkie <[email protected]> wrote:
>>> As this patch is a cherrypick of lp:~squid/squid/stringng, I'm not
>>> extracting the Makefile.am changes as it's too time-consuming. These
>>> changes are present in the branch Makefile.am and will be included at
>>> the final merge time, but are not really significant for review, are
>>> they?
>>
>> They are not, but a reviewer sometimes actually tests the patch. I know
>> it sounds crazy, but it does happen once in a while. You have actually
>> warned about the missing Makefile changes in your original submission,
>> but I forgot that caveat after so many emails on the thread. Sorry!
>
> Crazy stuff, you're saying :D
> The branch is routinely tested: I do test it before each submission,
> and I will pass it by the entire build farm before merge. I wish not
> to break the build as much as you do.
>
>> Since those exact Makefile changes would need to be done to trunk during
>> commit, I am guessing you exclude them now to save time if the patch
>> needs to be adjusted and re-posted for review, right? I am _not_ asking
>> for those changes to be included in the patch. Just trying to understand
>> your motivation or workflow. Not important.
>
> You perfectly got my motivation.
>
> This should be the last cherry picked off stringng, unless by chance
> the API you are drafting for a tokenizer substantially overlap the
> Tokenizer I have implemented in the stringng branch. If that happens,
> I can try to adapt the current code to the new API. If it doesn't,
> that code will be abandoned and the stringng branch closed.
> I hope it will never happen again that a feature-branch lives as long
> as this one has.
>
> --
> /kinkie
--
/kinkie
=== modified file 'src/SBuf.h'
--- src/SBuf.h 2013-10-08 04:17:17 +0000
+++ src/SBuf.h 2013-12-02 18:00:42 +0000
@@ -55,6 +55,7 @@
#define SQUIDSBUFPRINT(s) (s).plength(),(s).rawContent()
#endif /* SQUIDSBUFPH */
+// TODO: move within SBuf and rename
typedef enum {
caseSensitive,
caseInsensitive
=== added file 'src/SBufAlgos.h'
--- src/SBufAlgos.h 1970-01-01 00:00:00 +0000
+++ src/SBufAlgos.h 2013-12-04 17:25:51 +0000
@@ -0,0 +1,68 @@
+#ifndef SQUID_SBUFALGOS_H_
+#define SQUID_SBUFALGOS_H_
+
+#include "SBuf.h"
+#include <algorithm>
+
+/// SBuf equality predicate for STL algorithms etc
+class SBufEqual {
+public:
+ explicit SBufEqual(const SBuf &reference, SBufCaseSensitive caseSensitivity_ = caseSensitive) :
+ reference_(reference), sensitivity_(caseSensitivity_) {}
+ inline bool operator() (const SBuf & checking) { return 0 == checking.compare(reference_,sensitivity_); }
+private:
+ SBuf reference_;
+ SBufCaseSensitive sensitivity_;
+};
+
+/// SBuf "starts with" predicate for STL algorithms etc
+class SBufStartsWith {
+public:
+ explicit SBufStartsWith(const SBuf &prefix, SBufCaseSensitive caseSensitive = caseSensitive) :
+ prefix_(prefix), sensitive(caseSensitive) {}
+ inline bool operator() (const SBuf & checking) { return checking.startsWith(prefix_,sensitive); }
+private:
+ SBuf prefix_;
+ SBufCaseSensitive sensitive;
+};
+
+/** SBuf size addition accumulator for STL contaniners
+ *
+ * Equivalent to prefix_length + SBuf.length() + separator.length()
+ */
+class SBufAddLength {
+public:
+ explicit SBufAddLength(const SBuf &separator) :
+ separator_len(separator.length()) {}
+ SBuf::size_type operator()(const SBuf::size_type sz, const SBuf & item) {
+ return sz + item.length() + separator_len;
+ }
+private:
+ SBuf::size_type separator_len;
+};
+
+/// join all the SBuf in a container of SBuf into a single SBuf, separating with separator
+template <class Container>
+SBuf
+SBufContainerJoin(const Container &items, const SBuf& separator)
+{
+ // optimization: pre-calculate needed storage
+ SBuf::size_type sz;
+ sz = std::accumulate(items.begin(), items.end(), 0, SBufAddLength(separator));
+
+ // protect against blindly dereferencing items.begin() if items.size()==0
+ if (sz == 0)
+ return SBuf();
+
+ SBuf rv;
+ rv.reserveSpace(sz);
+
+ typename Container::const_iterator i(items.begin());
+ rv.append(*i);
+ ++i;
+ for (;i != items.end(); ++i)
+ rv.append(separator).append(*i);
+ return rv;
+}
+
+#endif /* SQUID_SBUFALGOS_H_ */
=== added file 'src/SBufList.cc'
--- src/SBufList.cc 1970-01-01 00:00:00 +0000
+++ src/SBufList.cc 2013-12-02 21:21:57 +0000
@@ -0,0 +1,21 @@
+#include "squid.h"
+#include "SBufList.h"
+#include "SBufAlgos.h"
+#include "wordlist.h"
+
+bool
+IsMember(const SBufList & sl, const SBuf &S, const SBufCaseSensitive case_sensitive)
+{
+ return std::find_if(sl.begin(), sl.end(), SBufEqual(S,case_sensitive)) != sl.end();
+}
+
+SBufList
+ToSBufList(wordlist *wl)
+{
+ SBufList rv;
+ while (wl != NULL) {
+ rv.push_back(SBuf(wl->key));
+ wl = wl->next;
+ }
+ return rv;
+}
=== added file 'src/SBufList.h'
--- src/SBufList.h 1970-01-01 00:00:00 +0000
+++ src/SBufList.h 2013-12-02 21:21:57 +0000
@@ -0,0 +1,22 @@
+#ifndef SQUID_SBUFLIST_H
+#define SQUID_SBUFLIST_H
+
+#include "SBuf.h"
+
+#include <list>
+
+typedef std::list<SBuf> SBufList;
+
+/** check for membership
+ *
+ * \return true if the supplied SBuf is a member of the list
+ * \param case_sensitive one of caseSensitive or caseInsensitive
+ */
+bool IsMember(const SBufList &, const SBuf &, const SBufCaseSensitive isCaseSensitive = caseSensitive);
+
+class wordlist;
+
+/// convert a wordlist to a SBufList
+SBufList ToSBufList(wordlist *);
+
+#endif /* SQUID_SBUFLIST_H */
=== added file 'src/tests/testSBufList.cc'
--- src/tests/testSBufList.cc 1970-01-01 00:00:00 +0000
+++ src/tests/testSBufList.cc 2013-12-02 21:21:57 +0000
@@ -0,0 +1,37 @@
+#include "squid.h"
+#include "SBufAlgos.h"
+#include "SBufList.h"
+#include "testSBufList.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( testSBufList );
+
+SBuf literal("The quick brown fox jumped over the lazy dog");
+static int sbuf_tokens_number=9;
+static SBuf tokens[]={
+ SBuf("The",3), SBuf("quick",5), SBuf("brown",5), SBuf("fox",3),
+ SBuf("jumped",6), SBuf("over",4), SBuf("the",3), SBuf("lazy",4),
+ SBuf("dog",3)
+};
+
+void
+testSBufList::testSBufListMembership()
+{
+ SBufList foo;
+ for (int j=0; j<sbuf_tokens_number; ++j)
+ foo.push_back(tokens[j]);
+ CPPUNIT_ASSERT_EQUAL(true,IsMember(foo,SBuf("fox")));
+ CPPUNIT_ASSERT_EQUAL(true,IsMember(foo,SBuf("Fox"),caseInsensitive));
+ CPPUNIT_ASSERT_EQUAL(false,IsMember(foo,SBuf("garble")));
+}
+
+void
+testSBufList::testSBufListJoin()
+{
+ SBufList foo;
+ CPPUNIT_ASSERT_EQUAL(SBuf(""),SBufContainerJoin(foo,SBuf()));
+ CPPUNIT_ASSERT_EQUAL(SBuf(""),SBufContainerJoin(foo,SBuf()));
+ for (int j = 0; j < sbuf_tokens_number; ++j)
+ foo.push_back(tokens[j]);
+ SBuf joined=SBufContainerJoin(foo,SBuf(" "));
+ CPPUNIT_ASSERT_EQUAL(literal,joined);
+}
=== added file 'src/tests/testSBufList.h'
--- src/tests/testSBufList.h 1970-01-01 00:00:00 +0000
+++ src/tests/testSBufList.h 2013-11-25 18:33:15 +0000
@@ -0,0 +1,19 @@
+#ifndef SQUID_SRC_TEST_TESTSBUF_H
+#define SQUID_SRC_TEST_TESTSBUF_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "OutOfBoundsException.h"
+
+class testSBufList : public CPPUNIT_NS::TestFixture
+{
+ CPPUNIT_TEST_SUITE( testSBufList );
+ CPPUNIT_TEST( testSBufListMembership );
+ CPPUNIT_TEST( testSBufListJoin );
+ CPPUNIT_TEST_SUITE_END();
+protected:
+ void testSBufListMembership();
+ void testSBufListJoin();
+};
+
+#endif
=== modified file 'src/wordlist.h'
--- src/wordlist.h 2012-09-21 14:57:30 +0000
+++ src/wordlist.h 2013-12-02 21:21:57 +0000
@@ -34,9 +34,12 @@
#include "MemPool.h"
#include "profiler/Profiler.h"
+/** A list of C-strings
+ *
+ * \deprecated use SBufList instead
+ */
class wordlist
{
-
public:
MEMPROXY_CLASS(wordlist);
char *key;
@@ -46,12 +49,29 @@
MEMPROXY_CLASS_INLINE(wordlist);
class MemBuf;
-
+/** Add a null-terminated c-string to a wordlist
+ *
+ * \deprecated use SBufList.push_back(SBuf(word)) instead
+ */
const char *wordlistAdd(wordlist **, const char *);
-void wordlistCat(const wordlist *, MemBuf * mb);
+/** Concatenate a wordlist
+ *
+ * \deprecated use SBufListContainerJoin(SBuf()) from SBufAlgos.h instead
+ */
+void wordlistCat(const wordlist *, MemBuf *);
+/** append a wordlist to another
+ *
+ * \deprecated use SBufList.merge(otherwordlist) instead
+ */
void wordlistAddWl(wordlist **, wordlist *);
+/** Concatenate the words in a wordlist
+ *
+ * \deprecated use SBufListContainerJoin(SBuf()) from SBufAlgos.h instead
+ */
void wordlistJoin(wordlist **, wordlist **);
+/// duplicate a wordlist
wordlist *wordlistDup(const wordlist *);
+/// destroy a wordlist
void wordlistDestroy(wordlist **);
#endif /* SQUID_WORDLIST_H */