xref: /aosp_15_r20/external/pigweed/pw_stream/interval_reader.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2020 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_stream/interval_reader.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include "pw_assert/check.h"
18*61c4878aSAndroid Build Coastguard Worker 
19*61c4878aSAndroid Build Coastguard Worker namespace pw::stream {
20*61c4878aSAndroid Build Coastguard Worker 
DoRead(ByteSpan destination)21*61c4878aSAndroid Build Coastguard Worker StatusWithSize IntervalReader::DoRead(ByteSpan destination) {
22*61c4878aSAndroid Build Coastguard Worker   if (!source_reader_) {
23*61c4878aSAndroid Build Coastguard Worker     return StatusWithSize(Status::FailedPrecondition(), 0);
24*61c4878aSAndroid Build Coastguard Worker   }
25*61c4878aSAndroid Build Coastguard Worker 
26*61c4878aSAndroid Build Coastguard Worker   if (!status_.ok()) {
27*61c4878aSAndroid Build Coastguard Worker     return StatusWithSize(status_, 0);
28*61c4878aSAndroid Build Coastguard Worker   }
29*61c4878aSAndroid Build Coastguard Worker 
30*61c4878aSAndroid Build Coastguard Worker   if (current_ == end_) {
31*61c4878aSAndroid Build Coastguard Worker     return StatusWithSize::OutOfRange();
32*61c4878aSAndroid Build Coastguard Worker   }
33*61c4878aSAndroid Build Coastguard Worker 
34*61c4878aSAndroid Build Coastguard Worker   // Seek the source reader to the `current_` offset of this IntervalReader
35*61c4878aSAndroid Build Coastguard Worker   // before reading.
36*61c4878aSAndroid Build Coastguard Worker   Status status = source_reader_->Seek(current_, Whence::kBeginning);
37*61c4878aSAndroid Build Coastguard Worker   if (!status.ok()) {
38*61c4878aSAndroid Build Coastguard Worker     return StatusWithSize(status, 0);
39*61c4878aSAndroid Build Coastguard Worker   }
40*61c4878aSAndroid Build Coastguard Worker 
41*61c4878aSAndroid Build Coastguard Worker   size_t to_read = std::min(destination.size(), end_ - current_);
42*61c4878aSAndroid Build Coastguard Worker   Result<ByteSpan> res = source_reader_->Read(destination.first(to_read));
43*61c4878aSAndroid Build Coastguard Worker   if (!res.ok()) {
44*61c4878aSAndroid Build Coastguard Worker     return StatusWithSize(res.status(), 0);
45*61c4878aSAndroid Build Coastguard Worker   }
46*61c4878aSAndroid Build Coastguard Worker 
47*61c4878aSAndroid Build Coastguard Worker   current_ += res.value().size();
48*61c4878aSAndroid Build Coastguard Worker   return StatusWithSize(res.value().size());
49*61c4878aSAndroid Build Coastguard Worker }
50*61c4878aSAndroid Build Coastguard Worker 
DoSeek(ptrdiff_t offset,Whence origin)51*61c4878aSAndroid Build Coastguard Worker Status IntervalReader::DoSeek(ptrdiff_t offset, Whence origin) {
52*61c4878aSAndroid Build Coastguard Worker   ptrdiff_t absolute_position = std::numeric_limits<ptrdiff_t>::min();
53*61c4878aSAndroid Build Coastguard Worker 
54*61c4878aSAndroid Build Coastguard Worker   // Convert from the position within the interval to the position within the
55*61c4878aSAndroid Build Coastguard Worker   // source reader stream.
56*61c4878aSAndroid Build Coastguard Worker   switch (origin) {
57*61c4878aSAndroid Build Coastguard Worker     case Whence::kBeginning:
58*61c4878aSAndroid Build Coastguard Worker       absolute_position = offset + start_;
59*61c4878aSAndroid Build Coastguard Worker       break;
60*61c4878aSAndroid Build Coastguard Worker 
61*61c4878aSAndroid Build Coastguard Worker     case Whence::kCurrent:
62*61c4878aSAndroid Build Coastguard Worker       absolute_position = current_ + offset;
63*61c4878aSAndroid Build Coastguard Worker       break;
64*61c4878aSAndroid Build Coastguard Worker 
65*61c4878aSAndroid Build Coastguard Worker     case Whence::kEnd:
66*61c4878aSAndroid Build Coastguard Worker       absolute_position = end_ + offset;
67*61c4878aSAndroid Build Coastguard Worker       break;
68*61c4878aSAndroid Build Coastguard Worker   }
69*61c4878aSAndroid Build Coastguard Worker 
70*61c4878aSAndroid Build Coastguard Worker   if (absolute_position < 0) {
71*61c4878aSAndroid Build Coastguard Worker     return Status::InvalidArgument();
72*61c4878aSAndroid Build Coastguard Worker   }
73*61c4878aSAndroid Build Coastguard Worker 
74*61c4878aSAndroid Build Coastguard Worker   if (static_cast<size_t>(absolute_position) < start_ ||
75*61c4878aSAndroid Build Coastguard Worker       static_cast<size_t>(absolute_position) > end_) {
76*61c4878aSAndroid Build Coastguard Worker     return Status::InvalidArgument();
77*61c4878aSAndroid Build Coastguard Worker   }
78*61c4878aSAndroid Build Coastguard Worker 
79*61c4878aSAndroid Build Coastguard Worker   current_ = absolute_position;
80*61c4878aSAndroid Build Coastguard Worker   return OkStatus();
81*61c4878aSAndroid Build Coastguard Worker }
82*61c4878aSAndroid Build Coastguard Worker 
83*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::stream
84