X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fio%2Fslice.cpp;fp=source%2Fio%2Fslice.cpp;h=423c1a6c8cae85e73c2f6e15e9733786b31d700e;hp=0000000000000000000000000000000000000000;hb=eedad559456b8e62ed3b9bd9e8253e5f8bcc02d6;hpb=1a6331551a025ddcc1772ae447c326ec70e0e107 diff --git a/source/io/slice.cpp b/source/io/slice.cpp new file mode 100644 index 0000000..423c1a6 --- /dev/null +++ b/source/io/slice.cpp @@ -0,0 +1,111 @@ +#include +#include "slice.h" + +using namespace std; + +namespace Msp { +namespace IO { + +Slice::Slice(Seekable &b, SeekOffset s, SeekOffset l): + below(b), + start_offset(s), + length(l), + position(0), + sync_position(true) +{ + if(s<0 || l<0) + throw invalid_argument("Slice"); + + mode = below.get_mode()&M_RDWR; + below.signal_flush_required.connect(sigc::mem_fun(this, &Slice::flush)); +} + +void Slice::flush() +{ + sync_position = true; +} + +unsigned Slice::prepare_op(unsigned size, Mode m) +{ + check_access(m); + + if(sync_position) + seek(position, S_BEG); + + SeekOffset remaining = start_offset+length-position; + if(size>remaining) + size = remaining; + if(!size && m==M_READ) + set_eof(); + + return size; +} + +unsigned Slice::do_write(const char *data, unsigned size) +{ + size = prepare_op(size, M_WRITE); + if(!size) + return 0; + + unsigned len = below.write(data, size); + position += len; + return len; +} + +unsigned Slice::do_read(char *data, unsigned size) +{ + size = prepare_op(size, M_READ); + if(!size) + return 0; + + unsigned len = below.read(data, size); + if(!len && below.eof()) + set_eof(); + position += len; + return len; +} + +unsigned Slice::put(char c) +{ + if(!prepare_op(1, M_WRITE)) + return 0; + + unsigned len = below.put(c); + position += len; + return len; +} + +int Slice::get() +{ + if(!prepare_op(1, M_READ)) + return 0; + + int c = below.get(); + if(c==-1 && below.eof()) + set_eof(); + else + ++position; + return c; +} + +SeekOffset Slice::seek(SeekOffset off, SeekType type) +{ + if(type==S_BEG) + off += start_offset; + else if(type==S_CUR) + off += position; + else if(type==S_END) + off += start_offset+length; + + if(offstart_offset+length) + throw bad_seek(off, type); + + signal_flush_required.emit(); + + position = below.seek(off, S_BEG)-start_offset; + sync_position = false; + return position; +} + +} // namespace IO +} // namespace Msp