Remove some unused code.
[mplayer.git] / libmpdemux / ebml.c
blob21aefb5b74e00be30539f13c420ba76d782ba4d1
1 /*
2 * native ebml reader for the Matroska demuxer
3 * Written by Aurelien Jacobs <aurel@gnuage.org>
4 * Based on the one written by Ronald Bultje for gstreamer
5 * Licence: GPL
6 */
8 #include "config.h"
10 #include <stdlib.h>
12 #include "stream.h"
13 #include "ebml.h"
14 #include "bswap.h"
17 #ifndef SIZE_MAX
18 #define SIZE_MAX ((size_t)-1)
19 #endif
22 * Read: the element content data ID.
23 * Return: the ID.
25 uint32_t
26 ebml_read_id (stream_t *s, int *length)
28 int i, len_mask = 0x80;
29 uint32_t id;
31 for (i=0, id=stream_read_char (s); i<4 && !(id & len_mask); i++)
32 len_mask >>= 1;
33 if (i >= 4)
34 return EBML_ID_INVALID;
35 if (length)
36 *length = i + 1;
37 while (i--)
38 id = (id << 8) | stream_read_char (s);
39 return id;
43 * Read a variable length unsigned int.
45 uint64_t
46 ebml_read_vlen_uint (uint8_t *buffer, int *length)
48 int i, j, num_ffs = 0, len_mask = 0x80;
49 uint64_t num;
51 for (i=0, num=*buffer++; i<8 && !(num & len_mask); i++)
52 len_mask >>= 1;
53 if (i >= 8)
54 return EBML_UINT_INVALID;
55 j = i+1;
56 if (length)
57 *length = j;
58 if ((int)(num &= (len_mask - 1)) == len_mask - 1)
59 num_ffs++;
60 while (i--)
62 num = (num << 8) | *buffer++;
63 if ((num & 0xFF) == 0xFF)
64 num_ffs++;
66 if (j == num_ffs)
67 return EBML_UINT_INVALID;
68 return num;
72 * Read a variable length signed int.
74 int64_t
75 ebml_read_vlen_int (uint8_t *buffer, int *length)
77 uint64_t unum;
78 int l;
80 /* read as unsigned number first */
81 unum = ebml_read_vlen_uint (buffer, &l);
82 if (unum == EBML_UINT_INVALID)
83 return EBML_INT_INVALID;
84 if (length)
85 *length = l;
87 return unum - ((1 << ((7 * l) - 1)) - 1);
91 * Read: element content length.
93 uint64_t
94 ebml_read_length (stream_t *s, int *length)
96 int i, j, num_ffs = 0, len_mask = 0x80;
97 uint64_t len;
99 for (i=0, len=stream_read_char (s); i<8 && !(len & len_mask); i++)
100 len_mask >>= 1;
101 if (i >= 8)
102 return EBML_UINT_INVALID;
103 j = i+1;
104 if (length)
105 *length = j;
106 if ((int)(len &= (len_mask - 1)) == len_mask - 1)
107 num_ffs++;
108 while (i--)
110 len = (len << 8) | stream_read_char (s);
111 if ((len & 0xFF) == 0xFF)
112 num_ffs++;
114 if (j == num_ffs)
115 return EBML_UINT_INVALID;
116 return len;
120 * Read the next element as an unsigned int.
122 uint64_t
123 ebml_read_uint (stream_t *s, uint64_t *length)
125 uint64_t len, value = 0;
126 int l;
128 len = ebml_read_length (s, &l);
129 if (len == EBML_UINT_INVALID || len < 1 || len > 8)
130 return EBML_UINT_INVALID;
131 if (length)
132 *length = len + l;
134 while (len--)
135 value = (value << 8) | stream_read_char (s);
137 return value;
141 * Read the next element as a signed int.
143 int64_t
144 ebml_read_int (stream_t *s, uint64_t *length)
146 int64_t value = 0;
147 uint64_t len;
148 int l;
150 len = ebml_read_length (s, &l);
151 if (len == EBML_UINT_INVALID || len < 1 || len > 8)
152 return EBML_INT_INVALID;
153 if (length)
154 *length = len + l;
156 len--;
157 l = stream_read_char (s);
158 if (l & 0x80)
159 value = -1;
160 value = (value << 8) | l;
161 while (len--)
162 value = (value << 8) | stream_read_char (s);
164 return value;
168 * Read the next element as a float.
170 long double
171 ebml_read_float (stream_t *s, uint64_t *length)
173 long double value;
174 uint64_t len;
175 int l;
177 len = ebml_read_length (s, &l);
178 switch (len)
180 case 4:
182 union {uint32_t i; float f;} u;
183 u.i = stream_read_dword (s);
184 value = u.f;
185 break;
188 case 8:
190 union {uint64_t i; double d;} u;
191 u.i = stream_read_qword (s);
192 value = u.d;
193 break;
196 case 10:
198 union {uint8_t data[10]; long double ld;} u;
199 if (stream_read (s, u.data, 10) != 10)
200 return EBML_FLOAT_INVALID;
201 value = be2me_ldbl(u.ld);
202 break;
205 default:
206 return EBML_FLOAT_INVALID;
209 if (length)
210 *length = len + l;
212 return value;
216 * Read the next element as an ASCII string.
218 char *
219 ebml_read_ascii (stream_t *s, uint64_t *length)
221 uint64_t len;
222 char *str;
223 int l;
225 len = ebml_read_length (s, &l);
226 if (len == EBML_UINT_INVALID)
227 return NULL;
228 if (len > SIZE_MAX - 1)
229 return NULL;
230 if (length)
231 *length = len + l;
233 str = (char *) malloc (len+1);
234 if (stream_read(s, str, len) != (int) len)
236 free (str);
237 return NULL;
239 str[len] = '\0';
241 return str;
245 * Read the next element as a UTF-8 string.
247 char *
248 ebml_read_utf8 (stream_t *s, uint64_t *length)
250 return ebml_read_ascii (s, length);
254 * Skip the next element.
257 ebml_read_skip (stream_t *s, uint64_t *length)
259 uint64_t len;
260 int l;
262 len = ebml_read_length (s, &l);
263 if (len == EBML_UINT_INVALID)
264 return 1;
265 if (length)
266 *length = len + l;
268 stream_skip(s, len);
270 return 0;
274 * Read the next element, but only the header. The contents
275 * are supposed to be sub-elements which can be read separately.
277 uint32_t
278 ebml_read_master (stream_t *s, uint64_t *length)
280 uint64_t len;
281 uint32_t id;
283 id = ebml_read_id (s, NULL);
284 if (id == EBML_ID_INVALID)
285 return id;
287 len = ebml_read_length (s, NULL);
288 if (len == EBML_UINT_INVALID)
289 return EBML_ID_INVALID;
290 if (length)
291 *length = len;
293 return id;
298 * Read an EBML header.
300 char *
301 ebml_read_header (stream_t *s, int *version)
303 uint64_t length, l, num;
304 uint32_t id;
305 char *str = NULL;
307 if (ebml_read_master (s, &length) != EBML_ID_HEADER)
308 return 0;
310 if (version)
311 *version = 1;
313 while (length > 0)
315 id = ebml_read_id (s, NULL);
316 if (id == EBML_ID_INVALID)
317 return NULL;
318 length -= 2;
320 switch (id)
322 /* is our read version uptodate? */
323 case EBML_ID_EBMLREADVERSION:
324 num = ebml_read_uint (s, &l);
325 if (num != EBML_VERSION)
326 return NULL;
327 break;
329 /* we only handle 8 byte lengths at max */
330 case EBML_ID_EBMLMAXSIZELENGTH:
331 num = ebml_read_uint (s, &l);
332 if (num != sizeof (uint64_t))
333 return NULL;
334 break;
336 /* we handle 4 byte IDs at max */
337 case EBML_ID_EBMLMAXIDLENGTH:
338 num = ebml_read_uint (s, &l);
339 if (num != sizeof (uint32_t))
340 return NULL;
341 break;
343 case EBML_ID_DOCTYPE:
344 str = ebml_read_ascii (s, &l);
345 if (str == NULL)
346 return NULL;
347 break;
349 case EBML_ID_DOCTYPEREADVERSION:
350 num = ebml_read_uint (s, &l);
351 if (num == EBML_UINT_INVALID)
352 return NULL;
353 if (version)
354 *version = num;
355 break;
357 /* we ignore these two, they don't tell us anything we care about */
358 case EBML_ID_VOID:
359 case EBML_ID_EBMLVERSION:
360 case EBML_ID_DOCTYPEVERSION:
361 default:
362 if (ebml_read_skip (s, &l))
363 return NULL;
364 break;
366 length -= l;
369 return str;