Hi,
  here's a merge proposal for Parser::Tokenizer, an implementation of
the API suggested by Alex.

The feature branch is available at lp:~squid/squid/sbuf-tokenizer


-- 
    /kinkie
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: kin...@squid-cache.org-20140106212057-vcewa3telo4kq2er
# target_branch: file:///home/kinkie/squid/workspace/trunk/
# testament_sha1: 202894c2b71d744c260b7b8798102f295e879d8e
# timestamp: 2014-01-06 22:21:02 +0100
# base_revision_id: kin...@squid-cache.org-20140105130744-\
#   gqkbrnvpk1feg3bm
# 
# Begin patch
=== modified file 'configure.ac'
--- configure.ac	2013-12-12 09:41:39 +0000
+++ configure.ac	2013-12-19 16:00:30 +0000
@@ -3429,6 +3429,7 @@
 	src/ipc/Makefile
 	src/ssl/Makefile
 	src/mgr/Makefile
+	src/parser/Makefile
 	src/snmp/Makefile
 	contrib/Makefile
 	icons/Makefile

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2014-01-03 10:32:53 +0000
+++ src/Makefile.am	2014-01-05 16:57:44 +0000
@@ -46,8 +46,8 @@
 	LoadableModules.h \
 	LoadableModules.cc
 
-SUBDIRS	= base anyp comm eui acl format fs repl
-DIST_SUBDIRS = base anyp comm eui acl format fs repl
+SUBDIRS	= base anyp parser comm eui acl format fs repl
+DIST_SUBDIRS = base anyp parser comm eui acl format fs repl
 
 if ENABLE_AUTH
 SUBDIRS += auth
@@ -646,6 +646,7 @@
 	$(ESI_LIBS) \
 	$(SSL_LIBS) \
 	$(SNMP_LIBS) \
+	parser/libsquid-parser.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \

=== added directory 'src/parser'
=== added file 'src/parser/Makefile.am'
--- src/parser/Makefile.am	1970-01-01 00:00:00 +0000
+++ src/parser/Makefile.am	2013-12-31 10:42:11 +0000
@@ -0,0 +1,49 @@
+include $(top_srcdir)/src/Common.am
+include $(top_srcdir)/src/TestHeaders.am
+
+EXTRA_PROGRAMS = \
+	testTokenizer
+	
+check_PROGRAMS += testTokenizer
+TESTS += testTokenizer
+
+noinst_LTLIBRARIES = libsquid-parser.la
+
+libsquid_parser_la_SOURCES = \
+	Tokenizer.h \
+	Tokenizer.cc
+
+SBUF_SOURCE= \
+	$(top_srcdir)/src/base/CharacterSet.h \
+	$(top_srcdir)/src/SBuf.h \
+	$(top_srcdir)/src/SBuf.cc \
+	$(top_srcdir)/src/MemBlob.h \
+	$(top_srcdir)/src/MemBlob.cc \
+	$(top_srcdir)/src/OutOfBoundsException.h \
+	$(top_srcdir)/src/SBufExceptions.h \
+	$(top_srcdir)/src/SBufExceptions.cc \
+	$(top_srcdir)/src/String.cc \
+	$(top_srcdir)/src/SquidString.h \
+	$(top_srcdir)/src/base/TextException.h \
+	$(top_srcdir)/src/base/TextException.cc
+
+testTokenizer_SOURCES = \
+	$(SBUF_SOURCE) \
+	testTokenizer.h \
+	testTokenizer.cc \
+	Tokenizer.h
+nodist_testTokenizer_SOURCES = \
+	$(top_srcdir)/src/tests/testMain.cc \
+	$(top_srcdir)/src/tests/stub_mem.cc \
+	$(top_srcdir)/src/tests/stub_debug.cc \
+	$(top_srcdir)/src/tests/stub_time.cc \
+	$(top_srcdir)/src/tests/stub_SBufDetailedStats.cc
+testTokenizer_LDFLAGS = $(LIBADD_DL)
+testTokenizer_LDADD = \
+	libsquid-parser.la \
+	$(top_builddir)/lib/libmiscutil.la \
+	$(top_builddir)/src/base/libbase.la \
+	$(SQUID_CPPUNIT_LIBS) \
+	$(SQUID_CPPUNIT_LA) \
+	$(COMPAT_LIB)
+testTokenizer_DEPENDENCIES = $(SQUID_CPPUNIT_LA)

=== added file 'src/parser/Tokenizer.cc'
--- src/parser/Tokenizer.cc	1970-01-01 00:00:00 +0000
+++ src/parser/Tokenizer.cc	2014-01-06 21:20:57 +0000
@@ -0,0 +1,60 @@
+#include "squid.h"
+#include "Tokenizer.h"
+
+namespace Parser {
+
+bool
+Tokenizer::token(SBuf &returnedToken, const CharacterSet &whitespace)
+{
+    SBuf savebuf(buf_);
+    SBuf saveRetVal(returnedToken);
+    skip(whitespace);
+    if (!(prefix(returnedToken,whitespace))) {
+        buf_=savebuf;
+        returnedToken=saveRetVal;
+        return false;
+    }
+    skip(whitespace);
+    return true;
+}
+
+bool
+Tokenizer::prefix(SBuf &returnedToken, const CharacterSet &tokenChars)
+{
+    SBuf::size_type prefixLen = buf_.findFirstNotOf(tokenChars);
+    if (prefixLen == 0)
+        return false;
+    returnedToken = buf_.consume(prefixLen);
+    return true;
+}
+
+bool
+Tokenizer::skip(const CharacterSet &tokenChars)
+{
+    SBuf::size_type prefixLen = buf_.findFirstNotOf(tokenChars);
+    if (prefixLen == 0)
+        return false;
+    buf_.consume(prefixLen);
+    return true;
+}
+
+bool
+Tokenizer::skip(const SBuf &tokenToSkip)
+{
+    if (buf_.startsWith(tokenToSkip)) {
+        buf_.consume(tokenToSkip.length());
+        return true;
+    }
+    return false;
+}
+
+bool
+Tokenizer::skip(const char tokenChar)
+{
+    if (buf_[0] == tokenChar) {
+        buf_.consume(1);
+        return true;
+    }
+    return false;
+}
+} /* namespace Parser */

=== added file 'src/parser/Tokenizer.h'
--- src/parser/Tokenizer.h	1970-01-01 00:00:00 +0000
+++ src/parser/Tokenizer.h	2013-12-19 16:00:30 +0000
@@ -0,0 +1,47 @@
+#ifndef SQUID_PARSER_TOKENIZER_H_
+#define SQUID_PARSER_TOKENIZER_H_
+
+#include "base/CharacterSet.h"
+#include "SBuf.h"
+
+namespace Parser {
+
+class Tokenizer {
+public:
+   explicit Tokenizer(const SBuf &inBuf) : buf_(inBuf) {}
+
+   bool atEnd() const { return !buf_.length(); }
+   const SBuf& remaining() const { return buf_; }
+   void reset(const SBuf &newBuf) { buf_ = newBuf; }
+
+   /* The following methods start from the beginning of the input buffer.
+    * They return true and consume parsed chars if a non-empty token is found.
+    * Otherwise, they return false without any side-effects. */
+
+   /** Basic strtok(3):
+    *  Skips all leading delimiters (if any),
+    *  accumulates all characters up to the first delimiter (a token), and
+    *  skips all trailing delimiters (if any).
+    *  Want to extract delimiters? Use three prefix() calls instead.
+    */
+   bool token(SBuf &returnedToken, const CharacterSet &whitespace);
+
+   /// Accumulates all sequential permitted characters (a token).
+   bool prefix(SBuf &returnedToken, const CharacterSet &tokenChars);
+
+   /// Skips all sequential permitted characters (a token).
+   bool skip(const CharacterSet &tokenChars);
+
+   /// Skips a given token.
+   bool skip(const SBuf &tokenToSkip);
+
+   /// Skips a given character (a token).
+   bool skip(const char tokenChar);
+
+private:
+   SBuf buf_; ///< yet unparsed input
+};
+
+
+} /* namespace Parser */
+#endif /* SQUID_PARSER_TOKENIZER_H_ */

=== added file 'src/parser/testTokenizer.cc'
--- src/parser/testTokenizer.cc	1970-01-01 00:00:00 +0000
+++ src/parser/testTokenizer.cc	2014-01-05 16:57:44 +0000
@@ -0,0 +1,109 @@
+#include "squid.h"
+
+#include "testTokenizer.h"
+#include "base/CharacterSet.h"
+#include "Tokenizer.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( testTokenizer );
+
+SBuf text("GET http://resource.com/path HTTP/1.1\r\n"
+    "Host: resource.com\r\n"
+    "Cookie: laijkpk3422r j1noin \r\n"
+    "\r\n");
+const CharacterSet alpha("alpha","abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+const CharacterSet whitespace("whitespace"," \r\n");
+const CharacterSet crlf("crlf","\r\n");
+const CharacterSet tab("tab","\t");
+const CharacterSet numbers("numbers","0123456789");
+
+void
+testTokenizer::testTokenizerPrefix()
+{
+    Parser::Tokenizer t(text);
+    SBuf s;
+
+    // successful prefix tokenization
+    CPPUNIT_ASSERT(t.prefix(s,alpha));
+    CPPUNIT_ASSERT_EQUAL(SBuf("GET"),s);
+    CPPUNIT_ASSERT(t.prefix(s,whitespace));
+    CPPUNIT_ASSERT_EQUAL(SBuf(" "),s);
+
+    //no match (first char is not in the prefix set)
+    CPPUNIT_ASSERT(!t.prefix(s,whitespace));
+    CPPUNIT_ASSERT_EQUAL(SBuf(" "),s);
+
+    // one more match to set S to something meaningful
+    CPPUNIT_ASSERT(t.prefix(s,alpha));
+    CPPUNIT_ASSERT_EQUAL(SBuf("http"),s);
+
+    //no match (no characters from the character set in the prefix)
+    CPPUNIT_ASSERT(!t.prefix(s,tab));
+    CPPUNIT_ASSERT_EQUAL(SBuf("http"),s); //output SBuf left untouched
+
+    // match until the end of the sample
+    CharacterSet all(whitespace);
+    all += alpha;
+    all += crlf;
+    all += numbers;
+    all.add(':').add('.').add('/');
+    CPPUNIT_ASSERT(t.prefix(s,all));
+    CPPUNIT_ASSERT_EQUAL(SBuf(),t.remaining());
+}
+
+void
+testTokenizer::testTokenizerSkip()
+{
+    Parser::Tokenizer t(text);
+    SBuf s;
+
+    // first scenario: patterns match
+    // prep for test
+    CPPUNIT_ASSERT(t.prefix(s,alpha));
+    CPPUNIT_ASSERT_EQUAL(SBuf("GET"),s);
+
+    // test skip testing character set
+    CPPUNIT_ASSERT(t.skip(whitespace));
+    // check that skip was right
+    CPPUNIT_ASSERT(t.prefix(s,alpha));
+    CPPUNIT_ASSERT_EQUAL(SBuf("http"),s);
+
+    //check skip prefix
+    CPPUNIT_ASSERT(t.skip(SBuf("://")));
+    // verify
+    CPPUNIT_ASSERT(t.prefix(s,alpha));
+    CPPUNIT_ASSERT_EQUAL(SBuf("resource"),s);
+
+    // no skip
+    CPPUNIT_ASSERT(!t.skip(alpha));
+    CPPUNIT_ASSERT(!t.skip(SBuf("://")));
+    CPPUNIT_ASSERT(!t.skip('a'));
+
+}
+
+void
+testTokenizer::testTokenizerToken()
+{
+    Parser::Tokenizer t(text);
+    SBuf s;
+
+    // first scenario: patterns match
+    CPPUNIT_ASSERT(t.token(s,whitespace));
+    CPPUNIT_ASSERT_EQUAL(SBuf("GET"),s);
+    CPPUNIT_ASSERT(t.token(s,whitespace));
+    CPPUNIT_ASSERT_EQUAL(SBuf("http://resource.com/path";),s);
+    CPPUNIT_ASSERT(t.token(s,whitespace));
+    CPPUNIT_ASSERT_EQUAL(SBuf("HTTP/1.1"),s);
+    CPPUNIT_ASSERT(t.token(s,whitespace));
+    CPPUNIT_ASSERT_EQUAL(SBuf("Host:"),s);
+
+    SBuf s2(s);
+    //no separator found
+    CPPUNIT_ASSERT(!t.token(s,tab));
+    CPPUNIT_ASSERT_EQUAL(s2,s); // check that the output parameter was untouched
+}
+
+void
+testTokenizer::testCharacterSet()
+{
+
+}

=== added file 'src/parser/testTokenizer.h'
--- src/parser/testTokenizer.h	1970-01-01 00:00:00 +0000
+++ src/parser/testTokenizer.h	2013-12-19 16:00:30 +0000
@@ -0,0 +1,22 @@
+#ifndef SQUID_TESTTOKENIZER_H_
+#define SQUID_TESTTOKENIZER_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class testTokenizer : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( testTokenizer );
+    CPPUNIT_TEST ( testCharacterSet );
+    CPPUNIT_TEST ( testTokenizerPrefix );
+    CPPUNIT_TEST ( testTokenizerSkip );
+    CPPUNIT_TEST ( testTokenizerToken );
+    CPPUNIT_TEST_SUITE_END();
+
+protected:
+    void testTokenizerPrefix();
+    void testTokenizerSkip();
+    void testTokenizerToken();
+    void testCharacterSet();
+};
+
+#endif /* SQUID_TESTTOKENIZER_H_ */

# Begin bundle
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
/JJ4mmUIj/xdyRThQkMxtpas

Reply via email to