]> git.tdb.fi Git - libs/core.git/blob - source/io/slice.cpp
Rewrite BufferedFile as a standalone class
[libs/core.git] / source / io / slice.cpp
1 #include <stdexcept>
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         position(0),
14         sync_position(true)
15 {
16         if(s<0 || l<0)
17                 throw invalid_argument("Slice");
18
19         mode = below.get_mode()&M_RDWR;
20         below.signal_flush_required.connect(sigc::mem_fun(this, &Slice::flush));
21 }
22
23 void Slice::flush()
24 {
25         sync_position = true;
26 }
27
28 unsigned Slice::prepare_op(unsigned size, Mode m)
29 {
30         check_access(m);
31
32         if(sync_position)
33                 seek(position, S_BEG);
34
35         SeekOffset remaining = start_offset+length-position;
36         if(size>remaining)
37                 size = remaining;
38         if(!size && m==M_READ)
39                 set_eof();
40
41         return size;
42 }
43
44 unsigned Slice::do_write(const char *data, unsigned size)
45 {
46         size = prepare_op(size, M_WRITE);
47         if(!size)
48                 return 0;
49
50         unsigned len = below.write(data, size);
51         position += len;
52         return len;
53 }
54
55 unsigned Slice::do_read(char *data, unsigned size)
56 {
57         size = prepare_op(size, M_READ);
58         if(!size)
59                 return 0;
60
61         unsigned len = below.read(data, size);
62         if(!len && below.eof())
63                 set_eof();
64         position += len;
65         return len;
66 }
67
68 unsigned Slice::put(char c)
69 {
70         if(!prepare_op(1, M_WRITE))
71                 return 0;
72
73         unsigned len = below.put(c);
74         position += len;
75         return len;
76 }
77
78 int Slice::get()
79 {
80         if(!prepare_op(1, M_READ))
81                 return 0;
82
83         int c = below.get();
84         if(c==-1 && below.eof())
85                 set_eof();
86         else
87                 ++position;
88         return c;
89 }
90
91 SeekOffset Slice::seek(SeekOffset off, SeekType type)
92 {
93         off += start_offset;
94         if(type==S_CUR)
95                 off += position;
96         else if(type==S_END)
97                 off += length;
98         else if(type!=S_BEG)
99                 throw invalid_argument("Slice::seek");
100
101         if(off<start_offset || off>start_offset+length)
102                 throw bad_seek(off, type);
103
104         signal_flush_required.emit();
105
106         position = below.seek(off, S_BEG)-start_offset;
107         sync_position = false;
108         return position;
109 }
110
111 } // namespace IO
112 } // namespace Msp