X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fbuffered.cpp;h=f53d2fc23fa49e38ede87da0188b40d3cfeadb50;hp=4cd5cb4d0eed742c81357cedd634895793dae7f2;hb=b97d4e9f86e90254ab9edef7ee62a910f6333c78;hpb=c0861d1f8e3869f058bc8b152cd35a08e5b03e73 diff --git a/source/buffered.cpp b/source/buffered.cpp index 4cd5cb4..f53d2fc 100644 --- a/source/buffered.cpp +++ b/source/buffered.cpp @@ -1,11 +1,6 @@ -/* $Id$ - -This file is part of libmspio -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ +#include #include "buffered.h" -#include "error.h" +#include "except.h" using namespace std; @@ -15,189 +10,178 @@ namespace IO { Buffered::Buffered(Base &b, unsigned s): below(b), buf_size(s), - in_buf(new char[buf_size]), - in_ptr(in_buf), - in_avail(0), - out_buf(new char[buf_size]), - out_used(0) + buf(new char[buf_size]), + begin(buf), + end(buf), + cur_op(M_NONE) { - mode=below.get_mode(); - below.signal_closing.connect(sigc::mem_fun(this, &Buffered::below_closing)); + mode = below.get_mode(); + below.signal_flush_required.connect(sigc::mem_fun(this, &Buffered::flush)); } -unsigned Buffered::put(char c) +Buffered::~Buffered() { - if(out_used0) - { - --in_avail; - return *in_ptr++; + if(len(c); + else if(cur_op==M_READ) + begin=end = buf; } -Handle Buffered::get_event_handle() +unsigned Buffered::do_write(const char *data, unsigned size) { - throw Exception("Buffered doesn't support events"); -} + set_op(M_WRITE); -Buffered::~Buffered() -{ - try + if(end+size0) - { - // XXX sub-obtimal - should try to write directly from input first - // Fill the buffer and pass it on - unsigned head=min(buf_size-out_used, size); - - memcpy(out_buf+out_used, buf, head); - out_used+=head; - - buf+=head; - size-=head; - ret+=head; + // Give out whatever is in the buffer already + memcpy(data, begin, end-begin); + unsigned ret = end-begin; + begin=end = buf; - if(!ok) break; + data += ret; + size -= ret; - unsigned len=below.write(out_buf, out_used); - - ok=(len==out_used); - if(ok) - out_used=0; - else - { - memmove(out_buf, out_buf+len, buf_size-len); - out_used=buf_size-len; - } + if(size(end-begin), size); + memcpy(data, begin, len); + begin += len; + ret += len; } + else + // Read the rest directly from the underlying object + ret += below.read(data, size); + + eof_flag = (below.eof() && begin==end); return ret; } } -unsigned Buffered::do_read(char *buf, unsigned size) +unsigned Buffered::put(char c) { - if(size<=in_avail) - { - // The request can be served from the buffer - memcpy(buf, in_ptr, size); - in_ptr+=size; - in_avail-=size; + set_op(M_WRITE); - return size; + if(end=buf_size) - ret+=below.read(buf, size); - else + for(char *i=begin; i!=end; ++i) + if(*i=='\n') { - // Read more data into the buffer - while(size>0) - { - in_avail=below.read(in_buf, buf_size); - if(in_avail==0) - { - eof_flag=true; - break; - } - - unsigned head=min(size, in_avail); - memcpy(buf, in_buf, head); - buf+=head; - size-=head; - - in_ptr=in_buf+head; - in_avail-=head; - ret+=head; - } + line.assign(begin, i-begin); + begin = i+1; + return true; } - return ret; - } + return Base::getline(line); +} + +int Buffered::get() +{ + set_op(M_READ); + + if(begin(*begin++); + + char c; + if(do_read(&c, 1)==0) + return -1; + return static_cast(c); +} + +void Buffered::set_op(Mode op) +{ + if(op!=cur_op) + flush(); + cur_op = op; +} + +unsigned Buffered::get_current_size() const +{ + return end-begin; +} + +Handle Buffered::get_event_handle() +{ + throw Exception("Buffered doesn't support events"); } } // namespace IO