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