panthema / 2006 / SDIOS06 / sdios06 / testapps / stltest / iostream (Download File)
#ifndef IOSTREAM_
#define IOSTREAM_

#include <new>

#include <assert.h>
#include <stdio.h>
#include <string.h>

#include "algorithm"
#include "streambuf"

namespace std {

	/** Super naive ostream implementation, doesn't even support streambufs */
	class ostream
	{
	public:
		typedef ostream& (*ostream_fptr) (ostream&);

		ostream(streambuf* new_sbuf)
			: sbuf(new_sbuf)
		{
			assert(sbuf != NULL);
		}
		
		~ostream()
		{
			sbuf->sync();
		}
		
		void write(const char* str)
		{
			size_t len = strlen(str);
			write(str, len);	
		}
		
		void write(const char* str, size_t len)
		{
			do {
				size_t ilen = min(len, size_t(sbuf->epptr() - sbuf->pptr()));
				if(ilen == 0) {
					sbuf->overflow(streambuf::eof);
					ilen = min(len, size_t(sbuf->epptr() - sbuf->pptr()));
				}
				memcpy(sbuf->pptr(), str, ilen);
				sbuf->pbump(static_cast<int>(ilen));
				str += ilen;
				len -= ilen;
			} while(len > 0);
		}
		
		void flush()
		{
			sbuf->sync();
		}

		ostream& operator<<(ostream_fptr f)
		{
			return f(*this);
		}
		
		streambuf* rdbuf()
		{
			return sbuf;
		}
		
	private:
		streambuf* sbuf;
	};
	
	static inline ostream& operator<<(ostream& out, const char* str)
	{
		out.write(str);
		return out;
	}
	
	static inline ostream& operator<<(ostream& out, int v)
	{
		char buf[20];
		snprintf(buf, sizeof(buf), "%d", v);
		out.write(buf);
		return out;
	}
	
	static inline ostream& operator<<(ostream& out, unsigned int v)
	{
		char buf[20];
		snprintf(buf, sizeof(buf), "%u", v);
		out.write(buf);
		return out;
	}
	
	static inline ostream& operator<<(ostream& out, long v)
	{
		char buf[20];
		snprintf(buf, sizeof(buf), "%ld", v);
		out.write(buf);
		return out;
	}	

	static inline ostream& operator<<(ostream& out, unsigned long v)
	{
		char buf[20];
		snprintf(buf, sizeof(buf), "%lu", v);
		out.write(buf);
		return out;
	}			

	static inline ostream& operator<<(ostream& out, float v)
	{
		char buf[30];
		snprintf(buf, sizeof(buf), "%f", v);
		out.write(buf);
		return out;
	}

	static inline ostream& endl(ostream& out)
	{
		out << "\n";
		out.flush();
		return out;
	}

	static inline ostream& flush(ostream& out)
	{
		out.flush();
		return out;
	}
	
	class fstreambuf : public streambuf
	{
	public:
		fstreambuf(FILE* newfile)
			: file(newfile)
		{
			setp(buf, buf + sizeof(buf) - 1);
			setg(NULL, NULL, NULL);
		}
		
		virtual ~fstreambuf()
		{
			sync();
		}
		
		virtual int overflow(int c)
    	{
			size_t len = size_t(pptr() - pbase());
			if(c != EOF) {
				*pptr() = c;
				++len;
			}
			
			// anything to send out
			if(len > 0) {
				const char* data = pbase();
				if(fwrite(data, 1, len, file) != len) {
					return EOF;
				}
				setp(buf, buf + sizeof(buf) - 1);
			}
			fflush(file);
		
			return 0;
    	}
    	
    	virtual int sync()
    	{
    		return overflow(eof);
    	}
		
	private:
		FILE* file;
		char buf[80];
	};
	
	extern fstreambuf stdoutbuf;
	extern ostream cout;
	extern ostream cerr;
}

#endif /*IOSTREAM_*/