add bytestream2_tell() and bytestream2_seek() functions
[libav.git] / libavcodec / bytestream.h
1 /*
2 * Bytestream functions
3 * copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@free.fr>
4 *
5 * This file is part of Libav.
6 *
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #ifndef AVCODEC_BYTESTREAM_H
23 #define AVCODEC_BYTESTREAM_H
24
25 #include <string.h>
26 #include "libavutil/common.h"
27 #include "libavutil/intreadwrite.h"
28
29 typedef struct {
30 const uint8_t *buffer, *buffer_end, *buffer_start;
31 } GetByteContext;
32
33 #define DEF_T(type, name, bytes, read, write) \
34 static av_always_inline type bytestream_get_ ## name(const uint8_t **b){\
35 (*b) += bytes;\
36 return read(*b - bytes);\
37 }\
38 static av_always_inline void bytestream_put_ ##name(uint8_t **b, const type value){\
39 write(*b, value);\
40 (*b) += bytes;\
41 }\
42 static av_always_inline type bytestream2_get_ ## name ## u(GetByteContext *g)\
43 {\
44 return bytestream_get_ ## name(&g->buffer);\
45 }\
46 static av_always_inline type bytestream2_get_ ## name(GetByteContext *g)\
47 {\
48 if (g->buffer_end - g->buffer < bytes)\
49 return 0;\
50 return bytestream2_get_ ## name ## u(g);\
51 }\
52 static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g)\
53 {\
54 if (g->buffer_end - g->buffer < bytes)\
55 return 0;\
56 return read(g->buffer);\
57 }
58
59 #define DEF(name, bytes, read, write) \
60 DEF_T(unsigned int, name, bytes, read, write)
61 #define DEF64(name, bytes, read, write) \
62 DEF_T(uint64_t, name, bytes, read, write)
63
64 DEF64(le64, 8, AV_RL64, AV_WL64)
65 DEF (le32, 4, AV_RL32, AV_WL32)
66 DEF (le24, 3, AV_RL24, AV_WL24)
67 DEF (le16, 2, AV_RL16, AV_WL16)
68 DEF64(be64, 8, AV_RB64, AV_WB64)
69 DEF (be32, 4, AV_RB32, AV_WB32)
70 DEF (be24, 3, AV_RB24, AV_WB24)
71 DEF (be16, 2, AV_RB16, AV_WB16)
72 DEF (byte, 1, AV_RB8 , AV_WB8 )
73
74 #undef DEF
75 #undef DEF64
76 #undef DEF_T
77
78 static av_always_inline void bytestream2_init(GetByteContext *g,
79 const uint8_t *buf, int buf_size)
80 {
81 g->buffer = buf;
82 g->buffer_start = buf;
83 g->buffer_end = buf + buf_size;
84 }
85
86 static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
87 {
88 return g->buffer_end - g->buffer;
89 }
90
91 static av_always_inline void bytestream2_skip(GetByteContext *g,
92 unsigned int size)
93 {
94 g->buffer += FFMIN(g->buffer_end - g->buffer, size);
95 }
96
97 static av_always_inline int bytestream2_tell(GetByteContext *g)
98 {
99 return (int)(g->buffer - g->buffer_start);
100 }
101
102 static av_always_inline int bytestream2_seek(GetByteContext *g, int offset,
103 int whence)
104 {
105 switch (whence) {
106 case SEEK_CUR:
107 offset = av_clip(offset, -(g->buffer - g->buffer_start),
108 g->buffer_end - g->buffer);
109 g->buffer += offset;
110 break;
111 case SEEK_END:
112 offset = av_clip(offset, -(g->buffer_end - g->buffer_start), 0);
113 g->buffer = g->buffer_end + offset;
114 break;
115 case SEEK_SET:
116 offset = av_clip(offset, 0, g->buffer_end - g->buffer_start);
117 g->buffer = g->buffer_start + offset;
118 break;
119 default:
120 return AVERROR(EINVAL);
121 }
122 return bytestream2_tell(g);
123 }
124
125 static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g,
126 uint8_t *dst,
127 unsigned int size)
128 {
129 int size2 = FFMIN(g->buffer_end - g->buffer, size);
130 memcpy(dst, g->buffer, size2);
131 g->buffer += size2;
132 return size2;
133 }
134
135 static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, uint8_t *dst, unsigned int size)
136 {
137 memcpy(dst, *b, size);
138 (*b) += size;
139 return size;
140 }
141
142 static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
143 {
144 memcpy(*b, src, size);
145 (*b) += size;
146 }
147
148 #endif /* AVCODEC_BYTESTREAM_H */