]> git.sesse.net Git - vlc/blob - include/vlc_block_helper.h
block_BytestreamRelease: remove useless zeroing (before free)
[vlc] / include / vlc_block_helper.h
1 /*****************************************************************************
2  * vlc_block_helper.h: Helper functions for data blocks management.
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifndef VLC_BLOCK_HELPER_H
25 #define VLC_BLOCK_HELPER_H 1
26
27 #include <vlc_block.h>
28
29 typedef struct block_bytestream_t
30 {
31     block_t             *p_chain;
32     block_t             *p_block;
33     size_t              i_offset;
34
35 } block_bytestream_t;
36
37 /*****************************************************************************
38  * block_bytestream_t management
39  *****************************************************************************/
40 VLC_USED
41 static inline block_bytestream_t block_BytestreamInit( void )
42 {
43     block_bytestream_t bytestream;
44
45     bytestream.i_offset = 0;
46     bytestream.p_chain = bytestream.p_block = NULL;
47
48     return bytestream;
49 }
50
51 static inline void block_BytestreamRelease( block_bytestream_t *p_bytestream )
52 {
53     while( p_bytestream->p_chain )
54     {
55         block_t *p_next;
56         p_next = p_bytestream->p_chain->p_next;
57         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
58         p_bytestream->p_chain = p_next;
59     }
60 }
61
62 /**
63  * It flush all data (read and unread) from a block_bytestream_t.
64  */
65 static inline void block_BytestreamEmpty( block_bytestream_t *p_bytestream )
66 {
67     block_BytestreamRelease( p_bytestream );
68
69     *p_bytestream = block_BytestreamInit();
70 }
71
72 /**
73  * It flushes all already read data from a block_bytestream_t.
74  */
75 static inline void block_BytestreamFlush( block_bytestream_t *p_bytestream )
76 {
77     while( p_bytestream->p_chain != p_bytestream->p_block )
78     {
79         block_t *p_next;
80         p_next = p_bytestream->p_chain->p_next;
81         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
82         p_bytestream->p_chain = p_next;
83     }
84     while( p_bytestream->p_block &&
85            (p_bytestream->p_block->i_buffer - p_bytestream->i_offset) == 0 )
86     {
87         block_t *p_next;
88         p_next = p_bytestream->p_chain->p_next;
89         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
90         p_bytestream->p_chain = p_bytestream->p_block = p_next;
91         p_bytestream->i_offset = 0;
92     }
93 }
94
95 static inline void block_BytestreamPush( block_bytestream_t *p_bytestream,
96                                          block_t *p_block )
97 {
98     block_ChainAppend( &p_bytestream->p_chain, p_block );
99     if( !p_bytestream->p_block ) p_bytestream->p_block = p_block;
100 }
101
102 VLC_USED
103 static inline block_t *block_BytestreamPop( block_bytestream_t *p_bytestream )
104 {
105     block_t *p_block;
106
107     block_BytestreamFlush( p_bytestream );
108
109     p_block = p_bytestream->p_block;
110     if( p_block == NULL )
111     {
112         return NULL;
113     }
114     else if( !p_block->p_next )
115     {
116         p_block->p_buffer += p_bytestream->i_offset;
117         p_block->i_buffer -= p_bytestream->i_offset;
118         p_bytestream->i_offset = 0;
119         p_bytestream->p_chain = p_bytestream->p_block = NULL;
120         return p_block;
121     }
122
123     while( p_block->p_next && p_block->p_next->p_next )
124         p_block = p_block->p_next;
125
126     {
127         block_t *p_block_old = p_block;
128         p_block = p_block->p_next;
129         p_block_old->p_next = NULL;
130     }
131
132     return p_block;
133 }
134
135 static inline int block_SkipByte( block_bytestream_t *p_bytestream )
136 {
137     /* Most common case first */
138     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
139     {
140         p_bytestream->i_offset++;
141         return VLC_SUCCESS;
142     }
143     else
144     {
145         block_t *p_block;
146
147         /* Less common case which is also slower */
148         for( p_block = p_bytestream->p_block->p_next;
149              p_block != NULL; p_block = p_block->p_next )
150         {
151             if( p_block->i_buffer )
152             {
153                 p_bytestream->i_offset = 1;
154                 p_bytestream->p_block = p_block;
155                 return VLC_SUCCESS;
156             }
157         }
158     }
159
160     /* Not enough data, bail out */
161     return VLC_EGENERIC;
162 }
163
164 static inline int block_PeekByte( block_bytestream_t *p_bytestream,
165                                   uint8_t *p_data )
166 {
167     /* Most common case first */
168     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
169     {
170         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
171         return VLC_SUCCESS;
172     }
173     else
174     {
175         block_t *p_block;
176
177         /* Less common case which is also slower */
178         for( p_block = p_bytestream->p_block->p_next;
179              p_block != NULL; p_block = p_block->p_next )
180         {
181             if( p_block->i_buffer )
182             {
183                 *p_data = p_block->p_buffer[0];
184                 return VLC_SUCCESS;
185             }
186         }
187     }
188
189     /* Not enough data, bail out */
190     return VLC_EGENERIC;
191 }
192
193 static inline int block_GetByte( block_bytestream_t *p_bytestream,
194                                  uint8_t *p_data )
195 {
196     /* Most common case first */
197     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
198     {
199         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
200         p_bytestream->i_offset++;
201         return VLC_SUCCESS;
202     }
203     else
204     {
205         block_t *p_block;
206
207         /* Less common case which is also slower */
208         for( p_block = p_bytestream->p_block->p_next;
209              p_block != NULL; p_block = p_block->p_next )
210         {
211             if( p_block->i_buffer )
212             {
213                 *p_data = p_block->p_buffer[0];
214                 p_bytestream->i_offset = 1;
215                 p_bytestream->p_block = p_block;
216                 return VLC_SUCCESS;
217             }
218         }
219     }
220
221     /* Not enough data, bail out */
222     return VLC_EGENERIC;
223 }
224
225 static inline int block_WaitBytes( block_bytestream_t *p_bytestream,
226                                    size_t i_data )
227 {
228     block_t *p_block;
229     size_t i_offset, i_copy, i_size;
230
231     /* Check we have that much data */
232     i_offset = p_bytestream->i_offset;
233     i_size = i_data;
234     i_copy = 0;
235     for( p_block = p_bytestream->p_block;
236          p_block != NULL; p_block = p_block->p_next )
237     {
238         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
239         i_size -= i_copy;
240         i_offset = 0;
241
242         if( !i_size ) break;
243     }
244
245     if( i_size )
246     {
247         /* Not enough data, bail out */
248         return VLC_EGENERIC;
249     }
250     return VLC_SUCCESS;
251 }
252
253 static inline int block_SkipBytes( block_bytestream_t *p_bytestream,
254                                    size_t i_data )
255 {
256     block_t *p_block;
257     size_t i_offset, i_copy;
258
259     /* Check we have that much data */
260     i_offset = p_bytestream->i_offset;
261     i_copy = 0;
262     for( p_block = p_bytestream->p_block;
263          p_block != NULL; p_block = p_block->p_next )
264     {
265         i_copy = __MIN( i_data, p_block->i_buffer - i_offset );
266         i_data -= i_copy;
267
268         if( !i_data ) break;
269
270         i_offset = 0;
271     }
272
273     if( i_data )
274     {
275         /* Not enough data, bail out */
276         return VLC_EGENERIC;
277     }
278
279     p_bytestream->p_block = p_block;
280     p_bytestream->i_offset = i_offset + i_copy;
281     return VLC_SUCCESS;
282 }
283
284 static inline int block_PeekBytes( block_bytestream_t *p_bytestream,
285                                    uint8_t *p_data, size_t i_data )
286 {
287     block_t *p_block;
288     size_t i_offset, i_copy, i_size;
289
290     /* Check we have that much data */
291     i_offset = p_bytestream->i_offset;
292     i_size = i_data;
293     i_copy = 0;
294     for( p_block = p_bytestream->p_block;
295          p_block != NULL; p_block = p_block->p_next )
296     {
297         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
298         i_size -= i_copy;
299         i_offset = 0;
300
301         if( !i_size ) break;
302     }
303
304     if( i_size )
305     {
306         /* Not enough data, bail out */
307         return VLC_EGENERIC;
308     }
309
310     /* Copy the data */
311     i_offset = p_bytestream->i_offset;
312     i_size = i_data;
313     i_copy = 0;
314     for( p_block = p_bytestream->p_block;
315          p_block != NULL; p_block = p_block->p_next )
316     {
317         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
318         i_size -= i_copy;
319
320         if( i_copy )
321         {
322             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
323             p_data += i_copy;
324         }
325
326         i_offset = 0;
327
328         if( !i_size ) break;
329     }
330
331     return VLC_SUCCESS;
332 }
333
334 static inline int block_GetBytes( block_bytestream_t *p_bytestream,
335                                   uint8_t *p_data, size_t i_data )
336 {
337     block_t *p_block;
338     size_t i_offset, i_copy, i_size;
339
340     /* Check we have that much data */
341     i_offset = p_bytestream->i_offset;
342     i_size = i_data;
343     i_copy = 0;
344     for( p_block = p_bytestream->p_block;
345          p_block != NULL; p_block = p_block->p_next )
346     {
347         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
348         i_size -= i_copy;
349         i_offset = 0;
350
351         if( !i_size ) break;
352     }
353
354     if( i_size )
355     {
356         /* Not enough data, bail out */
357         return VLC_EGENERIC;
358     }
359
360     /* Copy the data */
361     i_offset = p_bytestream->i_offset;
362     i_size = i_data;
363     i_copy = 0;
364     for( p_block = p_bytestream->p_block;
365          p_block != NULL; p_block = p_block->p_next )
366     {
367         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
368         i_size -= i_copy;
369
370         if( i_copy )
371         {
372             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
373             p_data += i_copy;
374         }
375
376         if( !i_size ) break;
377
378         i_offset = 0;
379     }
380
381     /* No buffer given, just skip the data */
382     p_bytestream->p_block = p_block;
383     p_bytestream->i_offset = i_offset + i_copy;
384
385     return VLC_SUCCESS;
386 }
387
388 static inline int block_PeekOffsetBytes( block_bytestream_t *p_bytestream,
389     size_t i_peek_offset, uint8_t *p_data, size_t i_data )
390 {
391     block_t *p_block;
392     size_t i_offset, i_copy, i_size;
393
394     /* Check we have that much data */
395     i_offset = p_bytestream->i_offset;
396     i_size = i_data + i_peek_offset;
397     i_copy = 0;
398     for( p_block = p_bytestream->p_block;
399          p_block != NULL; p_block = p_block->p_next )
400     {
401         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
402         i_size -= i_copy;
403         i_offset = 0;
404
405         if( !i_size ) break;
406     }
407
408     if( i_size )
409     {
410         /* Not enough data, bail out */
411         return VLC_EGENERIC;
412     }
413
414     /* Find the right place */
415     i_offset = p_bytestream->i_offset;
416     i_size = i_peek_offset;
417     i_copy = 0;
418     for( p_block = p_bytestream->p_block;
419          p_block != NULL; p_block = p_block->p_next )
420     {
421         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
422         i_size -= i_copy;
423
424         if( !i_size ) break;
425
426         i_offset = 0;
427     }
428
429     /* Copy the data */
430     i_offset += i_copy;
431     i_size = i_data;
432     i_copy = 0;
433     for( ; p_block != NULL; p_block = p_block->p_next )
434     {
435         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
436         i_size -= i_copy;
437
438         if( i_copy )
439         {
440             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
441             p_data += i_copy;
442         }
443
444         i_offset = 0;
445
446         if( !i_size ) break;
447     }
448
449     return VLC_SUCCESS;
450 }
451
452 static inline int block_FindStartcodeFromOffset(
453     block_bytestream_t *p_bytestream, size_t *pi_offset,
454     const uint8_t *p_startcode, int i_startcode_length )
455 {
456     block_t *p_block, *p_block_backup = 0;
457     int i_size = 0;
458     size_t i_offset, i_offset_backup = 0;
459     int i_caller_offset_backup = 0, i_match;
460
461     /* Find the right place */
462     i_size = *pi_offset + p_bytestream->i_offset;
463     for( p_block = p_bytestream->p_block;
464          p_block != NULL; p_block = p_block->p_next )
465     {
466         i_size -= p_block->i_buffer;
467         if( i_size < 0 ) break;
468     }
469
470     if( i_size >= 0 )
471     {
472         /* Not enough data, bail out */
473         return VLC_EGENERIC;
474     }
475
476     /* Begin the search.
477      * We first look for an occurrence of the 1st startcode byte and
478      * if found, we do a more thorough check. */
479     i_size += p_block->i_buffer;
480     *pi_offset -= i_size;
481     i_match = 0;
482     for( ; p_block != NULL; p_block = p_block->p_next )
483     {
484         for( i_offset = i_size; i_offset < p_block->i_buffer; i_offset++ )
485         {
486             if( p_block->p_buffer[i_offset] == p_startcode[i_match] )
487             {
488                 if( !i_match )
489                 {
490                     p_block_backup = p_block;
491                     i_offset_backup = i_offset;
492                     i_caller_offset_backup = *pi_offset;
493                 }
494
495                 if( i_match + 1 == i_startcode_length )
496                 {
497                     /* We have it */
498                     *pi_offset += i_offset - i_match;
499                     return VLC_SUCCESS;
500                 }
501
502                 i_match++;
503             }
504             else if ( i_match )
505             {
506                 /* False positive */
507                 p_block = p_block_backup;
508                 i_offset = i_offset_backup;
509                 *pi_offset = i_caller_offset_backup;
510                 i_match = 0;
511             }
512
513         }
514         i_size = 0;
515         *pi_offset += i_offset;
516     }
517
518     *pi_offset -= i_match;
519     return VLC_EGENERIC;
520 }
521
522 #endif /* VLC_BLOCK_HELPER_H */