]> git.tdb.fi Git - libs/core.git/blob - source/io/slice.cpp
Add move semantics to Variant
[libs/core.git] / source / io / slice.cpp
1 #include <msp/core/except.h>
2 #include "slice.h"
3
4 using namespace std;
5
6 namespace Msp {
7 namespace IO {
8
9 Slice::Slice(Seekable &b, SeekOffset s, SeekOffset l):
10         below(b),
11         start_offset(s),
12         length(l)
13 {
14         if(s<0 || l<0)
15                 throw invalid_argument("Slice::Slice");
16
17         Base::Synchronize sync(below);
18         mode = below.get_mode()&M_RDWR;
19         below.signal_flush_required.connect(sigc::mem_fun(this, &Slice::flush));
20 }
21
22 void Slice::set_block(bool)
23 {
24         throw unsupported("Slice::set_block");
25 }
26
27 void Slice::set_inherit(bool)
28 {
29         throw unsupported("Slice::set_inherit");
30 }
31
32 void Slice::flush()
33 {
34         sync_position = true;
35 }
36
37 unsigned Slice::prepare_op(unsigned size, Mode m)
38 {
39         check_access(m);
40
41         if(sync_position)
42         {
43                 SeekOffset pos = below.seek(start_offset+position, S_BEG)-start_offset;
44                 if(pos!=position)
45                         throw runtime_error("failed to restore position");
46                 sync_position = false;
47         }
48
49         SeekOffset remaining = length-position;
50         if(size>remaining)
51                 size = remaining;
52         if(!size && m==M_READ)
53                 set_eof();
54
55         return size;
56 }
57
58 size_t Slice::do_write(const char *data, size_t size)
59 {
60         Base::Synchronize sync(below);
61         size = prepare_op(size, M_WRITE);
62         if(!size)
63                 return 0;
64
65         size_t len = below.write(data, size);
66         position += len;
67         return len;
68 }
69
70 size_t Slice::do_read(char *data, size_t size)
71 {
72         Base::Synchronize sync(below);
73         size = prepare_op(size, M_READ);
74         if(!size)
75                 return 0;
76
77         size_t len = below.read(data, size);
78         if(!len && below.eof())
79                 set_eof();
80         position += len;
81         return len;
82 }
83
84 size_t Slice::put(char c)
85 {
86         Base::Synchronize sync(below);
87         if(!prepare_op(1, M_WRITE))
88                 return 0;
89
90         size_t len = below.put(c);
91         position += len;
92         return len;
93 }
94
95 int Slice::get()
96 {
97         Base::Synchronize sync(below);
98         if(!prepare_op(1, M_READ))
99                 return -1;
100
101         int c = below.get();
102         if(c==-1 && below.eof())
103                 set_eof();
104         else
105                 ++position;
106         return c;
107 }
108
109 const Handle &Slice::get_handle(Mode)
110 {
111         throw unsupported("Slice::get_handle");
112 }
113
114 SeekOffset Slice::seek(SeekOffset off, SeekType type)
115 {
116         Base::Synchronize sync(below);
117         off += start_offset;
118         if(type==S_CUR)
119                 off += position;
120         else if(type==S_END)
121                 off += length;
122         else if(type!=S_BEG)
123                 throw invalid_argument("Slice::seek");
124
125         if(off<start_offset || off>start_offset+length)
126                 throw bad_seek(off, type);
127
128         signal_flush_required.emit();
129
130         position = below.seek(off, S_BEG)-start_offset;
131         sync_position = false;
132         return position;
133 }
134
135 } // namespace IO
136 } // namespace Msp