=== modified file 'src/parser/Tokenizer.cc'
--- src/parser/Tokenizer.cc	2014-06-02 17:52:31 +0000
+++ src/parser/Tokenizer.cc	2014-06-02 18:59:23 +0000
@@ -29,12 +29,12 @@
 #endif
 
 bool
-Parser::Tokenizer::token(SBuf &returnedToken, const CharacterSet &delimiters)
+Parser::Tokenizer::token(SBuf &returnedToken, const CharacterSet &delimiters, const bool requireComplete)
 {
     const SBuf savebuf(buf_);
     skip(delimiters);
     const SBuf::size_type tokenLen = buf_.findFirstOf(delimiters); // not found = npos => consume to end
-    if (tokenLen == SBuf::npos && !delimiters['\0']) {
+    if (tokenLen == SBuf::npos && requireComplete) {
         // no delimiter found, nor is NUL/EOS/npos acceptible as one
         buf_ = savebuf;
         return false;

=== modified file 'src/parser/Tokenizer.h'
--- src/parser/Tokenizer.h	2014-06-02 00:15:10 +0000
+++ src/parser/Tokenizer.h	2014-06-02 18:59:24 +0000
@@ -42,12 +42,16 @@
      *
      *  Want to extract delimiters? Use prefix() instead.
      *
-     * At least one terminating delimiter is required. \0 may be passed
-     * as a delimiter to treat end of buffer content as the end of token.
-     *
+     * \param returnedToken output parameter, returns the token if tokenization
+     *        was successful; untouched otherwise
+     * \param delimiters the delimiters to be found (optionally before) and
+     *        after the token.
+     * \param requreComplete if true, requires that a delimiter be found after
+     *        the token for a successful parsing. If false or not provided,
+     *        end of parse buffer will be considered as an implicit delimiter
      * \return false if no terminal delimiter is found.
      */
-    bool token(SBuf &returnedToken, const CharacterSet &delimiters);
+    bool token(SBuf &returnedToken, const CharacterSet &delimiters, const bool requireComplete = false);
 
     /** Accumulates all sequential permitted characters up to an optional length limit.
      *

=== modified file 'src/parser/testTokenizer.cc'
--- src/parser/testTokenizer.cc	2014-06-02 00:15:10 +0000
+++ src/parser/testTokenizer.cc	2014-06-02 19:28:27 +0000
@@ -82,19 +82,45 @@
 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);
-
+    {
+        // match
+        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);
+    }
+    {
+        // complete / incomplete tokens
+        SBuf token;
+        Parser::Tokenizer t(token);
+
+        t.reset(SBuf("  foo  "));
+        CPPUNIT_ASSERT(t.token(token,whitespace));
+        CPPUNIT_ASSERT_EQUAL(SBuf("foo"),token);
+        token.clear();
+
+        t.reset(SBuf("  foo  "));
+        CPPUNIT_ASSERT(t.token(token,whitespace,true));
+        CPPUNIT_ASSERT_EQUAL(SBuf("foo"),token);
+        token.clear();
+
+        t.reset(SBuf("  foo"));
+        CPPUNIT_ASSERT(t.token(token,whitespace));
+        CPPUNIT_ASSERT_EQUAL(SBuf("foo"),token);
+        token.clear();
+
+        t.reset(SBuf("  foo"));
+        CPPUNIT_ASSERT(!t.token(token,whitespace,true));
+        CPPUNIT_ASSERT_EQUAL(SBuf(""),token);
+    }
 }
 
 void

