1 // Copyright (c) 2016 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 #include "test_utils/limited_reader.h"
9 
10 namespace webm {
11 
LimitedReader(std::unique_ptr<Reader> impl)12 LimitedReader::LimitedReader(std::unique_ptr<Reader> impl)
13     : impl_(std::move(impl)) {}
14 
Read(std::size_t num_to_read,std::uint8_t * buffer,std::uint64_t * num_actually_read)15 Status LimitedReader::Read(std::size_t num_to_read, std::uint8_t* buffer,
16                            std::uint64_t* num_actually_read) {
17   assert(num_to_read > 0);
18   assert(buffer != nullptr);
19   assert(num_actually_read != nullptr);
20 
21   *num_actually_read = 0;
22   std::size_t expected = num_to_read;
23 
24   num_to_read = std::min({num_to_read, single_read_limit_, total_read_limit_});
25 
26   // Handle total_read_skip_limit_ separately since std::size_t can be
27   // smaller than std::uint64_t.
28   if (num_to_read > total_read_skip_limit_) {
29     num_to_read = static_cast<std::size_t>(total_read_skip_limit_);
30   }
31 
32   if (num_to_read == 0) {
33     return return_status_when_blocked_;
34   }
35 
36   Status status = impl_->Read(num_to_read, buffer, num_actually_read);
37   assert(*num_actually_read <= num_to_read);
38 
39   if (status.code == Status::kOkCompleted && *num_actually_read < expected) {
40     status.code = Status::kOkPartial;
41   }
42 
43   if (total_read_limit_ != std::numeric_limits<std::size_t>::max()) {
44     total_read_limit_ -= static_cast<std::size_t>(*num_actually_read);
45   }
46 
47   if (total_read_skip_limit_ != std::numeric_limits<std::uint64_t>::max()) {
48     total_read_skip_limit_ -= *num_actually_read;
49   }
50 
51   return status;
52 }
53 
Skip(std::uint64_t num_to_skip,std::uint64_t * num_actually_skipped)54 Status LimitedReader::Skip(std::uint64_t num_to_skip,
55                            std::uint64_t* num_actually_skipped) {
56   assert(num_to_skip > 0);
57   assert(num_actually_skipped != nullptr);
58 
59   *num_actually_skipped = 0;
60   std::uint64_t expected = num_to_skip;
61 
62   num_to_skip = std::min({num_to_skip, single_skip_limit_, total_skip_limit_,
63                           total_read_skip_limit_});
64 
65   if (num_to_skip == 0) {
66     return return_status_when_blocked_;
67   }
68 
69   Status status = impl_->Skip(num_to_skip, num_actually_skipped);
70   assert(*num_actually_skipped <= num_to_skip);
71 
72   if (status.code == Status::kOkCompleted && *num_actually_skipped < expected) {
73     status.code = Status::kOkPartial;
74   }
75 
76   if (total_skip_limit_ != std::numeric_limits<std::uint64_t>::max()) {
77     total_skip_limit_ -= *num_actually_skipped;
78   }
79 
80   if (total_read_skip_limit_ != std::numeric_limits<std::uint64_t>::max()) {
81     total_read_skip_limit_ -= *num_actually_skipped;
82   }
83 
84   return status;
85 }
86 
Position() const87 std::uint64_t LimitedReader::Position() const { return impl_->Position(); }
88 
set_return_status_when_blocked(Status status)89 void LimitedReader::set_return_status_when_blocked(Status status) {
90   return_status_when_blocked_ = status;
91 }
92 
set_single_read_limit(std::size_t max_num_bytes)93 void LimitedReader::set_single_read_limit(std::size_t max_num_bytes) {
94   single_read_limit_ = max_num_bytes;
95 }
96 
set_single_skip_limit(std::uint64_t max_num_bytes)97 void LimitedReader::set_single_skip_limit(std::uint64_t max_num_bytes) {
98   single_skip_limit_ = max_num_bytes;
99 }
100 
set_total_read_limit(std::size_t max_num_bytes)101 void LimitedReader::set_total_read_limit(std::size_t max_num_bytes) {
102   total_read_limit_ = max_num_bytes;
103 }
104 
set_total_skip_limit(std::uint64_t max_num_bytes)105 void LimitedReader::set_total_skip_limit(std::uint64_t max_num_bytes) {
106   total_skip_limit_ = max_num_bytes;
107 }
108 
set_total_read_skip_limit(std::uint64_t max_num_bytes)109 void LimitedReader::set_total_read_skip_limit(std::uint64_t max_num_bytes) {
110   total_read_skip_limit_ = max_num_bytes;
111 }
112 
113 }  // namespace webm
114