/* (C) 2005  The Measurement Factory
   Licensed under the Apache License, Version 2.0 */

#ifndef TMF_BASE_XSTD__FXSTREAM_H
#define TMF_BASE_XSTD__FXSTREAM_H

#if defined(XSTD_HAVE_STREAMBUF)
#   include <streambuf>
#elsif defined(XSTD_HAVE_STREAMBUF_H)
#   include <streambuf.h>
#endif

// XXX: Keep in sync with the same classes in Polygraph's src/xstd/h/sstream.h

// A streambuf with a fixed-size user-owned storage area.
// The implementation is incomplete and too forgiving, 
// but hopefully sufficient.
class FixedStreamBuf: public std::streambuf {
	public:
		// based on http://www.dbforums.com/showthread.php?t=776452
		FixedStreamBuf(char_type *buffer, std::streamsize size) {
			setp(buffer, buffer + size);
			setg(buffer, buffer, buffer + size);
		}

		// set position relative to dir
		virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir,
			std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) {

			pos_type result = pos_type(-1);

			if (mode & std::ios_base::out) {
				// convert to absolute offset if needed
				if (dir == std::ios_base::cur)
					off = pptr() - pbase() + off;
				else
				if (dir == std::ios_base::end)
					off = epptr() - pbase() - off;
				result = seekpos(off);
			}
			// XXX: support std::ios_base::in mode
			return result;
		}

		// set absolute position (i.e., relative to the base)
		virtual pos_type seekpos(pos_type off,
			std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) {

			pos_type result = pos_type(-1);

			if (mode & std::ios_base::out) {
				if (0 <= off && off <= (epptr() - pbase())) {
					pbump(off - pos_type(pptr() - pbase()));
					result = off;
				}
			}
			// XXX: support std::ios_base::in mode
			return result;
		} 
};

// an output stream that uses our FixedStreamBuf
class OFixedStream: public std::ostream {
	public:
		OFixedStream(char_type *buffer, std::streamsize size):
			theBuffer(buffer, size) {
			this->init(&theBuffer); // set our custom buffer
		}

	private:
		FixedStreamBuf theBuffer;
};

// More "fixed size stream buffer" ideas at
// http://www.inf.uni-konstanz.de/~kuehl/c++/iostream/
// http://www.velocityreviews.com/forums/showpost.php?p=1532770


#endif

