blob: cba0e40f2be7b2c686f2956aed306ee2fe2a44c1 [file] [log] [blame]
Wyatt Hepler1927c282020-02-11 16:45:02 -08001// 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_kvs/alignment.h"
16
17namespace pw {
18
David Rogers6592d292020-02-14 14:19:26 -080019StatusWithSize AlignedWriter::Write(span<const std::byte> data) {
Wyatt Hepler1927c282020-02-11 16:45:02 -080020 while (!data.empty()) {
21 size_t to_copy = std::min(write_size_ - bytes_in_buffer_, data.size());
22
23 std::memcpy(&buffer_[bytes_in_buffer_], data.data(), to_copy);
24 data = data.subspan(to_copy);
25 bytes_in_buffer_ += to_copy;
26
27 // If the buffer is full, write it out.
28 if (bytes_in_buffer_ == write_size_) {
David Rogers6592d292020-02-14 14:19:26 -080029 StatusWithSize result = output_.Write(buffer_, write_size_);
30
31 // Always use write_size_ for the bytes written. If there was an error
32 // assume the space was written or at least disturbed.
33 bytes_written_ += write_size_;
34 if (!result.ok()) {
35 return StatusWithSize(result.status(), bytes_written_);
Wyatt Hepler1927c282020-02-11 16:45:02 -080036 }
37
Wyatt Hepler1927c282020-02-11 16:45:02 -080038 bytes_in_buffer_ = 0;
39 }
40 }
41
David Rogers6592d292020-02-14 14:19:26 -080042 return StatusWithSize(bytes_written_);
Wyatt Hepler1927c282020-02-11 16:45:02 -080043}
44
45StatusWithSize AlignedWriter::Flush() {
46 static constexpr std::byte kPadByte = std::byte{0};
47
48 // If data remains in the buffer, pad it to the alignment size and flush the
49 // remaining data.
50 if (bytes_in_buffer_ != 0u) {
51 const size_t remaining_bytes = AlignUp(bytes_in_buffer_, alignment_bytes_);
52 std::memset(&buffer_[bytes_in_buffer_],
53 int(kPadByte),
54 remaining_bytes - bytes_in_buffer_);
55
Wyatt Hepler50f70772020-02-13 11:25:10 -080056 if (auto result = output_.Write(buffer_, remaining_bytes); !result.ok()) {
57 return StatusWithSize(result.status(), bytes_written_);
Wyatt Hepler1927c282020-02-11 16:45:02 -080058 }
59
60 bytes_written_ += remaining_bytes; // Include padding in the total.
61 }
62
63 const StatusWithSize result(bytes_written_);
64 bytes_written_ = 0;
65 bytes_in_buffer_ = 0;
66 return result;
67}
68
69} // namespace pw