]> git.tdb.fi Git - libs/core.git/blob - source/buffered.cpp
Convert C-style casts to C++-style
[libs/core.git] / source / buffered.cpp
1 /* $Id$
2
3 This file is part of libmspio
4 Copyright © 2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <cstring>
9 #include "buffered.h"
10 #include "except.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace IO {
16
17 Buffered::Buffered(Base &b, unsigned s):
18         below(b),
19         buf_size(s),
20         buf(new char[buf_size]),
21         begin(buf),
22         end(buf),
23         cur_op(M_NONE)
24 {
25         mode=below.get_mode();
26         below.signal_flush_required.connect(sigc::mem_fun(this, &Buffered::flush));
27 }
28
29 unsigned Buffered::put(char c)
30 {
31         set_op(M_WRITE);
32
33         if(end<buf+buf_size)
34         {
35                 *end++=c;
36                 return 1;
37         }
38         else
39                 return do_write(&c, 1);
40 }
41
42 void Buffered::flush()
43 {
44         if(cur_op==M_WRITE)
45         {
46                 unsigned used=end-begin;
47                 if(used)
48                 {
49                         unsigned len=below.write(begin, used);
50
51                         begin=end=buf;
52
53                         if(len<used)
54                                 throw Exception("Couldn't flush all data");
55                 }
56         }
57         else if(cur_op==M_READ)
58                 begin=end=buf;
59 }
60
61 bool Buffered::getline(std::string &line)
62 {
63         set_op(M_READ);
64
65         for(char *i=begin; i!=end; ++i)
66                 if(*i=='\n')
67                 {
68                         line.assign(begin, i-begin);
69                         begin=i+1;
70                         return true;
71                 }
72
73         return Base::getline(line);
74 }
75
76 int Buffered::get()
77 {
78         set_op(M_READ);
79
80         if(begin<end)
81                 return static_cast<unsigned char>(*begin++);
82
83         char c;
84         if(do_read(&c, 1)==0)
85                 return -1;
86         return static_cast<unsigned char>(c);
87 }
88
89 Handle Buffered::get_event_handle()
90 {
91         throw Exception("Buffered doesn't support events");
92 }
93
94 unsigned Buffered::get_current_size() const
95 {
96         return end-begin;
97 }
98
99 Buffered::~Buffered()
100 {
101         try
102         {
103                 flush();
104         }
105         catch(...)
106         { }
107
108         delete[] buf;
109 }
110
111 void Buffered::set_op(Mode op)
112 {
113         if(op!=cur_op)
114                 flush();
115         cur_op=op;
116 }
117
118 unsigned Buffered::do_write(const char *data, unsigned size)
119 {
120         set_op(M_WRITE);
121
122         if(end+size<buf+buf_size)
123         {
124                 // All data fits in buffer with whatever is already there
125                 memcpy(end, data, size);
126                 end+=size;
127
128                 return size;
129         }
130         else
131         {
132                 // Clear the buffer to make more room
133                 flush();
134
135                 if(size<buf_size)
136                 {
137                         // Put new data in the buffer to wait for more
138                         memcpy(end, data, size);
139                         end+=size;
140
141                         return size;
142                 }
143                 else
144                         // New data still doesn't fit in the buffer, so write it directly
145                         return below.write(data, size);
146         }
147 }
148
149 unsigned Buffered::do_read(char *data, unsigned size)
150 {
151         set_op(M_READ);
152
153         if(begin+size<=end)
154         {
155                 // The request can be served from the buffer
156                 memcpy(data, begin, size);
157                 begin+=size;
158
159                 eof_flag=(below.eof() && begin==end);
160
161                 return size;
162         }
163         else
164         {
165                 // Give out whatever is in the buffer already
166                 memcpy(data, begin, end-begin);
167                 unsigned ret=end-begin;
168                 begin=end=buf;
169
170                 data+=ret;
171                 size-=ret;
172
173                 if(size<buf_size)
174                 {
175                         // Fill the buffer and serve the rest of the request from it
176                         unsigned len=below.read(end, buf+buf_size-end);
177                         end+=len;
178
179                         len=min(static_cast<unsigned>(end-begin), size);
180                         memcpy(data, begin, len);
181                         begin+=len;
182                         ret+=len;
183                 }
184                 else
185                         // Read the rest directly from the underlying object
186                         ret+=below.read(data, size);
187
188                 eof_flag=(below.eof() && begin==end);
189
190                 return ret;
191         }
192 }
193
194 } // namespace IO
195 } // namespace Msp