added: htsp support to the xbox branch (now enabled)
[xbmc:xbmc-antiquated.git] / xbmc / lib / libhts / htsbuf.c
1 /*
2  *  Buffer management functions
3  *  Copyright (C) 2008 Andreas Ă–man
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <assert.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include "htsbuf.h"
26 #ifdef _MSC_VER
27 #include "msvc.h"
28 #endif
29
30 #ifndef MIN
31 #define MIN(a, b) ((a) < (b) ? (a) : (b))
32 #endif
33
34 #ifndef MAX
35 #define MAX(a, b) ((a) > (b) ? (a) : (b))
36 #endif
37
38
39 /**
40  *
41  */
42 void
43 htsbuf_queue_init(htsbuf_queue_t *hq, unsigned int maxsize)
44 {
45   if(maxsize == 0)
46     maxsize = INT32_MAX;
47   TAILQ_INIT(&hq->hq_q);
48   hq->hq_size = 0;
49   hq->hq_maxsize = maxsize;
50 }
51
52
53 /**
54  *
55  */
56 void
57 htsbuf_data_free(htsbuf_queue_t *hq, htsbuf_data_t *hd)
58 {
59   TAILQ_REMOVE(&hq->hq_q, hd, hd_link);
60   free(hd->hd_data);
61   free(hd);
62 }
63
64
65 /**
66  *
67  */
68 void
69 htsbuf_queue_flush(htsbuf_queue_t *hq)
70 {
71   htsbuf_data_t *hd;
72
73   hq->hq_size = 0;
74
75   while((hd = TAILQ_FIRST(&hq->hq_q)) != NULL)
76     htsbuf_data_free(hq, hd);
77 }
78
79 /**
80  *
81  */
82 void
83 htsbuf_append(htsbuf_queue_t *hq, const char *buf, size_t len)
84 {
85   htsbuf_data_t *hd = TAILQ_LAST(&hq->hq_q, htsbuf_data_queue);
86   int c;
87   hq->hq_size += len;
88
89   if(hd != NULL) {
90     /* Fill out any previous buffer */
91     c = MIN(hd->hd_data_size - hd->hd_data_len, len);
92     memcpy(hd->hd_data + hd->hd_data_len, buf, c);
93     hd->hd_data_len += c;
94     buf += c;
95     len -= c;
96   }
97   if(len == 0)
98     return;
99   
100   hd = malloc(sizeof(htsbuf_data_t));
101   TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link);
102   
103   c = MAX(len, 1000); /* Allocate 1000 bytes to support lots of small writes */
104
105   hd->hd_data = malloc(c);
106   hd->hd_data_size = c;
107   hd->hd_data_len = len;
108   hd->hd_data_off = 0;
109   memcpy(hd->hd_data, buf, len);
110 }
111
112 /**
113  *
114  */
115 void
116 htsbuf_append_prealloc(htsbuf_queue_t *hq, const char *buf, size_t len)
117 {
118   htsbuf_data_t *hd;
119
120   hq->hq_size += len;
121
122   hd = malloc(sizeof(htsbuf_data_t));
123   TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link);
124   
125   hd->hd_data = (void *)buf;
126   hd->hd_data_size = len;
127   hd->hd_data_len = len;
128   hd->hd_data_off = 0;
129 }
130
131 /**
132  *
133  */
134 size_t
135 htsbuf_read(htsbuf_queue_t *hq, char *buf, size_t len)
136 {
137   size_t r = 0;
138   int c;
139
140   htsbuf_data_t *hd;
141   
142   while(len > 0) {
143     hd = TAILQ_FIRST(&hq->hq_q);
144     if(hd == NULL)
145       break;
146
147     c = MIN(hd->hd_data_len - hd->hd_data_off, len);
148     memcpy(buf, hd->hd_data + hd->hd_data_off, c);
149
150     r += c;
151     buf += c;
152     len -= c;
153     hd->hd_data_off += c;
154     hq->hq_size -= c;
155     if(hd->hd_data_off == hd->hd_data_len)
156       htsbuf_data_free(hq, hd);
157   }
158   return r;
159 }
160
161
162 /**
163  *
164  */
165 size_t
166 htsbuf_find(htsbuf_queue_t *hq, uint8_t v)
167 {
168   htsbuf_data_t *hd;
169   int i, o = 0;
170
171   TAILQ_FOREACH(hd, &hq->hq_q, hd_link) {
172     for(i = hd->hd_data_off; i < hd->hd_data_len; i++) {
173       if(hd->hd_data[i] == v) 
174         return o + i - hd->hd_data_off;
175     }
176     o += hd->hd_data_len - hd->hd_data_off;
177   }
178   return -1;
179 }
180
181
182
183 /**
184  *
185  */
186 size_t
187 htsbuf_peek(htsbuf_queue_t *hq, char *buf, size_t len)
188 {
189   size_t r = 0;
190   int c;
191
192   htsbuf_data_t *hd = TAILQ_FIRST(&hq->hq_q);
193   
194   while(len > 0 && hd != NULL) {
195     c = MIN(hd->hd_data_len - hd->hd_data_off, len);
196     memcpy(buf, hd->hd_data + hd->hd_data_off, c);
197
198     buf += c;
199     len -= c;
200
201     hd = TAILQ_NEXT(hd, hd_link);
202   }
203   return r;
204 }
205
206 /**
207  *
208  */
209 size_t
210 htsbuf_drop(htsbuf_queue_t *hq, size_t len)
211 {
212   size_t r = 0;
213   int c;
214   htsbuf_data_t *hd;
215   
216   while(len > 0) {
217     hd = TAILQ_FIRST(&hq->hq_q);
218     if(hd == NULL)
219       break;
220
221     c = MIN(hd->hd_data_len - hd->hd_data_off, len);
222     len -= c;
223     hd->hd_data_off += c;
224     
225     if(hd->hd_data_off == hd->hd_data_len)
226       htsbuf_data_free(hq, hd);
227   }
228   return r;
229 }
230
231 /**
232  *
233  */
234 void
235 htsbuf_vqprintf(htsbuf_queue_t *hq, const char *fmt, va_list ap)
236 {
237   char buf[5000];
238   htsbuf_append(hq, buf, vsnprintf(buf, sizeof(buf), fmt, ap));
239 }
240
241
242 /**
243  *
244  */
245 void
246 htsbuf_qprintf(htsbuf_queue_t *hq, const char *fmt, ...)
247 {
248   va_list ap;
249   va_start(ap, fmt);
250   htsbuf_vqprintf(hq, fmt, ap);
251   va_end(ap);
252 }
253
254