Merge branch 'obi/master'
[enigma2.git] / lib / base / buffer.cpp
1 #include <lib/base/buffer.h>
2 #include <lib/base/eerror.h>
3 #include <cerrno>
4 #include <cstdio>
5 #include <cstring>
6 #include <unistd.h>
7
8 void eIOBuffer::removeblock()
9 {
10         ASSERT(!buffer.empty());
11         eIOBufferData &b=buffer.front();
12         delete[] b.data;
13         buffer.pop_front();
14         ptr=0;
15 }
16
17 eIOBuffer::eIOBufferData &eIOBuffer::addblock()
18 {
19         eIOBufferData s;
20         s.data=new __u8[allocationsize];
21         s.len=0;
22         buffer.push_back(s);
23         return buffer.back();
24 }
25
26 eIOBuffer::~eIOBuffer()
27 {
28         clear();
29 }
30
31 void eIOBuffer::clear()
32 {
33         while (!buffer.empty())
34                 removeblock();
35 }
36
37 int eIOBuffer::size() const
38 {
39         int total=0;
40         for (std::list<eIOBufferData>::const_iterator i(buffer.begin()); i != buffer.end(); ++i)
41                 total+=i->len;
42         total-=ptr;
43         return total;
44 }
45
46 int eIOBuffer::empty() const
47 {
48         return buffer.empty();
49 }
50
51 int eIOBuffer::peek(void *dest, int len) const
52 {
53         __u8 *dst=(__u8*)dest;
54         std::list<eIOBufferData>::const_iterator i(buffer.begin());
55         int p=ptr;
56         int written=0;
57         while (len)
58         {       
59                 if (i == buffer.end())
60                         break;
61                 int tc=i->len-p;
62                 if (tc > len)
63                         tc = len;
64         
65                 memcpy(dst, i->data+p, tc);
66                 dst+=tc;
67                 written+=tc;
68         
69                 ++i;
70                 p=0;
71                         
72                 len-=tc;
73         }
74         return written;
75 }
76
77 void eIOBuffer::skip(int len)
78 {
79         while (len)
80         {
81                 ASSERT(! buffer.empty());
82                 int tn=len;
83                 if (tn > (buffer.front().len-ptr))
84                         tn=buffer.front().len-ptr;
85
86                 ptr+=tn;
87                 if (ptr == buffer.front().len)
88                         removeblock();
89                 len-=tn;
90         }
91 }
92
93 int eIOBuffer::read(void *dest, int len)
94 {
95         __u8 *dst=(__u8*)dest;
96         len=peek(dst, len);
97         skip(len);
98         return len;
99 }
100
101 void eIOBuffer::write(const void *source, int len)
102 {
103         const __u8 *src=(const __u8*)source;
104         while (len)
105         {
106                 int tc=len;
107                 if (buffer.empty() || (allocationsize == buffer.back().len))
108                         addblock();
109                 if (tc > allocationsize-buffer.back().len)
110                         tc=allocationsize-buffer.back().len;
111                 memcpy(buffer.back().data+buffer.back().len, src, tc);
112                 src+=tc;
113                 buffer.back().len+=tc;
114                 len-=tc;
115         }
116 }
117
118 int eIOBuffer::fromfile(int fd, int len)
119 {
120         int re=0;
121         while (len)
122         {
123                 int tc=len;
124                 int r=0;
125                 if (buffer.empty() || (allocationsize == buffer.back().len))
126                         addblock();
127                 if (tc > allocationsize-buffer.back().len)
128                         tc=allocationsize-buffer.back().len;
129                 r=::read(fd, buffer.back().data+buffer.back().len, tc);
130                 buffer.back().len+=r;
131                 if (r < 0)
132                 {
133                         if (errno != EWOULDBLOCK && errno != EBUSY && errno != EINTR)
134                                 eDebug("couldn't read: %m");
135                 }
136                 else
137                 {
138                         len-=r;
139                         re+=r;
140                         if (r != tc)
141                                 break;
142                 }
143         }
144         return re;
145 }
146
147 int eIOBuffer::tofile(int fd, int len)
148 {
149         int written=0;
150         int w;
151         while (len && !buffer.empty())
152         {       
153                 if (buffer.begin() == buffer.end())
154                         break;
155                 int tc=buffer.front().len-ptr;
156                 if (tc > len)
157                         tc = len;
158         
159                 w=::write(fd, buffer.front().data+ptr, tc);
160                 if (w < 0)
161                 {
162                         if (errno != EWOULDBLOCK && errno != EBUSY && errno != EINTR)
163                                 eDebug("write: %m");
164                         w=0;
165                 }
166                 ptr+=w;
167                 if (ptr == buffer.front().len)
168                         removeblock();
169                 written+=w;     
170
171                 len-=w;
172                 if (tc != w)
173                         break;
174         }
175         return written;
176 }
177
178 int eIOBuffer::searchchr(char ch) const
179 {
180         std::list<eIOBufferData>::const_iterator i(buffer.begin());
181         int p=ptr;
182         int c=0;
183         while (1)
184         {       
185                 if (i == buffer.end())
186                         break;
187                 while (p < i->len)
188                 {
189                         if (i->data[p] == ch)
190                                 return c;
191                         else
192                                 c++, p++;
193                 }
194                 ++i;
195                 p=0;
196         }
197         return -1;
198 }
199