1 // Copyright 2021 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 // Defines functions for implementing seeking in a stream.
16 #pragma once
17
18 #include <cstddef>
19
20 #include "pw_stream/stream.h"
21
22 namespace pw::stream {
23
24 // Adds a seek offset to the specified origin.
ResolveSeekOffset(ptrdiff_t offset,Stream::Whence origin,size_t end_position,size_t current_position)25 constexpr ptrdiff_t ResolveSeekOffset(ptrdiff_t offset,
26 Stream::Whence origin,
27 size_t end_position,
28 size_t current_position) {
29 switch (origin) {
30 case Stream::kBeginning:
31 return offset;
32 case Stream::kCurrent:
33 return static_cast<ptrdiff_t>(current_position) + offset;
34 case Stream::kEnd:
35 default:
36 return static_cast<ptrdiff_t>(end_position) + offset;
37 }
38 }
39
40 // Implements seek for a class that supports absolute position changes. The
41 // new position is calculated and assigned to the provided position variable.
42 //
43 // Returns OUT_OF_RANGE for seeks to a negative position or past the end.
CalculateSeek(ptrdiff_t offset,Stream::Whence origin,size_t end_position,size_t & current_position)44 constexpr Status CalculateSeek(ptrdiff_t offset,
45 Stream::Whence origin,
46 size_t end_position,
47 size_t& current_position) {
48 const ptrdiff_t new_position =
49 ResolveSeekOffset(offset, origin, end_position, current_position);
50
51 if (new_position < 0 || static_cast<size_t>(new_position) > end_position) {
52 return Status::OutOfRange();
53 }
54
55 current_position = static_cast<size_t>(new_position);
56 return OkStatus();
57 }
58
59 } // namespace pw::stream
60