1*fb1b10abSAndroid Build Coastguard Worker // Copyright (c) 2010 The WebM project authors. All Rights Reserved.
2*fb1b10abSAndroid Build Coastguard Worker //
3*fb1b10abSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license
4*fb1b10abSAndroid Build Coastguard Worker // that can be found in the LICENSE file in the root of the source
5*fb1b10abSAndroid Build Coastguard Worker // tree. An additional intellectual property rights grant can be found
6*fb1b10abSAndroid Build Coastguard Worker // in the file PATENTS. All contributing project authors may
7*fb1b10abSAndroid Build Coastguard Worker // be found in the AUTHORS file in the root of the source tree.
8*fb1b10abSAndroid Build Coastguard Worker #include "mkvparser/mkvreader.h"
9*fb1b10abSAndroid Build Coastguard Worker
10*fb1b10abSAndroid Build Coastguard Worker #include <sys/types.h>
11*fb1b10abSAndroid Build Coastguard Worker
12*fb1b10abSAndroid Build Coastguard Worker #include <cassert>
13*fb1b10abSAndroid Build Coastguard Worker
14*fb1b10abSAndroid Build Coastguard Worker namespace mkvparser {
15*fb1b10abSAndroid Build Coastguard Worker
MkvReader()16*fb1b10abSAndroid Build Coastguard Worker MkvReader::MkvReader() : m_file(NULL), reader_owns_file_(true) {}
17*fb1b10abSAndroid Build Coastguard Worker
MkvReader(FILE * fp)18*fb1b10abSAndroid Build Coastguard Worker MkvReader::MkvReader(FILE* fp) : m_file(fp), reader_owns_file_(false) {
19*fb1b10abSAndroid Build Coastguard Worker GetFileSize();
20*fb1b10abSAndroid Build Coastguard Worker }
21*fb1b10abSAndroid Build Coastguard Worker
~MkvReader()22*fb1b10abSAndroid Build Coastguard Worker MkvReader::~MkvReader() {
23*fb1b10abSAndroid Build Coastguard Worker if (reader_owns_file_)
24*fb1b10abSAndroid Build Coastguard Worker Close();
25*fb1b10abSAndroid Build Coastguard Worker m_file = NULL;
26*fb1b10abSAndroid Build Coastguard Worker }
27*fb1b10abSAndroid Build Coastguard Worker
Open(const char * fileName)28*fb1b10abSAndroid Build Coastguard Worker int MkvReader::Open(const char* fileName) {
29*fb1b10abSAndroid Build Coastguard Worker if (fileName == NULL)
30*fb1b10abSAndroid Build Coastguard Worker return -1;
31*fb1b10abSAndroid Build Coastguard Worker
32*fb1b10abSAndroid Build Coastguard Worker if (m_file)
33*fb1b10abSAndroid Build Coastguard Worker return -1;
34*fb1b10abSAndroid Build Coastguard Worker
35*fb1b10abSAndroid Build Coastguard Worker #ifdef _MSC_VER
36*fb1b10abSAndroid Build Coastguard Worker const errno_t e = fopen_s(&m_file, fileName, "rb");
37*fb1b10abSAndroid Build Coastguard Worker
38*fb1b10abSAndroid Build Coastguard Worker if (e)
39*fb1b10abSAndroid Build Coastguard Worker return -1; // error
40*fb1b10abSAndroid Build Coastguard Worker #else
41*fb1b10abSAndroid Build Coastguard Worker m_file = fopen(fileName, "rb");
42*fb1b10abSAndroid Build Coastguard Worker
43*fb1b10abSAndroid Build Coastguard Worker if (m_file == NULL)
44*fb1b10abSAndroid Build Coastguard Worker return -1;
45*fb1b10abSAndroid Build Coastguard Worker #endif
46*fb1b10abSAndroid Build Coastguard Worker return !GetFileSize();
47*fb1b10abSAndroid Build Coastguard Worker }
48*fb1b10abSAndroid Build Coastguard Worker
GetFileSize()49*fb1b10abSAndroid Build Coastguard Worker bool MkvReader::GetFileSize() {
50*fb1b10abSAndroid Build Coastguard Worker if (m_file == NULL)
51*fb1b10abSAndroid Build Coastguard Worker return false;
52*fb1b10abSAndroid Build Coastguard Worker #ifdef _MSC_VER
53*fb1b10abSAndroid Build Coastguard Worker int status = _fseeki64(m_file, 0L, SEEK_END);
54*fb1b10abSAndroid Build Coastguard Worker
55*fb1b10abSAndroid Build Coastguard Worker if (status)
56*fb1b10abSAndroid Build Coastguard Worker return false; // error
57*fb1b10abSAndroid Build Coastguard Worker
58*fb1b10abSAndroid Build Coastguard Worker m_length = _ftelli64(m_file);
59*fb1b10abSAndroid Build Coastguard Worker #else
60*fb1b10abSAndroid Build Coastguard Worker fseek(m_file, 0L, SEEK_END);
61*fb1b10abSAndroid Build Coastguard Worker m_length = ftell(m_file);
62*fb1b10abSAndroid Build Coastguard Worker #endif
63*fb1b10abSAndroid Build Coastguard Worker assert(m_length >= 0);
64*fb1b10abSAndroid Build Coastguard Worker
65*fb1b10abSAndroid Build Coastguard Worker if (m_length < 0)
66*fb1b10abSAndroid Build Coastguard Worker return false;
67*fb1b10abSAndroid Build Coastguard Worker
68*fb1b10abSAndroid Build Coastguard Worker #ifdef _MSC_VER
69*fb1b10abSAndroid Build Coastguard Worker status = _fseeki64(m_file, 0L, SEEK_SET);
70*fb1b10abSAndroid Build Coastguard Worker
71*fb1b10abSAndroid Build Coastguard Worker if (status)
72*fb1b10abSAndroid Build Coastguard Worker return false; // error
73*fb1b10abSAndroid Build Coastguard Worker #else
74*fb1b10abSAndroid Build Coastguard Worker fseek(m_file, 0L, SEEK_SET);
75*fb1b10abSAndroid Build Coastguard Worker #endif
76*fb1b10abSAndroid Build Coastguard Worker
77*fb1b10abSAndroid Build Coastguard Worker return true;
78*fb1b10abSAndroid Build Coastguard Worker }
79*fb1b10abSAndroid Build Coastguard Worker
Close()80*fb1b10abSAndroid Build Coastguard Worker void MkvReader::Close() {
81*fb1b10abSAndroid Build Coastguard Worker if (m_file != NULL) {
82*fb1b10abSAndroid Build Coastguard Worker fclose(m_file);
83*fb1b10abSAndroid Build Coastguard Worker m_file = NULL;
84*fb1b10abSAndroid Build Coastguard Worker }
85*fb1b10abSAndroid Build Coastguard Worker }
86*fb1b10abSAndroid Build Coastguard Worker
Length(long long * total,long long * available)87*fb1b10abSAndroid Build Coastguard Worker int MkvReader::Length(long long* total, long long* available) {
88*fb1b10abSAndroid Build Coastguard Worker if (m_file == NULL)
89*fb1b10abSAndroid Build Coastguard Worker return -1;
90*fb1b10abSAndroid Build Coastguard Worker
91*fb1b10abSAndroid Build Coastguard Worker if (total)
92*fb1b10abSAndroid Build Coastguard Worker *total = m_length;
93*fb1b10abSAndroid Build Coastguard Worker
94*fb1b10abSAndroid Build Coastguard Worker if (available)
95*fb1b10abSAndroid Build Coastguard Worker *available = m_length;
96*fb1b10abSAndroid Build Coastguard Worker
97*fb1b10abSAndroid Build Coastguard Worker return 0;
98*fb1b10abSAndroid Build Coastguard Worker }
99*fb1b10abSAndroid Build Coastguard Worker
Read(long long offset,long len,unsigned char * buffer)100*fb1b10abSAndroid Build Coastguard Worker int MkvReader::Read(long long offset, long len, unsigned char* buffer) {
101*fb1b10abSAndroid Build Coastguard Worker if (m_file == NULL)
102*fb1b10abSAndroid Build Coastguard Worker return -1;
103*fb1b10abSAndroid Build Coastguard Worker
104*fb1b10abSAndroid Build Coastguard Worker if (offset < 0)
105*fb1b10abSAndroid Build Coastguard Worker return -1;
106*fb1b10abSAndroid Build Coastguard Worker
107*fb1b10abSAndroid Build Coastguard Worker if (len < 0)
108*fb1b10abSAndroid Build Coastguard Worker return -1;
109*fb1b10abSAndroid Build Coastguard Worker
110*fb1b10abSAndroid Build Coastguard Worker if (len == 0)
111*fb1b10abSAndroid Build Coastguard Worker return 0;
112*fb1b10abSAndroid Build Coastguard Worker
113*fb1b10abSAndroid Build Coastguard Worker if (offset >= m_length)
114*fb1b10abSAndroid Build Coastguard Worker return -1;
115*fb1b10abSAndroid Build Coastguard Worker
116*fb1b10abSAndroid Build Coastguard Worker #ifdef _MSC_VER
117*fb1b10abSAndroid Build Coastguard Worker const int status = _fseeki64(m_file, offset, SEEK_SET);
118*fb1b10abSAndroid Build Coastguard Worker
119*fb1b10abSAndroid Build Coastguard Worker if (status)
120*fb1b10abSAndroid Build Coastguard Worker return -1; // error
121*fb1b10abSAndroid Build Coastguard Worker #elif defined(_WIN32)
122*fb1b10abSAndroid Build Coastguard Worker fseeko64(m_file, static_cast<off_t>(offset), SEEK_SET);
123*fb1b10abSAndroid Build Coastguard Worker #elif !(defined(__ANDROID__) && __ANDROID_API__ < 24 && !defined(__LP64__) && \
124*fb1b10abSAndroid Build Coastguard Worker defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64)
125*fb1b10abSAndroid Build Coastguard Worker // POSIX.1 has fseeko and ftello. fseeko and ftello are not available before
126*fb1b10abSAndroid Build Coastguard Worker // Android API level 24. See
127*fb1b10abSAndroid Build Coastguard Worker // https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md
128*fb1b10abSAndroid Build Coastguard Worker fseeko(m_file, static_cast<off_t>(offset), SEEK_SET);
129*fb1b10abSAndroid Build Coastguard Worker #else
130*fb1b10abSAndroid Build Coastguard Worker fseek(m_file, static_cast<long>(offset), SEEK_SET);
131*fb1b10abSAndroid Build Coastguard Worker #endif
132*fb1b10abSAndroid Build Coastguard Worker
133*fb1b10abSAndroid Build Coastguard Worker const size_t size = fread(buffer, 1, len, m_file);
134*fb1b10abSAndroid Build Coastguard Worker
135*fb1b10abSAndroid Build Coastguard Worker if (size < size_t(len))
136*fb1b10abSAndroid Build Coastguard Worker return -1; // error
137*fb1b10abSAndroid Build Coastguard Worker
138*fb1b10abSAndroid Build Coastguard Worker return 0; // success
139*fb1b10abSAndroid Build Coastguard Worker }
140*fb1b10abSAndroid Build Coastguard Worker
141*fb1b10abSAndroid Build Coastguard Worker } // namespace mkvparser
142