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