Merge pull request #4791 from jmarshallnz/playlist_settings
[vuplus_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
6  *  modify it under the terms of the GNU General Public License
7  *  as published by the Free Software Foundation; either version 2
8  *  of the License, or (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, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19
20 #include <assert.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include "htsbuf.h"
27 #ifdef _MSC_VER
28 #include "msvc.h"
29 #endif
30
31 #ifndef MIN
32 #define MIN(a, b) ((a) < (b) ? (a) : (b))
33 #endif
34
35 #ifndef MAX
36 #define MAX(a, b) ((a) > (b) ? (a) : (b))
37 #endif
38
39
40 /**
41  *
42  */
43 void
44 htsbuf_queue_init(htsbuf_queue_t *hq, unsigned int maxsize)
45 {
46   if(maxsize == 0)
47     maxsize = INT32_MAX;
48   TAILQ_INIT(&hq->hq_q);
49   hq->hq_size = 0;
50   hq->hq_maxsize = maxsize;
51 }
52
53
54 /**
55  *
56  */
57 void
58 htsbuf_data_free(htsbuf_queue_t *hq, htsbuf_data_t *hd)
59 {
60   TAILQ_REMOVE(&hq->hq_q, hd, hd_link);
61   free(hd->hd_data);
62   free(hd);
63 }
64
65
66 /**
67  *
68  */
69 void
70 htsbuf_queue_flush(htsbuf_queue_t *hq)
71 {
72   htsbuf_data_t *hd;
73
74   hq->hq_size = 0;
75
76   while((hd = TAILQ_FIRST(&hq->hq_q)) != NULL)
77     htsbuf_data_free(hq, hd);
78 }
79
80 /**
81  *
82  */
83 void
84 htsbuf_append(htsbuf_queue_t *hq, const char *buf, size_t len)
85 {
86   htsbuf_data_t *hd = TAILQ_LAST(&hq->hq_q, htsbuf_data_queue);
87   int c;
88   hq->hq_size += len;
89
90   if(hd != NULL) {
91     /* Fill out any previous buffer */
92     c = MIN(hd->hd_data_size - hd->hd_data_len, len);
93     memcpy(hd->hd_data + hd->hd_data_len, buf, c);
94     hd->hd_data_len += c;
95     buf += c;
96     len -= c;
97   }
98   if(len == 0)
99     return;
100   
101   hd = malloc(sizeof(htsbuf_data_t));
102   TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link);
103   
104   c = MAX(len, 1000); /* Allocate 1000 bytes to support lots of small writes */
105
106   hd->hd_data = malloc(c);
107   hd->hd_data_size = c;
108   hd->hd_data_len = len;
109   hd->hd_data_off = 0;
110   memcpy(hd->hd_data, buf, len);
111 }
112
113 /**
114  *
115  */
116 void
117 htsbuf_append_prealloc(htsbuf_queue_t *hq, const char *buf, size_t len)
118 {
119   htsbuf_data_t *hd;
120
121   hq->hq_size += len;
122
123   hd = malloc(sizeof(htsbuf_data_t));
124   TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link);
125   
126   hd->hd_data = (void *)buf;
127   hd->hd_data_size = len;
128   hd->hd_data_len = len;
129   hd->hd_data_off = 0;
130 }
131
132 /**
133  *
134  */
135 size_t
136 htsbuf_read(htsbuf_queue_t *hq, char *buf, size_t len)
137 {
138   size_t r = 0;
139   int c;
140
141   htsbuf_data_t *hd;
142   
143   while(len > 0) {
144     hd = TAILQ_FIRST(&hq->hq_q);
145     if(hd == NULL)
146       break;
147
148     c = MIN(hd->hd_data_len - hd->hd_data_off, len);
149     memcpy(buf, hd->hd_data + hd->hd_data_off, c);
150
151     r += c;
152     buf += c;
153     len -= c;
154     hd->hd_data_off += c;
155     hq->hq_size -= c;
156     if(hd->hd_data_off == hd->hd_data_len)
157       htsbuf_data_free(hq, hd);
158   }
159   return r;
160 }
161
162
163 /**
164  *
165  */
166 size_t
167 htsbuf_find(htsbuf_queue_t *hq, uint8_t v)
168 {
169   htsbuf_data_t *hd;
170   unsigned int i, o = 0;
171
172   TAILQ_FOREACH(hd, &hq->hq_q, hd_link) {
173     for(i = hd->hd_data_off; i < hd->hd_data_len; i++) {
174       if(hd->hd_data[i] == v) 
175         return o + i - hd->hd_data_off;
176     }
177     o += hd->hd_data_len - hd->hd_data_off;
178   }
179   return -1;
180 }
181
182
183
184 /**
185  *
186  */
187 size_t
188 htsbuf_peek(htsbuf_queue_t *hq, char *buf, size_t len)
189 {
190   size_t r = 0;
191   int c;
192
193   htsbuf_data_t *hd = TAILQ_FIRST(&hq->hq_q);
194   
195   while(len > 0 && hd != NULL) {
196     c = MIN(hd->hd_data_len - hd->hd_data_off, len);
197     memcpy(buf, hd->hd_data + hd->hd_data_off, c);
198
199     buf += c;
200     len -= c;
201
202     hd = TAILQ_NEXT(hd, hd_link);
203   }
204   return r;
205 }
206
207 /**
208  *
209  */
210 size_t
211 htsbuf_drop(htsbuf_queue_t *hq, size_t len)
212 {
213   size_t r = 0;
214   int c;
215   htsbuf_data_t *hd;
216   
217   while(len > 0) {
218     hd = TAILQ_FIRST(&hq->hq_q);
219     if(hd == NULL)
220       break;
221
222     c = MIN(hd->hd_data_len - hd->hd_data_off, len);
223     len -= c;
224     hd->hd_data_off += c;
225     
226     if(hd->hd_data_off == hd->hd_data_len)
227       htsbuf_data_free(hq, hd);
228   }
229   return r;
230 }
231
232 /**
233  *
234  */
235 void
236 htsbuf_vqprintf(htsbuf_queue_t *hq, const char *fmt, va_list ap)
237 {
238   char buf[5000];
239   htsbuf_append(hq, buf, vsnprintf(buf, sizeof(buf), fmt, ap));
240 }
241
242
243 /**
244  *
245  */
246 void
247 htsbuf_qprintf(htsbuf_queue_t *hq, const char *fmt, ...)
248 {
249   va_list ap;
250   va_start(ap, fmt);
251   htsbuf_vqprintf(hq, fmt, ap);
252   va_end(ap);
253 }
254
255