This patch implements Alex's suggestion for step 1 of String removal by ...

Replace String class internals with an SBuf.

This method allows all String code to be converted quickly to SBuf without so much worry about correct API conversion elsewhere around the code since the wrapper provides exemplar cut-n-paste code to work from.

Addition of a SBuf constructor and toSBuf() accessor to String allows code using String to be converted directly to the SBuf API in smaller portions later. These obsolete the SBuf API converters to String and help reduce the SBuf API.

Amos

=== modified file 'src/Makefile.am'
--- src/Makefile.am     2013-10-04 13:02:57 +0000
+++ src/Makefile.am     2013-10-05 14:04:58 +0000
@@ -22,7 +22,8 @@
        SBuf.h \
        SBuf.cc \
        SBufExceptions.h \
-       SBufExceptions.cc
+       SBufExceptions.cc \
+       SquidString.h
 
 LOADABLE_MODULES_SOURCES = \
        LoadableModule.h \
@@ -462,9 +463,9 @@
        refresh.cc \
        RemovalPolicy.cc \
        RemovalPolicy.h \
+       $(SBUF_SOURCE) \
        send-announce.h \
        send-announce.cc \
-       $(SBUF_SOURCE) \
        $(SNMP_SOURCE) \
        SquidMath.h \
        SquidMath.cc \
@@ -476,7 +477,6 @@
        StatCounters.cc \
        StatHist.h \
        StatHist.cc \
-       String.cc \
        StrList.h \
        StrList.cc \
        stmem.cc \
@@ -580,8 +580,6 @@
        MemBuf.h \
        Store.cci \
        StoreEntryStream.h \
-       String.cci \
-       SquidString.h \
        SquidTime.h
 
 BUILT_SOURCES = \
@@ -719,6 +717,7 @@
        MemBuf.cci \
        MemBuf.h \
        Parsing.h \
+       $(SBUF_SOURCE) \
        store_key_md5.h \
        store_key_md5.cc \
        StoreMeta.cc \
@@ -728,7 +727,6 @@
        StoreMetaUnpacker.cc \
        StoreMetaURL.cc \
        StoreMetaVary.cc \
-       String.cc \
        SquidNew.cc \
        time.cc \
        ufsdump.cc \
@@ -1147,9 +1145,8 @@
        mime_header.cc \
        Packer.cc \
        Packer.h \
-       SquidString.h \
+       $(SBUF_SOURCE) \
        SquidTime.h \
-       String.cc \
        StrList.h \
        StrList.cc \
        log/access_log.h \
@@ -1243,6 +1240,7 @@
        mem_node.cc \
        Packer.cc \
        Parsing.cc \
+       $(SBUF_SOURCE) \
        SquidMath.cc \
        StatCounters.cc \
        StatCounters.h \
@@ -1251,7 +1249,6 @@
        StrList.cc \
        tests/stub_StatHist.cc \
        stmem.cc \
-       String.cc \
        store_dir.cc \
        StoreIOState.cc \
        StoreMeta.cc \
@@ -1376,7 +1373,7 @@
        HttpRequestMethod.cc \
        Mem.h \
        mem.cc \
-       String.cc \
+       $(SBUF_SOURCE) \
        tests/testCacheManager.cc \
        tests/testCacheManager.h \
        tests/testMain.cc \
@@ -1480,7 +1477,6 @@
        multicast.h \
        multicast.cc \
        mem_node.cc \
-       MemBlob.cc \
        MemBuf.cc \
        MemObject.cc \
        mime.h \
@@ -1671,6 +1667,7 @@
        RemovalPolicy.cc \
        RequestFlags.h \
        RequestFlags.cc \
+       $(SBUF_SOURCE) \
        StatCounters.h \
        StatCounters.cc \
        StatHist.h \
@@ -1694,7 +1691,6 @@
        store_swapmeta.cc \
        repl_modules.h \
        store.cc \
-       String.cc \
        StrList.h \
        StrList.cc \
        SwapDir.cc \
@@ -1900,7 +1896,6 @@
        Mem.h \
        mem.cc \
        mem_node.cc \
-       MemBlob.cc \
        MemBuf.cc \
        MemObject.cc \
        mime.h \
@@ -1929,6 +1924,7 @@
        refresh.h \
        refresh.cc \
        RemovalPolicy.cc \
+       $(SBUF_SOURCE) \
        Server.cc \
        StrList.h \
        StrList.cc \
@@ -1970,7 +1966,6 @@
        StoreMetaURL.cc \
        StoreMetaVary.cc \
        StoreSwapLogData.cc \
-       String.cc \
        SwapDir.cc \
        tests/CapturingStoreEntry.h \
        tests/testEvent.cc \
@@ -2147,7 +2142,6 @@
        SquidList.cc \
        MasterXaction.cc \
        MasterXaction.h \
-       MemBlob.cc \
        MemBuf.cc \
        MemObject.cc \
        Mem.h \
@@ -2179,6 +2173,7 @@
        redirect.cc \
        refresh.h \
        refresh.cc \
+       $(SBUF_SOURCE) \
        Server.cc \
        $(SNMP_SOURCE) \
        SquidMath.h \
@@ -2219,7 +2214,6 @@
        StoreMetaURL.cc \
        StoreMetaVary.cc \
        StoreSwapLogData.cc \
-       String.cc \
        StrList.h \
        StrList.cc \
        SwapDir.cc \
@@ -2394,7 +2388,6 @@
        SquidList.cc \
        MasterXaction.cc \
        MasterXaction.h \
-       MemBlob.cc \
        MemBuf.cc \
        MemObject.cc \
        Mem.h \
@@ -2426,6 +2419,7 @@
        refresh.h \
        refresh.cc \
        RemovalPolicy.cc \
+       $(SBUF_SOURCE) \
        Server.cc \
        $(SNMP_SOURCE) \
        SquidMath.h \
@@ -2465,7 +2459,6 @@
        StoreMetaURL.cc \
        StoreMetaVary.cc \
        StoreSwapLogData.cc \
-       String.cc \
        StrList.h \
        StrList.cc \
        SwapDir.cc \
@@ -2542,7 +2535,7 @@
        MemBuf.h \
        Mem.h \
        mem.cc \
-       String.cc \
+       $(SBUF_SOURCE) \
        cache_cf.h \
        YesNoNone.h \
        tests/stub_cache_cf.cc \
@@ -2585,7 +2578,7 @@
        HttpRequestMethod.cc \
        Mem.h \
        mem.cc \
-       String.cc \
+       $(SBUF_SOURCE) \
        tests/testHttpRequest.h \
        tests/testHttpRequest.cc \
        tests/testHttpRequestMethod.h \
@@ -2689,7 +2682,6 @@
        multicast.h \
        multicast.cc \
        mem_node.cc \
-       MemBlob.cc \
        MemBuf.cc \
        MemObject.cc \
        mime.h \
@@ -2871,6 +2863,7 @@
        RemovalPolicy.cc \
        refresh.h \
        refresh.cc \
+       $(SBUF_SOURCE) \
        StatCounters.h \
        StatCounters.cc \
        StatHist.h \
@@ -2892,7 +2885,6 @@
        StoreSwapLogData.cc \
        store_key_md5.h \
        store_key_md5.cc \
-       String.cc \
        StrList.h \
        StrList.cc \
        SwapDir.cc \
@@ -2997,7 +2989,7 @@
        Mem.h \
        mem.cc \
        MemBuf.cc \
-       String.cc \
+       $(SBUF_SOURCE) \
        tests/testMain.cc \
        tests/testString.cc \
        tests/testString.h \
@@ -3084,6 +3076,7 @@
        int.cc \
        RequestFlags.h \
        RequestFlags.cc \
+       $(SBUF_SOURCE) \
        SquidList.h \
        SquidList.cc \
        MasterXaction.cc \
@@ -3127,7 +3120,6 @@
        tests/stub_cache_cf.cc \
        tests/stub_helper.cc \
        cbdata.cc \
-       String.cc \
        tests/stub_debug.cc \
        tests/stub_client_side_request.cc \
        tests/stub_http.cc \
@@ -3286,6 +3278,7 @@
        RemovalPolicy.cc \
        RequestFlags.cc \
        RequestFlags.h \
+       $(SBUF_SOURCE) \
        StatCounters.h \
        StatCounters.cc \
        StatHist.h \
@@ -3309,7 +3302,6 @@
        store_key_md5.cc \
        store_swapmeta.cc \
        store_swapout.cc \
-       String.cc \
        StrList.h \
        StrList.cc \
        SwapDir.cc \
@@ -3503,7 +3495,6 @@
        Mem.h \
        mem.cc \
        mem_node.cc \
-       MemBlob.cc \
        MemBuf.cc \
        MemObject.cc \
        mime.h \
@@ -3530,6 +3521,7 @@
        refresh.h \
        refresh.cc \
        RemovalPolicy.cc \
+       $(SBUF_SOURCE) \
        Server.cc \
        $(SNMP_SOURCE) \
        SquidMath.h \
@@ -3569,7 +3561,6 @@
        StoreMetaURL.cc \
        StoreMetaVary.cc \
        StoreSwapLogData.cc \
-       String.cc \
        StrList.h \
        StrList.cc \
        SwapDir.cc \
@@ -3662,8 +3653,6 @@
        tests/stub_store.cc \
        tests/stub_store_stats.cc \
        tests/stub_tools.cc \
-       SquidString.h \
-       String.cc \
        wordlist.cc \
        MemBuf.cc
 nodist_tests_testSBuf_SOURCES=$(TESTSOURCES)
@@ -3685,7 +3674,6 @@
        Mem.h \
        mem.cc \
        MemBuf.cc \
-       String.cc \
        ConfigParser.cc \
        fatal.h \
        tests/stub_fatal.cc \
@@ -3693,6 +3681,7 @@
        tests/testConfigParser.cc \
        tests/testConfigParser.h \
        cache_cf.h \
+       $(SBUF_SOURCE) \
        YesNoNone.h \
        tests/stub_cache_cf.cc \
        tests/stub_cache_manager.cc \
@@ -3726,7 +3715,6 @@
        MemBuf.cc \
        StatHist.cc \
        StatHist.h \
-       String.cc \
        tests/stub_cache_manager.cc \
        tests/stub_comm.cc \
        tests/stub_debug.cc \
@@ -3740,6 +3728,7 @@
        tests/stub_pconn.cc \
        tests/stub_stmem.cc \
        repl_modules.h \
+       $(SBUF_SOURCE) \
        tests/stub_store.cc \
        tests/stub_store_stats.cc \
        tools.h \

=== modified file 'src/SBuf.cc'
--- src/SBuf.cc 2013-10-07 11:23:58 +0000
+++ src/SBuf.cc 2013-10-10 07:13:57 +0000
@@ -115,16 +115,6 @@
     ++stats.live;
 }
 
-SBuf::SBuf(const String &S)
-        : store_(GetStorePrototype()), off_(0), len_(0)
-{
-    debugs(24, 8, id << " created from string");
-    assign(S.rawBuf(), S.size());
-    ++stats.alloc;
-    ++stats.allocFromString;
-    ++stats.live;
-}
-
 SBuf::SBuf(const std::string &s)
         : store_(GetStorePrototype()), off_(0), len_(0)
 {
@@ -738,7 +728,7 @@
     os <<
     "SBuf stats:\nnumber of allocations: " << alloc <<
     "\ncopy-allocations: " << allocCopy <<
-    "\ncopy-allocations from SquidString: " << allocFromString <<
+    "\ncopy-allocations from std::string: " << allocFromString <<
     "\ncopy-allocations from C String: " << allocFromCString <<
     "\nlive references: " << live <<
     "\nno-copy assignments: " << assignFast <<
@@ -805,15 +795,6 @@
         throw OutOfBoundsException(*this, pos, __FILE__, __LINE__);
 }
 
-String
-SBuf::toString() const
-{
-    String rv;
-    rv.limitInit(buf(), length());
-    ++stats.copyOut;
-    return rv;
-}
-
 /** re-allocate the backing store of the SBuf.
  *
  * If there are contents in the SBuf, they will be copied over.

=== modified file 'src/SBuf.h'
--- src/SBuf.h  2013-10-08 04:17:17 +0000
+++ src/SBuf.h  2013-10-10 07:12:17 +0000
@@ -32,7 +32,6 @@
 #include "base/InstanceId.h"
 #include "MemBlob.h"
 #include "SBufExceptions.h"
-#include "SquidString.h"
 
 #if HAVE_CLIMITS
 #include <climits>
@@ -131,12 +130,6 @@
      */
     explicit SBuf(const char *S, size_type n = npos);
 
-    /** Constructor: import SquidString, copying contents.
-     *
-     * This method will be removed once SquidString has gone.
-     */
-    explicit SBuf(const String &S);
-
     /// Constructor: import std::string. Contents are copied.
     explicit SBuf(const std::string &s);
 
@@ -310,7 +303,7 @@
     /** exports a pointer to the SBuf internal storage.
      * \warning ACCESSING RAW STORAGE IS DANGEROUS!
      *
-     * Returns a ead-only pointer to SBuf's content. No terminating null
+     * Returns a read-only pointer to SBuf's content. No terminating null
      * character is appended (use c_str() for that).
      * The returned value points to an internal location whose contents
      * are guaranteed to remain unchanged only until the next call
@@ -536,11 +529,13 @@
      */
     SBuf toUpper() const;
 
+#if 0
     /** String export function
      * converts the SBuf to a legacy String, by copy.
      * \deprecated
      */
     String toString() const;
+#endif
 
     /// std::string export function
     std::string toStdString() const { return std::string(buf(),length()); }

=== modified file 'src/SquidString.h'
--- src/SquidString.h   2013-10-04 13:55:21 +0000
+++ src/SquidString.h   2013-10-10 07:48:46 +0000
@@ -1,42 +1,21 @@
-/*
- * DEBUG: section 67    String
- * AUTHOR: Duane Wessels
- *
- * 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.
- *
- */
-
 #ifndef SQUID_STRING_H
 #define SQUID_STRING_H
 
+#include "SBuf.h"
+
+#include <cstring>
 #if HAVE_OSTREAM
 #include <ostream>
 #endif
 
+#if HAVE_STDINT_H
+#include <stdint.h>
+#else /* HAVE_STDINT_H */
+#ifndef INT_MAX
+#define INT_MAX 1<<31 //hack but a safe bet
+#endif /* INT_MAX */
+#endif /* HAVE_STDINT_H */
+
 /* squid string placeholder (for printf) */
 #ifndef SQUIDSTRINGPH
 #define SQUIDSTRINGPH "%.*s"
@@ -45,107 +24,261 @@
 
 class String
 {
-
 public:
-    _SQUID_INLINE_ String();
-    String(char const *);
-    String(String const &);
-    ~String();
-
-    typedef size_t size_type; //storage size intentionally unspecified
-    const static size_type npos = std::string::npos;
-
-    String &operator =(char const *);
-    String &operator =(String const &);
-    bool operator ==(String const &) const;
-    bool operator !=(String const &) const;
-
-    /**
-     * Retrieve a single character in the string.
-     \param pos        Position of character to retrieve.
-     */
-    _SQUID_INLINE_ char operator [](unsigned int pos) const;
-
-    _SQUID_INLINE_ size_type size() const;
+    String() : buf_(), defined_(false) {}
+    String(char const *s) : buf_(s), defined_(s != NULL) {}
+    String(String const &s) : buf_(s.toSBuf()), defined_(s.defined()) {}
+    String(SBuf const &s) : buf_(s), defined_(s.length() > 0) {}
+
+    typedef SBuf::size_type size_type; //storage size intentionally unspecified
+    const static size_type npos = SBuf::npos;
+
+    String &operator =(char const *s) {reset(s);return *this;}
+    String &operator =(String const &s) {
+        buf_.clear();
+        defined_=false;
+        append(s.toSBuf());
+        return *this;
+    }
+    bool operator ==(String const &s) const {return buf_ == s.toSBuf();}
+    bool operator !=(String const &s) const {return buf_ != s.toSBuf();}
+
+    char operator [](unsigned int p) const {return buf_[p];}
+
+    size_type size() const {return buf_.length();}
+
     /// variant of size() suited to be used for printf-alikes.
-    /// throws when size() > MAXINT
-    int psize() const;
+    /// throws when size() would overflow
+    int psize() const {
+        Must(buf_.length() < INT_MAX);
+        return buf_.length();
+    }
 
-    /**
-     * \retval true the String has some contents
-     */
-    _SQUID_INLINE_ bool defined() const;
-    /**
-     * \retval true the String does not hold any contents
-     */
-    _SQUID_INLINE_ bool undefined() const;
+    bool defined() const {return defined_;}
+    bool undefined() const {return !defined();}
     /**
      * Returns a raw pointer to the underlying backing store. The caller has 
been
      * verified not to make any assumptions about null-termination
      */
-    _SQUID_INLINE_ char const * rawBuf() const;
+    char const * rawBuf() const {return termedBuf();}
     /**
      * Returns a raw pointer to the underlying backing store.
      * The caller requires it to be null-terminated.
      */
-    _SQUID_INLINE_ char const * termedBuf() const;
-    void limitInit(const char *str, int len); // TODO: rename to assign()
-    void clean();
-    void reset(char const *str);
-    void append(char const *buf, int len);
-    void append(char const *buf);
-    void append(char const);
-    void append(String const &);
-    void absorb(String &old);
-    const char * pos(char const *aString) const;
-    const char * pos(char const ch) const;
+    char const * termedBuf() const {
+        if (!defined()) return NULL;
+        // XXX: callers will probably try and write to the buffer,
+        // but SquidString never offered any more guarantee than SBuf
+        // does now about buffers existence.
+        return buf_.c_str();
+    }
+    SBuf &toSBuf() const {return buf_;}
+    void limitInit(const char *str, int len) {
+        buf_.clear();
+        buf_.reserveCapacity(len);
+        defined_=true;
+        buf_.append(str);
+    }
+    void clean() {buf_.clear();defined_=false;}
+    void reset(char const *str) {buf_.clear();if(str!=NULL) {defined_=true; 
buf_.append(str);}}
+    void append(char const *buf, int len) {buf_.append(buf,len);defined_=true;}
+    void append(char const *buf) {buf_.append(buf);defined_=true;}
+    void append(char const chr) {
+        char myString[2];
+        myString[0]=chr;
+        myString[1]='\0';
+        append(myString, 1);
+    }
+    void append(String const &s) {buf_.append(s.toSBuf());defined_=true;}
+    void absorb(String &old) {
+        buf_.clear();
+        buf_=old.toSBuf();
+        defined_=old.defined();
+        old.clean();
+    }
+    const char * pos(char const *aString) const {
+        if (!defined())
+            return NULL;
+        return strstr(termedBuf(), aString);
+    }
+    const char * pos(char const ch) const {
+        if (!defined())
+            return NULL;
+        return strchr(termedBuf(), ch);
+    }
     ///offset from string start of the first occurrence of ch
     /// returns String::npos if ch is not found
-    size_type find(char const ch) const;
-    size_type find(char const *aString) const;
-    const char * rpos(char const ch) const;
-    size_type rfind(char const ch) const;
-    _SQUID_INLINE_ int cmp(char const *) const;
-    _SQUID_INLINE_ int cmp(char const *, size_type count) const;
-    _SQUID_INLINE_ int cmp(String const &) const;
-    _SQUID_INLINE_ int caseCmp(char const *) const;
-    _SQUID_INLINE_ int caseCmp(char const *, size_type count) const;
-    _SQUID_INLINE_ int caseCmp(String const &) const;
-
-    String substr(size_type from, size_type to) const;
-
-    _SQUID_INLINE_ void cut(size_type newLength);
+    size_type find(char const ch) const {
+        const char *c;
+        c=pos(ch);
+        if (c==NULL)
+            return npos;
+        return c-rawBuf();
+    }
+    size_type find(char const *aString) const {
+        const char *c=pos(aString);
+        if (c==NULL)
+            return npos;
+        return c-rawBuf();
+    }
+    const char * rpos(char const ch) const {
+        if (!defined())
+            return NULL;
+        return strrchr(termedBuf(), (ch));
+    }
+    size_type rfind(char const ch) const {
+        const char *c = rpos(ch);
+        if (c==NULL)
+            return npos;
+        return c-rawBuf();
+    }
+
+    int cmp(char const *s) const {return buf_.cmp(SBuf(s));}
+    int cmp(char const *s, size_type count) const {
+        // XXX: SquidString ignores the terminator. SBuf treats it as a byte.
+        if (s!=NULL && strlen(s) < count)
+            count = strlen(s);
+        return buf_.cmp(SBuf(s,count), count);
+    }
+    int cmp(String const &s) const {return buf_.cmp(s.toSBuf());}
+    int caseCmp(char const *s) const {return buf_.caseCmp(SBuf(s));}
+    int caseCmp(char const *s, size_type count) const {
+        // XXX: SquidString ignores the terminator. SBuf treats it as a byte.
+        if (s!=NULL && strlen(s) < count)
+            count = strlen(s);
+        return buf_.caseCmp(SBuf(s,count), count);
+    }
+    int caseCmp(String const &s) const {return buf_.caseCmp(s.toSBuf());}
+
+    String substr(size_type from, size_type to) const {
+        Must(from < buf_.length());
+        Must(to > 0 && to <= buf_.length());
+        Must(to > from);
+        return String(buf_.substr(from, to-from));
+    }
+
+    void cut(size_type newLength) {
+        if (newLength > buf_.length()) return;
+        if (buf_.length() == 0 && !defined()) return;
+        buf_.setAt(newLength, '\0');
+        buf_.chop(newLength);
+    }
 
 private:
-    void allocAndFill(const char *str, int len);
-    void allocBuffer(size_type sz);
-    void setBuffer(char *buf, size_type sz);
-
-    _SQUID_INLINE_ bool nilCmp(bool, bool, int &) const;
-
-    /* never reference these directly! */
-    size_type size_; /* buffer size; 64K limit */
-
-    size_type len_;  /* current length  */
-
-    char *buf_;
-
-    _SQUID_INLINE_ void set(char const *loc, char const ch);
-    _SQUID_INLINE_ void cutPointer(char const *loc);
-
+    mutable SBuf buf_;
+
+    // SquidString used to track whether buf_ was NULL or not
+    // and some code makes use of this property.
+    // Until that is all checked and defined()/undefined() erased
+    // we explicitly track whether SquidString would have had
+    // buf_ allocated.
+    mutable bool defined_;
 };
 
-_SQUID_INLINE_ std::ostream & operator<<(std::ostream& os, String const 
&aString);
-
-_SQUID_INLINE_ bool operator<(const String &a, const String &b);
-
-#if _USE_INLINE_
-#include "String.cci"
-#endif
-
-const char *checkNullString(const char *p);
-int stringHasWhitespace(const char *);
-int stringHasCntl(const char *);
-char *strwordtok(char *buf, char **t);
+inline std::ostream & operator<<(std::ostream& os, String const &aString) {
+    return os << aString.toSBuf();
+}
+
+inline bool operator<(const String &a, const String &b) {
+    return a.toSBuf().cmp(b.toSBuf());
+}
+
+inline const char *checkNullString(const char *p) {
+    return p ? p : "(NULL)";
+}
+
+inline int stringHasWhitespace(const char *s) {
+    return strpbrk(s, w_space) != NULL;
+}
+
+inline int stringHasCntl(const char *s) {
+    unsigned char c;
+    while ((c = (unsigned char) *s++) != '\0') {
+        if (c <= 0x1f)
+            return 1;
+        if (c >= 0x7f && c <= 0x9f)
+            return 1;
+    }
+    return 0;
+}
+
+/*
+ * Similar to strtok, but has some rudimentary knowledge
+ * of quoting
+ */
+inline char *strwordtok(char *buf, char **t) {
+    unsigned char *word = NULL;
+    unsigned char *p = (unsigned char *) buf;
+    unsigned char *d;
+    unsigned char ch;
+    bool quoted = false;
+
+    if (!p)
+        p = (unsigned char *) *t;
+
+    if (!p) {
+        *t = (char *) p;
+        return (char *) word;
+    }
+
+    while (*p && xisspace(*p))
+        ++p;
+
+    if (!*p) {
+        *t = (char *) p;
+        return (char *) word;
+    }
+
+    word = d = p;
+
+    while ((ch = *p)) {
+        switch (ch) {
+
+        case '\\':
+            ++p;
+
+            switch (*p) {
+            case 'n':
+                ch = '\n';
+                break;
+            case 'r':
+                ch = '\r';
+                break;
+            default:
+                ch = *p;
+                break;
+            }
+
+            *d = ch;
+            ++d;
+
+            if (ch)
+                ++p;
+            break;
+
+        case '"':
+            quoted = !quoted;
+            ++p;
+            break;
+
+        default:
+            if (!quoted && xisspace(*p)) {
+                ++p;
+                *d = '\0';
+                *t = (char *) p;
+                return (char *) word;
+            }
+
+            *d = *p;
+            ++d;
+            ++p;
+            break;
+        }
+    }
+
+    *d = '\0';
+    *t = (char *) p;
+    return (char *) word;
+}
 
 #endif /* SQUID_STRING_H */

=== modified file 'src/tests/testSBuf.cc'
--- src/tests/testSBuf.cc       2013-10-07 10:23:48 +0000
+++ src/tests/testSBuf.cc       2013-10-10 07:21:28 +0000
@@ -105,13 +105,6 @@
         CPPUNIT_ASSERT_EQUAL(s4,s3);
     }
 
-    // TEST: go via SquidString adapters.
-    {
-        String str(fox);
-        SBuf s1(str);
-        CPPUNIT_ASSERT_EQUAL(literal,s1);
-    }
-
     // TEST: go via std::string adapter.
     {
         std::string str(fox);


=== removed file 'src/String.cc'

=== removed file 'src/String.cci'

Reply via email to