]> git.vomp.tv Git - vompclient.git/blob - stream.cc
Corruption fixes
[vompclient.git] / stream.cc
1 /*
2     Copyright 2005 Mark Calderbank
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "stream.h"
22
23 Stream::Stream()
24 {
25   initted = 0;
26 }
27
28 Stream::~Stream()
29 {
30   shutdown();
31 }
32
33 void Stream::shutdown()
34 {
35   if (initted) {
36     free(outbuf);
37   }
38   initted = 0;
39 }
40
41 int Stream::init(int bufsize)
42 {
43   outbuf = (UCHAR*) malloc(bufsize);
44   if (!outbuf) return 0;
45   bufferSize = bufsize;
46   bufferHead = bufferTail = 0;
47   initted = 1;
48   return 1;
49 }
50
51 void Stream::flush()
52 {
53   bufferHead = bufferTail = 0;
54 }
55
56 int Stream::put(UCHAR* inbuf, int len)
57 {
58   int ret = 0;
59   int freespace;
60   int localTail = bufferTail;
61   if (localTail == 0) localTail = bufferSize;
62   if (len == 0) return ret;
63
64   freespace = localTail - bufferHead - 1;
65   if (freespace < 0) freespace += bufferSize;
66   if (len > freespace) return ret;
67
68   if (bufferHead >= localTail)
69   {
70     // We have free rein to the end of the buffer
71     if (len < (bufferSize - bufferHead))
72     {
73       // We won't reach the end of the buffer.
74       memcpy(outbuf + bufferHead, inbuf, len);
75       bufferHead += len;
76       ret += len; return ret;
77     } else
78     {
79       // We'll reach the end of the buffer and loop round.
80       memcpy(outbuf + bufferHead, inbuf, (bufferSize - bufferHead));
81       inbuf += (bufferSize - bufferHead);
82       ret += (bufferSize - bufferHead);
83       len -= (bufferSize - bufferHead);
84       bufferHead = 0;
85       if (len == 0) return ret;
86     }
87   }
88
89   if (localTail - bufferHead == 1) return ret; // Full
90
91   // We can advance the head up to the tail
92   // If we reach it, we are full.
93   if (len < (localTail - bufferHead - 1))
94   {
95     // We'll fall short of the tail.
96     memcpy(outbuf + bufferHead, inbuf, len);
97     bufferHead += len;
98     ret += len; return ret;
99   } else
100   {
101     // We'll hit the tail.
102     memcpy(outbuf + bufferHead, inbuf, (localTail - bufferHead - 1));
103     ret += (localTail - bufferHead - 1);
104     bufferHead = localTail - 1;
105     return ret;
106   }
107 }
108
109 int Stream::drain(int fd)
110 {
111   int ret = 0;
112   int localHead = bufferHead;
113   int written;
114
115   if (localHead < bufferTail)
116   {
117     // Drain to the end of the buffer
118     written = write(fd, outbuf + bufferTail, (bufferSize - bufferTail));
119     if (written < 0) return ret;
120     ret += written;
121     if (written == (bufferSize - bufferTail))
122       bufferTail = 0;
123     else
124     {
125       bufferTail += written;
126       return ret;
127     }
128   }
129
130   if (localHead == bufferTail) return ret; // Empty
131
132   written = write(fd, outbuf + bufferTail, (localHead - bufferTail));
133   if (written < 0) return ret;
134   ret += written;
135   bufferTail += written;
136   return ret;
137 }