=== modified file 'src/sbuf/Algorithms.h'
--- src/sbuf/Algorithms.h	2016-02-29 10:11:37 +0000
+++ src/sbuf/Algorithms.h	2016-11-05 20:04:33 +0000
@@ -37,65 +37,84 @@
     SBuf prefix_;
     SBufCaseSensitive sensitivity_;
 };
 
 /** SBuf size addition accumulator for STL contaniners
  *
  * Equivalent to prefix_length +  SBuf.length() +  separator.length()
  */
 class SBufAddLength
 {
 public:
     explicit SBufAddLength(const SBuf &separator) :
         separatorLen_(separator.length()) {}
     SBuf::size_type operator()(const SBuf::size_type sz, const SBuf & item) {
         return sz + item.length() + separatorLen_;
     }
 private:
     SBuf::size_type separatorLen_;
 };
 
-/// 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)
+/** Join container of SBufs and append to supplied target
+ *
+ * append to the target SBuf all elements in the [begin,end) range from
+ * an iterable container, prefixed by prefix, separated by separator and
+ * followed by suffix. Prefix and suffix are added also in case of empty
+ * iterable
+ *
+ * \return the modified dest
+ */
+template <class ContainerIterator>
+SBuf&
+JoinContainerIntoSBuf(SBuf &dest, const ContainerIterator &begin,
+		const ContainerIterator &end, const SBuf& separator,
+		const SBuf& prefix = SBuf(), const SBuf& suffix = SBuf())
 {
-    // optimization: pre-calculate needed storage
-    const SBuf::size_type sz = std::accumulate(items.begin(), items.end(), 0, SBufAddLength(separator));
-
-    // sz can be zero in two cases: either items is empty, or all items
-    //  are zero-length. In the former case, we must protect against
-    //  dereferencing the iterator later on, and checking sz is more efficient
-    //  than checking items.size(). This check also provides an optimization
-    //  for the latter case without adding complexity.
-    if (sz == 0)
-        return SBuf();
-
-    SBuf rv;
-    rv.reserveSpace(sz);
+    if (begin == end) {
+    	dest.append(prefix).append(suffix);
+        return dest;
+    }
 
-    typename Container::const_iterator i(items.begin());
-    rv.append(*i);
+    // optimization: pre-calculate needed storage
+    const SBuf::size_type totalContainerSize =
+    		std::accumulate(begin, end, 0, SBufAddLength(separator));
+    dest.reserveSpace(prefix.length() + totalContainerSize + suffix.length());
+
+    auto i = begin;
+    dest.append(prefix);
+    dest.append(*i);
     ++i;
-    for (; i != items.end(); ++i)
-        rv.append(separator).append(*i);
-    return rv;
+    for (; i != end; ++i)
+        dest.append(separator).append(*i);
+    dest.append(suffix);
+    return dest;
+}
+
+/// convenience wrapper of JoinContainerIntoSBuf with no caller-supplied SBuf
+template <class ContainerIterator>
+SBuf
+JoinContainerToSBuf(const ContainerIterator &begin,
+		const ContainerIterator &end, const SBuf& separator,
+		const SBuf& prefix = SBuf(), const SBuf& suffix = SBuf())
+{
+	SBuf rv;
+	return JoinContainerIntoSBuf(rv, begin, end, separator, prefix, suffix);
 }
 
 namespace std {
 /// default hash functor to support std::unordered_map<SBuf,*>
 template <>
 struct hash<SBuf>
 {
     size_t operator()(const SBuf &) const noexcept;
 };
 }
 
 /** hash functor for SBufs, meant so support case-insensitive std::unordered_map
  *
  * Typical use:
  * \code
  * auto m = std::unordered_map<SBuf, ValueType, CaseInsensitiveSBufHash>();
  * \endcode
  */
 class CaseInsensitiveSBufHash
 {

=== modified file 'src/tests/testSBufList.cc'
--- src/tests/testSBufList.cc	2016-03-01 09:58:44 +0000
+++ src/tests/testSBufList.cc	2016-11-04 06:28:43 +0000
@@ -20,28 +20,34 @@
     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()));
+    CPPUNIT_ASSERT_EQUAL(SBuf(""),JoinContainerToSBuf(foo.begin(), foo.end(),SBuf()));
     for (int j = 0; j < sbuf_tokens_number; ++j)
         foo.push_back(tokens[j]);
-    SBuf joined=SBufContainerJoin(foo,SBuf(" "));
+    SBuf joined=JoinContainerToSBuf(foo.begin(), foo.end(),SBuf(" "));
     CPPUNIT_ASSERT_EQUAL(literal,joined);
+    SBuf s1("1"), s2("2"), s3("3"), full("(1,2,3)");
+    SBufList sl{s1,s2,s3};
+    CPPUNIT_ASSERT_EQUAL(full, JoinContainerToSBuf(sl.begin(),
+    		sl.end(), SBuf(","), SBuf("("), SBuf(")")));
+
+    CPPUNIT_ASSERT_EQUAL(SBuf(""),JoinContainerToSBuf(foo.begin(), foo.begin(),SBuf()));
+
 }
 

