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