Coverage Report

Created: 2026-08-11 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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