Coverage Report

Created: 2026-01-25 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/exiv2/include/exiv2/value.hpp
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
#ifndef EXIV2_VALUE_HPP
4
#define EXIV2_VALUE_HPP
5
6
// *****************************************************************************
7
#include "exiv2lib_export.h"
8
9
// included header files
10
#include "types.hpp"
11
12
// + standard includes
13
#include <cmath>
14
#include <cstring>
15
#include <iomanip>
16
#include <map>
17
#include <memory>
18
19
// *****************************************************************************
20
// namespace extensions
21
namespace Exiv2 {
22
// *****************************************************************************
23
// class definitions
24
25
/*!
26
  @brief Common interface for all types of values used with metadata.
27
28
  The interface provides a uniform way to access values independent of
29
  their actual C++ type for simple tasks like reading the values from a
30
  string or data buffer.  For other tasks, like modifying values you may
31
  need to downcast it to a specific subclass to access its interface.
32
 */
33
class EXIV2API Value {
34
 public:
35
  //! Shortcut for a %Value auto pointer.
36
  using UniquePtr = std::unique_ptr<Value>;
37
38
  //! @name Creators
39
  //@{
40
  //! Constructor, taking a type id to initialize the base class with
41
  explicit Value(TypeId typeId);
42
  //! Virtual destructor.
43
2.04M
  virtual ~Value() = default;
44
  //@}
45
46
  //! @name Manipulators
47
  //@{
48
49
  /// @brief Read the value from a character buffer.
50
  /// @param buf Pointer to the data buffer to read from
51
  /// @param len Number of bytes in the data buffer
52
  /// @param byteOrder Applicable byte order (little or big endian).
53
  /// @return 0 if successful.
54
  virtual int read(const byte* buf, size_t len, ByteOrder byteOrder) = 0;
55
56
  /*!
57
    @brief Set the value from a string buffer. The format of the string
58
           corresponds to that of the write() method, i.e., a string
59
           obtained through the write() method can be read by this
60
           function.
61
62
    @param buf The string to read from.
63
64
    @return 0 if successful.
65
   */
66
  virtual int read(const std::string& buf) = 0;
67
  /*!
68
    @brief Set the data area, if the value has one by copying (cloning)
69
           the buffer pointed to by buf.
70
71
    Values may have a data area, which can contain additional
72
    information besides the actual value. This method is used to set such
73
    a data area.
74
75
    @param buf Pointer to the source data area
76
    @param len Size of the data area
77
    @return Return -1 if the value has no data area, else 0.
78
   */
79
  virtual int setDataArea(const byte* buf, size_t len);
80
  //@}
81
82
  //! @name Accessors
83
  //@{
84
  //! Return the type identifier (Exif data format type).
85
630k
  TypeId typeId() const {
86
630k
    return type_;
87
630k
  }
88
  /*!
89
    @brief Return an auto-pointer to a copy of itself (deep copy).
90
           The caller owns this copy and the auto-pointer ensures that
91
           it will be deleted.
92
   */
93
1.73M
  UniquePtr clone() const {
94
1.73M
    return UniquePtr(clone_());
95
1.73M
  }
96
  /*!
97
    @brief Write value to a data buffer.
98
99
    The user must ensure that the buffer has enough memory. Otherwise
100
    the call results in undefined behaviour.
101
102
    @param buf Data buffer to write to.
103
    @param byteOrder Applicable byte order (little or big endian).
104
    @return Number of bytes written.
105
  */
106
  virtual size_t copy(byte* buf, ByteOrder byteOrder) const = 0;
107
  //! Return the number of components of the value
108
  virtual size_t count() const = 0;
109
  //! Return the size of the value in bytes
110
  virtual size_t size() const = 0;
111
  /*!
112
    @brief Write the value to an output stream. You do not usually have
113
           to use this function; it is used for the implementation of
114
           the output operator for %Value,
115
           operator<<(std::ostream &os, const Value &value).
116
  */
117
  virtual std::ostream& write(std::ostream& os) const = 0;
118
  /*!
119
    @brief Return the value as a string. Implemented in terms of
120
           write(std::ostream& os) const of the concrete class.
121
   */
122
  std::string toString() const;
123
  /*!
124
    @brief Return the <EM>n</EM>-th component of the value as a string.
125
           The default implementation returns toString(). The behaviour
126
           of this method may be undefined if there is no <EM>n</EM>-th
127
           component.
128
   */
129
  virtual std::string toString(size_t n) const;
130
  /*!
131
    @brief Convert the <EM>n</EM>-th component of the value to an int64_t.
132
           The behaviour of this method may be undefined if there is no
133
           <EM>n</EM>-th component.
134
135
    @return The converted value.
136
   */
137
  virtual int64_t toInt64(size_t n = 0) const = 0;
138
  /*!
139
    @brief Convert the <EM>n</EM>-th component of the value to a float.
140
           The behaviour of this method may be undefined if there is no
141
           <EM>n</EM>-th component.
142
143
    @return The converted value.
144
   */
145
  virtual uint32_t toUint32(size_t n = 0) const = 0;
146
  /*!
147
    @brief Convert the <EM>n</EM>-th component of the value to a float.
148
           The behaviour of this method may be undefined if there is no
149
           <EM>n</EM>-th component.
150
151
    @return The converted value.
152
   */
153
  virtual float toFloat(size_t n = 0) const = 0;
154
  /*!
155
    @brief Convert the <EM>n</EM>-th component of the value to a Rational.
156
           The behaviour of this method may be undefined if there is no
157
           <EM>n</EM>-th component.
158
159
    @return The converted value.
160
   */
161
  virtual Rational toRational(size_t n = 0) const = 0;
162
  //! Return the size of the data area, 0 if there is none.
163
  virtual size_t sizeDataArea() const;
164
  /*!
165
    @brief Return a copy of the data area if the value has one. The
166
           caller owns this copy and DataBuf ensures that it will be
167
           deleted.
168
169
    Values may have a data area, which can contain additional
170
    information besides the actual value. This method is used to access
171
    such a data area.
172
173
    @return A DataBuf containing a copy of the data area or an empty
174
            DataBuf if the value does not have a data area assigned.
175
   */
176
  virtual DataBuf dataArea() const;
177
  /*!
178
    @brief Check the \em ok status indicator. After a to<Type> conversion,
179
           this indicator shows whether the conversion was successful.
180
   */
181
0
  bool ok() const {
182
0
    return ok_;
183
0
  }
184
  //@}
185
186
  /*!
187
    @brief A (simple) factory to create a Value type.
188
189
    The following Value subclasses are created depending on typeId:<BR><BR>
190
    <TABLE>
191
    <TR><TD><B>typeId</B></TD><TD><B>%Value subclass</B></TD></TR>
192
    <TR><TD><CODE>invalidTypeId</CODE></TD><TD>%DataValue(invalidTypeId)</TD></TR>
193
    <TR><TD><CODE>unsignedByte</CODE></TD><TD>%DataValue(unsignedByte)</TD></TR>
194
    <TR><TD><CODE>asciiString</CODE></TD><TD>%AsciiValue</TD></TR>
195
    <TR><TD><CODE>string</CODE></TD><TD>%StringValue</TD></TR>
196
    <TR><TD><CODE>unsignedShort</CODE></TD><TD>%ValueType &lt; uint16_t &gt;</TD></TR>
197
    <TR><TD><CODE>unsignedLong</CODE></TD><TD>%ValueType &lt; uint32_t &gt;</TD></TR>
198
    <TR><TD><CODE>unsignedRational</CODE></TD><TD>%ValueType &lt; URational &gt;</TD></TR>
199
    <TR><TD><CODE>invalid6</CODE></TD><TD>%DataValue(invalid6)</TD></TR>
200
    <TR><TD><CODE>undefined</CODE></TD><TD>%DataValue</TD></TR>
201
    <TR><TD><CODE>signedShort</CODE></TD><TD>%ValueType &lt; int16_t &gt;</TD></TR>
202
    <TR><TD><CODE>signedLong</CODE></TD><TD>%ValueType &lt; int32_t &gt;</TD></TR>
203
    <TR><TD><CODE>signedRational</CODE></TD><TD>%ValueType &lt; Rational &gt;</TD></TR>
204
    <TR><TD><CODE>tiffFloat</CODE></TD><TD>%ValueType &lt; float &gt;</TD></TR>
205
    <TR><TD><CODE>tiffDouble</CODE></TD><TD>%ValueType &lt; double &gt;</TD></TR>
206
    <TR><TD><CODE>tiffIfd</CODE></TD><TD>%ValueType &lt; uint32_t &gt;</TD></TR>
207
    <TR><TD><CODE>date</CODE></TD><TD>%DateValue</TD></TR>
208
    <TR><TD><CODE>time</CODE></TD><TD>%TimeValue</TD></TR>
209
    <TR><TD><CODE>comment</CODE></TD><TD>%CommentValue</TD></TR>
210
    <TR><TD><CODE>xmpText</CODE></TD><TD>%XmpTextValue</TD></TR>
211
    <TR><TD><CODE>xmpBag</CODE></TD><TD>%XmpArrayValue</TD></TR>
212
    <TR><TD><CODE>xmpSeq</CODE></TD><TD>%XmpArrayValue</TD></TR>
213
    <TR><TD><CODE>xmpAlt</CODE></TD><TD>%XmpArrayValue</TD></TR>
214
    <TR><TD><CODE>langAlt</CODE></TD><TD>%LangAltValue</TD></TR>
215
    <TR><TD><EM>default</EM></TD><TD>%DataValue(typeId)</TD></TR>
216
    </TABLE>
217
218
    @param typeId Type of the value.
219
    @return Auto-pointer to the newly created Value. The caller owns this
220
            copy and the auto-pointer ensures that it will be deleted.
221
   */
222
  static UniquePtr create(TypeId typeId);
223
224
 protected:
225
1.61M
  Value(const Value&) = default;
226
  /*!
227
    @brief Assignment operator. Protected so that it can only be used
228
           by subclasses but not directly.
229
   */
230
  Value& operator=(const Value&) = default;
231
  // DATA
232
  mutable bool ok_{true};  //!< Indicates the status of the previous to<Type> conversion
233
234
 private:
235
  //! Internal virtual copy constructor.
236
  virtual Value* clone_() const = 0;
237
  // DATA
238
  TypeId type_;  //!< Type of the data
239
};
240
241
//! Output operator for Value types
242
0
inline std::ostream& operator<<(std::ostream& os, const Value& value) {
243
0
  return value.write(os);
244
0
}
245
246
//! %Value for an undefined data type.
247
class EXIV2API DataValue : public Value {
248
 public:
249
  //! Shortcut for a %DataValue auto pointer.
250
  using UniquePtr = std::unique_ptr<DataValue>;
251
252
  explicit DataValue(TypeId typeId = undefined);
253
254
  DataValue(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder, TypeId typeId = undefined);
255
256
  //! @name Manipulators
257
  //@{
258
  int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
259
  //! Set the data from a string of integer values (e.g., "0 1 2 3")
260
  int read(const std::string& buf) override;
261
  //@}
262
263
  //! @name Accessors
264
  //@{
265
0
  UniquePtr clone() const {
266
0
    return UniquePtr(clone_());
267
0
  }
268
  /*!
269
    @brief Write value to a character data buffer.
270
271
    @note The byte order is required by the interface but not used by this
272
          method, so just use the default.
273
274
    The user must ensure that the buffer has enough memory. Otherwise
275
    the call results in undefined behaviour.
276
277
    @param buf Data buffer to write to.
278
    @param byteOrder Byte order. Not needed.
279
    @return Number of characters written.
280
  */
281
  size_t copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
282
  size_t count() const override;
283
  size_t size() const override;
284
  std::ostream& write(std::ostream& os) const override;
285
  /*!
286
    @brief Return the <EM>n</EM>-th component of the value as a string.
287
           The behaviour of this method may be undefined if there is no
288
           <EM>n</EM>-th component.
289
   */
290
  std::string toString(size_t n) const override;
291
  int64_t toInt64(size_t n = 0) const override;
292
  uint32_t toUint32(size_t n = 0) const override;
293
  float toFloat(size_t n = 0) const override;
294
  Rational toRational(size_t n = 0) const override;
295
  //@}
296
297
 private:
298
  //! Internal virtual copy constructor.
299
  DataValue* clone_() const override;
300
301
 public:
302
  //! Type used to store the data.
303
  using ValueType = std::vector<byte>;
304
  // DATA
305
  ValueType value_;  //!< Stores the data value
306
307
};  // class DataValue
308
309
/*!
310
  @brief Abstract base class for a string based %Value type.
311
312
  Uses a std::string to store the value and implements defaults for
313
  most operations.
314
 */
315
class EXIV2API StringValueBase : public Value {
316
  using Value::Value;
317
318
 public:
319
  //! Shortcut for a %StringValueBase auto pointer.
320
  using UniquePtr = std::unique_ptr<StringValueBase>;
321
322
  //! @name Creators
323
  //@{
324
  //! Constructor for subclasses
325
  StringValueBase(TypeId typeId, const std::string& buf);
326
  //@}
327
328
  //! @name Manipulators
329
  //@{
330
  //! Read the value from buf. This default implementation uses buf as it is.
331
  int read(const std::string& buf) override;
332
  int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
333
  //@}
334
335
  //! @name Accessors
336
  //@{
337
0
  UniquePtr clone() const {
338
0
    return UniquePtr(clone_());
339
0
  }
340
  /*!
341
    @brief Write value to a character data buffer.
342
343
    The user must ensure that the buffer has enough memory. Otherwise
344
    the call results in undefined behaviour.
345
346
    @note The byte order is required by the interface but not used by this
347
          method, so just use the default.
348
349
    @param buf Data buffer to write to.
350
    @param byteOrder Byte order. Not used.
351
    @return Number of characters written.
352
  */
353
  size_t copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
354
  size_t count() const override;
355
  size_t size() const override;
356
  int64_t toInt64(size_t n = 0) const override;
357
  uint32_t toUint32(size_t n = 0) const override;
358
  float toFloat(size_t n = 0) const override;
359
  Rational toRational(size_t n = 0) const override;
360
  std::ostream& write(std::ostream& os) const override;
361
  //@}
362
363
 protected:
364
  //! Internal virtual copy constructor.
365
  StringValueBase* clone_() const override = 0;
366
367
 public:
368
  // DATA
369
  std::string value_;  //!< Stores the string value.
370
371
};  // class StringValueBase
372
373
/*!
374
  @brief %Value for string type.
375
376
  This can be a plain Ascii string or a multiple byte encoded string. It is
377
  left to caller to decode and encode the string to and from readable
378
  text if that is required.
379
*/
380
class EXIV2API StringValue : public StringValueBase {
381
 public:
382
  //! Shortcut for a %StringValue auto pointer.
383
  using UniquePtr = std::unique_ptr<StringValue>;
384
385
  //! @name Creators
386
  //@{
387
  //! Default constructor.
388
  StringValue();
389
  //! Constructor
390
  explicit StringValue(const std::string& buf);
391
  //@}
392
393
  //! @name Accessors
394
  //@{
395
0
  UniquePtr clone() const {
396
0
    return UniquePtr(clone_());
397
0
  }
398
  //@}
399
400
 private:
401
  //! Internal virtual copy constructor.
402
  StringValue* clone_() const override;
403
404
};  // class StringValue
405
406
/*!
407
  @brief %Value for an Ascii string type.
408
409
  This class is for null terminated single byte Ascii strings.
410
  This class also ensures that the string is null terminated.
411
 */
412
class EXIV2API AsciiValue : public StringValueBase {
413
 public:
414
  //! Shortcut for a %AsciiValue auto pointer.
415
  using UniquePtr = std::unique_ptr<AsciiValue>;
416
417
  //! @name Creators
418
  //@{
419
  //! Default constructor.
420
  AsciiValue();
421
  //! Constructor
422
  explicit AsciiValue(const std::string& buf);
423
  //@}
424
425
  //! @name Manipulators
426
  //@{
427
  using StringValueBase::read;
428
  /*!
429
    @brief Set the value to that of the string buf. Overrides base class
430
           to append a terminating '\\0' character if buf doesn't end
431
           with '\\0'.
432
   */
433
  int read(const std::string& buf) override;
434
  //@}
435
436
  //! @name Accessors
437
  //@{
438
0
  UniquePtr clone() const {
439
0
    return UniquePtr(clone_());
440
0
  }
441
  /*!
442
    @brief Write the ASCII value up to the first '\\0' character to an
443
           output stream.  Any further characters are ignored and not
444
           written to the output stream.
445
  */
446
  std::ostream& write(std::ostream& os) const override;
447
  //@}
448
449
 private:
450
  //! Internal virtual copy constructor.
451
  AsciiValue* clone_() const override;
452
453
};  // class AsciiValue
454
455
/*!
456
  @brief %Value for an Exif comment.
457
458
  This can be a plain Ascii string or a multiple byte encoded string. The
459
  comment is expected to be encoded in the character set indicated (default
460
  undefined), but this is not checked. It is left to caller to decode and
461
  encode the string to and from readable text if that is required.
462
*/
463
class EXIV2API CommentValue : public StringValueBase {
464
 public:
465
  //! Character set identifiers for the character sets defined by %Exif
466
  enum CharsetId { ascii, jis, unicode, undefined, invalidCharsetId, lastCharsetId };
467
  //! Information pertaining to the defined character sets
468
  struct CharsetTable {
469
    CharsetId charsetId_;  //!< Charset id
470
    const char* name_;     //!< Name of the charset
471
    const char* code_;     //!< Code of the charset
472
  };
473
474
  //! Charset information lookup functions. Implemented as a static class.
475
  class EXIV2API CharsetInfo {
476
   public:
477
    //! Return the name for a charset id
478
    static const char* name(CharsetId charsetId);
479
    //! Return the code for a charset id
480
    static const char* code(CharsetId charsetId);
481
    //! Return the charset id for a name
482
    static CharsetId charsetIdByName(const std::string& name);
483
    //! Return the charset id for a code
484
    static CharsetId charsetIdByCode(const std::string& code);
485
486
   private:
487
    static const CharsetTable charsetTable_[];
488
  };  // class CharsetInfo
489
490
  //! Shortcut for a %CommentValue auto pointer.
491
  using UniquePtr = std::unique_ptr<CommentValue>;
492
493
  //! @name Creators
494
  //@{
495
  //! Default constructor.
496
  CommentValue();
497
  //! Constructor, uses read(const std::string& comment)
498
  explicit CommentValue(const std::string& comment);
499
  //@}
500
501
  //! @name Manipulators
502
  //@{
503
  /*!
504
    @brief Read the value from a comment
505
506
    The format of \em comment is:
507
    <BR>
508
    <CODE>[charset=["]Ascii|Jis|Unicode|Undefined["] ]comment</CODE>
509
    <BR>
510
    The default charset is Undefined.
511
512
    @return 0 if successful<BR>
513
            1 if an invalid character set is encountered
514
  */
515
  int read(const std::string& comment) override;
516
  int read(const byte* buf, size_t len, ByteOrder byteOrder) override;
517
  //@}
518
519
  //! @name Accessors
520
  //@{
521
0
  UniquePtr clone() const {
522
0
    return UniquePtr(clone_());
523
0
  }
524
  size_t copy(byte* buf, ByteOrder byteOrder) const override;
525
  /*!
526
    @brief Write the comment in a format which can be read by
527
    read(const std::string& comment).
528
   */
529
  std::ostream& write(std::ostream& os) const override;
530
  /*!
531
    @brief Return the comment (without a charset="..." prefix)
532
533
    The comment is decoded to UTF-8. For Exif UNICODE comments, the
534
    function makes an attempt to correctly determine the character
535
    encoding of the value. Alternatively, the optional \em encoding
536
    parameter can be used to specify it.
537
538
    @param encoding Optional argument to specify the character encoding
539
        that the comment is encoded in, as an iconv(3) name. Only used
540
        for Exif UNICODE comments.
541
542
    @return A string containing the comment converted to UTF-8.
543
   */
544
  std::string comment(const char* encoding = nullptr) const;
545
  /*!
546
    @brief Determine the character encoding that was used to encode the
547
        UNICODE comment value as an iconv(3) name.
548
549
    If the comment \em c starts with a BOM, the BOM is interpreted and
550
    removed from the string.
551
552
    Todo: Implement rules to guess if the comment is UTF-8 encoded.
553
   */
554
  const char* detectCharset(std::string& c) const;
555
  //! Return the Exif charset id of the comment
556
  CharsetId charsetId() const;
557
  //@}
558
559
 private:
560
  //! Internal virtual copy constructor.
561
  CommentValue* clone_() const override;
562
563
 public:
564
  // DATA
565
  ByteOrder byteOrder_{littleEndian};  //!< Byte order of the comment string that was read
566
567
};  // class CommentValue
568
569
/*!
570
  @brief Base class for all Exiv2 values used to store XMP property values.
571
 */
572
class EXIV2API XmpValue : public Value {
573
  using Value::Value;
574
575
 public:
576
  //! Shortcut for a %XmpValue auto pointer.
577
  using UniquePtr = std::unique_ptr<XmpValue>;
578
579
  //! XMP array types.
580
  enum XmpArrayType { xaNone, xaAlt, xaBag, xaSeq };
581
  //! XMP structure indicator.
582
  enum XmpStruct { xsNone, xsStruct };
583
584
  //! @name Accessors
585
  //@{
586
  //! Return XMP array type, indicates if an XMP value is an array.
587
  XmpArrayType xmpArrayType() const;
588
  //! Return XMP struct, indicates if an XMP value is a structure.
589
  XmpStruct xmpStruct() const;
590
  size_t size() const override;
591
  /*!
592
    @brief Write value to a character data buffer.
593
594
    The user must ensure that the buffer has enough memory. Otherwise
595
    the call results in undefined behaviour.
596
597
    @note The byte order is required by the interface but not used by this
598
          method, so just use the default.
599
600
    @param buf Data buffer to write to.
601
    @param byteOrder Byte order. Not used.
602
    @return Number of characters written.
603
  */
604
  size_t copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
605
  //@}
606
607
  //! @name Manipulators
608
  //@{
609
  //! Set the XMP array type to indicate that an XMP value is an array.
610
  void setXmpArrayType(XmpArrayType xmpArrayType);
611
  //! Set the XMP struct type to indicate that an XMP value is a structure.
612
  void setXmpStruct(XmpStruct xmpStruct = xsStruct);
613
614
  /// @note Uses read(const std::string& buf)
615
  int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
616
  int read(const std::string& buf) override = 0;
617
  //@}
618
619
  /*!
620
    @brief Return XMP array type for an array Value TypeId, xaNone if
621
           \em typeId is not an XMP array value type.
622
   */
623
  static XmpArrayType xmpArrayType(TypeId typeId);
624
625
 private:
626
  // DATA
627
  XmpArrayType xmpArrayType_{xaNone};  //!< Type of XMP array
628
  XmpStruct xmpStruct_{xsNone};        //!< XMP structure indicator
629
630
};  // class XmpValue
631
632
/*!
633
  @brief %Value type suitable for simple XMP properties and
634
         XMP nodes of complex types which are not parsed into
635
         specific values.
636
637
  Uses a std::string to store the value.
638
 */
639
class EXIV2API XmpTextValue : public XmpValue {
640
 public:
641
  //! Shortcut for a %XmpTextValue auto pointer.
642
  using UniquePtr = std::unique_ptr<XmpTextValue>;
643
644
  //! @name Creators
645
  //@{
646
  //! Constructor.
647
  XmpTextValue();
648
  //! Constructor, reads the value from a string.
649
  explicit XmpTextValue(const std::string& buf);
650
  //@}
651
652
  //! @name Manipulators
653
  //@{
654
  using XmpValue::read;
655
  /*!
656
    @brief Read a simple property value from \em buf to set the value.
657
658
    Sets the value to the contents of \em buf. A optional keyword,
659
    \em type is supported to set the XMP value type. This is useful for
660
    complex value types for which Exiv2 does not have direct support.
661
662
    The format of \em buf is:
663
    <BR>
664
    <CODE>[type=["]Alt|Bag|Seq|Struct["] ]text</CODE>
665
    <BR>
666
667
    @return 0 if successful.
668
   */
669
670
  int read(const std::string& buf) override;
671
  //@}
672
673
  //! @name Accessors
674
  //@{
675
  UniquePtr clone() const;
676
  size_t size() const override;
677
  size_t count() const override;
678
  /*!
679
    @brief Convert the value to an int64_t.
680
           The optional parameter \em n is not used and is ignored.
681
682
    @return The converted value.
683
   */
684
  int64_t toInt64(size_t n = 0) const override;
685
  /*!
686
    @brief Convert the value to an uint32_t.
687
           The optional parameter \em n is not used and is ignored.
688
689
    @return The converted value.
690
   */
691
  uint32_t toUint32(size_t n = 0) const override;
692
  /*!
693
    @brief Convert the value to a float.
694
           The optional parameter \em n is not used and is ignored.
695
696
    @return The converted value.
697
   */
698
  float toFloat(size_t n = 0) const override;
699
  /*!
700
    @brief Convert the value to a Rational.
701
           The optional parameter \em n is not used and is ignored.
702
703
    @return The converted value.
704
   */
705
  Rational toRational(size_t n = 0) const override;
706
  std::ostream& write(std::ostream& os) const override;
707
  //@}
708
709
 private:
710
  //! Internal virtual copy constructor.
711
  XmpTextValue* clone_() const override;
712
713
 public:
714
  // DATA
715
  std::string value_;  //!< Stores the string values.
716
717
};  // class XmpTextValue
718
719
/*!
720
  @brief %Value type for simple arrays. Each item in the array is a simple
721
         value, without qualifiers. The array may be an ordered (\em seq),
722
         unordered (\em bag) or alternative array (\em alt). The array
723
         items must not contain qualifiers. For language alternatives use
724
         LangAltValue.
725
726
  Uses a vector of std::string to store the value(s).
727
 */
728
class EXIV2API XmpArrayValue : public XmpValue {
729
 public:
730
  //! Shortcut for a %XmpArrayValue auto pointer.
731
  using UniquePtr = std::unique_ptr<XmpArrayValue>;
732
733
  //! @name Creators
734
  //@{
735
  //! Constructor. \em typeId can be one of xmpBag, xmpSeq or xmpAlt.
736
  explicit XmpArrayValue(TypeId typeId = xmpBag);
737
  //@}
738
739
  //! @name Manipulators
740
  //@{
741
  using XmpValue::read;
742
  /*!
743
    @brief Read a simple property value from \em buf and append it
744
           to the value.
745
746
    Appends \em buf to the value after the last existing array element.
747
    Subsequent calls will therefore populate multiple array elements in
748
    the order they are read.
749
750
    @return 0 if successful.
751
   */
752
  int read(const std::string& buf) override;
753
  //@}
754
755
  //! @name Accessors
756
  //@{
757
  UniquePtr clone() const;
758
  size_t count() const override;
759
  /*!
760
    @brief Return the <EM>n</EM>-th component of the value as a string.
761
           The behaviour of this method may be undefined if there is no
762
           <EM>n</EM>-th component.
763
   */
764
  std::string toString(size_t n) const override;
765
  int64_t toInt64(size_t n = 0) const override;
766
  uint32_t toUint32(size_t n = 0) const override;
767
  float toFloat(size_t n = 0) const override;
768
  Rational toRational(size_t n = 0) const override;
769
  /*!
770
    @brief Write all elements of the value to \em os, separated by commas.
771
772
    @note The output of this method cannot directly be used as the parameter
773
          for read().
774
   */
775
  std::ostream& write(std::ostream& os) const override;
776
  //@}
777
778
 private:
779
  //! Internal virtual copy constructor.
780
  XmpArrayValue* clone_() const override;
781
782
  std::vector<std::string> value_;  //!< Stores the string values.
783
784
};  // class XmpArrayValue
785
786
/*!
787
  @brief %LangAltValueComparator
788
789
  #1058
790
  https://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart1.pdf
791
  XMP spec chapter B.4 (page 42) the xml:lang qualifier is to be compared case insensitive.
792
  */
793
struct LangAltValueComparator {
794
  //! LangAltValueComparator comparison case insensitive function
795
0
  bool operator()(const std::string& str1, const std::string& str2) const {
796
0
    if (str1.size() != str2.size())
797
0
      return str1.size() > str2.size();
798
799
0
    auto f = [](unsigned char a, unsigned char b) { return std::tolower(a) > std::tolower(b); };
800
0
    return std::lexicographical_compare(str1.begin(), str1.end(), str2.begin(), str2.end(), f);
801
0
  }
802
};
803
804
/*!
805
  @brief %Value type for XMP language alternative properties.
806
807
  A language alternative is an array consisting of simple text values,
808
  each of which has a language qualifier.
809
 */
810
class EXIV2API LangAltValue : public XmpValue {
811
 public:
812
  //! Shortcut for a %LangAltValue auto pointer.
813
  using UniquePtr = std::unique_ptr<LangAltValue>;
814
815
  //! @name Creators
816
  //@{
817
  //! Constructor.
818
  LangAltValue();
819
  //! Constructor, reads the value from a string.
820
  explicit LangAltValue(const std::string& buf);
821
  //@}
822
823
  //! @name Manipulators
824
  //@{
825
  using XmpValue::read;
826
  /*!
827
    @brief Read a simple property value from \em buf and append it
828
           to the value.
829
830
    Appends \em buf to the value after the last existing array element.
831
    Subsequent calls will therefore populate multiple array elements in
832
    the order they are read.
833
834
    The format of \em buf is:
835
    <BR>
836
    <CODE>[lang=["]language code["] ]text</CODE>
837
    <BR>
838
    The XMP default language code <CODE>x-default</CODE> is used if
839
    \em buf doesn't start with the keyword <CODE>lang</CODE>.
840
841
    @return 0 if successful.
842
   */
843
  int read(const std::string& buf) override;
844
  //@}
845
846
  //! @name Accessors
847
  //@{
848
  UniquePtr clone() const;
849
  size_t count() const override;
850
  /*!
851
    @brief Return the text value associated with the default language
852
           qualifier \c x-default. The parameter \em n is not used, but
853
           it is suggested that only 0 is passed in. Returns an empty
854
           string and sets the ok-flag to \c false if there is no
855
           default value.
856
   */
857
  std::string toString(size_t n) const override;
858
  /*!
859
    @brief Return the text value associated with the language qualifier
860
           \em qualifier. Returns an empty string and sets the ok-flag
861
           to \c false if there is no entry for the language qualifier.
862
   */
863
  std::string toString(const std::string& qualifier) const;
864
  int64_t toInt64(size_t n = 0) const override;
865
  uint32_t toUint32(size_t n = 0) const override;
866
  float toFloat(size_t n = 0) const override;
867
  Rational toRational(size_t n = 0) const override;
868
  /*!
869
    @brief Write all elements of the value to \em os, separated by commas.
870
871
    @note The output of this method cannot directly be used as the parameter
872
          for read().
873
   */
874
  std::ostream& write(std::ostream& os) const override;
875
  //@}
876
877
 private:
878
  //! Internal virtual copy constructor.
879
  LangAltValue* clone_() const override;
880
881
 public:
882
  //! Type used to store language alternative arrays.
883
  using ValueType = std::map<std::string, std::string, LangAltValueComparator>;
884
  // DATA
885
  /*!
886
    @brief Map to store the language alternative values. The language
887
           qualifier is used as the key for the map entries.
888
   */
889
  ValueType value_;
890
891
};  // class LangAltValue
892
893
/*!
894
  @brief %Value for simple ISO 8601 dates
895
896
  This class is limited to parsing simple date strings in the ISO 8601
897
  format CCYYMMDD (century, year, month, day).
898
 */
899
class EXIV2API DateValue : public Value {
900
 public:
901
  //! Shortcut for a %DateValue auto pointer.
902
  using UniquePtr = std::unique_ptr<DateValue>;
903
904
  //! @name Creators
905
  //@{
906
  //! Default constructor.
907
  DateValue();
908
  //! Constructor
909
  DateValue(int32_t year, int32_t month, int32_t day);
910
  //@}
911
912
  //! Simple Date helper structure
913
  struct EXIV2API Date {
914
    int32_t year;   //!< Year
915
    int32_t month;  //!< Month
916
    int32_t day;    //!< Day
917
  };
918
919
  //! @name Manipulators
920
  //@{
921
922
  /// @return 0 if successful<BR>
923
  ///         1 in case of an unsupported date format
924
  int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
925
  /*!
926
    @brief Set the value to that of the string buf.
927
928
    @param buf String containing the date
929
930
    @return 0 if successful<BR>
931
            1 in case of an unsupported date format
932
   */
933
  int read(const std::string& buf) override;
934
  //! Set the date
935
  void setDate(const Date& src);
936
  //@}
937
938
  //! @name Accessors
939
  //@{
940
0
  UniquePtr clone() const {
941
0
    return UniquePtr(clone_());
942
0
  }
943
  /*!
944
    @brief Write value to a character data buffer.
945
946
    The user must ensure that the buffer has enough memory. Otherwise
947
    the call results in undefined behaviour.
948
949
    @note The byte order is required by the interface but not used by this
950
          method, so just use the default.
951
952
    @param buf Data buffer to write to.
953
    @param byteOrder Byte order. Not used.
954
    @return Number of characters written.
955
  */
956
  size_t copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
957
958
  //! Return date struct containing date information
959
  virtual const Date& getDate() const;
960
  size_t count() const override;
961
  size_t size() const override;
962
  std::ostream& write(std::ostream& os) const override;
963
  //! Return the value as a UNIX calendar time converted to int64_t.
964
  int64_t toInt64(size_t n = 0) const override;
965
  //! Return the value as a UNIX calendar time converted to uint32_t.
966
  uint32_t toUint32(size_t n = 0) const override;
967
  //! Return the value as a UNIX calendar time converted to float.
968
  float toFloat(size_t n = 0) const override;
969
  //! Return the value as a UNIX calendar time converted to Rational.
970
  Rational toRational(size_t n = 0) const override;
971
  //@}
972
973
 private:
974
  //! Internal virtual copy constructor.
975
  DateValue* clone_() const override;
976
977
  // DATA
978
  Date date_;
979
980
};  // class DateValue
981
982
/*!
983
 @brief %Value for simple ISO 8601 times.
984
985
 This class is limited to handling simple time strings in the ISO 8601
986
 format HHMMSS±HHMM where HHMMSS refers to local hour, minute and
987
 seconds and ±HHMM refers to hours and minutes ahead or behind
988
 Universal Coordinated Time.
989
 */
990
class EXIV2API TimeValue : public Value {
991
 public:
992
  //! Shortcut for a %TimeValue auto pointer.
993
  using UniquePtr = std::unique_ptr<TimeValue>;
994
995
  //! @name Creators
996
  //@{
997
  //! Default constructor.
998
  TimeValue();
999
  //! Constructor
1000
  TimeValue(int32_t hour, int32_t minute, int32_t second = 0, int32_t tzHour = 0, int32_t tzMinute = 0);
1001
  //@}
1002
1003
  //! Simple Time helper structure
1004
  struct Time {
1005
    int32_t hour;      //!< Hour
1006
    int32_t minute;    //!< Minute
1007
    int32_t second;    //!< Second
1008
    int32_t tzHour;    //!< Hours ahead or behind UTC
1009
    int32_t tzMinute;  //!< Minutes ahead or behind UTC
1010
  };
1011
1012
  //! @name Manipulators
1013
  //@{
1014
1015
  ///  @return 0 if successful<BR>
1016
  ///          1 in case of an unsupported time format
1017
  int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
1018
  /*!
1019
    @brief Set the value to that of the string buf.
1020
1021
    @param buf String containing the time.
1022
1023
    @return 0 if successful<BR>
1024
            1 in case of an unsupported time format
1025
   */
1026
  int read(const std::string& buf) override;
1027
  //! Set the time
1028
  void setTime(const Time& src);
1029
  //@}
1030
1031
  //! @name Accessors
1032
  //@{
1033
0
  UniquePtr clone() const {
1034
0
    return UniquePtr(clone_());
1035
0
  }
1036
  /*!
1037
    @brief Write value to a character data buffer.
1038
1039
    The user must ensure that the buffer has enough memory. Otherwise
1040
    the call results in undefined behaviour.
1041
1042
    @note The byte order is required by the interface but not used by this
1043
          method, so just use the default.
1044
1045
    @param buf Data buffer to write to.
1046
    @param byteOrder Byte order. Not used.
1047
    @return Number of characters written.
1048
  */
1049
  size_t copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
1050
  //! Return time struct containing time information
1051
  virtual const Time& getTime() const;
1052
  size_t count() const override;
1053
  size_t size() const override;
1054
  std::ostream& write(std::ostream& os) const override;
1055
  //! Returns number of seconds in the day in UTC.
1056
  int64_t toInt64(size_t n = 0) const override;
1057
  //! Returns number of seconds in the day in UTC.
1058
  uint32_t toUint32(size_t n = 0) const override;
1059
  //! Returns number of seconds in the day in UTC converted to float.
1060
  float toFloat(size_t n = 0) const override;
1061
  //! Returns number of seconds in the day in UTC converted to Rational.
1062
  Rational toRational(size_t n = 0) const override;
1063
  //@}
1064
1065
 private:
1066
  //! @name Accessors
1067
  //@{
1068
  //! Internal virtual copy constructor.
1069
  TimeValue* clone_() const override;
1070
  //@}
1071
1072
  // DATA
1073
  Time time_;
1074
1075
};  // class TimeValue
1076
1077
//! Template to determine the TypeId for a type T
1078
template <typename T>
1079
TypeId getType();
1080
1081
//! Specialization for an unsigned short
1082
template <>
1083
12.1k
inline TypeId getType<uint16_t>() {
1084
12.1k
  return unsignedShort;
1085
12.1k
}
1086
//! Specialization for an unsigned long
1087
template <>
1088
259
inline TypeId getType<uint32_t>() {
1089
259
  return unsignedLong;
1090
259
}
1091
//! Specialization for an unsigned rational
1092
template <>
1093
5.17k
inline TypeId getType<URational>() {
1094
5.17k
  return unsignedRational;
1095
5.17k
}
1096
//! Specialization for a signed short
1097
template <>
1098
1.46k
inline TypeId getType<int16_t>() {
1099
1.46k
  return signedShort;
1100
1.46k
}
1101
//! Specialization for a signed long
1102
template <>
1103
1.43k
inline TypeId getType<int32_t>() {
1104
1.43k
  return signedLong;
1105
1.43k
}
1106
//! Specialization for a signed rational
1107
template <>
1108
1.78k
inline TypeId getType<Rational>() {
1109
1.78k
  return signedRational;
1110
1.78k
}
1111
//! Specialization for a float
1112
template <>
1113
386
inline TypeId getType<float>() {
1114
386
  return tiffFloat;
1115
386
}
1116
//! Specialization for a double
1117
template <>
1118
486
inline TypeId getType<double>() {
1119
486
  return tiffDouble;
1120
486
}
1121
1122
// No default implementation: let the compiler/linker complain
1123
// template<typename T> inline TypeId getType() { return invalid; }
1124
1125
/*!
1126
  @brief Template for a %Value of a basic type. This is used for unsigned
1127
         and signed short, long and rationals.
1128
 */
1129
template <typename T>
1130
class ValueType : public Value {
1131
  using Value::Value;
1132
1133
 public:
1134
  //! Shortcut for a %ValueType\<T\> auto pointer.
1135
  using UniquePtr = std::unique_ptr<ValueType<T>>;
1136
1137
  //! @name Creators
1138
  //@{
1139
  //! Default Constructor.
1140
  ValueType();
1141
  //! Constructor.
1142
  ValueType(const byte* buf, size_t len, ByteOrder byteOrder, TypeId typeId = getType<T>());
1143
  //! Constructor.
1144
  explicit ValueType(const T& val, TypeId typeId = getType<T>());
1145
  //! Copy constructor
1146
  ValueType(const ValueType<T>& rhs);
1147
  //@}
1148
1149
  //! @name Manipulators
1150
  //@{
1151
  //! Assignment operator.
1152
  ValueType<T>& operator=(const ValueType<T>& rhs);
1153
  int read(const byte* buf, size_t len, ByteOrder byteOrder) override;
1154
  /*!
1155
    @brief Set the data from a string of values of type T (e.g.,
1156
           "0 1 2 3" or "1/2 1/3 1/4" depending on what T is).
1157
           Generally, the accepted input format is the same as that
1158
           produced by the write() method.
1159
   */
1160
  int read(const std::string& buf) override;
1161
  /*!
1162
    @brief Set the data area. This method copies (clones) the buffer
1163
           pointed to by buf.
1164
   */
1165
  int setDataArea(const byte* buf, size_t len) override;
1166
  //@}
1167
1168
  //! @name Accessors
1169
  //@{
1170
  UniquePtr clone() const {
1171
    return UniquePtr(clone_());
1172
  }
1173
  size_t copy(byte* buf, ByteOrder byteOrder) const override;
1174
  size_t count() const override;
1175
  size_t size() const override;
1176
  std::ostream& write(std::ostream& os) const override;
1177
  /*!
1178
    @brief Return the <EM>n</EM>-th component of the value as a string.
1179
           The behaviour of this method may be undefined if there is no
1180
           <EM>n</EM>-th
1181
           component.
1182
   */
1183
  std::string toString(size_t n) const override;
1184
  int64_t toInt64(size_t n = 0) const override;
1185
  uint32_t toUint32(size_t n = 0) const override;
1186
  float toFloat(size_t n = 0) const override;
1187
  Rational toRational(size_t n = 0) const override;
1188
  //! Return the size of the data area.
1189
  size_t sizeDataArea() const override;
1190
  /*!
1191
    @brief Return a copy of the data area in a DataBuf. The caller owns
1192
           this copy and DataBuf ensures that it will be deleted.
1193
   */
1194
  DataBuf dataArea() const override;
1195
  //@}
1196
1197
  //! Container for values
1198
  using ValueList = std::vector<T>;
1199
1200
  // DATA
1201
  /*!
1202
    @brief The container for all values. In your application, if you know
1203
           what subclass of Value you're dealing with (and possibly the T)
1204
           then you can access this STL container through the usual
1205
           standard library functions.
1206
   */
1207
  ValueList value_;
1208
1209
 private:
1210
  //! Utility for toInt64, toUint32, etc.
1211
  template <typename I>
1212
93
  I float_to_integer_helper(size_t n) const {
1213
93
    const auto v = value_.at(n);
1214
93
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
73
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
39
      return static_cast<I>(std::lround(v));
1217
39
    }
1218
54
    return 0;
1219
93
  }
long Exiv2::ValueType<double>::float_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1212
21
  I float_to_integer_helper(size_t n) const {
1213
21
    const auto v = value_.at(n);
1214
21
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
17
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
11
      return static_cast<I>(std::lround(v));
1217
11
    }
1218
10
    return 0;
1219
21
  }
unsigned int Exiv2::ValueType<double>::float_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1212
37
  I float_to_integer_helper(size_t n) const {
1213
37
    const auto v = value_.at(n);
1214
37
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
25
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
5
      return static_cast<I>(std::lround(v));
1217
5
    }
1218
32
    return 0;
1219
37
  }
long Exiv2::ValueType<float>::float_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1212
29
  I float_to_integer_helper(size_t n) const {
1213
29
    const auto v = value_.at(n);
1214
29
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
26
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
19
      return static_cast<I>(std::lround(v));
1217
19
    }
1218
10
    return 0;
1219
29
  }
unsigned int Exiv2::ValueType<float>::float_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1212
6
  I float_to_integer_helper(size_t n) const {
1213
6
    const auto v = value_.at(n);
1214
6
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
5
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
4
      return static_cast<I>(std::lround(v));
1217
4
    }
1218
2
    return 0;
1219
6
  }
1220
1221
  //! Utility for toInt64, toUint32, etc.
1222
  template <typename I>
1223
251
  I rational_to_integer_helper(size_t n) const {
1224
251
    auto a = value_.at(n).first;
1225
251
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
251
    if (b <= 0) {
1229
87
      return 0;
1230
87
    }
1231
1232
    // Check for integer overflow.
1233
164
#ifdef __cpp_if_constexpr
1234
164
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
121
      const auto imin = std::numeric_limits<I>::min();
1240
121
      const auto imax = std::numeric_limits<I>::max();
1241
121
      if (imax < b || a < imin || imax < a) {
1242
0
        return 0;
1243
0
      }
1244
121
#ifdef __cpp_if_constexpr
1245
121
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
39
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
39
      if (imax < b || imax < a) {
1252
0
        return 0;
1253
0
      }
1254
39
    } else {
1255
      // conversion is from signed to unsigned
1256
4
      const auto imax = std::numeric_limits<I>::max();
1257
4
      if (a < 0) {
1258
0
        return 0;
1259
0
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
4
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
4
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
4
      if (imax < b_u || imax < a_u) {
1264
0
        return 0;
1265
0
      }
1266
4
    }
1267
1268
164
    return static_cast<I>(a) / static_cast<I>(b);
1269
251
  }
long Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::rational_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1223
49
  I rational_to_integer_helper(size_t n) const {
1224
49
    auto a = value_.at(n).first;
1225
49
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
49
    if (b <= 0) {
1229
10
      return 0;
1230
10
    }
1231
1232
    // Check for integer overflow.
1233
39
#ifdef __cpp_if_constexpr
1234
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
      const auto imin = std::numeric_limits<I>::min();
1240
      const auto imax = std::numeric_limits<I>::max();
1241
      if (imax < b || a < imin || imax < a) {
1242
        return 0;
1243
      }
1244
#ifdef __cpp_if_constexpr
1245
39
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
39
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
39
      if (imax < b || imax < a) {
1252
0
        return 0;
1253
0
      }
1254
    } else {
1255
      // conversion is from signed to unsigned
1256
      const auto imax = std::numeric_limits<I>::max();
1257
      if (a < 0) {
1258
        return 0;
1259
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
      if (imax < b_u || imax < a_u) {
1264
        return 0;
1265
      }
1266
    }
1267
1268
39
    return static_cast<I>(a) / static_cast<I>(b);
1269
49
  }
unsigned int Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::rational_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1223
3
  I rational_to_integer_helper(size_t n) const {
1224
3
    auto a = value_.at(n).first;
1225
3
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
3
    if (b <= 0) {
1229
3
      return 0;
1230
3
    }
1231
1232
    // Check for integer overflow.
1233
0
#ifdef __cpp_if_constexpr
1234
0
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
0
      const auto imin = std::numeric_limits<I>::min();
1240
0
      const auto imax = std::numeric_limits<I>::max();
1241
0
      if (imax < b || a < imin || imax < a) {
1242
0
        return 0;
1243
0
      }
1244
0
#ifdef __cpp_if_constexpr
1245
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
      if (imax < b || imax < a) {
1252
        return 0;
1253
      }
1254
    } else {
1255
      // conversion is from signed to unsigned
1256
      const auto imax = std::numeric_limits<I>::max();
1257
      if (a < 0) {
1258
        return 0;
1259
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
      if (imax < b_u || imax < a_u) {
1264
        return 0;
1265
      }
1266
    }
1267
1268
0
    return static_cast<I>(a) / static_cast<I>(b);
1269
3
  }
long Exiv2::ValueType<std::__1::pair<int, int> >::rational_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1223
191
  I rational_to_integer_helper(size_t n) const {
1224
191
    auto a = value_.at(n).first;
1225
191
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
191
    if (b <= 0) {
1229
70
      return 0;
1230
70
    }
1231
1232
    // Check for integer overflow.
1233
121
#ifdef __cpp_if_constexpr
1234
121
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
121
      const auto imin = std::numeric_limits<I>::min();
1240
121
      const auto imax = std::numeric_limits<I>::max();
1241
121
      if (imax < b || a < imin || imax < a) {
1242
0
        return 0;
1243
0
      }
1244
121
#ifdef __cpp_if_constexpr
1245
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
      if (imax < b || imax < a) {
1252
        return 0;
1253
      }
1254
    } else {
1255
      // conversion is from signed to unsigned
1256
      const auto imax = std::numeric_limits<I>::max();
1257
      if (a < 0) {
1258
        return 0;
1259
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
      if (imax < b_u || imax < a_u) {
1264
        return 0;
1265
      }
1266
    }
1267
1268
121
    return static_cast<I>(a) / static_cast<I>(b);
1269
191
  }
unsigned int Exiv2::ValueType<std::__1::pair<int, int> >::rational_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1223
8
  I rational_to_integer_helper(size_t n) const {
1224
8
    auto a = value_.at(n).first;
1225
8
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
8
    if (b <= 0) {
1229
4
      return 0;
1230
4
    }
1231
1232
    // Check for integer overflow.
1233
4
#ifdef __cpp_if_constexpr
1234
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
      const auto imin = std::numeric_limits<I>::min();
1240
      const auto imax = std::numeric_limits<I>::max();
1241
      if (imax < b || a < imin || imax < a) {
1242
        return 0;
1243
      }
1244
#ifdef __cpp_if_constexpr
1245
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
      if (imax < b || imax < a) {
1252
        return 0;
1253
      }
1254
4
    } else {
1255
      // conversion is from signed to unsigned
1256
4
      const auto imax = std::numeric_limits<I>::max();
1257
4
      if (a < 0) {
1258
0
        return 0;
1259
0
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
4
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
4
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
4
      if (imax < b_u || imax < a_u) {
1264
0
        return 0;
1265
0
      }
1266
4
    }
1267
1268
4
    return static_cast<I>(a) / static_cast<I>(b);
1269
8
  }
1270
1271
  //! Internal virtual copy constructor.
1272
  ValueType<T>* clone_() const override;
1273
1274
  // DATA
1275
  //! Pointer to the buffer, nullptr if none has been allocated
1276
  Blob pDataArea_;
1277
};  // class ValueType
1278
1279
//! Unsigned short value type
1280
using UShortValue = ValueType<uint16_t>;
1281
//! Unsigned long value type
1282
using ULongValue = ValueType<uint32_t>;
1283
//! Unsigned rational value type
1284
using URationalValue = ValueType<URational>;
1285
//! Signed short value type
1286
using ShortValue = ValueType<int16_t>;
1287
//! Signed long value type
1288
using LongValue = ValueType<int32_t>;
1289
//! Signed rational value type
1290
using RationalValue = ValueType<Rational>;
1291
//! Float value type
1292
using FloatValue = ValueType<float>;
1293
//! Double value type
1294
using DoubleValue = ValueType<double>;
1295
1296
// *****************************************************************************
1297
// free functions, template and inline definitions
1298
1299
/*!
1300
  @brief Read a value of type T from the data buffer.
1301
1302
  We need this template function for the ValueType template classes.
1303
  There are only specializations of this function available; no default
1304
  implementation is provided.
1305
1306
  @param buf Pointer to the data buffer to read from.
1307
  @param byteOrder Applicable byte order (little or big endian).
1308
  @return A value of type T.
1309
 */
1310
template <typename T>
1311
T getValue(const byte* buf, ByteOrder byteOrder);
1312
// Specialization for a 2 byte unsigned short value.
1313
template <>
1314
8.24M
inline uint16_t getValue(const byte* buf, ByteOrder byteOrder) {
1315
8.24M
  return getUShort(buf, byteOrder);
1316
8.24M
}
1317
// Specialization for a 4 byte unsigned long value.
1318
template <>
1319
0
inline uint32_t getValue(const byte* buf, ByteOrder byteOrder) {
1320
0
  return getULong(buf, byteOrder);
1321
0
}
1322
// Specialization for an 8 byte unsigned rational value.
1323
template <>
1324
72.2k
inline URational getValue(const byte* buf, ByteOrder byteOrder) {
1325
72.2k
  return getURational(buf, byteOrder);
1326
72.2k
}
1327
// Specialization for a 2 byte signed short value.
1328
template <>
1329
614k
inline int16_t getValue(const byte* buf, ByteOrder byteOrder) {
1330
614k
  return getShort(buf, byteOrder);
1331
614k
}
1332
// Specialization for a 4 byte signed long value.
1333
template <>
1334
56.4k
inline int32_t getValue(const byte* buf, ByteOrder byteOrder) {
1335
56.4k
  return getLong(buf, byteOrder);
1336
56.4k
}
1337
// Specialization for an 8 byte signed rational value.
1338
template <>
1339
34.9k
inline Rational getValue(const byte* buf, ByteOrder byteOrder) {
1340
34.9k
  return getRational(buf, byteOrder);
1341
34.9k
}
1342
// Specialization for a 4 byte float value.
1343
template <>
1344
20.8k
inline float getValue(const byte* buf, ByteOrder byteOrder) {
1345
20.8k
  return getFloat(buf, byteOrder);
1346
20.8k
}
1347
// Specialization for a 8 byte double value.
1348
template <>
1349
8.97k
inline double getValue(const byte* buf, ByteOrder byteOrder) {
1350
8.97k
  return getDouble(buf, byteOrder);
1351
8.97k
}
1352
1353
/*!
1354
  @brief Convert a value of type T to data, write the data to the data buffer.
1355
1356
  We need this template function for the ValueType template classes.
1357
  There are only specializations of this function available; no default
1358
  implementation is provided.
1359
1360
  @param buf Pointer to the data buffer to write to.
1361
  @param t Value to be converted.
1362
  @param byteOrder Applicable byte order (little or big endian).
1363
  @return The number of bytes written to the buffer.
1364
 */
1365
template <typename T>
1366
size_t toData(byte* buf, T t, ByteOrder byteOrder);
1367
/*!
1368
  @brief Specialization to write an unsigned short to the data buffer.
1369
         Return the number of bytes written.
1370
 */
1371
template <>
1372
16.2M
inline size_t toData(byte* buf, uint16_t t, ByteOrder byteOrder) {
1373
16.2M
  return us2Data(buf, t, byteOrder);
1374
16.2M
}
1375
/*!
1376
  @brief Specialization to write an unsigned long to the data buffer.
1377
         Return the number of bytes written.
1378
 */
1379
template <>
1380
0
inline size_t toData(byte* buf, uint32_t t, ByteOrder byteOrder) {
1381
0
  return ul2Data(buf, t, byteOrder);
1382
0
}
1383
/*!
1384
  @brief Specialization to write an unsigned rational to the data buffer.
1385
         Return the number of bytes written.
1386
 */
1387
template <>
1388
68.9k
inline size_t toData(byte* buf, URational t, ByteOrder byteOrder) {
1389
68.9k
  return ur2Data(buf, t, byteOrder);
1390
68.9k
}
1391
/*!
1392
  @brief Specialization to write a signed short to the data buffer.
1393
         Return the number of bytes written.
1394
 */
1395
template <>
1396
1.19M
inline size_t toData(byte* buf, int16_t t, ByteOrder byteOrder) {
1397
1.19M
  return s2Data(buf, t, byteOrder);
1398
1.19M
}
1399
/*!
1400
  @brief Specialization to write a signed long to the data buffer.
1401
         Return the number of bytes written.
1402
 */
1403
template <>
1404
101k
inline size_t toData(byte* buf, int32_t t, ByteOrder byteOrder) {
1405
101k
  return l2Data(buf, t, byteOrder);
1406
101k
}
1407
/*!
1408
  @brief Specialization to write a signed rational to the data buffer.
1409
         Return the number of bytes written.
1410
 */
1411
template <>
1412
20.2k
inline size_t toData(byte* buf, Rational t, ByteOrder byteOrder) {
1413
20.2k
  return r2Data(buf, t, byteOrder);
1414
20.2k
}
1415
/*!
1416
  @brief Specialization to write a float to the data buffer.
1417
         Return the number of bytes written.
1418
 */
1419
template <>
1420
20.4k
inline size_t toData(byte* buf, float t, ByteOrder byteOrder) {
1421
20.4k
  return f2Data(buf, t, byteOrder);
1422
20.4k
}
1423
/*!
1424
  @brief Specialization to write a double to the data buffer.
1425
         Return the number of bytes written.
1426
 */
1427
template <>
1428
3.35k
inline size_t toData(byte* buf, double t, ByteOrder byteOrder) {
1429
3.35k
  return d2Data(buf, t, byteOrder);
1430
3.35k
}
1431
1432
template <typename T>
1433
23.1k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
23.1k
}
Exiv2::ValueType<unsigned short>::ValueType()
Line
Count
Source
1433
12.1k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
12.1k
}
Exiv2::ValueType<unsigned int>::ValueType()
Line
Count
Source
1433
259
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
259
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::ValueType()
Line
Count
Source
1433
5.17k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
5.17k
}
Exiv2::ValueType<short>::ValueType()
Line
Count
Source
1433
1.46k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
1.46k
}
Exiv2::ValueType<int>::ValueType()
Line
Count
Source
1433
1.43k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
1.43k
}
Exiv2::ValueType<std::__1::pair<int, int> >::ValueType()
Line
Count
Source
1433
1.78k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
1.78k
}
Exiv2::ValueType<float>::ValueType()
Line
Count
Source
1433
386
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
386
}
Exiv2::ValueType<double>::ValueType()
Line
Count
Source
1433
486
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
486
}
1435
1436
template <typename T>
1437
ValueType<T>::ValueType(const byte* buf, size_t len, ByteOrder byteOrder, TypeId typeId) : Value(typeId) {
1438
  read(buf, len, byteOrder);
1439
}
1440
1441
template <typename T>
1442
ValueType<T>::ValueType(const T& val, TypeId typeId) : Value(typeId) {
1443
  value_.push_back(val);
1444
}
1445
1446
template <typename T>
1447
83.5k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
83.5k
  if (!rhs.pDataArea_.empty())
1449
0
    pDataArea_ = rhs.pDataArea_;
1450
83.5k
}
Exiv2::ValueType<unsigned short>::ValueType(Exiv2::ValueType<unsigned short> const&)
Line
Count
Source
1447
41.1k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
41.1k
  if (!rhs.pDataArea_.empty())
1449
0
    pDataArea_ = rhs.pDataArea_;
1450
41.1k
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::ValueType(Exiv2::ValueType<unsigned int> const&)
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::ValueType(Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> > const&)
Line
Count
Source
1447
17.2k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
17.2k
  if (!rhs.pDataArea_.empty())
1449
0
    pDataArea_ = rhs.pDataArea_;
1450
17.2k
}
Exiv2::ValueType<short>::ValueType(Exiv2::ValueType<short> const&)
Line
Count
Source
1447
6.76k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
6.76k
  if (!rhs.pDataArea_.empty())
1449
0
    pDataArea_ = rhs.pDataArea_;
1450
6.76k
}
Exiv2::ValueType<int>::ValueType(Exiv2::ValueType<int> const&)
Line
Count
Source
1447
6.19k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
6.19k
  if (!rhs.pDataArea_.empty())
1449
0
    pDataArea_ = rhs.pDataArea_;
1450
6.19k
}
Exiv2::ValueType<std::__1::pair<int, int> >::ValueType(Exiv2::ValueType<std::__1::pair<int, int> > const&)
Line
Count
Source
1447
8.09k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
8.09k
  if (!rhs.pDataArea_.empty())
1449
0
    pDataArea_ = rhs.pDataArea_;
1450
8.09k
}
Exiv2::ValueType<float>::ValueType(Exiv2::ValueType<float> const&)
Line
Count
Source
1447
1.77k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
1.77k
  if (!rhs.pDataArea_.empty())
1449
0
    pDataArea_ = rhs.pDataArea_;
1450
1.77k
}
Exiv2::ValueType<double>::ValueType(Exiv2::ValueType<double> const&)
Line
Count
Source
1447
2.30k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
2.30k
  if (!rhs.pDataArea_.empty())
1449
0
    pDataArea_ = rhs.pDataArea_;
1450
2.30k
}
1451
1452
template <typename T>
1453
ValueType<T>& ValueType<T>::operator=(const ValueType<T>& rhs) {
1454
  if (this == &rhs)
1455
    return *this;
1456
  value_ = rhs.value_;
1457
1458
  if (!rhs.pDataArea_.empty())
1459
    pDataArea_ = rhs.pDataArea_;
1460
  else
1461
    pDataArea_.clear();
1462
1463
  return *this;
1464
}
1465
1466
template <typename T>
1467
22.8k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
22.8k
  value_.clear();
1469
22.8k
  size_t ts = TypeInfo::typeSize(typeId());
1470
22.8k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
9.07M
  for (size_t i = 0; i < len; i += ts) {
1473
9.05M
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
9.05M
  }
1475
22.8k
  return 0;
1476
22.8k
}
Exiv2::ValueType<unsigned short>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
12.1k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
12.1k
  value_.clear();
1469
12.1k
  size_t ts = TypeInfo::typeSize(typeId());
1470
12.1k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
8.25M
  for (size_t i = 0; i < len; i += ts) {
1473
8.24M
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
8.24M
  }
1475
12.1k
  return 0;
1476
12.1k
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
5.17k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
5.17k
  value_.clear();
1469
5.17k
  size_t ts = TypeInfo::typeSize(typeId());
1470
5.17k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
77.3k
  for (size_t i = 0; i < len; i += ts) {
1473
72.2k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
72.2k
  }
1475
5.17k
  return 0;
1476
5.17k
}
Exiv2::ValueType<short>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
1.46k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
1.46k
  value_.clear();
1469
1.46k
  size_t ts = TypeInfo::typeSize(typeId());
1470
1.46k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
615k
  for (size_t i = 0; i < len; i += ts) {
1473
614k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
614k
  }
1475
1.46k
  return 0;
1476
1.46k
}
Exiv2::ValueType<int>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
1.43k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
1.43k
  value_.clear();
1469
1.43k
  size_t ts = TypeInfo::typeSize(typeId());
1470
1.43k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
57.8k
  for (size_t i = 0; i < len; i += ts) {
1473
56.4k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
56.4k
  }
1475
1.43k
  return 0;
1476
1.43k
}
Exiv2::ValueType<std::__1::pair<int, int> >::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
1.78k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
1.78k
  value_.clear();
1469
1.78k
  size_t ts = TypeInfo::typeSize(typeId());
1470
1.78k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
36.7k
  for (size_t i = 0; i < len; i += ts) {
1473
34.9k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
34.9k
  }
1475
1.78k
  return 0;
1476
1.78k
}
Exiv2::ValueType<float>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
386
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
386
  value_.clear();
1469
386
  size_t ts = TypeInfo::typeSize(typeId());
1470
386
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
21.1k
  for (size_t i = 0; i < len; i += ts) {
1473
20.8k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
20.8k
  }
1475
386
  return 0;
1476
386
}
Exiv2::ValueType<double>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
486
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
486
  value_.clear();
1469
486
  size_t ts = TypeInfo::typeSize(typeId());
1470
486
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
9.46k
  for (size_t i = 0; i < len; i += ts) {
1473
8.97k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
8.97k
  }
1475
486
  return 0;
1476
486
}
1477
1478
template <typename T>
1479
0
int ValueType<T>::read(const std::string& buf) {
1480
0
  std::istringstream is(buf);
1481
0
  T tmp;
1482
0
  ValueList val;
1483
0
  while (is >> tmp)
1484
0
    val.push_back(tmp);
1485
0
  if (!is.eof())
1486
0
    return 1;
1487
0
  value_ = std::move(val);
1488
0
  return 0;
1489
0
}
Unexecuted instantiation: Exiv2::ValueType<unsigned short>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<short>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<int>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<int, int> >::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<float>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<double>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
1490
1491
template <typename T>
1492
6.04k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
6.04k
  size_t offset = 0;
1494
17.6M
  for (const auto& val : value_) {
1495
17.6M
    offset += toData(buf + offset, val, byteOrder);
1496
17.6M
  }
1497
6.04k
  return offset;
1498
6.04k
}
Exiv2::ValueType<unsigned short>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
2.21k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
2.21k
  size_t offset = 0;
1494
16.2M
  for (const auto& val : value_) {
1495
16.2M
    offset += toData(buf + offset, val, byteOrder);
1496
16.2M
  }
1497
2.21k
  return offset;
1498
2.21k
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::copy(unsigned char*, Exiv2::ByteOrder) const
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
793
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
793
  size_t offset = 0;
1494
68.9k
  for (const auto& val : value_) {
1495
68.9k
    offset += toData(buf + offset, val, byteOrder);
1496
68.9k
  }
1497
793
  return offset;
1498
793
}
Exiv2::ValueType<short>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
674
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
674
  size_t offset = 0;
1494
1.19M
  for (const auto& val : value_) {
1495
1.19M
    offset += toData(buf + offset, val, byteOrder);
1496
1.19M
  }
1497
674
  return offset;
1498
674
}
Exiv2::ValueType<int>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
896
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
896
  size_t offset = 0;
1494
101k
  for (const auto& val : value_) {
1495
101k
    offset += toData(buf + offset, val, byteOrder);
1496
101k
  }
1497
896
  return offset;
1498
896
}
Exiv2::ValueType<std::__1::pair<int, int> >::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
1.02k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
1.02k
  size_t offset = 0;
1494
20.2k
  for (const auto& val : value_) {
1495
20.2k
    offset += toData(buf + offset, val, byteOrder);
1496
20.2k
  }
1497
1.02k
  return offset;
1498
1.02k
}
Exiv2::ValueType<float>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
188
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
188
  size_t offset = 0;
1494
20.4k
  for (const auto& val : value_) {
1495
20.4k
    offset += toData(buf + offset, val, byteOrder);
1496
20.4k
  }
1497
188
  return offset;
1498
188
}
Exiv2::ValueType<double>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
248
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
248
  size_t offset = 0;
1494
3.35k
  for (const auto& val : value_) {
1495
3.35k
    offset += toData(buf + offset, val, byteOrder);
1496
3.35k
  }
1497
248
  return offset;
1498
248
}
1499
1500
template <typename T>
1501
29.3k
size_t ValueType<T>::count() const {
1502
29.3k
  return value_.size();
1503
29.3k
}
Exiv2::ValueType<unsigned short>::count() const
Line
Count
Source
1501
15.1k
size_t ValueType<T>::count() const {
1502
15.1k
  return value_.size();
1503
15.1k
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::count() const
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::count() const
Line
Count
Source
1501
5.83k
size_t ValueType<T>::count() const {
1502
5.83k
  return value_.size();
1503
5.83k
}
Exiv2::ValueType<short>::count() const
Line
Count
Source
1501
2.28k
size_t ValueType<T>::count() const {
1502
2.28k
  return value_.size();
1503
2.28k
}
Exiv2::ValueType<int>::count() const
Line
Count
Source
1501
2.01k
size_t ValueType<T>::count() const {
1502
2.01k
  return value_.size();
1503
2.01k
}
Exiv2::ValueType<std::__1::pair<int, int> >::count() const
Line
Count
Source
1501
2.74k
size_t ValueType<T>::count() const {
1502
2.74k
  return value_.size();
1503
2.74k
}
Exiv2::ValueType<float>::count() const
Line
Count
Source
1501
595
size_t ValueType<T>::count() const {
1502
595
  return value_.size();
1503
595
}
Exiv2::ValueType<double>::count() const
Line
Count
Source
1501
807
size_t ValueType<T>::count() const {
1502
807
  return value_.size();
1503
807
}
1504
1505
template <typename T>
1506
14.6k
size_t ValueType<T>::size() const {
1507
14.6k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
14.6k
}
Exiv2::ValueType<unsigned short>::size() const
Line
Count
Source
1506
5.21k
size_t ValueType<T>::size() const {
1507
5.21k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
5.21k
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::size() const
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::size() const
Line
Count
Source
1506
1.98k
size_t ValueType<T>::size() const {
1507
1.98k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
1.98k
}
Exiv2::ValueType<short>::size() const
Line
Count
Source
1506
1.87k
size_t ValueType<T>::size() const {
1507
1.87k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
1.87k
}
Exiv2::ValueType<int>::size() const
Line
Count
Source
1506
1.86k
size_t ValueType<T>::size() const {
1507
1.86k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
1.86k
}
Exiv2::ValueType<std::__1::pair<int, int> >::size() const
Line
Count
Source
1506
2.50k
size_t ValueType<T>::size() const {
1507
2.50k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
2.50k
}
Exiv2::ValueType<float>::size() const
Line
Count
Source
1506
494
size_t ValueType<T>::size() const {
1507
494
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
494
}
Exiv2::ValueType<double>::size() const
Line
Count
Source
1506
675
size_t ValueType<T>::size() const {
1507
675
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
675
}
1509
1510
template <typename T>
1511
83.5k
ValueType<T>* ValueType<T>::clone_() const {
1512
83.5k
  return new ValueType<T>(*this);
1513
83.5k
}
Exiv2::ValueType<unsigned short>::clone_() const
Line
Count
Source
1511
41.1k
ValueType<T>* ValueType<T>::clone_() const {
1512
41.1k
  return new ValueType<T>(*this);
1513
41.1k
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::clone_() const
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::clone_() const
Line
Count
Source
1511
17.2k
ValueType<T>* ValueType<T>::clone_() const {
1512
17.2k
  return new ValueType<T>(*this);
1513
17.2k
}
Exiv2::ValueType<short>::clone_() const
Line
Count
Source
1511
6.76k
ValueType<T>* ValueType<T>::clone_() const {
1512
6.76k
  return new ValueType<T>(*this);
1513
6.76k
}
Exiv2::ValueType<int>::clone_() const
Line
Count
Source
1511
6.19k
ValueType<T>* ValueType<T>::clone_() const {
1512
6.19k
  return new ValueType<T>(*this);
1513
6.19k
}
Exiv2::ValueType<std::__1::pair<int, int> >::clone_() const
Line
Count
Source
1511
8.09k
ValueType<T>* ValueType<T>::clone_() const {
1512
8.09k
  return new ValueType<T>(*this);
1513
8.09k
}
Exiv2::ValueType<float>::clone_() const
Line
Count
Source
1511
1.77k
ValueType<T>* ValueType<T>::clone_() const {
1512
1.77k
  return new ValueType<T>(*this);
1513
1.77k
}
Exiv2::ValueType<double>::clone_() const
Line
Count
Source
1511
2.30k
ValueType<T>* ValueType<T>::clone_() const {
1512
2.30k
  return new ValueType<T>(*this);
1513
2.30k
}
1514
1515
template <typename T>
1516
107
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
107
  auto end = value_.end();
1518
107
  auto i = value_.begin();
1519
6.72k
  while (i != end) {
1520
6.62k
    os << std::setprecision(15) << *i;
1521
6.62k
    if (++i != end)
1522
6.55k
      os << " ";
1523
6.62k
  }
1524
107
  return os;
1525
107
}
Exiv2::ValueType<unsigned short>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
6
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
6
  auto end = value_.end();
1518
6
  auto i = value_.begin();
1519
6
  while (i != end) {
1520
0
    os << std::setprecision(15) << *i;
1521
0
    if (++i != end)
1522
0
      os << " ";
1523
0
  }
1524
6
  return os;
1525
6
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
2
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
2
  auto end = value_.end();
1518
2
  auto i = value_.begin();
1519
2
  while (i != end) {
1520
0
    os << std::setprecision(15) << *i;
1521
0
    if (++i != end)
1522
0
      os << " ";
1523
0
  }
1524
2
  return os;
1525
2
}
Exiv2::ValueType<short>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
47
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
47
  auto end = value_.end();
1518
47
  auto i = value_.begin();
1519
3.87k
  while (i != end) {
1520
3.82k
    os << std::setprecision(15) << *i;
1521
3.82k
    if (++i != end)
1522
3.79k
      os << " ";
1523
3.82k
  }
1524
47
  return os;
1525
47
}
Exiv2::ValueType<int>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
26
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
26
  auto end = value_.end();
1518
26
  auto i = value_.begin();
1519
1.41k
  while (i != end) {
1520
1.39k
    os << std::setprecision(15) << *i;
1521
1.39k
    if (++i != end)
1522
1.37k
      os << " ";
1523
1.39k
  }
1524
26
  return os;
1525
26
}
Exiv2::ValueType<std::__1::pair<int, int> >::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
12
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
12
  auto end = value_.end();
1518
12
  auto i = value_.begin();
1519
1.02k
  while (i != end) {
1520
1.01k
    os << std::setprecision(15) << *i;
1521
1.01k
    if (++i != end)
1522
1.00k
      os << " ";
1523
1.01k
  }
1524
12
  return os;
1525
12
}
Exiv2::ValueType<float>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
4
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
4
  auto end = value_.end();
1518
4
  auto i = value_.begin();
1519
7
  while (i != end) {
1520
3
    os << std::setprecision(15) << *i;
1521
3
    if (++i != end)
1522
0
      os << " ";
1523
3
  }
1524
4
  return os;
1525
4
}
Exiv2::ValueType<double>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
10
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
10
  auto end = value_.end();
1518
10
  auto i = value_.begin();
1519
395
  while (i != end) {
1520
385
    os << std::setprecision(15) << *i;
1521
385
    if (++i != end)
1522
380
      os << " ";
1523
385
  }
1524
10
  return os;
1525
10
}
1526
1527
template <typename T>
1528
0
std::string ValueType<T>::toString(size_t n) const {
1529
0
  ok_ = true;
1530
0
  return Exiv2::toString<T>(value_.at(n));
1531
0
}
Unexecuted instantiation: Exiv2::ValueType<unsigned short>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<short>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<int>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<int, int> >::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<float>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<double>::toString(unsigned long) const
1532
1533
// Default implementation
1534
template <typename T>
1535
571
int64_t ValueType<T>::toInt64(size_t n) const {
1536
571
  ok_ = true;
1537
571
  return static_cast<int64_t>(value_.at(n));
1538
571
}
Exiv2::ValueType<unsigned short>::toInt64(unsigned long) const
Line
Count
Source
1535
504
int64_t ValueType<T>::toInt64(size_t n) const {
1536
504
  ok_ = true;
1537
504
  return static_cast<int64_t>(value_.at(n));
1538
504
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::toInt64(unsigned long) const
Exiv2::ValueType<short>::toInt64(unsigned long) const
Line
Count
Source
1535
17
int64_t ValueType<T>::toInt64(size_t n) const {
1536
17
  ok_ = true;
1537
17
  return static_cast<int64_t>(value_.at(n));
1538
17
}
Exiv2::ValueType<int>::toInt64(unsigned long) const
Line
Count
Source
1535
50
int64_t ValueType<T>::toInt64(size_t n) const {
1536
50
  ok_ = true;
1537
50
  return static_cast<int64_t>(value_.at(n));
1538
50
}
1539
template <typename T>
1540
234
uint32_t ValueType<T>::toUint32(size_t n) const {
1541
234
  ok_ = true;
1542
234
  return static_cast<uint32_t>(value_.at(n));
1543
234
}
Exiv2::ValueType<unsigned short>::toUint32(unsigned long) const
Line
Count
Source
1540
215
uint32_t ValueType<T>::toUint32(size_t n) const {
1541
215
  ok_ = true;
1542
215
  return static_cast<uint32_t>(value_.at(n));
1543
215
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::toUint32(unsigned long) const
Exiv2::ValueType<short>::toUint32(unsigned long) const
Line
Count
Source
1540
1
uint32_t ValueType<T>::toUint32(size_t n) const {
1541
1
  ok_ = true;
1542
1
  return static_cast<uint32_t>(value_.at(n));
1543
1
}
Exiv2::ValueType<int>::toUint32(unsigned long) const
Line
Count
Source
1540
18
uint32_t ValueType<T>::toUint32(size_t n) const {
1541
18
  ok_ = true;
1542
18
  return static_cast<uint32_t>(value_.at(n));
1543
18
}
1544
// #55 crash when value_.at(n).first == LONG_MIN
1545
#define LARGE_INT 1000000
1546
// Specialization for double
1547
template <>
1548
21
inline int64_t ValueType<double>::toInt64(size_t n) const {
1549
21
  return float_to_integer_helper<int64_t>(n);
1550
21
}
1551
1552
template <>
1553
37
inline uint32_t ValueType<double>::toUint32(size_t n) const {
1554
37
  return float_to_integer_helper<uint32_t>(n);
1555
37
}
1556
// Specialization for float
1557
template <>
1558
29
inline int64_t ValueType<float>::toInt64(size_t n) const {
1559
29
  return float_to_integer_helper<int64_t>(n);
1560
29
}
1561
template <>
1562
6
inline uint32_t ValueType<float>::toUint32(size_t n) const {
1563
6
  return float_to_integer_helper<uint32_t>(n);
1564
6
}
1565
// Specialization for rational
1566
template <>
1567
191
inline int64_t ValueType<Rational>::toInt64(size_t n) const {
1568
191
  return rational_to_integer_helper<int64_t>(n);
1569
191
}
1570
template <>
1571
8
inline uint32_t ValueType<Rational>::toUint32(size_t n) const {
1572
8
  return rational_to_integer_helper<uint32_t>(n);
1573
8
}
1574
// Specialization for unsigned rational
1575
template <>
1576
49
inline int64_t ValueType<URational>::toInt64(size_t n) const {
1577
49
  return rational_to_integer_helper<int64_t>(n);
1578
49
}
1579
template <>
1580
3
inline uint32_t ValueType<URational>::toUint32(size_t n) const {
1581
3
  return rational_to_integer_helper<uint32_t>(n);
1582
3
}
1583
// Default implementation
1584
template <typename T>
1585
0
float ValueType<T>::toFloat(size_t n) const {
1586
0
  ok_ = true;
1587
0
  return static_cast<float>(value_.at(n));
1588
0
}
Unexecuted instantiation: Exiv2::ValueType<unsigned short>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<short>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<int>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<float>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<double>::toFloat(unsigned long) const
1589
// Specialization for rational
1590
template <>
1591
0
inline float ValueType<Rational>::toFloat(size_t n) const {
1592
0
  ok_ = (value_.at(n).second != 0);
1593
0
  if (!ok_)
1594
0
    return 0.0f;
1595
0
  return static_cast<float>(value_.at(n).first) / value_.at(n).second;
1596
0
}
1597
// Specialization for unsigned rational
1598
template <>
1599
0
inline float ValueType<URational>::toFloat(size_t n) const {
1600
0
  ok_ = (value_.at(n).second != 0);
1601
0
  if (!ok_)
1602
0
    return 0.0f;
1603
0
  return static_cast<float>(value_.at(n).first) / value_.at(n).second;
1604
0
}
1605
// Default implementation
1606
template <typename T>
1607
0
Rational ValueType<T>::toRational(size_t n) const {
1608
0
  ok_ = true;
1609
0
  return {value_.at(n), 1};
1610
0
}
Unexecuted instantiation: Exiv2::ValueType<unsigned short>::toRational(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::toRational(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<short>::toRational(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<int>::toRational(unsigned long) const
1611
// Specialization for rational
1612
template <>
1613
0
inline Rational ValueType<Rational>::toRational(size_t n) const {
1614
0
  ok_ = true;
1615
0
  return {value_.at(n).first, value_.at(n).second};
1616
0
}
1617
// Specialization for unsigned rational
1618
template <>
1619
0
inline Rational ValueType<URational>::toRational(size_t n) const {
1620
0
  ok_ = true;
1621
0
  return {value_.at(n).first, value_.at(n).second};
1622
0
}
1623
// Specialization for float.
1624
template <>
1625
0
inline Rational ValueType<float>::toRational(size_t n) const {
1626
0
  ok_ = true;
1627
  // Warning: This is a very simple conversion, see floatToRationalCast()
1628
0
  return floatToRationalCast(value_.at(n));
1629
0
}
1630
// Specialization for double.
1631
template <>
1632
0
inline Rational ValueType<double>::toRational(size_t n) const {
1633
0
  ok_ = true;
1634
  // Warning: This is a very simple conversion, see floatToRationalCast()
1635
0
  return floatToRationalCast(static_cast<float>(value_.at(n)));
1636
0
}
1637
1638
template <typename T>
1639
39
size_t ValueType<T>::sizeDataArea() const {
1640
39
  return pDataArea_.size();
1641
39
}
Exiv2::ValueType<unsigned short>::sizeDataArea() const
Line
Count
Source
1639
13
size_t ValueType<T>::sizeDataArea() const {
1640
13
  return pDataArea_.size();
1641
13
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::sizeDataArea() const
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::sizeDataArea() const
Line
Count
Source
1639
2
size_t ValueType<T>::sizeDataArea() const {
1640
2
  return pDataArea_.size();
1641
2
}
Exiv2::ValueType<short>::sizeDataArea() const
Line
Count
Source
1639
8
size_t ValueType<T>::sizeDataArea() const {
1640
8
  return pDataArea_.size();
1641
8
}
Exiv2::ValueType<int>::sizeDataArea() const
Line
Count
Source
1639
2
size_t ValueType<T>::sizeDataArea() const {
1640
2
  return pDataArea_.size();
1641
2
}
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<int, int> >::sizeDataArea() const
Exiv2::ValueType<float>::sizeDataArea() const
Line
Count
Source
1639
8
size_t ValueType<T>::sizeDataArea() const {
1640
8
  return pDataArea_.size();
1641
8
}
Exiv2::ValueType<double>::sizeDataArea() const
Line
Count
Source
1639
6
size_t ValueType<T>::sizeDataArea() const {
1640
6
  return pDataArea_.size();
1641
6
}
1642
1643
template <typename T>
1644
40
DataBuf ValueType<T>::dataArea() const {
1645
40
  return {pDataArea_.data(), pDataArea_.size()};
1646
40
}
Exiv2::ValueType<unsigned short>::dataArea() const
Line
Count
Source
1644
23
DataBuf ValueType<T>::dataArea() const {
1645
23
  return {pDataArea_.data(), pDataArea_.size()};
1646
23
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::dataArea() const
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::dataArea() const
Line
Count
Source
1644
3
DataBuf ValueType<T>::dataArea() const {
1645
3
  return {pDataArea_.data(), pDataArea_.size()};
1646
3
}
Exiv2::ValueType<short>::dataArea() const
Line
Count
Source
1644
9
DataBuf ValueType<T>::dataArea() const {
1645
9
  return {pDataArea_.data(), pDataArea_.size()};
1646
9
}
Exiv2::ValueType<int>::dataArea() const
Line
Count
Source
1644
1
DataBuf ValueType<T>::dataArea() const {
1645
1
  return {pDataArea_.data(), pDataArea_.size()};
1646
1
}
Exiv2::ValueType<std::__1::pair<int, int> >::dataArea() const
Line
Count
Source
1644
1
DataBuf ValueType<T>::dataArea() const {
1645
1
  return {pDataArea_.data(), pDataArea_.size()};
1646
1
}
Exiv2::ValueType<float>::dataArea() const
Line
Count
Source
1644
3
DataBuf ValueType<T>::dataArea() const {
1645
3
  return {pDataArea_.data(), pDataArea_.size()};
1646
3
}
Unexecuted instantiation: Exiv2::ValueType<double>::dataArea() const
1647
1648
template <typename T>
1649
16
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
16
  if (len > 0)
1651
0
    pDataArea_ = Blob(buf, buf + len);
1652
16
  else
1653
16
    pDataArea_.clear();
1654
16
  return 0;
1655
16
}
Exiv2::ValueType<unsigned short>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1649
16
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
16
  if (len > 0)
1651
0
    pDataArea_ = Blob(buf, buf + len);
1652
16
  else
1653
16
    pDataArea_.clear();
1654
16
  return 0;
1655
16
}
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::setDataArea(unsigned char const*, unsigned long)
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::setDataArea(unsigned char const*, unsigned long)
Unexecuted instantiation: Exiv2::ValueType<short>::setDataArea(unsigned char const*, unsigned long)
Unexecuted instantiation: Exiv2::ValueType<int>::setDataArea(unsigned char const*, unsigned long)
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<int, int> >::setDataArea(unsigned char const*, unsigned long)
Unexecuted instantiation: Exiv2::ValueType<float>::setDataArea(unsigned char const*, unsigned long)
Unexecuted instantiation: Exiv2::ValueType<double>::setDataArea(unsigned char const*, unsigned long)
1656
}  // namespace Exiv2
1657
1658
#endif  // EXIV2_VALUE_HPP