Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2025 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 : #include "iodevice.h"
23 :
24 : #include <cstring>
25 :
26 : #ifndef NO_QT_SUPPORT
27 : #include <QByteArray>
28 : #endif
29 :
30 : #include "log.h"
31 :
32 : using namespace muse;
33 : using namespace muse::io;
34 :
35 7050 : bool IODevice::open(IODevice::OpenMode mode)
36 : {
37 7050 : if (isOpen()) {
38 0 : return true;
39 : }
40 :
41 7050 : bool ok = doOpen(mode);
42 7050 : if (ok) {
43 7041 : m_mode = mode;
44 7041 : m_pos = mode == Append ? dataSize() : 0;
45 : }
46 :
47 7050 : return ok;
48 : }
49 :
50 8535 : void IODevice::close()
51 : {
52 8535 : doClose();
53 8535 : m_mode = Unknown;
54 8535 : }
55 :
56 382154 : bool IODevice::isOpen() const
57 : {
58 382154 : return m_mode != OpenMode::Unknown;
59 : }
60 :
61 742 : IODevice::OpenMode IODevice::openMode() const
62 : {
63 742 : return m_mode;
64 : }
65 :
66 112688 : bool IODevice::isOpenModeReadable() const
67 : {
68 112688 : return m_mode == OpenMode::ReadOnly || m_mode == OpenMode::ReadWrite;
69 : }
70 :
71 160 : bool IODevice::isReadable() const
72 : {
73 160 : return isOpenModeReadable() && m_pos < size();
74 : }
75 :
76 7113 : bool IODevice::isOpenModeWriteable() const
77 : {
78 7113 : return m_mode == OpenMode::WriteOnly || m_mode == OpenMode::ReadWrite || m_mode == OpenMode::Append;
79 : }
80 :
81 9 : void IODevice::setError(int error, const std::string& errorString)
82 : {
83 9 : m_error = error;
84 9 : m_errorString = errorString;
85 9 : }
86 :
87 0 : bool IODevice::isWriteable() const
88 : {
89 0 : return isOpenModeWriteable();
90 : }
91 :
92 358124 : size_t IODevice::size() const
93 : {
94 358124 : IF_ASSERT_FAILED(isOpen()) {
95 0 : return 0;
96 : }
97 :
98 358124 : return dataSize();
99 : }
100 :
101 13179 : size_t IODevice::pos() const
102 : {
103 13179 : return m_pos;
104 : }
105 :
106 9182 : bool IODevice::seek(size_t pos)
107 : {
108 9182 : IF_ASSERT_FAILED(isOpen()) {
109 0 : return false;
110 : }
111 :
112 9182 : if (pos <= size()) {
113 9182 : m_pos = pos;
114 9182 : return true;
115 : }
116 :
117 0 : bool ok = resizeData(pos);
118 0 : if (ok) {
119 0 : m_pos = pos;
120 : }
121 :
122 0 : return ok;
123 : }
124 :
125 97395 : size_t IODevice::read(uint8_t* data, size_t len)
126 : {
127 97395 : IF_ASSERT_FAILED(isOpenModeReadable()) {
128 0 : return 0;
129 : }
130 :
131 97395 : IF_ASSERT_FAILED(m_pos <= size()) {
132 0 : return 0;
133 : }
134 :
135 97395 : if (m_pos == size()) {
136 0 : memset(data, 0, len);
137 0 : return 0;
138 : }
139 :
140 97395 : size_t left = size() - m_pos;
141 97395 : if (left < len) {
142 0 : len = left;
143 : }
144 :
145 97395 : std::memcpy(data, cdataOffsetted(), len);
146 :
147 97395 : m_pos += len;
148 97395 : return len;
149 : }
150 :
151 14957 : ByteArray IODevice::read(size_t len)
152 : {
153 14957 : IF_ASSERT_FAILED(isOpenModeReadable()) {
154 0 : return ByteArray();
155 : }
156 :
157 14957 : IF_ASSERT_FAILED(m_pos <= size()) {
158 0 : return ByteArray();
159 : }
160 :
161 14957 : if (m_pos == size()) {
162 191 : return ByteArray();
163 : }
164 :
165 14766 : size_t left = size() - m_pos;
166 14766 : if (left < len) {
167 1 : len = left;
168 : }
169 :
170 14766 : ByteArray result(cdataOffsetted(), len);
171 :
172 14766 : m_pos += len;
173 :
174 14766 : return result;
175 14766 : }
176 :
177 112161 : const uint8_t* IODevice::cdataOffsetted() const
178 : {
179 112161 : const uint8_t* d = rawData();
180 112161 : IF_ASSERT_FAILED(d) {
181 0 : return nullptr;
182 : }
183 112161 : return d + m_pos;
184 : }
185 :
186 4597 : ByteArray IODevice::readAll()
187 : {
188 4597 : return doReadAll();
189 : }
190 :
191 4424 : ByteArray IODevice::doReadAll()
192 : {
193 4424 : return read(size());
194 : }
195 :
196 0 : const uint8_t* IODevice::readData()
197 : {
198 0 : IF_ASSERT_FAILED(isOpen()) {
199 0 : return nullptr;
200 : }
201 0 : return rawData();
202 : }
203 :
204 7113 : size_t IODevice::write(const uint8_t* data, size_t len)
205 : {
206 7113 : IF_ASSERT_FAILED(isOpenModeWriteable()) {
207 0 : return 0;
208 : }
209 :
210 7113 : size_t left = size() - m_pos;
211 7113 : if (left < len) {
212 3806 : bool ok = resizeData(m_pos + len);
213 3806 : if (!ok) {
214 0 : LOGE() << "failed resize data";
215 0 : return 0;
216 : }
217 : }
218 :
219 7113 : len = writeData(data, len);
220 7113 : m_pos += len;
221 :
222 7113 : return len;
223 : }
224 :
225 125 : size_t IODevice::write(const ByteArray& ba)
226 : {
227 125 : return write(ba.constData(), ba.size());
228 : }
229 :
230 : #ifndef NO_QT_SUPPORT
231 836 : size_t IODevice::write(const QByteArray& ba)
232 : {
233 836 : return write(reinterpret_cast<const uint8_t*>(ba.constData()), ba.size());
234 : }
235 :
236 : #endif
237 :
238 879 : const std::string& IODevice::meta(const std::string& key) const
239 : {
240 879 : auto it = m_meta.find(key);
241 879 : if (it != m_meta.end()) {
242 879 : return it->second;
243 : }
244 :
245 0 : static const std::string dummyVal;
246 0 : return dummyVal;
247 : }
248 :
249 5441 : void IODevice::setMeta(const std::string& key, const std::string& val)
250 : {
251 5441 : m_meta[key] = val;
252 5441 : }
253 :
254 318 : bool IODevice::hasError() const
255 : {
256 318 : return m_error != 0;
257 : }
258 :
259 0 : int IODevice::error() const
260 : {
261 0 : return m_error;
262 : }
263 :
264 0 : const std::string& IODevice::errorString() const
265 : {
266 0 : return m_errorString;
267 : }
|