xref: /aosp_15_r20/external/executorch/backends/apple/coreml/runtime/inmemoryfs/memory_stream.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1 //
2 // memory_stream.cpp
3 //
4 // Copyright © 2024 Apple Inc. All rights reserved.
5 //
6 // Please refer to the license found in the LICENSE file in the root directory of the source tree.
7 
8 #include "memory_stream.hpp"
9 
10 #include <limits>
11 
12 namespace inmemoryfs {
13 
MemoryStreamBuf(const std::shared_ptr<MemoryBuffer> & buffer)14 MemoryStreamBuf::MemoryStreamBuf(const std::shared_ptr<MemoryBuffer>& buffer) noexcept : buffer_(buffer) {
15     auto start = static_cast<char*>(buffer->data());
16     auto end = start + buffer->size();
17     setg(start, start, end);
18     setp(start, end);
19 }
20 
iseekoff(std::streambuf::off_type offset,std::ios_base::seekdir dir)21 std::streambuf::pos_type MemoryStreamBuf::iseekoff(std::streambuf::off_type offset, std::ios_base::seekdir dir) {
22     std::streambuf::off_type next = -1;
23     const std::ptrdiff_t size = std::ptrdiff_t(egptr() - eback());
24     switch (dir) {
25         case std::ios_base::beg: {
26             next = offset;
27             break;
28         }
29         case std::ios_base::cur: {
30             next = std::streambuf::off_type(std::ptrdiff_t(gptr() - eback())) + offset;
31             break;
32         }
33         case std::ios_base::end: {
34             next = std::streambuf::off_type(size) + offset;
35             break;
36         }
37         default:
38             break;
39     }
40 
41     if (next < 0 || next >= std::streambuf::off_type(size)) {
42         return std::streambuf::pos_type(std::streambuf::off_type(-1));
43     }
44 
45     setg(eback(), eback() + next, egptr());
46     return gptr() - eback();
47 }
48 
oseekoff(std::streambuf::off_type offset,std::ios_base::seekdir dir)49 std::streambuf::pos_type MemoryStreamBuf::oseekoff(std::streambuf::off_type offset, std::ios_base::seekdir dir) {
50     std::streambuf::off_type next = -1;
51     const std::ptrdiff_t size = std::ptrdiff_t(epptr() - pbase());
52     switch (dir) {
53         case std::ios_base::beg: {
54             next = offset;
55             break;
56         }
57         case std::ios_base::cur: {
58             next = std::streambuf::off_type(std::ptrdiff_t(pptr() - pbase())) + offset;
59             break;
60         }
61         case std::ios_base::end: {
62             next = std::streambuf::off_type(size) + offset;
63             break;
64         }
65         default: {
66             break;
67         }
68     }
69 
70     if (next < 0 || next > std::streambuf::off_type(size)) {
71         return std::streambuf::pos_type(std::streambuf::off_type(-1));
72     }
73 
74     setp(pbase(), epptr());
75     pbump(static_cast<int>(next));
76     return pptr() - pbase();
77 }
78 
79 std::streambuf::pos_type
seekoff(std::streambuf::off_type offset,std::ios_base::seekdir dir,std::ios_base::openmode which)80 MemoryStreamBuf::seekoff(std::streambuf::off_type offset, std::ios_base::seekdir dir, std::ios_base::openmode which) {
81     if (which & std::ios_base::out) {
82         return oseekoff(offset, dir);
83     } else if (which & std::ios_base::in) {
84         return iseekoff(offset, dir);
85     } else {
86         return std::streambuf::pos_type(std::streambuf::off_type(-1));
87     }
88 }
89 
seekpos(std::streambuf::pos_type pos,std::ios_base::openmode which)90 std::streambuf::pos_type MemoryStreamBuf::seekpos(std::streambuf::pos_type pos, std::ios_base::openmode which) {
91     return seekoff(pos - std::streambuf::pos_type(std::streambuf::off_type(0)), std::ios::beg, which);
92 }
93 
showmanyc()94 std::streamsize MemoryStreamBuf::showmanyc() {
95     std::ptrdiff_t n = egptr() - gptr();
96     std::streamsize max = std::numeric_limits<std::streamsize>::max();
97     return (n <= max ? std::streamsize(n) : max);
98 }
99 
pbackfail(std::streambuf::int_type ch)100 std::streambuf::int_type MemoryStreamBuf::pbackfail(std::streambuf::int_type ch) {
101     if (eback() == gptr() || (ch != traits_type::eof() && ch != gptr()[-1])) {
102         return traits_type::eof();
103     }
104     gbump(-1);
105     return ch;
106 }
107 
underflow()108 std::streambuf::int_type MemoryStreamBuf::underflow() {
109     if (gptr() == egptr()) {
110         return traits_type::eof();
111     }
112     return traits_type::to_int_type(*gptr());
113 }
114 
uflow()115 std::streambuf::int_type MemoryStreamBuf::uflow() {
116     if (gptr() == egptr()) {
117         return traits_type::eof();
118     }
119     const std::streambuf::char_type ch = *gptr();
120     gbump(1);
121     return traits_type::to_int_type(ch);
122 }
123 
overflow(std::streambuf::int_type ch)124 std::streambuf::int_type MemoryStreamBuf::overflow(std::streambuf::int_type ch) {
125     if (ch == traits_type::eof()) {
126         return ch;
127     }
128     const std::streambuf::char_type c = traits_type::to_char_type(ch);
129     xsputn(&c, 1);
130     return ch;
131 }
132 
xsgetn(char * s,std::streamsize n)133 std::streamsize MemoryStreamBuf::xsgetn(char* s, std::streamsize n) {
134     const ptrdiff_t remaining = egptr() - gptr();
135     n = std::min(n, remaining);
136     if (n <= 0) {
137         return std::streamsize(0);
138     }
139     auto current = epptr();
140     for (std::streamsize i = 0; i < n; i++) {
141         *(s + i) = *(current + i);
142     }
143     setg(eback(), current + n, egptr());
144     return n;
145 }
146 
xsputn(const char * s,std::streamsize n)147 std::streamsize MemoryStreamBuf::xsputn(const char* s, std::streamsize n) {
148     const ptrdiff_t remaining = epptr() - pptr();
149     n = std::min(n, remaining);
150     if (n <= 0) {
151         return std::streamsize(0);
152     }
153     auto current = pptr();
154     for (std::streamsize i = 0; i < n; i++) {
155         *(current + i) = *(s + i);
156     }
157 
158     pbump(static_cast<int>(n));
159     return n;
160 }
161 
MemoryIStream(const std::shared_ptr<MemoryBuffer> & buffer)162 MemoryIStream::MemoryIStream(const std::shared_ptr<MemoryBuffer>& buffer) noexcept
163     : std::istream(nullptr), streambuf(buffer) {
164     rdbuf(&streambuf);
165 }
166 
MemoryOStream(const std::shared_ptr<MemoryBuffer> & buffer)167 MemoryOStream::MemoryOStream(const std::shared_ptr<MemoryBuffer>& buffer) noexcept
168     : std::ostream(nullptr), streambuf(buffer) {
169     rdbuf(&streambuf);
170 }
171 
172 } // namespace inmemoryfs
173