roo_io
API Documentation for roo_io
Loading...
Searching...
No Matches
file_output_iterator.h
Go to the documentation of this file.
1#pragma once
2
3#ifdef ARDUINO
4
5#include <FS.h>
6
7#include <cstring>
8#include <memory>
9
11
12namespace roo_io {
13
14static const size_t kArduinoFileOutputIteratorBufferSize = 64;
15
17 public:
19
21
23
24 ~ArduinoFileOutputIterator() { flush(); }
25
26 void write(byte v) { rep_->write(v); }
27
28 size_t write(const byte* buf, size_t count) {
29 return rep_->write(buf, count);
30 }
31
32 /// `rep_` can be nullptr after move.
33 void flush() {
34 if (rep_ != nullptr) rep_->flush();
35 }
36
37 Status status() const { return rep_->status(); }
38 bool ok() const { return status() == roo_io::kOk; }
39
40 private:
41 class Rep {
42 public:
43 Rep();
44 Rep(::fs::File file);
45 // ~Rep();
46
47 void write(byte v);
48 size_t write(const byte* buf, size_t count);
49 void flush();
50
51 Status status() const { return status_; }
52
53 private:
54 Rep(const Rep&) = delete;
55 Rep(Rep&&);
56 Rep& operator=(const Rep&);
57 void writeBuffer();
58
59 ::fs::File file_;
60 byte buffer_[kArduinoFileOutputIteratorBufferSize];
61 uint8_t offset_;
62 Status status_;
63 };
64
65 /// Rep is heap-allocated to keep stack usage low, match underlying heap-
66 /// allocated file structures, and keep iterator move operations cheap.
67 std::unique_ptr<Rep> rep_;
68};
69
70inline ArduinoFileOutputIterator::Rep::Rep()
71 : file_(),
73 status_(kClosed) {}
74
75inline ArduinoFileOutputIterator::Rep::Rep(::fs::File file)
76 : file_(std::move(file)), offset_(0), status_(file_ ? kOk : kClosed) {
77 if (status_ != kOk) offset_ = kArduinoFileOutputIteratorBufferSize;
78}
79
80inline void ArduinoFileOutputIterator::Rep::writeBuffer() {
81 if (file_.write((const uint8_t*)buffer_, offset_) < offset_) {
82 status_ = kWriteError;
83 }
84 offset_ = 0;
85}
86
87inline void ArduinoFileOutputIterator::Rep::write(byte v) {
88 if (offset_ >= kArduinoFileOutputIteratorBufferSize) {
89 if (status_ != kOk) return;
90 writeBuffer();
91 }
92 buffer_[offset_++] = v;
93}
94
95inline size_t ArduinoFileOutputIterator::Rep::write(const byte* buf,
96 size_t len) {
97 if (offset_ > 0 || len < kArduinoFileOutputIteratorBufferSize) {
98 size_t cap = kArduinoFileOutputIteratorBufferSize - offset_;
99 if (len > cap) len = cap;
100 memcpy(&buffer_[offset_], buf, len);
101 offset_ += len;
102 if (offset_ >= kArduinoFileOutputIteratorBufferSize) {
103 if (status_ != kOk) return 0;
104 writeBuffer();
105 }
106 return len;
107 }
108 if (status_ != kOk) return 0;
109 size_t result = file_.write((const uint8_t*)buf, len);
110 if (result < len) {
111 status_ = kWriteError;
112 }
113 return result;
114}
115
116inline void ArduinoFileOutputIterator::Rep::flush() {
117 if (status_ == kOk) {
118 if (offset_ > 0) writeBuffer();
119 file_.flush();
120 if (!file_) status_ = kWriteError;
121 }
122}
123
124} // namespace roo_io
125
126#endif // ARDUINO
Definition byte.h:6
roo::basic_string_view< CharT, Traits > basic_string_view
Definition string_view.h:8
size_t count
Definition compare.h:45
Status
Definition status.h:7
@ kOk
Definition status.h:8
@ kClosed
Definition status.h:10
@ kWriteError
Definition status.h:15