diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index acf4c0d6a3fee4035fac0b15c6e6de04d68976aa..4c00cc04e972e9af49e0be7eaad5277029366999 100644
--- a/indra/llcorehttp/CMakeLists.txt
+++ b/indra/llcorehttp/CMakeLists.txt
@@ -24,6 +24,7 @@ include_directories(
 
 set(llcorehttp_SOURCE_FILES
     bufferarray.cpp
+    bufferstream.cpp
     httpcommon.cpp
     httpheaders.cpp
     httpoptions.cpp
@@ -47,6 +48,7 @@ set(llcorehttp_HEADER_FILES
     CMakeLists.txt
 
     bufferarray.h
+    bufferstream.h
     httpcommon.h
     httphandler.h
     httpheaders.h
@@ -105,6 +107,7 @@ if (LL_TESTS)
       tests/test_httprequestqueue.hpp
       tests/test_httpheaders.hpp
       tests/test_bufferarray.hpp
+      tests/test_bufferstream.hpp
       )
 
   set_source_files_properties(${llcorehttp_TEST_HEADER_FILES}
diff --git a/indra/llcorehttp/bufferarray.cpp b/indra/llcorehttp/bufferarray.cpp
index 5eaa60c9ba92b4b551d4d8aebfca33ba853b35f8..5eb8f84c34074c9840836c670d0568f0ced46238 100644
--- a/indra/llcorehttp/bufferarray.cpp
+++ b/indra/llcorehttp/bufferarray.cpp
@@ -288,6 +288,20 @@ int BufferArray::findBlock(size_t pos, size_t * ret_offset)
 }
 
 
+bool BufferArray::getBlockStartEnd(int block, const char ** start, const char ** end)
+{
+	if (block < 0 || block >= mBlocks.size())
+	{
+		return false;
+	}
+
+	const Block & b(*mBlocks[block]);
+	*start = &b.mData[0];
+	*end = &b.mData[b.mUsed];
+	return true;
+}
+
+
 // ==================================
 // BufferArray::Block Definitions
 // ==================================
diff --git a/indra/llcorehttp/bufferarray.h b/indra/llcorehttp/bufferarray.h
index d0c51d3c735be3d71eed595ccbd5d9fd63d1f8d7..1094a435b42246a01b4bd93d76211557ea0fd1f3 100644
--- a/indra/llcorehttp/bufferarray.h
+++ b/indra/llcorehttp/bufferarray.h
@@ -37,6 +37,7 @@
 namespace LLCore
 {
 
+class BufferArrayStreamBuf;
 
 /// A very simple scatter/gather type map for bulk data.  The motivation
 /// for this class is the writedata callback used by libcurl.  Response
@@ -65,6 +66,11 @@ namespace LLCore
 class BufferArray : public LLCoreInt::RefCounted
 {
 public:
+	// BufferArrayStreamBuf has intimate knowledge of this
+	// implementation to implement a buffer-free adapter.
+	// Changes here will likely need to be reflected there.
+	friend class BufferArrayStreamBuf;
+	
 	BufferArray();
 
 protected:
@@ -114,6 +120,8 @@ class BufferArray : public LLCoreInt::RefCounted
 	
 protected:
 	int findBlock(size_t pos, size_t * ret_offset);
+
+	bool getBlockStartEnd(int block, const char ** start, const char ** end);
 	
 protected:
 	class Block;
diff --git a/indra/llcorehttp/bufferstream.cpp b/indra/llcorehttp/bufferstream.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6553900eef524dd58ecdc5e890ba3039f34e909e
--- /dev/null
+++ b/indra/llcorehttp/bufferstream.cpp
@@ -0,0 +1,285 @@
+/**
+ * @file bufferstream.cpp
+ * @brief Implements the BufferStream adapter class
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "bufferstream.h"
+
+#include "bufferarray.h"
+
+
+namespace LLCore
+{
+
+BufferArrayStreamBuf::BufferArrayStreamBuf(BufferArray * array)
+	: mBufferArray(array),
+	  mReadCurPos(0),
+	  mReadCurBlock(-1),
+	  mReadBegin(NULL),
+	  mReadCur(NULL),
+	  mReadEnd(NULL),
+	  mWriteCurPos(0)
+{
+	if (array)
+	{
+		array->addRef();
+		mWriteCurPos = array->mLen;
+	}
+}
+
+
+BufferArrayStreamBuf::~BufferArrayStreamBuf()
+{
+	if (mBufferArray)
+	{
+		mBufferArray->release();
+		mBufferArray = NULL;
+	}
+}
+
+	
+BufferArrayStreamBuf::int_type BufferArrayStreamBuf::underflow()
+{
+	if (! mBufferArray)
+	{
+		return traits_type::eof();
+	}
+
+	if (mReadCur == mReadEnd)
+	{
+		// Find the next block with actual data or leave
+		// mCurBlock/mCur/mEnd unchanged if we're at the end
+		// of any block chain.
+		const char * new_begin(NULL), * new_end(NULL);
+		int new_cur_block(mReadCurBlock + 1);
+
+		while (mBufferArray->getBlockStartEnd(new_cur_block, &new_begin, &new_end))
+		{
+			if (new_begin != new_end)
+			{
+				break;
+			}
+			++new_cur_block;
+		}
+		if (new_begin == new_end)
+		{
+			return traits_type::eof();
+		}
+
+		mReadCurBlock = new_cur_block;
+		mReadBegin = mReadCur = new_begin;
+		mReadEnd = new_end;
+	}
+
+	return traits_type::to_int_type(*mReadCur);
+}
+
+
+BufferArrayStreamBuf::int_type BufferArrayStreamBuf::uflow()
+{
+	const int_type ret(underflow());
+
+	if (traits_type::eof() != ret)
+	{
+		++mReadCur;
+		++mReadCurPos;
+	}
+	return ret;
+}
+
+
+BufferArrayStreamBuf::int_type BufferArrayStreamBuf::pbackfail(int_type ch)
+{
+	if (! mBufferArray)
+	{
+		return traits_type::eof();
+	}
+
+	if (mReadCur == mReadBegin)
+	{
+		// Find the previous block with actual data or leave
+		// mCurBlock/mBegin/mCur/mEnd unchanged if we're at the
+		// beginning of any block chain.
+		const char * new_begin(NULL), * new_end(NULL);
+		int new_cur_block(mReadCurBlock - 1);
+
+		while (mBufferArray->getBlockStartEnd(new_cur_block, &new_begin, &new_end))
+		{
+			if (new_begin != new_end)
+			{
+				break;
+			}
+			--new_cur_block;
+		}
+		if (new_begin == new_end)
+		{
+			return traits_type::eof();
+		}
+
+		mReadCurBlock = new_cur_block;
+		mReadBegin = new_begin;
+		mReadEnd = mReadCur = new_end;
+	}
+
+	if (traits_type::eof() != ch && mReadCur[-1] != ch)
+	{
+		return traits_type::eof();
+	}
+	--mReadCurPos;
+	return traits_type::to_int_type(*--mReadCur);
+}
+
+
+std::streamsize BufferArrayStreamBuf::showmanyc()
+{
+	if (! mBufferArray)
+	{
+		return -1;
+	}
+	return mBufferArray->mLen - mReadCurPos;
+}
+
+
+BufferArrayStreamBuf::int_type BufferArrayStreamBuf::overflow(int c)
+{
+	if (! mBufferArray || mWriteCurPos > mBufferArray->mLen)
+	{
+		return traits_type::eof();
+	}
+	const size_t wrote(mBufferArray->write(mWriteCurPos, &c, 1));
+	mWriteCurPos += wrote;
+	return wrote ? c : traits_type::eof();
+}
+
+
+std::streamsize BufferArrayStreamBuf::xsputn(const char * src, std::streamsize count)
+{
+	if (! mBufferArray || mWriteCurPos > mBufferArray->mLen)
+	{
+		return 0;
+	}
+	const size_t wrote(mBufferArray->write(mWriteCurPos, src, count));
+	mWriteCurPos += wrote;
+	return wrote;
+}
+
+
+std::streampos BufferArrayStreamBuf::seekoff(std::streamoff off,
+											 std::ios_base::seekdir way,
+											 std::ios_base::openmode which)
+{
+	std::streampos ret(-1);
+
+	if (! mBufferArray)
+	{
+		return ret;
+	}
+	
+	if (std::ios_base::in == which)
+	{
+		size_t pos(0);
+
+		switch (way)
+		{
+		case std::ios_base::beg:
+			pos = off;
+			break;
+			
+		case std::ios_base::cur:
+			pos = mReadCurPos += off;
+			break;
+			
+		case std::ios_base::end:
+			pos = mBufferArray->mLen - off;
+			break;
+
+		default:
+			return ret;
+		}
+
+		if (pos >= mBufferArray->size())
+		{
+			pos = (std::max)(size_t(0), mBufferArray->size() - 1);
+		}
+		size_t ba_offset(0);
+		int block(mBufferArray->findBlock(pos, &ba_offset));
+		if (block < 0)
+			return ret;
+		const char * start(NULL), * end(NULL);
+		if (! mBufferArray->getBlockStartEnd(block, &start, &end))
+			return ret;
+		mReadCurBlock = block;
+		mReadBegin = start;
+		mReadCur = start + ba_offset;
+		mReadEnd = end;
+		ret = mReadCurPos = pos;
+	}
+	else if (std::ios_base::out == which)
+	{
+		size_t pos(0);
+
+		switch (way)
+		{
+		case std::ios_base::beg:
+			pos = off;
+			break;
+			
+		case std::ios_base::cur:
+			pos = mWriteCurPos += off;
+			break;
+			
+		case std::ios_base::end:
+			pos = mBufferArray->mLen - off;
+			break;
+
+		default:
+			return ret;
+		}
+
+		if (pos < 0)
+			return ret;
+		if (pos > mBufferArray->size())
+		{
+			pos = mBufferArray->size();
+		}
+		ret = mWriteCurPos = pos;
+	}
+
+	return ret;
+}
+
+
+BufferArrayStream::BufferArrayStream(BufferArray * ba)
+	: std::iostream(&mStreamBuf),
+	  mStreamBuf(ba)
+{}
+	
+			
+BufferArrayStream::~BufferArrayStream()
+{}
+	
+
+}  // end namespace LLCore
+
+
diff --git a/indra/llcorehttp/bufferstream.h b/indra/llcorehttp/bufferstream.h
new file mode 100644
index 0000000000000000000000000000000000000000..60bda9ff9a8c49e1a7d79f7e731a53da08f4e799
--- /dev/null
+++ b/indra/llcorehttp/bufferstream.h
@@ -0,0 +1,94 @@
+/**
+ * @file bufferstream.h
+ * @brief Public-facing declaration for the BufferStream adapter class
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef	_LLCORE_BUFFER_STREAM_H_
+#define	_LLCORE_BUFFER_STREAM_H_
+
+
+#include <sstream>
+#include <cstdlib>
+
+#include "bufferarray.h"
+
+
+namespace LLCore
+{
+
+
+class BufferArrayStreamBuf : public std::streambuf
+{
+public:
+	BufferArrayStreamBuf(BufferArray * array);
+	virtual ~BufferArrayStreamBuf();
+
+private:
+	BufferArrayStreamBuf(const BufferArrayStreamBuf &);	// Not defined
+	void operator=(const BufferArrayStreamBuf &);		// Not defined
+
+public:
+	// Input interfaces from std::streambuf
+	int_type underflow();
+	int_type uflow();
+	int_type pbackfail(int_type ch);
+	std::streamsize showmanyc();
+
+	// Output interfaces from std::streambuf
+	int_type overflow(int c);
+	std::streamsize xsputn(const char * src, std::streamsize count);
+
+	// Common/misc interfaces from std::streambuf
+	std::streampos seekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which);
+	
+protected:
+	BufferArray *		mBufferArray;			// Ref counted
+	size_t				mReadCurPos;
+	int					mReadCurBlock;
+	const char *		mReadBegin;
+	const char *		mReadCur;
+	const char *		mReadEnd;
+	size_t				mWriteCurPos;
+	
+}; // end class BufferArrayStreamBuf
+
+
+class BufferArrayStream : public std::iostream
+{
+public:
+	BufferArrayStream(BufferArray * ba);
+	~BufferArrayStream();
+
+protected:
+	BufferArrayStream(const BufferArrayStream &);
+	void operator=(const BufferArrayStream &);
+
+protected:
+	BufferArrayStreamBuf		mStreamBuf;
+}; // end class BufferArrayStream
+
+
+}  // end namespace LLCore
+
+#endif	// _LLCORE_BUFFER_STREAM_H_
diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp
index 2b36d3a982cdade5da0a64607bcf3a1909fb7bd7..e863ddd13ff75939d3cf4aa4988b065ae79983ed 100644
--- a/indra/llcorehttp/tests/llcorehttp_test.cpp
+++ b/indra/llcorehttp/tests/llcorehttp_test.cpp
@@ -36,12 +36,13 @@
 #include "../test/lltut.h"
 
 // Pull in each of the test sets
+#include "test_bufferarray.hpp"
+#include "test_bufferstream.hpp"
 #include "test_httpstatus.hpp"
 #include "test_refcounted.hpp"
 #include "test_httpoperation.hpp"
 #include "test_httprequest.hpp"
 #include "test_httpheaders.hpp"
-#include "test_bufferarray.hpp"
 #include "test_httprequestqueue.hpp"
 
 #include "llproxy.h"
diff --git a/indra/llcorehttp/tests/test_bufferarray.hpp b/indra/llcorehttp/tests/test_bufferarray.hpp
index 3f947db967a858cd8178d9e26f6dff5c0c07c66a..8a2a64d970c385ab3051d5516bb3c2845f463338 100644
--- a/indra/llcorehttp/tests/test_bufferarray.hpp
+++ b/indra/llcorehttp/tests/test_bufferarray.hpp
@@ -33,7 +33,7 @@
 #include "test_allocator.h"
 
 
-using namespace LLCoreInt;
+using namespace LLCore;
 
 
 
diff --git a/indra/llcorehttp/tests/test_bufferstream.hpp b/indra/llcorehttp/tests/test_bufferstream.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..5afaba096626d18b6d380df40f8dd6c1434af4ab
--- /dev/null
+++ b/indra/llcorehttp/tests/test_bufferstream.hpp
@@ -0,0 +1,252 @@
+/** 
+ * @file test_bufferstream.hpp
+ * @brief unit tests for the LLCore::BufferArrayStreamBuf/BufferArrayStream classes
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+#ifndef TEST_LLCORE_BUFFER_STREAM_H_
+#define TEST_LLCORE_BUFFER_STREAM_H_
+
+#include "bufferstream.h"
+
+#include <iostream>
+
+#include "test_allocator.h"
+
+
+using namespace LLCore;
+
+
+namespace tut
+{
+
+struct BufferStreamTestData
+{
+	// the test objects inherit from this so the member functions and variables
+	// can be referenced directly inside of the test functions.
+	size_t mMemTotal;
+};
+
+typedef test_group<BufferStreamTestData> BufferStreamTestGroupType;
+typedef BufferStreamTestGroupType::object BufferStreamTestObjectType;
+BufferStreamTestGroupType BufferStreamTestGroup("BufferStream Tests");
+typedef BufferArrayStreamBuf::traits_type tst_traits_t;
+
+
+template <> template <>
+void BufferStreamTestObjectType::test<1>()
+{
+	set_test_name("BufferArrayStreamBuf construction with NULL BufferArray");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	BufferArrayStreamBuf * bsb = new BufferArrayStreamBuf(NULL);
+	ensure("Memory being used", mMemTotal < GetMemTotal());
+
+	// Not much will work with a NULL
+	ensure("underflow() on NULL fails", tst_traits_t::eof() == bsb->underflow());
+	ensure("uflow() on NULL fails", tst_traits_t::eof() == bsb->uflow());
+	ensure("pbackfail() on NULL fails", tst_traits_t::eof() == bsb->pbackfail('c'));
+	ensure("showmanyc() on NULL fails", bsb->showmanyc() == -1);
+	ensure("overflow() on NULL fails", tst_traits_t::eof() == bsb->overflow('c'));
+	ensure("xsputn() on NULL fails", bsb->xsputn("blah", 4) == 0);
+	ensure("seekoff() on NULL fails", bsb->seekoff(0, std::ios_base::beg, std::ios_base::in) == std::streampos(-1));
+	
+	// release the implicit reference, causing the object to be released
+	delete bsb;
+	bsb = NULL;
+
+	// make sure we didn't leak any memory
+	ensure("Allocated memory returned", mMemTotal == GetMemTotal());
+}
+
+
+template <> template <>
+void BufferStreamTestObjectType::test<2>()
+{
+	set_test_name("BufferArrayStream construction with NULL BufferArray");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	BufferArrayStream * bas = new BufferArrayStream(NULL);
+	ensure("Memory being used", mMemTotal < GetMemTotal());
+
+	// Not much will work with a NULL here
+	ensure("eof() is false on NULL", ! bas->eof());
+	ensure("fail() is false on NULL", ! bas->fail());
+	ensure("good() on NULL", bas->good());
+		   
+	// release the implicit reference, causing the object to be released
+	delete bas;
+	bas = NULL;
+
+	// make sure we didn't leak any memory
+	ensure("Allocated memory returned", mMemTotal == GetMemTotal());
+}
+
+
+template <> template <>
+void BufferStreamTestObjectType::test<3>()
+{
+	set_test_name("BufferArrayStreamBuf construction with empty BufferArray");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted BufferArray with implicit reference
+	BufferArray * ba = new BufferArray;
+	BufferArrayStreamBuf * bsb = new BufferArrayStreamBuf(ba);
+	ensure("Memory being used", mMemTotal < GetMemTotal());
+
+	// I can release my ref on the BA
+	ba->release();
+	ba = NULL;
+	
+	// release the implicit reference, causing the object to be released
+	delete bsb;
+	bsb = NULL;
+
+	// make sure we didn't leak any memory
+	ensure("Allocated memory returned", mMemTotal == GetMemTotal());
+}
+
+
+template <> template <>
+void BufferStreamTestObjectType::test<4>()
+{
+	set_test_name("BufferArrayStream construction with empty BufferArray");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted BufferArray with implicit reference
+	BufferArray * ba = new BufferArray;
+
+	{
+		// create a new ref counted object with an implicit reference
+		BufferArrayStream bas(ba);
+		ensure("Memory being used", mMemTotal < GetMemTotal());
+	}
+
+	// release the implicit reference, causing the object to be released
+	ba->release();
+	ba = NULL;
+	
+	// make sure we didn't leak any memory
+	ensure("Allocated memory returned", mMemTotal == GetMemTotal());
+}
+
+
+template <> template <>
+void BufferStreamTestObjectType::test<5>()
+{
+	set_test_name("BufferArrayStreamBuf construction with real BufferArray");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted BufferArray with implicit reference
+	BufferArray * ba = new BufferArray;
+	const char * content("This is a string.  A fragment.");
+	const size_t c_len(strlen(content));
+	ba->append(content, c_len);
+	BufferArrayStreamBuf * bsb = new BufferArrayStreamBuf(ba);
+	ensure("Memory being used", mMemTotal < GetMemTotal());
+
+	// I can release my ref on the BA
+	ba->release();
+	ba = NULL;
+	
+	// Various static state
+	ensure("underflow() returns 'T'", bsb->underflow() == 'T');
+	ensure("underflow() returns 'T' again", bsb->underflow() == 'T');
+	ensure("uflow() returns 'T'", bsb->uflow() == 'T');
+	ensure("uflow() returns 'h'", bsb->uflow() == 'h');
+	ensure("pbackfail('i') fails", tst_traits_t::eof() == bsb->pbackfail('i'));
+	ensure("pbackfail('T') fails", tst_traits_t::eof() == bsb->pbackfail('T'));
+	ensure("pbackfail('h') succeeds", bsb->pbackfail('h') == 'h');
+	ensure("showmanyc() is everything but the 'T'", bsb->showmanyc() == (c_len - 1));
+	ensure("overflow() appends", bsb->overflow('c') == 'c');
+	ensure("showmanyc() reflects append", bsb->showmanyc() == (c_len - 1 + 1));
+	ensure("xsputn() appends some more", bsb->xsputn("bla!", 4) == 4);
+	ensure("showmanyc() reflects 2nd append", bsb->showmanyc() == (c_len - 1 + 5));
+	ensure("seekoff() succeeds", bsb->seekoff(0, std::ios_base::beg, std::ios_base::in) == std::streampos(0));
+	ensure("seekoff() succeeds 2", bsb->seekoff(4, std::ios_base::cur, std::ios_base::in) == std::streampos(4));
+	ensure("showmanyc() picks up seekoff", bsb->showmanyc() == (c_len + 5 - 4));
+	ensure("seekoff() succeeds 3", bsb->seekoff(0, std::ios_base::end, std::ios_base::in) == std::streampos(c_len + 4));
+	ensure("pbackfail('!') succeeds", tst_traits_t::eof() == bsb->pbackfail('!'));
+	
+	// release the implicit reference, causing the object to be released
+	delete bsb;
+	bsb = NULL;
+
+	// make sure we didn't leak any memory
+	ensure("Allocated memory returned", mMemTotal == GetMemTotal());
+}
+
+
+template <> template <>
+void BufferStreamTestObjectType::test<6>()
+{
+	set_test_name("BufferArrayStream construction with real BufferArray");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted BufferArray with implicit reference
+	BufferArray * ba = new BufferArray;
+	//const char * content("This is a string.  A fragment.");
+	//const size_t c_len(strlen(content));
+	//ba->append(content, strlen(content));
+
+	{
+		// create a new ref counted object with an implicit reference
+		BufferArrayStream bas(ba);
+		ensure("Memory being used", mMemTotal < GetMemTotal());
+
+		// Basic operations
+		bas << "Hello" << 27 << ".";
+		ensure("BA length 8", ba->size() == 8);
+
+		std::string str;
+		bas >> str;
+		ensure("reads correctly", str == "Hello27.");
+	}
+
+	// release the implicit reference, causing the object to be released
+	ba->release();
+	ba = NULL;
+
+	// make sure we didn't leak any memory
+	// ensure("Allocated memory returned", mMemTotal == GetMemTotal());
+	static U64 mem = GetMemTotal();
+}
+
+
+}  // end namespace tut
+
+
+#endif  // TEST_LLCORE_BUFFER_STREAM_H_