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