xref: /aosp_15_r20/external/libwebm/webm_parser/src/file_reader.cc (revision 103e46e4cd4b6efcf6001f23fa8665fb110abf8d)
1*103e46e4SHarish Mahendrakar // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2*103e46e4SHarish Mahendrakar //
3*103e46e4SHarish Mahendrakar // Use of this source code is governed by a BSD-style license
4*103e46e4SHarish Mahendrakar // that can be found in the LICENSE file in the root of the source
5*103e46e4SHarish Mahendrakar // tree. An additional intellectual property rights grant can be found
6*103e46e4SHarish Mahendrakar // in the file PATENTS.  All contributing project authors may
7*103e46e4SHarish Mahendrakar // be found in the AUTHORS file in the root of the source tree.
8*103e46e4SHarish Mahendrakar #include "webm/file_reader.h"
9*103e46e4SHarish Mahendrakar 
10*103e46e4SHarish Mahendrakar #include <cassert>
11*103e46e4SHarish Mahendrakar #include <cstdint>
12*103e46e4SHarish Mahendrakar #include <cstdio>
13*103e46e4SHarish Mahendrakar #include <cstdlib>
14*103e46e4SHarish Mahendrakar #include <limits>
15*103e46e4SHarish Mahendrakar #include <memory>
16*103e46e4SHarish Mahendrakar 
17*103e46e4SHarish Mahendrakar #include "webm/status.h"
18*103e46e4SHarish Mahendrakar 
19*103e46e4SHarish Mahendrakar #ifdef _MSC_VER
20*103e46e4SHarish Mahendrakar #define FSEEK_(stream, offset, whence) _fseeki64(stream, offset, whence)
21*103e46e4SHarish Mahendrakar #elif defined(_WIN32)
22*103e46e4SHarish Mahendrakar #define FSEEK_(stream, offset, whence) \
23*103e46e4SHarish Mahendrakar   fseeko64(stream, static_cast<off_t>(offset), whence)
24*103e46e4SHarish Mahendrakar #elif _POSIX_C_SOURCE >= 200112L
25*103e46e4SHarish Mahendrakar #define FSEEK_(stream, offset, whence) \
26*103e46e4SHarish Mahendrakar   fseeko(stream, static_cast<off_t>(offset), whence)
27*103e46e4SHarish Mahendrakar #else
28*103e46e4SHarish Mahendrakar #define FSEEK_(stream, offset, whence) \
29*103e46e4SHarish Mahendrakar   std::fseek(stream, static_cast<long>(offset), whence)
30*103e46e4SHarish Mahendrakar #endif
31*103e46e4SHarish Mahendrakar 
32*103e46e4SHarish Mahendrakar namespace webm {
33*103e46e4SHarish Mahendrakar 
FileReader(FILE * file)34*103e46e4SHarish Mahendrakar FileReader::FileReader(FILE* file) : file_(file) { assert(file); }
35*103e46e4SHarish Mahendrakar 
FileReader(FileReader && other)36*103e46e4SHarish Mahendrakar FileReader::FileReader(FileReader&& other)
37*103e46e4SHarish Mahendrakar     : file_(std::move(other.file_)), position_(other.position_) {
38*103e46e4SHarish Mahendrakar   other.position_ = 0;
39*103e46e4SHarish Mahendrakar }
40*103e46e4SHarish Mahendrakar 
operator =(FileReader && other)41*103e46e4SHarish Mahendrakar FileReader& FileReader::operator=(FileReader&& other) {
42*103e46e4SHarish Mahendrakar   if (this != &other) {
43*103e46e4SHarish Mahendrakar     file_ = std::move(other.file_);
44*103e46e4SHarish Mahendrakar     position_ = other.position_;
45*103e46e4SHarish Mahendrakar     other.position_ = 0;
46*103e46e4SHarish Mahendrakar   }
47*103e46e4SHarish Mahendrakar   return *this;
48*103e46e4SHarish Mahendrakar }
49*103e46e4SHarish Mahendrakar 
Read(std::size_t num_to_read,std::uint8_t * buffer,std::uint64_t * num_actually_read)50*103e46e4SHarish Mahendrakar Status FileReader::Read(std::size_t num_to_read, std::uint8_t* buffer,
51*103e46e4SHarish Mahendrakar                         std::uint64_t* num_actually_read) {
52*103e46e4SHarish Mahendrakar   assert(num_to_read > 0);
53*103e46e4SHarish Mahendrakar   assert(buffer != nullptr);
54*103e46e4SHarish Mahendrakar   assert(num_actually_read != nullptr);
55*103e46e4SHarish Mahendrakar 
56*103e46e4SHarish Mahendrakar   if (file_ == nullptr) {
57*103e46e4SHarish Mahendrakar     *num_actually_read = 0;
58*103e46e4SHarish Mahendrakar     return Status(Status::kEndOfFile);
59*103e46e4SHarish Mahendrakar   }
60*103e46e4SHarish Mahendrakar 
61*103e46e4SHarish Mahendrakar   std::size_t actual =
62*103e46e4SHarish Mahendrakar       std::fread(static_cast<void*>(buffer), 1, num_to_read, file_.get());
63*103e46e4SHarish Mahendrakar   *num_actually_read = static_cast<std::uint64_t>(actual);
64*103e46e4SHarish Mahendrakar   position_ += *num_actually_read;
65*103e46e4SHarish Mahendrakar 
66*103e46e4SHarish Mahendrakar   if (actual == 0) {
67*103e46e4SHarish Mahendrakar     return Status(Status::kEndOfFile);
68*103e46e4SHarish Mahendrakar   }
69*103e46e4SHarish Mahendrakar 
70*103e46e4SHarish Mahendrakar   if (actual == num_to_read) {
71*103e46e4SHarish Mahendrakar     return Status(Status::kOkCompleted);
72*103e46e4SHarish Mahendrakar   } else {
73*103e46e4SHarish Mahendrakar     return Status(Status::kOkPartial);
74*103e46e4SHarish Mahendrakar   }
75*103e46e4SHarish Mahendrakar }
76*103e46e4SHarish Mahendrakar 
Skip(std::uint64_t num_to_skip,std::uint64_t * num_actually_skipped)77*103e46e4SHarish Mahendrakar Status FileReader::Skip(std::uint64_t num_to_skip,
78*103e46e4SHarish Mahendrakar                         std::uint64_t* num_actually_skipped) {
79*103e46e4SHarish Mahendrakar   assert(num_to_skip > 0);
80*103e46e4SHarish Mahendrakar   assert(num_actually_skipped != nullptr);
81*103e46e4SHarish Mahendrakar 
82*103e46e4SHarish Mahendrakar   *num_actually_skipped = 0;
83*103e46e4SHarish Mahendrakar 
84*103e46e4SHarish Mahendrakar   if (file_ == nullptr) {
85*103e46e4SHarish Mahendrakar     return Status(Status::kEndOfFile);
86*103e46e4SHarish Mahendrakar   }
87*103e46e4SHarish Mahendrakar 
88*103e46e4SHarish Mahendrakar   // Try seeking forward first.
89*103e46e4SHarish Mahendrakar   long seek_offset = std::numeric_limits<long>::max();  // NOLINT
90*103e46e4SHarish Mahendrakar   if (num_to_skip < static_cast<unsigned long>(seek_offset)) {  // NOLINT
91*103e46e4SHarish Mahendrakar     seek_offset = static_cast<long>(num_to_skip);  // NOLINT
92*103e46e4SHarish Mahendrakar   }
93*103e46e4SHarish Mahendrakar   if (!FSEEK_(file_.get(), seek_offset, SEEK_CUR)) {
94*103e46e4SHarish Mahendrakar     *num_actually_skipped = static_cast<std::uint64_t>(seek_offset);
95*103e46e4SHarish Mahendrakar     position_ += static_cast<std::uint64_t>(seek_offset);
96*103e46e4SHarish Mahendrakar     if (static_cast<unsigned long>(seek_offset) == num_to_skip) {  // NOLINT
97*103e46e4SHarish Mahendrakar       return Status(Status::kOkCompleted);
98*103e46e4SHarish Mahendrakar     } else {
99*103e46e4SHarish Mahendrakar       return Status(Status::kOkPartial);
100*103e46e4SHarish Mahendrakar     }
101*103e46e4SHarish Mahendrakar   }
102*103e46e4SHarish Mahendrakar   std::clearerr(file_.get());
103*103e46e4SHarish Mahendrakar 
104*103e46e4SHarish Mahendrakar   // Seeking doesn't work on things like pipes, so if seeking failed then fall
105*103e46e4SHarish Mahendrakar   // back to reading the data into a junk buffer.
106*103e46e4SHarish Mahendrakar   std::size_t actual = 0;
107*103e46e4SHarish Mahendrakar   do {
108*103e46e4SHarish Mahendrakar     std::uint8_t junk[1024];
109*103e46e4SHarish Mahendrakar     std::size_t num_to_read = sizeof(junk);
110*103e46e4SHarish Mahendrakar     if (num_to_skip < num_to_read) {
111*103e46e4SHarish Mahendrakar       num_to_read = static_cast<std::size_t>(num_to_skip);
112*103e46e4SHarish Mahendrakar     }
113*103e46e4SHarish Mahendrakar 
114*103e46e4SHarish Mahendrakar     std::size_t actual =
115*103e46e4SHarish Mahendrakar         std::fread(static_cast<void*>(junk), 1, num_to_read, file_.get());
116*103e46e4SHarish Mahendrakar     *num_actually_skipped += static_cast<std::uint64_t>(actual);
117*103e46e4SHarish Mahendrakar     position_ += static_cast<std::uint64_t>(actual);
118*103e46e4SHarish Mahendrakar     num_to_skip -= static_cast<std::uint64_t>(actual);
119*103e46e4SHarish Mahendrakar   } while (actual > 0 && num_to_skip > 0);
120*103e46e4SHarish Mahendrakar 
121*103e46e4SHarish Mahendrakar   if (*num_actually_skipped == 0) {
122*103e46e4SHarish Mahendrakar     return Status(Status::kEndOfFile);
123*103e46e4SHarish Mahendrakar   }
124*103e46e4SHarish Mahendrakar 
125*103e46e4SHarish Mahendrakar   if (num_to_skip == 0) {
126*103e46e4SHarish Mahendrakar     return Status(Status::kOkCompleted);
127*103e46e4SHarish Mahendrakar   } else {
128*103e46e4SHarish Mahendrakar     return Status(Status::kOkPartial);
129*103e46e4SHarish Mahendrakar   }
130*103e46e4SHarish Mahendrakar }
131*103e46e4SHarish Mahendrakar 
Seek(std::uint64_t seek_position)132*103e46e4SHarish Mahendrakar Status FileReader::Seek(std::uint64_t seek_position) {
133*103e46e4SHarish Mahendrakar   if (FSEEK_(file_.get(), seek_position, SEEK_SET)) {
134*103e46e4SHarish Mahendrakar     return Status(Status::kSeekFailed);
135*103e46e4SHarish Mahendrakar   }
136*103e46e4SHarish Mahendrakar   position_ = seek_position;
137*103e46e4SHarish Mahendrakar   return Status(Status::kOkCompleted);
138*103e46e4SHarish Mahendrakar }
139*103e46e4SHarish Mahendrakar 
Position() const140*103e46e4SHarish Mahendrakar std::uint64_t FileReader::Position() const { return position_; }
141*103e46e4SHarish Mahendrakar 
142*103e46e4SHarish Mahendrakar }  // namespace webm
143