/src/exiv2/include/exiv2/basicio.hpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | |
3 | | #ifndef EXIV2_BASICIO_HPP |
4 | | #define EXIV2_BASICIO_HPP |
5 | | |
6 | | // ***************************************************************************** |
7 | | #include "exiv2lib_export.h" |
8 | | |
9 | | // included header files |
10 | | #include "config.h" |
11 | | #include "error.hpp" |
12 | | #include "types.hpp" |
13 | | |
14 | | // + standard includes |
15 | | #include <memory> |
16 | | |
17 | | // ***************************************************************************** |
18 | | // namespace extensions |
19 | | namespace Exiv2 { |
20 | | // ***************************************************************************** |
21 | | // class definitions |
22 | | |
23 | | /*! |
24 | | @brief An interface for simple binary IO. |
25 | | |
26 | | Designed to have semantics and names similar to those of C style FILE* |
27 | | operations. Subclasses should all behave the same so that they can be |
28 | | interchanged. |
29 | | */ |
30 | | class EXIV2API BasicIo { |
31 | | public: |
32 | | //! BasicIo auto_ptr type |
33 | | using UniquePtr = std::unique_ptr<BasicIo>; |
34 | | |
35 | | //! Seek starting positions |
36 | | enum Position { beg, cur, end }; |
37 | | |
38 | | //! @name Creators |
39 | | //@{ |
40 | 58.5k | BasicIo() = default; |
41 | | //! Destructor |
42 | | virtual ~BasicIo(); |
43 | | BasicIo(const BasicIo&) = delete; |
44 | | BasicIo& operator=(const BasicIo&) = delete; |
45 | | //@} |
46 | | |
47 | | //! @name Manipulators |
48 | | //@{ |
49 | | /*! |
50 | | @brief Open the IO source using the default access mode. The |
51 | | default mode should allow for reading and writing. |
52 | | |
53 | | This method can also be used to "reopen" an IO source which will |
54 | | flush any unwritten data and reset the IO position to the start. |
55 | | Subclasses may provide custom methods to allow for |
56 | | opening IO sources differently. |
57 | | |
58 | | @return 0 if successful;<BR> |
59 | | Nonzero if failure. |
60 | | */ |
61 | | virtual int open() = 0; |
62 | | |
63 | | /*! |
64 | | @brief Close the IO source. After closing a BasicIo instance can not |
65 | | be read or written. Closing flushes any unwritten data. It is |
66 | | safe to call close on a closed instance. |
67 | | @return 0 if successful;<BR> |
68 | | Nonzero if failure. |
69 | | */ |
70 | | virtual int close() = 0; |
71 | | /*! |
72 | | @brief Write data to the IO source. Current IO position is advanced |
73 | | by the number of bytes written. |
74 | | @param data Pointer to data. Data must be at least \em wcount |
75 | | bytes long |
76 | | @param wcount Number of bytes to be written. |
77 | | @return Number of bytes written to IO source successfully;<BR> |
78 | | 0 if failure; |
79 | | */ |
80 | | virtual size_t write(const byte* data, size_t wcount) = 0; |
81 | | /*! |
82 | | @brief Write data that is read from another BasicIo instance to |
83 | | the IO source. Current IO position is advanced by the number |
84 | | of bytes written. |
85 | | @param src Reference to another BasicIo instance. Reading start |
86 | | at the source's current IO position |
87 | | @return Number of bytes written to IO source successfully;<BR> |
88 | | 0 if failure; |
89 | | */ |
90 | | virtual size_t write(BasicIo& src) = 0; |
91 | | /*! |
92 | | @brief Write one byte to the IO source. Current IO position is |
93 | | advanced by one byte. |
94 | | @param data The single byte to be written. |
95 | | @return The value of the byte written if successful;<BR> |
96 | | EOF if failure; |
97 | | */ |
98 | | virtual int putb(byte data) = 0; |
99 | | /*! |
100 | | @brief Read data from the IO source. Reading starts at the current |
101 | | IO position and the position is advanced by the number of bytes |
102 | | read. |
103 | | @param rcount Maximum number of bytes to read. Fewer bytes may be |
104 | | read if \em rcount bytes are not available. |
105 | | @return DataBuf instance containing the bytes read. Use the |
106 | | DataBuf::size_ member to find the number of bytes read. |
107 | | DataBuf::size_ will be 0 on failure. |
108 | | */ |
109 | | virtual DataBuf read(size_t rcount) = 0; |
110 | | /*! |
111 | | @brief Read data from the IO source. Reading starts at the current |
112 | | IO position and the position is advanced by the number of bytes |
113 | | read. |
114 | | @param buf Pointer to a block of memory into which the read data |
115 | | is stored. The memory block must be at least \em rcount bytes |
116 | | long. |
117 | | @param rcount Maximum number of bytes to read. Fewer bytes may be |
118 | | read if \em rcount bytes are not available. |
119 | | @return Number of bytes read from IO source successfully;<BR> |
120 | | 0 if failure; |
121 | | */ |
122 | | virtual size_t read(byte* buf, size_t rcount) = 0; |
123 | | /*! |
124 | | @brief Safe version of `read()` that checks for errors and throws |
125 | | an exception if the read was unsuccessful. |
126 | | @param buf Pointer to a block of memory into which the read data |
127 | | is stored. The memory block must be at least \em rcount bytes |
128 | | long. |
129 | | @param rcount Maximum number of bytes to read. Fewer bytes may be |
130 | | read if \em rcount bytes are not available. |
131 | | @param err Error code to use if an exception is thrown. |
132 | | */ |
133 | | void readOrThrow(byte* buf, size_t rcount, ErrorCode err = ErrorCode::kerCorruptedMetadata); |
134 | | /*! |
135 | | @brief Read one byte from the IO source. Current IO position is |
136 | | advanced by one byte. |
137 | | @return The byte read from the IO source if successful;<BR> |
138 | | EOF if failure; |
139 | | */ |
140 | | virtual int getb() = 0; |
141 | | /*! |
142 | | @brief Remove all data from this object's IO source and then transfer |
143 | | data from the \em src BasicIo object into this object. |
144 | | |
145 | | The source object is invalidated by this operation and should not be |
146 | | used after this method returns. This method exists primarily to |
147 | | be used with the BasicIo::temporary() method. |
148 | | |
149 | | @param src Reference to another BasicIo instance. The entire contents |
150 | | of src are transferred to this object. The \em src object is |
151 | | invalidated by the method. |
152 | | @throw Error In case of failure |
153 | | */ |
154 | | virtual void transfer(BasicIo& src) = 0; |
155 | | /*! |
156 | | @brief Move the current IO position. |
157 | | @param offset Number of bytes to move the position relative |
158 | | to the starting position specified by \em pos |
159 | | @param pos Position from which the seek should start |
160 | | @return 0 if successful;<BR> |
161 | | Nonzero if failure; |
162 | | */ |
163 | | virtual int seek(int64_t offset, Position pos) = 0; |
164 | | |
165 | | /*! |
166 | | @brief Safe version of `seek()` that checks for errors and throws |
167 | | an exception if the seek was unsuccessful. |
168 | | @param offset Number of bytes to move the position relative |
169 | | to the starting position specified by \em pos |
170 | | @param pos Position from which the seek should start |
171 | | @param err Error code to use if an exception is thrown. |
172 | | */ |
173 | | void seekOrThrow(int64_t offset, Position pos, ErrorCode err); |
174 | | |
175 | | /*! |
176 | | @brief Direct access to the IO data. For files, this is done by |
177 | | mapping the file into the process's address space; for memory |
178 | | blocks, this allows direct access to the memory block. |
179 | | @param isWriteable Set to true if the mapped area should be writeable |
180 | | (default is false). |
181 | | @return A pointer to the mapped area. |
182 | | @throw Error In case of failure. |
183 | | */ |
184 | | virtual byte* mmap(bool isWriteable = false) = 0; |
185 | | /*! |
186 | | @brief Remove a mapping established with mmap(). If the mapped area |
187 | | is writeable, this ensures that changes are written back. |
188 | | @return 0 if successful;<BR> |
189 | | Nonzero if failure; |
190 | | */ |
191 | | virtual int munmap() = 0; |
192 | | |
193 | | //@} |
194 | | |
195 | | //! @name Accessors |
196 | | //@{ |
197 | | /*! |
198 | | @brief Get the current IO position. |
199 | | @return Offset from the start of IO |
200 | | */ |
201 | | [[nodiscard]] virtual size_t tell() const = 0; |
202 | | /*! |
203 | | @brief Get the current size of the IO source in bytes. |
204 | | @return Size of the IO source in bytes;<BR> |
205 | | -1 if failure; |
206 | | */ |
207 | | [[nodiscard]] virtual size_t size() const = 0; |
208 | | //! Returns true if the IO source is open, otherwise false. |
209 | | [[nodiscard]] virtual bool isopen() const = 0; |
210 | | //! Returns 0 if the IO source is in a valid state, otherwise nonzero. |
211 | | [[nodiscard]] virtual int error() const = 0; |
212 | | //! Returns true if the IO position has reached the end, otherwise false. |
213 | | [[nodiscard]] virtual bool eof() const = 0; |
214 | | /*! |
215 | | @brief Return the path to the IO resource. Often used to form |
216 | | comprehensive error messages where only a BasicIo instance is |
217 | | available. |
218 | | */ |
219 | | [[nodiscard]] virtual const std::string& path() const noexcept = 0; |
220 | | |
221 | | /*! |
222 | | @brief Mark all the bNone blocks to bKnow. This avoids allocating memory |
223 | | for parts of the file that contain image-date (non-metadata/pixel data) |
224 | | |
225 | | @note This method should be only called after the concerned data (metadata) |
226 | | are all downloaded from the remote file to memory. |
227 | | */ |
228 | | virtual void populateFakeData() = 0; |
229 | | |
230 | | /*! |
231 | | @brief this is allocated and populated by mmap() |
232 | | */ |
233 | | byte* bigBlock_{}; |
234 | | |
235 | | //@} |
236 | | }; // class BasicIo |
237 | | |
238 | | /*! |
239 | | @brief Utility class that closes a BasicIo instance upon destruction. |
240 | | Meant to be used as a stack variable in functions that need to |
241 | | ensure BasicIo instances get closed. Useful when functions return |
242 | | errors from many locations. |
243 | | */ |
244 | | class EXIV2API IoCloser { |
245 | | public: |
246 | | //! @name Creators |
247 | | //@{ |
248 | | //! Constructor, takes a BasicIo reference |
249 | 115k | explicit IoCloser(BasicIo& bio) : bio_(bio) { |
250 | 115k | } |
251 | | //! Destructor, closes the BasicIo reference |
252 | 115k | virtual ~IoCloser() { |
253 | 115k | close(); |
254 | 115k | } |
255 | | //@} |
256 | | |
257 | | //! @name Manipulators |
258 | | //@{ |
259 | | //! Close the BasicIo if it is open |
260 | 115k | void close() { |
261 | 115k | if (bio_.isopen()) |
262 | 115k | bio_.close(); |
263 | 115k | } |
264 | | //@} |
265 | | |
266 | | // DATA |
267 | | //! The BasicIo reference |
268 | | BasicIo& bio_; |
269 | | }; // class IoCloser |
270 | | |
271 | | #ifdef EXV_ENABLE_FILESYSTEM |
272 | | /*! |
273 | | @brief Provides binary file IO by implementing the BasicIo |
274 | | interface. |
275 | | */ |
276 | | class EXIV2API FileIo : public BasicIo { |
277 | | public: |
278 | | //! @name Creators |
279 | | //@{ |
280 | | /*! |
281 | | @brief Constructor that accepts the file path on which IO will be |
282 | | performed. The constructor does not open the file, and |
283 | | therefore never fails. |
284 | | @param path The full path of a file |
285 | | */ |
286 | | explicit FileIo(const std::string& path); |
287 | | #ifdef _WIN32 |
288 | | explicit FileIo(const std::wstring& path); |
289 | | #endif |
290 | | |
291 | | //! Destructor. Flushes and closes an open file. |
292 | | ~FileIo() override; |
293 | | //@} |
294 | | |
295 | | //! @name Manipulators |
296 | | //@{ |
297 | | /*! |
298 | | @brief Open the file using the specified mode. |
299 | | |
300 | | This method can also be used to "reopen" a file which will flush any |
301 | | unwritten data and reset the IO position to the start. Although |
302 | | files can be opened in binary or text mode, this class has |
303 | | only been tested carefully in binary mode. |
304 | | |
305 | | @param mode Specified that type of access allowed on the file. |
306 | | Valid values match those of the C fopen command exactly. |
307 | | @return 0 if successful;<BR> |
308 | | Nonzero if failure. |
309 | | */ |
310 | | int open(const std::string& mode); |
311 | | /*! |
312 | | @brief Open the file using the default access mode of "rb". |
313 | | This method can also be used to "reopen" a file which will flush |
314 | | any unwritten data and reset the IO position to the start. |
315 | | @return 0 if successful;<BR> |
316 | | Nonzero if failure. |
317 | | */ |
318 | | int open() override; |
319 | | /*! |
320 | | @brief Flush and unwritten data and close the file . It is |
321 | | safe to call close on an already closed instance. |
322 | | @return 0 if successful;<BR> |
323 | | Nonzero if failure; |
324 | | */ |
325 | | int close() override; |
326 | | /*! |
327 | | @brief Write data to the file. The file position is advanced |
328 | | by the number of bytes written. |
329 | | @param data Pointer to data. Data must be at least \em wcount |
330 | | bytes long |
331 | | @param wcount Number of bytes to be written. |
332 | | @return Number of bytes written to the file successfully;<BR> |
333 | | 0 if failure; |
334 | | */ |
335 | | size_t write(const byte* data, size_t wcount) override; |
336 | | /*! |
337 | | @brief Write data that is read from another BasicIo instance to |
338 | | the file. The file position is advanced by the number |
339 | | of bytes written. |
340 | | @param src Reference to another BasicIo instance. Reading start |
341 | | at the source's current IO position |
342 | | @return Number of bytes written to the file successfully;<BR> |
343 | | 0 if failure; |
344 | | */ |
345 | | size_t write(BasicIo& src) override; |
346 | | /*! |
347 | | @brief Write one byte to the file. The file position is |
348 | | advanced by one byte. |
349 | | @param data The single byte to be written. |
350 | | @return The value of the byte written if successful;<BR> |
351 | | EOF if failure; |
352 | | */ |
353 | | int putb(byte data) override; |
354 | | /*! |
355 | | @brief Read data from the file. Reading starts at the current |
356 | | file position and the position is advanced by the number of |
357 | | bytes read. |
358 | | @param rcount Maximum number of bytes to read. Fewer bytes may be |
359 | | read if \em rcount bytes are not available. |
360 | | @return DataBuf instance containing the bytes read. Use the |
361 | | DataBuf::size_ member to find the number of bytes read. |
362 | | DataBuf::size_ will be 0 on failure. |
363 | | */ |
364 | | DataBuf read(size_t rcount) override; |
365 | | /*! |
366 | | @brief Read data from the file. Reading starts at the current |
367 | | file position and the position is advanced by the number of |
368 | | bytes read. |
369 | | @param buf Pointer to a block of memory into which the read data |
370 | | is stored. The memory block must be at least \em rcount bytes |
371 | | long. |
372 | | @param rcount Maximum number of bytes to read. Fewer bytes may be |
373 | | read if \em rcount bytes are not available. |
374 | | @return Number of bytes read from the file successfully;<BR> |
375 | | 0 if failure; |
376 | | */ |
377 | | size_t read(byte* buf, size_t rcount) override; |
378 | | /*! |
379 | | @brief Read one byte from the file. The file position is |
380 | | advanced by one byte. |
381 | | @return The byte read from the file if successful;<BR> |
382 | | EOF if failure; |
383 | | */ |
384 | | int getb() override; |
385 | | /*! |
386 | | @brief Remove the contents of the file and then transfer data from |
387 | | the \em src BasicIo object into the empty file. |
388 | | |
389 | | This method is optimized to simply rename the source file if the |
390 | | source object is another FileIo instance. The source BasicIo object |
391 | | is invalidated by this operation and should not be used after this |
392 | | method returns. This method exists primarily to be used with |
393 | | the BasicIo::temporary() method. |
394 | | |
395 | | @note If the caller doesn't have permissions to write to the file, |
396 | | an exception is raised and \em src is deleted. |
397 | | |
398 | | @param src Reference to another BasicIo instance. The entire contents |
399 | | of src are transferred to this object. The \em src object is |
400 | | invalidated by the method. |
401 | | @throw Error In case of failure |
402 | | */ |
403 | | void transfer(BasicIo& src) override; |
404 | | |
405 | | int seek(int64_t offset, Position pos) override; |
406 | | |
407 | | /*! |
408 | | @brief Map the file into the process's address space. The file must be |
409 | | open before mmap() is called. If the mapped area is writeable, |
410 | | changes may not be written back to the underlying file until |
411 | | munmap() is called. The pointer is valid only as long as the |
412 | | FileIo object exists. |
413 | | @param isWriteable Set to true if the mapped area should be writeable |
414 | | (default is false). |
415 | | @return A pointer to the mapped area. |
416 | | @throw Error In case of failure. |
417 | | */ |
418 | | byte* mmap(bool isWriteable = false) override; |
419 | | /*! |
420 | | @brief Remove a mapping established with mmap(). If the mapped area is |
421 | | writeable, this ensures that changes are written back to the |
422 | | underlying file. |
423 | | @return 0 if successful;<BR> |
424 | | Nonzero if failure; |
425 | | */ |
426 | | int munmap() override; |
427 | | /*! |
428 | | @brief close the file source and set a new path. |
429 | | */ |
430 | | virtual void setPath(const std::string& path); |
431 | | #ifdef _WIN32 |
432 | | virtual void setPath(const std::wstring& path); |
433 | | #endif |
434 | | |
435 | | //@} |
436 | | //! @name Accessors |
437 | | //@{ |
438 | | /*! |
439 | | @brief Get the current file position. |
440 | | @return Offset from the start of the file |
441 | | */ |
442 | | [[nodiscard]] size_t tell() const override; |
443 | | /*! |
444 | | @brief Flush any buffered writes and get the current file size |
445 | | in bytes. |
446 | | @return Size of the file in bytes;<BR> |
447 | | -1 if failure; |
448 | | */ |
449 | | [[nodiscard]] size_t size() const override; |
450 | | //! Returns true if the file is open, otherwise false. |
451 | | [[nodiscard]] bool isopen() const override; |
452 | | //! Returns 0 if the file is in a valid state, otherwise nonzero. |
453 | | [[nodiscard]] int error() const override; |
454 | | //! Returns true if the file position has reached the end, otherwise false. |
455 | | [[nodiscard]] bool eof() const override; |
456 | | //! Returns the path of the file |
457 | | [[nodiscard]] const std::string& path() const noexcept override; |
458 | | |
459 | | /*! |
460 | | @brief Mark all the bNone blocks to bKnow. This avoids allocating memory |
461 | | for parts of the file that contain image-date (non-metadata/pixel data) |
462 | | |
463 | | @note This method should be only called after the concerned data (metadata) |
464 | | are all downloaded from the remote file to memory. |
465 | | */ |
466 | | void populateFakeData() override; |
467 | | //@} |
468 | | |
469 | | private: |
470 | | // Pimpl idiom |
471 | | class Impl; |
472 | | std::unique_ptr<Impl> p_; |
473 | | |
474 | | }; // class FileIo |
475 | | #endif |
476 | | |
477 | | /*! |
478 | | @brief Provides binary IO on blocks of memory by implementing the BasicIo |
479 | | interface. A copy-on-write implementation ensures that the data passed |
480 | | in is only copied when necessary, i.e., as soon as data is written to |
481 | | the MemIo. The original data is only used for reading. If writes are |
482 | | performed, the changed data can be retrieved using the read methods |
483 | | (since the data used in construction is never modified). |
484 | | |
485 | | @note If read only usage of this class is common, it might be worth |
486 | | creating a specialized readonly class or changing this one to |
487 | | have a readonly mode. |
488 | | */ |
489 | | class EXIV2API MemIo : public BasicIo { |
490 | | public: |
491 | | //! @name Creators |
492 | | //@{ |
493 | | //! Default constructor that results in an empty object |
494 | | MemIo(); |
495 | | /*! |
496 | | @brief Constructor that accepts a block of memory. A copy-on-write |
497 | | algorithm allows read operations directly from the original data |
498 | | and will create a copy of the buffer on the first write operation. |
499 | | @param data Pointer to data. Data must be at least \em size bytes long |
500 | | @param size Number of bytes to copy. |
501 | | */ |
502 | | MemIo(const byte* data, size_t size); |
503 | | //! Destructor. Releases all managed memory |
504 | | ~MemIo() override; |
505 | | //@} |
506 | | |
507 | | //! @name Manipulators |
508 | | //@{ |
509 | | /*! |
510 | | @brief Memory IO is always open for reading and writing. This method |
511 | | therefore only resets the IO position to the start. |
512 | | |
513 | | @return 0 |
514 | | */ |
515 | | int open() override; |
516 | | /*! |
517 | | @brief Does nothing on MemIo objects. |
518 | | @return 0 |
519 | | */ |
520 | | int close() override; |
521 | | /*! |
522 | | @brief Write data to the memory block. If needed, the size of the |
523 | | internal memory block is expanded. The IO position is advanced |
524 | | by the number of bytes written. |
525 | | @param data Pointer to data. Data must be at least \em wcount |
526 | | bytes long |
527 | | @param wcount Number of bytes to be written. |
528 | | @return Number of bytes written to the memory block successfully;<BR> |
529 | | 0 if failure; |
530 | | */ |
531 | | size_t write(const byte* data, size_t wcount) override; |
532 | | /*! |
533 | | @brief Write data that is read from another BasicIo instance to |
534 | | the memory block. If needed, the size of the internal memory |
535 | | block is expanded. The IO position is advanced by the number |
536 | | of bytes written. |
537 | | @param src Reference to another BasicIo instance. Reading start |
538 | | at the source's current IO position |
539 | | @return Number of bytes written to the memory block successfully;<BR> |
540 | | 0 if failure; |
541 | | */ |
542 | | size_t write(BasicIo& src) override; |
543 | | /*! |
544 | | @brief Write one byte to the memory block. The IO position is |
545 | | advanced by one byte. |
546 | | @param data The single byte to be written. |
547 | | @return The value of the byte written if successful;<BR> |
548 | | EOF if failure; |
549 | | */ |
550 | | int putb(byte data) override; |
551 | | /*! |
552 | | @brief Read data from the memory block. Reading starts at the current |
553 | | IO position and the position is advanced by the number of |
554 | | bytes read. |
555 | | @param rcount Maximum number of bytes to read. Fewer bytes may be |
556 | | read if \em rcount bytes are not available. |
557 | | @return DataBuf instance containing the bytes read. Use the |
558 | | DataBuf::size_ member to find the number of bytes read. |
559 | | DataBuf::size_ will be 0 on failure. |
560 | | */ |
561 | | DataBuf read(size_t rcount) override; |
562 | | /*! |
563 | | @brief Read data from the memory block. Reading starts at the current |
564 | | IO position and the position is advanced by the number of |
565 | | bytes read. |
566 | | @param buf Pointer to a block of memory into which the read data |
567 | | is stored. The memory block must be at least \em rcount bytes |
568 | | long. |
569 | | @param rcount Maximum number of bytes to read. Fewer bytes may be |
570 | | read if \em rcount bytes are not available. |
571 | | @return Number of bytes read from the memory block successfully;<BR> |
572 | | 0 if failure; |
573 | | */ |
574 | | size_t read(byte* buf, size_t rcount) override; |
575 | | /*! |
576 | | @brief Read one byte from the memory block. The IO position is |
577 | | advanced by one byte. |
578 | | @return The byte read from the memory block if successful;<BR> |
579 | | EOF if failure; |
580 | | */ |
581 | | int getb() override; |
582 | | /*! |
583 | | @brief Clear the memory block and then transfer data from |
584 | | the \em src BasicIo object into a new block of memory. |
585 | | |
586 | | This method is optimized to simply swap memory block if the source |
587 | | object is another MemIo instance. The source BasicIo instance |
588 | | is invalidated by this operation and should not be used after this |
589 | | method returns. This method exists primarily to be used with |
590 | | the BasicIo::temporary() method. |
591 | | |
592 | | @param src Reference to another BasicIo instance. The entire contents |
593 | | of src are transferred to this object. The \em src object is |
594 | | invalidated by the method. |
595 | | @throw Error In case of failure |
596 | | */ |
597 | | void transfer(BasicIo& src) override; |
598 | | |
599 | | int seek(int64_t offset, Position pos) override; |
600 | | |
601 | | /*! |
602 | | @brief Allow direct access to the underlying data buffer. The buffer |
603 | | is not protected against write access in any way, the argument |
604 | | is ignored. |
605 | | @note The application must ensure that the memory pointed to by the |
606 | | returned pointer remains valid and allocated as long as the |
607 | | MemIo object exists. |
608 | | */ |
609 | | byte* mmap(bool /*isWriteable*/ = false) override; |
610 | | int munmap() override; |
611 | | //@} |
612 | | |
613 | | //! @name Accessors |
614 | | //@{ |
615 | | /*! |
616 | | @brief Get the current IO position. |
617 | | @return Offset from the start of the memory block |
618 | | */ |
619 | | [[nodiscard]] size_t tell() const override; |
620 | | /*! |
621 | | @brief Get the current memory buffer size in bytes. |
622 | | @return Size of the in memory data in bytes;<BR> |
623 | | -1 if failure; |
624 | | */ |
625 | | [[nodiscard]] size_t size() const override; |
626 | | //! Always returns true |
627 | | [[nodiscard]] bool isopen() const override; |
628 | | //! Always returns 0 |
629 | | [[nodiscard]] int error() const override; |
630 | | //! Returns true if the IO position has reached the end, otherwise false. |
631 | | [[nodiscard]] bool eof() const override; |
632 | | //! Returns a dummy path, indicating that memory access is used |
633 | | [[nodiscard]] const std::string& path() const noexcept override; |
634 | | |
635 | | /*! |
636 | | @brief Mark all the bNone blocks to bKnow. This avoids allocating memory |
637 | | for parts of the file that contain image-date (non-metadata/pixel data) |
638 | | |
639 | | @note This method should be only called after the concerned data (metadata) |
640 | | are all downloaded from the remote file to memory. |
641 | | */ |
642 | | void populateFakeData() override; |
643 | | |
644 | | //@} |
645 | | |
646 | | private: |
647 | | // Pimpl idiom |
648 | | class Impl; |
649 | | std::unique_ptr<Impl> p_; |
650 | | |
651 | | }; // class MemIo |
652 | | |
653 | | /*! |
654 | | @brief Provides binary IO for the data from stdin and data uri path. |
655 | | */ |
656 | | #ifdef EXV_ENABLE_FILESYSTEM |
657 | | class EXIV2API XPathIo : public FileIo { |
658 | | public: |
659 | | /*! |
660 | | @brief The extension of the temporary file which is created when getting input data |
661 | | to read metadata. This file will be deleted in destructor. |
662 | | */ |
663 | | static constexpr auto TEMP_FILE_EXT = ".exiv2_temp"; |
664 | | /*! |
665 | | @brief The extension of the generated file which is created when getting input data |
666 | | to add or modify the metadata. |
667 | | */ |
668 | | static constexpr auto GEN_FILE_EXT = ".exiv2"; |
669 | | |
670 | | //! @name Creators |
671 | | //@{ |
672 | | //! Default constructor that reads data from stdin/data uri path and writes them to the temp file. |
673 | | explicit XPathIo(const std::string& orgPath); |
674 | | |
675 | | //! Destructor. Releases all managed memory and removes the temp file. |
676 | | ~XPathIo() override; |
677 | | //@} |
678 | | |
679 | | //! @name Manipulators |
680 | | //@{ |
681 | | /*! |
682 | | @brief Change the name of the temp file and make it untemporary before |
683 | | calling the method of superclass FileIo::transfer. |
684 | | */ |
685 | | void transfer(BasicIo& src) override; |
686 | | |
687 | | //@} |
688 | | |
689 | | //! @name Static methods |
690 | | //@{ |
691 | | /*! |
692 | | @brief Read the data from stdin/data uri path and write them to the file. |
693 | | @param orgPath It equals "-" if the input data's from stdin. Otherwise, it's data uri path. |
694 | | @return the name of the new file. |
695 | | @throw Error if it fails. |
696 | | */ |
697 | | static std::string writeDataToFile(const std::string& orgPath); |
698 | | //@} |
699 | | |
700 | | private: |
701 | | // True if the file is a temporary file and it should be deleted in destructor. |
702 | | bool isTemp_{true}; |
703 | | std::string tempFilePath_; |
704 | | }; // class XPathIo |
705 | | #endif |
706 | | |
707 | | /*! |
708 | | @brief Provides remote binary file IO by implementing the BasicIo interface. This is an |
709 | | abstract class. The logics for remote access are implemented in HttpIo, CurlIo, SshIo which |
710 | | are the derived classes of RemoteIo. |
711 | | */ |
712 | | class EXIV2API RemoteIo : public BasicIo { |
713 | | public: |
714 | | //! Destructor. Releases all managed memory. |
715 | | RemoteIo(); |
716 | | ~RemoteIo() override; |
717 | | //@} |
718 | | |
719 | | //! @name Manipulators |
720 | | //@{ |
721 | | /*! |
722 | | @brief Connect to the remote server, get the size of the remote file and |
723 | | allocate the array of blocksMap. |
724 | | |
725 | | If the blocksMap is already allocated (this method has been called before), |
726 | | it just reset IO position to the start and does not flush the old data. |
727 | | @return 0 if successful;<BR> |
728 | | Nonzero if failure. |
729 | | */ |
730 | | int open() override; |
731 | | |
732 | | /*! |
733 | | @brief Reset the IO position to the start. It does not release the data. |
734 | | @return 0 if successful;<BR> |
735 | | Nonzero if failure. |
736 | | */ |
737 | | int close() override; |
738 | | /*! |
739 | | @brief Not support this method. |
740 | | @return 0 means failure |
741 | | */ |
742 | | size_t write(const byte* data, size_t wcount) override; |
743 | | /*! |
744 | | @brief Write data that is read from another BasicIo instance to the remote file. |
745 | | |
746 | | The write access is done in an efficient way. It only sends the range of different |
747 | | bytes between the current data and BasicIo instance to the remote machine. |
748 | | |
749 | | @param src Reference to another BasicIo instance. Reading start |
750 | | at the source's current IO position |
751 | | @return The size of BasicIo instance;<BR> |
752 | | 0 if failure; |
753 | | @throw Error In case of failure |
754 | | |
755 | | @note The write access is only supported by http, https, ssh. |
756 | | */ |
757 | | size_t write(BasicIo& src) override; |
758 | | |
759 | | /*! |
760 | | @brief Not support |
761 | | @return 0 means failure |
762 | | */ |
763 | | int putb(byte data) override; |
764 | | /*! |
765 | | @brief Read data from the memory blocks. Reading starts at the current |
766 | | IO position and the position is advanced by the number of |
767 | | bytes read. |
768 | | If the memory blocks are not populated (False), it will connect to server |
769 | | and populate the data to memory blocks. |
770 | | @param rcount Maximum number of bytes to read. Fewer bytes may be |
771 | | read if \em rcount bytes are not available. |
772 | | @return DataBuf instance containing the bytes read. Use the |
773 | | DataBuf::size_ member to find the number of bytes read. |
774 | | DataBuf::size_ will be 0 on failure. |
775 | | */ |
776 | | DataBuf read(size_t rcount) override; |
777 | | /*! |
778 | | @brief Read data from the memory blocks. Reading starts at the current |
779 | | IO position and the position is advanced by the number of |
780 | | bytes read. |
781 | | If the memory blocks are not populated (!= bMemory), it will connect to server |
782 | | and populate the data to memory blocks. |
783 | | @param buf Pointer to a block of memory into which the read data |
784 | | is stored. The memory block must be at least \em rcount bytes |
785 | | long. |
786 | | @param rcount Maximum number of bytes to read. Fewer bytes may be |
787 | | read if \em rcount bytes are not available. |
788 | | @return Number of bytes read from the memory block successfully;<BR> |
789 | | 0 if failure; |
790 | | */ |
791 | | size_t read(byte* buf, size_t rcount) override; |
792 | | /*! |
793 | | @brief Read one byte from the memory blocks. The IO position is |
794 | | advanced by one byte. |
795 | | If the memory block is not populated (!= bMemory), it will connect to server |
796 | | and populate the data to the memory block. |
797 | | @return The byte read from the memory block if successful;<BR> |
798 | | EOF if failure; |
799 | | */ |
800 | | int getb() override; |
801 | | /*! |
802 | | @brief Remove the contents of the file and then transfer data from |
803 | | the \em src BasicIo object into the empty file. |
804 | | |
805 | | The write access is done in an efficient way. It only sends the range of different |
806 | | bytes between the current data and BasicIo instance to the remote machine. |
807 | | |
808 | | @param src Reference to another BasicIo instance. The entire contents |
809 | | of src are transferred to this object. The \em src object is |
810 | | invalidated by the method. |
811 | | @throw Error In case of failure |
812 | | |
813 | | @note The write access is only supported by http, https, ssh. |
814 | | */ |
815 | | void transfer(BasicIo& src) override; |
816 | | |
817 | | int seek(int64_t offset, Position pos) override; |
818 | | |
819 | | /*! |
820 | | @brief Not support |
821 | | @return NULL |
822 | | */ |
823 | | byte* mmap(bool /*isWriteable*/ = false) override; |
824 | | /*! |
825 | | @brief Not support |
826 | | @return 0 |
827 | | */ |
828 | | int munmap() override; |
829 | | //@} |
830 | | //! @name Accessors |
831 | | //@{ |
832 | | /*! |
833 | | @brief Get the current IO position. |
834 | | @return Offset from the start of the memory block |
835 | | */ |
836 | | [[nodiscard]] size_t tell() const override; |
837 | | /*! |
838 | | @brief Get the current memory buffer size in bytes. |
839 | | @return Size of the in memory data in bytes;<BR> |
840 | | -1 if failure; |
841 | | */ |
842 | | [[nodiscard]] size_t size() const override; |
843 | | //! Returns true if the memory area is allocated. |
844 | | [[nodiscard]] bool isopen() const override; |
845 | | //! Always returns 0 |
846 | | [[nodiscard]] int error() const override; |
847 | | //! Returns true if the IO position has reached the end, otherwise false. |
848 | | [[nodiscard]] bool eof() const override; |
849 | | //! Returns the URL of the file. |
850 | | [[nodiscard]] const std::string& path() const noexcept override; |
851 | | |
852 | | /*! |
853 | | @brief Mark all the bNone blocks to bKnow. This avoids allocating memory |
854 | | for parts of the file that contain image-date (non-metadata/pixel data) |
855 | | |
856 | | @note This method should be only called after the concerned data (metadata) |
857 | | are all downloaded from the remote file to memory. |
858 | | */ |
859 | | void populateFakeData() override; |
860 | | |
861 | | //@} |
862 | | |
863 | | protected: |
864 | | // Pimpl idiom |
865 | | class Impl; |
866 | | //! Pointer to implementation |
867 | | std::unique_ptr<Impl> p_; |
868 | | }; // class RemoteIo |
869 | | |
870 | | /*! |
871 | | @brief Provides the http read/write access for the RemoteIo. |
872 | | */ |
873 | | class EXIV2API HttpIo : public RemoteIo { |
874 | | public: |
875 | | //! @name Creators |
876 | | //@{ |
877 | | /*! |
878 | | @brief Constructor that accepts the http URL on which IO will be |
879 | | performed. The constructor does not open the file, and |
880 | | therefore never fails. |
881 | | @param url The full path of url |
882 | | @param blockSize the size of the memory block. The file content is |
883 | | divided into the memory blocks. These blocks are populated |
884 | | on demand from the server, so it avoids copying the complete file. |
885 | | */ |
886 | | explicit HttpIo(const std::string& url, size_t blockSize = 1024); |
887 | | ~HttpIo() override; |
888 | | |
889 | | private: |
890 | | // Pimpl idiom |
891 | | class HttpImpl; |
892 | | }; |
893 | | |
894 | | #ifdef EXV_USE_CURL |
895 | | /*! |
896 | | @brief Provides the http, https read/write access and ftp read access for the RemoteIo. |
897 | | This class is based on libcurl. |
898 | | */ |
899 | | class EXIV2API CurlIo : public RemoteIo { |
900 | | public: |
901 | | //! @name Creators |
902 | | //@{ |
903 | | /*! |
904 | | @brief Constructor that accepts the URL on which IO will be |
905 | | performed. |
906 | | @param url The full path of url |
907 | | @param blockSize the size of the memory block. The file content is |
908 | | divided into the memory blocks. These blocks are populated |
909 | | on demand from the server, so it avoids copying the complete file. |
910 | | @throw Error if it is unable to init curl pointer. |
911 | | */ |
912 | | explicit CurlIo(const std::string& url, size_t blockSize = 0); |
913 | | |
914 | | /*! |
915 | | @brief Write access is only available for some protocols. This method |
916 | | will call RemoteIo::write(const byte* data, long wcount) if the write |
917 | | access is available for the protocol. Otherwise, it throws the Error. |
918 | | */ |
919 | | size_t write(const byte* data, size_t wcount) override; |
920 | | /*! |
921 | | @brief Write access is only available for some protocols. This method |
922 | | will call RemoteIo::write(BasicIo& src) if the write access is available |
923 | | for the protocol. Otherwise, it throws the Error. |
924 | | */ |
925 | | size_t write(BasicIo& src) override; |
926 | | |
927 | | protected: |
928 | | // Pimpl idiom |
929 | | class CurlImpl; |
930 | | }; |
931 | | #endif |
932 | | |
933 | | // ***************************************************************************** |
934 | | // template, inline and free functions |
935 | | |
936 | | /*! |
937 | | @brief Read file \em path into a DataBuf, which is returned. |
938 | | @return Buffer containing the file. |
939 | | @throw Error In case of failure. |
940 | | */ |
941 | | EXIV2API DataBuf readFile(const std::string& path); |
942 | | /*! |
943 | | @brief Write DataBuf \em buf to file \em path. |
944 | | @return Return the number of bytes written. |
945 | | @throw Error In case of failure. |
946 | | */ |
947 | | EXIV2API size_t writeFile(const DataBuf& buf, const std::string& path); |
948 | | #ifdef EXV_USE_CURL |
949 | | /*! |
950 | | @brief The callback function is called by libcurl to write the data |
951 | | */ |
952 | | EXIV2API size_t curlWriter(char* data, size_t size, size_t nmemb, std::string* writerData); |
953 | | #endif |
954 | | } // namespace Exiv2 |
955 | | #endif // EXIV2_BASICIO_HPP |