1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
#include "read.h"
#include "vint.h"
#include "ebml_float.h"
#include "ebml_unsigned.h"
#include "ebml_signed.h"
#include <limits.h>
#ifdef WA_VALIDATE
extern uint64_t max_id_length;
extern uint64_t max_size_length;
#endif
// returns bytes read. 0 means EOF
uint64_t read_vint(nsmkv::MKVReader *reader, uint64_t *val)
{
uint8_t data[9] = {0};
size_t bytes_read = 0;
reader->Read(data, 1, &bytes_read);
if (bytes_read != 1)
return 0;
uint8_t length = vint_get_number_bytes(data[0]);
reader->Read(data+1, length, &bytes_read);
if (bytes_read != length)
return 0;
*val = vint_read_ptr(data);
return bytes_read+1;
}
// returns bytes read. 0 means EOF
uint64_t read_ebml_node(nsmkv::MKVReader *reader, ebml_node *node)
{
uint64_t bytes_read = read_vint(reader, &node->id);
if (!bytes_read)
return 0;
bytes_read += read_vint(reader, &node->size);
return bytes_read;
}
uint64_t read_utf8(nsmkv::MKVReader *reader, uint64_t size, char **utf8)
{
if (utf8)
{
if (size == SIZE_MAX) // prevent integer overflow
return 0;
char *&val = *utf8;
val = (char *)calloc((size_t)size + 1, sizeof(char));
if (val)
{
val[size]=0;
size_t bytes_read;
reader->Read(val, (size_t)size, &bytes_read);
if (bytes_read != (size_t)size)
{
free(val);
return 0;
}
return size;
}
return 0; // actually, out of memory and not EOF, but still we should abort ASAP
}
else
{
reader->Skip(size);
return size;
}
}
#if 0
int fseek64(nsmkv::MKVReader *reader, int64_t pos, int whence)
{
switch(whence)
{
case SEEK_SET:
return fsetpos(f, &pos);
case SEEK_CUR:
{
fpos_t curpos=0;
int ret = fgetpos(f, &curpos);
if (ret != 0)
return ret;
pos+=curpos;
return fsetpos(f, &pos);
}
case SEEK_END:
{
return _fseeki64(f, pos, SEEK_END);
}
}
return 1;
}
int64_t ftell64(nsmkv::MKVReader *reader)
{
fpos_t pos;
if (fgetpos(f, &pos) == 0)
return pos;
else
return -1L;
}
#endif
uint64_t read_unsigned(nsmkv::MKVReader *reader, uint64_t size, uint64_t *val)
{
uint8_t data[8] = {0};
if (size == 0 || size > 8)
return 0;
size_t bytes_read = 0;
reader->Read(data, (size_t)size, &bytes_read);
if (bytes_read != size)
{
return 0;
}
*val = unsigned_read_ptr_len(size, data);
return size;
}
uint64_t read_float(nsmkv::MKVReader *reader, uint64_t size, double *val)
{
uint8_t data[10] = {0};
if (size == 0 || size > 10)
return 0;
size_t bytes_read = 0;
reader->Read(data, (size_t)size, &bytes_read);
if (bytes_read != size)
{
return 0;
}
*val = float_read_ptr_len(size, data);
return size;
}
uint64_t read_signed(nsmkv::MKVReader *reader, uint64_t size, int64_t *val)
{
uint8_t data[8] = {0};
if (size == 0 || size > 8)
return 0;
size_t bytes_read = 0;
reader->Read(data, (size_t)size, &bytes_read);
if (bytes_read != size)
{
return 0;
}
*val = signed_read_ptr_len(size, data);
return size;
}
|