Coverage Report

Created: 2025-11-11 06:55

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
82.8M
  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
95.1M
  TypeId typeId() const {
86
95.1M
    return type_;
87
95.1M
  }
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
56.3M
  UniquePtr clone() const {
94
56.3M
    return UniquePtr(clone_());
95
56.3M
  }
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
1.17k
  bool ok() const {
182
1.17k
    return ok_;
183
1.17k
  }
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
11.8M
  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
230k
inline std::ostream& operator<<(std::ostream& os, const Value& value) {
243
230k
  return value.write(os);
244
230k
}
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
244
  bool operator()(const std::string& str1, const std::string& str2) const {
796
244
    if (str1.size() != str2.size())
797
76
      return str1.size() > str2.size();
798
799
2.28k
    auto f = [](unsigned char a, unsigned char b) { return std::tolower(a) > std::tolower(b); };
800
168
    return std::lexicographical_compare(str1.begin(), str1.end(), str2.begin(), str2.end(), f);
801
244
  }
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
19.3M
inline TypeId getType<uint16_t>() {
1084
19.3M
  return unsignedShort;
1085
19.3M
}
1086
//! Specialization for an unsigned long
1087
template <>
1088
20.8k
inline TypeId getType<uint32_t>() {
1089
20.8k
  return unsignedLong;
1090
20.8k
}
1091
//! Specialization for an unsigned rational
1092
template <>
1093
33.9k
inline TypeId getType<URational>() {
1094
33.9k
  return unsignedRational;
1095
33.9k
}
1096
//! Specialization for a signed short
1097
template <>
1098
2.53M
inline TypeId getType<int16_t>() {
1099
2.53M
  return signedShort;
1100
2.53M
}
1101
//! Specialization for a signed long
1102
template <>
1103
40.7k
inline TypeId getType<int32_t>() {
1104
40.7k
  return signedLong;
1105
40.7k
}
1106
//! Specialization for a signed rational
1107
template <>
1108
22.7k
inline TypeId getType<Rational>() {
1109
22.7k
  return signedRational;
1110
22.7k
}
1111
//! Specialization for a float
1112
template <>
1113
6.49k
inline TypeId getType<float>() {
1114
6.49k
  return tiffFloat;
1115
6.49k
}
1116
//! Specialization for a double
1117
template <>
1118
5.27k
inline TypeId getType<double>() {
1119
5.27k
  return tiffDouble;
1120
5.27k
}
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
  //! Virtual destructor.
1148
  ~ValueType() override;
1149
  //@}
1150
1151
  //! @name Manipulators
1152
  //@{
1153
  //! Assignment operator.
1154
  ValueType<T>& operator=(const ValueType<T>& rhs);
1155
  int read(const byte* buf, size_t len, ByteOrder byteOrder) override;
1156
  /*!
1157
    @brief Set the data from a string of values of type T (e.g.,
1158
           "0 1 2 3" or "1/2 1/3 1/4" depending on what T is).
1159
           Generally, the accepted input format is the same as that
1160
           produced by the write() method.
1161
   */
1162
  int read(const std::string& buf) override;
1163
  /*!
1164
    @brief Set the data area. This method copies (clones) the buffer
1165
           pointed to by buf.
1166
   */
1167
  int setDataArea(const byte* buf, size_t len) override;
1168
  //@}
1169
1170
  //! @name Accessors
1171
  //@{
1172
  UniquePtr clone() const {
1173
    return UniquePtr(clone_());
1174
  }
1175
  size_t copy(byte* buf, ByteOrder byteOrder) const override;
1176
  size_t count() const override;
1177
  size_t size() const override;
1178
  std::ostream& write(std::ostream& os) const override;
1179
  /*!
1180
    @brief Return the <EM>n</EM>-th component of the value as a string.
1181
           The behaviour of this method may be undefined if there is no
1182
           <EM>n</EM>-th
1183
           component.
1184
   */
1185
  std::string toString(size_t n) const override;
1186
  int64_t toInt64(size_t n = 0) const override;
1187
  uint32_t toUint32(size_t n = 0) const override;
1188
  float toFloat(size_t n = 0) const override;
1189
  Rational toRational(size_t n = 0) const override;
1190
  //! Return the size of the data area.
1191
  size_t sizeDataArea() const override;
1192
  /*!
1193
    @brief Return a copy of the data area in a DataBuf. The caller owns
1194
           this copy and DataBuf ensures that it will be deleted.
1195
   */
1196
  DataBuf dataArea() const override;
1197
  //@}
1198
1199
  //! Container for values
1200
  using ValueList = std::vector<T>;
1201
1202
  // DATA
1203
  /*!
1204
    @brief The container for all values. In your application, if you know
1205
           what subclass of Value you're dealing with (and possibly the T)
1206
           then you can access this STL container through the usual
1207
           standard library functions.
1208
   */
1209
  ValueList value_;
1210
1211
 private:
1212
  //! Utility for toInt64, toUint32, etc.
1213
  template <typename I>
1214
8.28k
  I float_to_integer_helper(size_t n) const {
1215
8.28k
    const auto v = value_.at(n);
1216
8.28k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1217
7.04k
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1218
5.54k
      return static_cast<I>(std::lround(v));
1219
5.54k
    }
1220
2.73k
    return 0;
1221
8.28k
  }
long Exiv2::ValueType<double>::float_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1214
1.18k
  I float_to_integer_helper(size_t n) const {
1215
1.18k
    const auto v = value_.at(n);
1216
1.18k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1217
1.02k
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1218
782
      return static_cast<I>(std::lround(v));
1219
782
    }
1220
400
    return 0;
1221
1.18k
  }
unsigned int Exiv2::ValueType<double>::float_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1214
1.19k
  I float_to_integer_helper(size_t n) const {
1215
1.19k
    const auto v = value_.at(n);
1216
1.19k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1217
1.10k
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1218
609
      return static_cast<I>(std::lround(v));
1219
609
    }
1220
589
    return 0;
1221
1.19k
  }
long Exiv2::ValueType<float>::float_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1214
4.71k
  I float_to_integer_helper(size_t n) const {
1215
4.71k
    const auto v = value_.at(n);
1216
4.71k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1217
3.93k
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1218
3.25k
      return static_cast<I>(std::lround(v));
1219
3.25k
    }
1220
1.46k
    return 0;
1221
4.71k
  }
unsigned int Exiv2::ValueType<float>::float_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1214
1.18k
  I float_to_integer_helper(size_t n) const {
1215
1.18k
    const auto v = value_.at(n);
1216
1.18k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1217
987
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1218
905
      return static_cast<I>(std::lround(v));
1219
905
    }
1220
280
    return 0;
1221
1.18k
  }
1222
1223
  //! Utility for toInt64, toUint32, etc.
1224
  template <typename I>
1225
74.3k
  I rational_to_integer_helper(size_t n) const {
1226
74.3k
    auto a = value_.at(n).first;
1227
74.3k
    auto b = value_.at(n).second;
1228
1229
    // Protect against divide-by-zero.
1230
74.3k
    if (b <= 0) {
1231
11.0k
      return 0;
1232
11.0k
    }
1233
1234
    // Check for integer overflow.
1235
63.2k
#ifdef __cpp_if_constexpr
1236
63.2k
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1237
#else
1238
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1239
#endif
1240
      // conversion does not change sign
1241
35.3k
      const auto imin = std::numeric_limits<I>::min();
1242
35.3k
      const auto imax = std::numeric_limits<I>::max();
1243
35.3k
      if (imax < b || a < imin || imax < a) {
1244
0
        return 0;
1245
0
      }
1246
35.3k
#ifdef __cpp_if_constexpr
1247
35.3k
    } else if constexpr (std::is_signed_v<I>) {
1248
#else
1249
    } else if (std::is_signed<I>::value) {
1250
#endif
1251
      // conversion is from unsigned to signed
1252
13.1k
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1253
13.1k
      if (imax < b || imax < a) {
1254
0
        return 0;
1255
0
      }
1256
14.7k
    } else {
1257
      // conversion is from signed to unsigned
1258
14.7k
      const auto imax = std::numeric_limits<I>::max();
1259
14.7k
      if (a < 0) {
1260
1.18k
        return 0;
1261
1.18k
      }
1262
      // Inputs are not negative so convert them to unsigned.
1263
13.6k
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1264
13.6k
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1265
13.6k
      if (imax < b_u || imax < a_u) {
1266
0
        return 0;
1267
0
      }
1268
13.6k
    }
1269
1270
62.0k
    return static_cast<I>(a) / static_cast<I>(b);
1271
74.3k
  }
long Exiv2::ValueType<std::__1::pair<int, int> >::rational_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1225
40.4k
  I rational_to_integer_helper(size_t n) const {
1226
40.4k
    auto a = value_.at(n).first;
1227
40.4k
    auto b = value_.at(n).second;
1228
1229
    // Protect against divide-by-zero.
1230
40.4k
    if (b <= 0) {
1231
7.24k
      return 0;
1232
7.24k
    }
1233
1234
    // Check for integer overflow.
1235
33.2k
#ifdef __cpp_if_constexpr
1236
33.2k
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1237
#else
1238
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1239
#endif
1240
      // conversion does not change sign
1241
33.2k
      const auto imin = std::numeric_limits<I>::min();
1242
33.2k
      const auto imax = std::numeric_limits<I>::max();
1243
33.2k
      if (imax < b || a < imin || imax < a) {
1244
0
        return 0;
1245
0
      }
1246
33.2k
#ifdef __cpp_if_constexpr
1247
    } else if constexpr (std::is_signed_v<I>) {
1248
#else
1249
    } else if (std::is_signed<I>::value) {
1250
#endif
1251
      // conversion is from unsigned to signed
1252
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1253
      if (imax < b || imax < a) {
1254
        return 0;
1255
      }
1256
    } else {
1257
      // conversion is from signed to unsigned
1258
      const auto imax = std::numeric_limits<I>::max();
1259
      if (a < 0) {
1260
        return 0;
1261
      }
1262
      // Inputs are not negative so convert them to unsigned.
1263
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1264
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1265
      if (imax < b_u || imax < a_u) {
1266
        return 0;
1267
      }
1268
    }
1269
1270
33.2k
    return static_cast<I>(a) / static_cast<I>(b);
1271
40.4k
  }
unsigned int Exiv2::ValueType<std::__1::pair<int, int> >::rational_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1225
18.2k
  I rational_to_integer_helper(size_t n) const {
1226
18.2k
    auto a = value_.at(n).first;
1227
18.2k
    auto b = value_.at(n).second;
1228
1229
    // Protect against divide-by-zero.
1230
18.2k
    if (b <= 0) {
1231
3.42k
      return 0;
1232
3.42k
    }
1233
1234
    // Check for integer overflow.
1235
14.7k
#ifdef __cpp_if_constexpr
1236
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1237
#else
1238
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1239
#endif
1240
      // conversion does not change sign
1241
      const auto imin = std::numeric_limits<I>::min();
1242
      const auto imax = std::numeric_limits<I>::max();
1243
      if (imax < b || a < imin || imax < a) {
1244
        return 0;
1245
      }
1246
#ifdef __cpp_if_constexpr
1247
    } else if constexpr (std::is_signed_v<I>) {
1248
#else
1249
    } else if (std::is_signed<I>::value) {
1250
#endif
1251
      // conversion is from unsigned to signed
1252
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1253
      if (imax < b || imax < a) {
1254
        return 0;
1255
      }
1256
14.7k
    } else {
1257
      // conversion is from signed to unsigned
1258
14.7k
      const auto imax = std::numeric_limits<I>::max();
1259
14.7k
      if (a < 0) {
1260
1.18k
        return 0;
1261
1.18k
      }
1262
      // Inputs are not negative so convert them to unsigned.
1263
13.6k
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1264
13.6k
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1265
13.6k
      if (imax < b_u || imax < a_u) {
1266
0
        return 0;
1267
0
      }
1268
13.6k
    }
1269
1270
13.6k
    return static_cast<I>(a) / static_cast<I>(b);
1271
18.2k
  }
long Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::rational_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1225
13.3k
  I rational_to_integer_helper(size_t n) const {
1226
13.3k
    auto a = value_.at(n).first;
1227
13.3k
    auto b = value_.at(n).second;
1228
1229
    // Protect against divide-by-zero.
1230
13.3k
    if (b <= 0) {
1231
241
      return 0;
1232
241
    }
1233
1234
    // Check for integer overflow.
1235
13.1k
#ifdef __cpp_if_constexpr
1236
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1237
#else
1238
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1239
#endif
1240
      // conversion does not change sign
1241
      const auto imin = std::numeric_limits<I>::min();
1242
      const auto imax = std::numeric_limits<I>::max();
1243
      if (imax < b || a < imin || imax < a) {
1244
        return 0;
1245
      }
1246
#ifdef __cpp_if_constexpr
1247
13.1k
    } else if constexpr (std::is_signed_v<I>) {
1248
#else
1249
    } else if (std::is_signed<I>::value) {
1250
#endif
1251
      // conversion is from unsigned to signed
1252
13.1k
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1253
13.1k
      if (imax < b || imax < a) {
1254
0
        return 0;
1255
0
      }
1256
    } else {
1257
      // conversion is from signed to unsigned
1258
      const auto imax = std::numeric_limits<I>::max();
1259
      if (a < 0) {
1260
        return 0;
1261
      }
1262
      // Inputs are not negative so convert them to unsigned.
1263
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1264
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1265
      if (imax < b_u || imax < a_u) {
1266
        return 0;
1267
      }
1268
    }
1269
1270
13.1k
    return static_cast<I>(a) / static_cast<I>(b);
1271
13.3k
  }
unsigned int Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::rational_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1225
2.21k
  I rational_to_integer_helper(size_t n) const {
1226
2.21k
    auto a = value_.at(n).first;
1227
2.21k
    auto b = value_.at(n).second;
1228
1229
    // Protect against divide-by-zero.
1230
2.21k
    if (b <= 0) {
1231
135
      return 0;
1232
135
    }
1233
1234
    // Check for integer overflow.
1235
2.08k
#ifdef __cpp_if_constexpr
1236
2.08k
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1237
#else
1238
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1239
#endif
1240
      // conversion does not change sign
1241
2.08k
      const auto imin = std::numeric_limits<I>::min();
1242
2.08k
      const auto imax = std::numeric_limits<I>::max();
1243
2.08k
      if (imax < b || a < imin || imax < a) {
1244
0
        return 0;
1245
0
      }
1246
2.08k
#ifdef __cpp_if_constexpr
1247
    } else if constexpr (std::is_signed_v<I>) {
1248
#else
1249
    } else if (std::is_signed<I>::value) {
1250
#endif
1251
      // conversion is from unsigned to signed
1252
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1253
      if (imax < b || imax < a) {
1254
        return 0;
1255
      }
1256
    } else {
1257
      // conversion is from signed to unsigned
1258
      const auto imax = std::numeric_limits<I>::max();
1259
      if (a < 0) {
1260
        return 0;
1261
      }
1262
      // Inputs are not negative so convert them to unsigned.
1263
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1264
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1265
      if (imax < b_u || imax < a_u) {
1266
        return 0;
1267
      }
1268
    }
1269
1270
2.08k
    return static_cast<I>(a) / static_cast<I>(b);
1271
2.21k
  }
1272
1273
  //! Internal virtual copy constructor.
1274
  ValueType<T>* clone_() const override;
1275
1276
  // DATA
1277
  //! Pointer to the buffer, nullptr if none has been allocated
1278
  byte* pDataArea_{nullptr};
1279
  //! The current size of the buffer
1280
  size_t sizeDataArea_{0};
1281
};  // class ValueType
1282
1283
//! Unsigned short value type
1284
using UShortValue = ValueType<uint16_t>;
1285
//! Unsigned long value type
1286
using ULongValue = ValueType<uint32_t>;
1287
//! Unsigned rational value type
1288
using URationalValue = ValueType<URational>;
1289
//! Signed short value type
1290
using ShortValue = ValueType<int16_t>;
1291
//! Signed long value type
1292
using LongValue = ValueType<int32_t>;
1293
//! Signed rational value type
1294
using RationalValue = ValueType<Rational>;
1295
//! Float value type
1296
using FloatValue = ValueType<float>;
1297
//! Double value type
1298
using DoubleValue = ValueType<double>;
1299
1300
// *****************************************************************************
1301
// free functions, template and inline definitions
1302
1303
/*!
1304
  @brief Read a value of type T from the data buffer.
1305
1306
  We need this template function for the ValueType template classes.
1307
  There are only specializations of this function available; no default
1308
  implementation is provided.
1309
1310
  @param buf Pointer to the data buffer to read from.
1311
  @param byteOrder Applicable byte order (little or big endian).
1312
  @return A value of type T.
1313
 */
1314
template <typename T>
1315
T getValue(const byte* buf, ByteOrder byteOrder);
1316
// Specialization for a 2 byte unsigned short value.
1317
template <>
1318
20.2M
inline uint16_t getValue(const byte* buf, ByteOrder byteOrder) {
1319
20.2M
  return getUShort(buf, byteOrder);
1320
20.2M
}
1321
// Specialization for a 4 byte unsigned long value.
1322
template <>
1323
1.85M
inline uint32_t getValue(const byte* buf, ByteOrder byteOrder) {
1324
1.85M
  return getULong(buf, byteOrder);
1325
1.85M
}
1326
// Specialization for an 8 byte unsigned rational value.
1327
template <>
1328
219k
inline URational getValue(const byte* buf, ByteOrder byteOrder) {
1329
219k
  return getURational(buf, byteOrder);
1330
219k
}
1331
// Specialization for a 2 byte signed short value.
1332
template <>
1333
7.29M
inline int16_t getValue(const byte* buf, ByteOrder byteOrder) {
1334
7.29M
  return getShort(buf, byteOrder);
1335
7.29M
}
1336
// Specialization for a 4 byte signed long value.
1337
template <>
1338
8.78M
inline int32_t getValue(const byte* buf, ByteOrder byteOrder) {
1339
8.78M
  return getLong(buf, byteOrder);
1340
8.78M
}
1341
// Specialization for an 8 byte signed rational value.
1342
template <>
1343
579k
inline Rational getValue(const byte* buf, ByteOrder byteOrder) {
1344
579k
  return getRational(buf, byteOrder);
1345
579k
}
1346
// Specialization for a 4 byte float value.
1347
template <>
1348
117k
inline float getValue(const byte* buf, ByteOrder byteOrder) {
1349
117k
  return getFloat(buf, byteOrder);
1350
117k
}
1351
// Specialization for a 8 byte double value.
1352
template <>
1353
11.4k
inline double getValue(const byte* buf, ByteOrder byteOrder) {
1354
11.4k
  return getDouble(buf, byteOrder);
1355
11.4k
}
1356
1357
/*!
1358
  @brief Convert a value of type T to data, write the data to the data buffer.
1359
1360
  We need this template function for the ValueType template classes.
1361
  There are only specializations of this function available; no default
1362
  implementation is provided.
1363
1364
  @param buf Pointer to the data buffer to write to.
1365
  @param t Value to be converted.
1366
  @param byteOrder Applicable byte order (little or big endian).
1367
  @return The number of bytes written to the buffer.
1368
 */
1369
template <typename T>
1370
size_t toData(byte* buf, T t, ByteOrder byteOrder);
1371
/*!
1372
  @brief Specialization to write an unsigned short to the data buffer.
1373
         Return the number of bytes written.
1374
 */
1375
template <>
1376
306k
inline size_t toData(byte* buf, uint16_t t, ByteOrder byteOrder) {
1377
306k
  return us2Data(buf, t, byteOrder);
1378
306k
}
1379
/*!
1380
  @brief Specialization to write an unsigned long to the data buffer.
1381
         Return the number of bytes written.
1382
 */
1383
template <>
1384
42.0k
inline size_t toData(byte* buf, uint32_t t, ByteOrder byteOrder) {
1385
42.0k
  return ul2Data(buf, t, byteOrder);
1386
42.0k
}
1387
/*!
1388
  @brief Specialization to write an unsigned rational to the data buffer.
1389
         Return the number of bytes written.
1390
 */
1391
template <>
1392
314k
inline size_t toData(byte* buf, URational t, ByteOrder byteOrder) {
1393
314k
  return ur2Data(buf, t, byteOrder);
1394
314k
}
1395
/*!
1396
  @brief Specialization to write a signed short to the data buffer.
1397
         Return the number of bytes written.
1398
 */
1399
template <>
1400
133k
inline size_t toData(byte* buf, int16_t t, ByteOrder byteOrder) {
1401
133k
  return s2Data(buf, t, byteOrder);
1402
133k
}
1403
/*!
1404
  @brief Specialization to write a signed long to the data buffer.
1405
         Return the number of bytes written.
1406
 */
1407
template <>
1408
15.5k
inline size_t toData(byte* buf, int32_t t, ByteOrder byteOrder) {
1409
15.5k
  return l2Data(buf, t, byteOrder);
1410
15.5k
}
1411
/*!
1412
  @brief Specialization to write a signed rational to the data buffer.
1413
         Return the number of bytes written.
1414
 */
1415
template <>
1416
47.5k
inline size_t toData(byte* buf, Rational t, ByteOrder byteOrder) {
1417
47.5k
  return r2Data(buf, t, byteOrder);
1418
47.5k
}
1419
/*!
1420
  @brief Specialization to write a float to the data buffer.
1421
         Return the number of bytes written.
1422
 */
1423
template <>
1424
113k
inline size_t toData(byte* buf, float t, ByteOrder byteOrder) {
1425
113k
  return f2Data(buf, t, byteOrder);
1426
113k
}
1427
/*!
1428
  @brief Specialization to write a double to the data buffer.
1429
         Return the number of bytes written.
1430
 */
1431
template <>
1432
23.2k
inline size_t toData(byte* buf, double t, ByteOrder byteOrder) {
1433
23.2k
  return d2Data(buf, t, byteOrder);
1434
23.2k
}
1435
1436
template <typename T>
1437
21.9M
ValueType<T>::ValueType() : Value(getType<T>()) {
1438
21.9M
}
Exiv2::ValueType<unsigned short>::ValueType()
Line
Count
Source
1437
19.3M
ValueType<T>::ValueType() : Value(getType<T>()) {
1438
19.3M
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::ValueType()
Line
Count
Source
1437
33.9k
ValueType<T>::ValueType() : Value(getType<T>()) {
1438
33.9k
}
Exiv2::ValueType<short>::ValueType()
Line
Count
Source
1437
2.53M
ValueType<T>::ValueType() : Value(getType<T>()) {
1438
2.53M
}
Exiv2::ValueType<int>::ValueType()
Line
Count
Source
1437
40.7k
ValueType<T>::ValueType() : Value(getType<T>()) {
1438
40.7k
}
Exiv2::ValueType<std::__1::pair<int, int> >::ValueType()
Line
Count
Source
1437
22.7k
ValueType<T>::ValueType() : Value(getType<T>()) {
1438
22.7k
}
Exiv2::ValueType<float>::ValueType()
Line
Count
Source
1437
6.49k
ValueType<T>::ValueType() : Value(getType<T>()) {
1438
6.49k
}
Exiv2::ValueType<double>::ValueType()
Line
Count
Source
1437
5.27k
ValueType<T>::ValueType() : Value(getType<T>()) {
1438
5.27k
}
Exiv2::ValueType<unsigned int>::ValueType()
Line
Count
Source
1437
20.8k
ValueType<T>::ValueType() : Value(getType<T>()) {
1438
20.8k
}
1439
1440
template <typename T>
1441
ValueType<T>::ValueType(const byte* buf, size_t len, ByteOrder byteOrder, TypeId typeId) : Value(typeId) {
1442
  read(buf, len, byteOrder);
1443
}
1444
1445
template <typename T>
1446
ValueType<T>::ValueType(const T& val, TypeId typeId) : Value(typeId) {
1447
  value_.push_back(val);
1448
}
1449
1450
template <typename T>
1451
ValueType<T>::ValueType(const ValueType<T>& rhs) :
1452
44.5M
    Value(rhs.typeId()),
1453
44.5M
    value_(rhs.value_)
1454
1455
44.5M
{
1456
44.5M
  if (rhs.sizeDataArea_ > 0) {
1457
2.10k
    pDataArea_ = new byte[rhs.sizeDataArea_];
1458
2.10k
    std::memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_);
1459
2.10k
    sizeDataArea_ = rhs.sizeDataArea_;
1460
2.10k
  }
1461
44.5M
}
Exiv2::ValueType<unsigned short>::ValueType(Exiv2::ValueType<unsigned short> const&)
Line
Count
Source
1452
38.6M
    Value(rhs.typeId()),
1453
38.6M
    value_(rhs.value_)
1454
1455
38.6M
{
1456
38.6M
  if (rhs.sizeDataArea_ > 0) {
1457
122
    pDataArea_ = new byte[rhs.sizeDataArea_];
1458
122
    std::memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_);
1459
122
    sizeDataArea_ = rhs.sizeDataArea_;
1460
122
  }
1461
38.6M
}
Exiv2::ValueType<unsigned int>::ValueType(Exiv2::ValueType<unsigned int> const&)
Line
Count
Source
1452
490k
    Value(rhs.typeId()),
1453
490k
    value_(rhs.value_)
1454
1455
490k
{
1456
490k
  if (rhs.sizeDataArea_ > 0) {
1457
409
    pDataArea_ = new byte[rhs.sizeDataArea_];
1458
409
    std::memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_);
1459
409
    sizeDataArea_ = rhs.sizeDataArea_;
1460
409
  }
1461
490k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::ValueType(Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> > const&)
Line
Count
Source
1452
89.6k
    Value(rhs.typeId()),
1453
89.6k
    value_(rhs.value_)
1454
1455
89.6k
{
1456
89.6k
  if (rhs.sizeDataArea_ > 0) {
1457
48
    pDataArea_ = new byte[rhs.sizeDataArea_];
1458
48
    std::memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_);
1459
48
    sizeDataArea_ = rhs.sizeDataArea_;
1460
48
  }
1461
89.6k
}
Exiv2::ValueType<short>::ValueType(Exiv2::ValueType<short> const&)
Line
Count
Source
1452
5.07M
    Value(rhs.typeId()),
1453
5.07M
    value_(rhs.value_)
1454
1455
5.07M
{
1456
5.07M
  if (rhs.sizeDataArea_ > 0) {
1457
161
    pDataArea_ = new byte[rhs.sizeDataArea_];
1458
161
    std::memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_);
1459
161
    sizeDataArea_ = rhs.sizeDataArea_;
1460
161
  }
1461
5.07M
}
Exiv2::ValueType<int>::ValueType(Exiv2::ValueType<int> const&)
Line
Count
Source
1452
85.6k
    Value(rhs.typeId()),
1453
85.6k
    value_(rhs.value_)
1454
1455
85.6k
{
1456
85.6k
  if (rhs.sizeDataArea_ > 0) {
1457
58
    pDataArea_ = new byte[rhs.sizeDataArea_];
1458
58
    std::memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_);
1459
58
    sizeDataArea_ = rhs.sizeDataArea_;
1460
58
  }
1461
85.6k
}
Exiv2::ValueType<std::__1::pair<int, int> >::ValueType(Exiv2::ValueType<std::__1::pair<int, int> > const&)
Line
Count
Source
1452
54.0k
    Value(rhs.typeId()),
1453
54.0k
    value_(rhs.value_)
1454
1455
54.0k
{
1456
54.0k
  if (rhs.sizeDataArea_ > 0) {
1457
1.09k
    pDataArea_ = new byte[rhs.sizeDataArea_];
1458
1.09k
    std::memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_);
1459
1.09k
    sizeDataArea_ = rhs.sizeDataArea_;
1460
1.09k
  }
1461
54.0k
}
Exiv2::ValueType<float>::ValueType(Exiv2::ValueType<float> const&)
Line
Count
Source
1452
17.6k
    Value(rhs.typeId()),
1453
17.6k
    value_(rhs.value_)
1454
1455
17.6k
{
1456
17.6k
  if (rhs.sizeDataArea_ > 0) {
1457
152
    pDataArea_ = new byte[rhs.sizeDataArea_];
1458
152
    std::memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_);
1459
152
    sizeDataArea_ = rhs.sizeDataArea_;
1460
152
  }
1461
17.6k
}
Exiv2::ValueType<double>::ValueType(Exiv2::ValueType<double> const&)
Line
Count
Source
1452
16.8k
    Value(rhs.typeId()),
1453
16.8k
    value_(rhs.value_)
1454
1455
16.8k
{
1456
16.8k
  if (rhs.sizeDataArea_ > 0) {
1457
64
    pDataArea_ = new byte[rhs.sizeDataArea_];
1458
64
    std::memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_);
1459
64
    sizeDataArea_ = rhs.sizeDataArea_;
1460
64
  }
1461
16.8k
}
1462
1463
template <typename T>
1464
66.7M
ValueType<T>::~ValueType() {
1465
66.7M
  delete[] pDataArea_;
1466
66.7M
}
Exiv2::ValueType<unsigned short>::~ValueType()
Line
Count
Source
1464
58.0M
ValueType<T>::~ValueType() {
1465
58.0M
  delete[] pDataArea_;
1466
58.0M
}
Exiv2::ValueType<unsigned int>::~ValueType()
Line
Count
Source
1464
729k
ValueType<T>::~ValueType() {
1465
729k
  delete[] pDataArea_;
1466
729k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::~ValueType()
Line
Count
Source
1464
123k
ValueType<T>::~ValueType() {
1465
123k
  delete[] pDataArea_;
1466
123k
}
Exiv2::ValueType<short>::~ValueType()
Line
Count
Source
1464
7.61M
ValueType<T>::~ValueType() {
1465
7.61M
  delete[] pDataArea_;
1466
7.61M
}
Exiv2::ValueType<int>::~ValueType()
Line
Count
Source
1464
126k
ValueType<T>::~ValueType() {
1465
126k
  delete[] pDataArea_;
1466
126k
}
Exiv2::ValueType<std::__1::pair<int, int> >::~ValueType()
Line
Count
Source
1464
76.7k
ValueType<T>::~ValueType() {
1465
76.7k
  delete[] pDataArea_;
1466
76.7k
}
Exiv2::ValueType<float>::~ValueType()
Line
Count
Source
1464
24.1k
ValueType<T>::~ValueType() {
1465
24.1k
  delete[] pDataArea_;
1466
24.1k
}
Exiv2::ValueType<double>::~ValueType()
Line
Count
Source
1464
22.1k
ValueType<T>::~ValueType() {
1465
22.1k
  delete[] pDataArea_;
1466
22.1k
}
1467
1468
template <typename T>
1469
ValueType<T>& ValueType<T>::operator=(const ValueType<T>& rhs) {
1470
  if (this == &rhs)
1471
    return *this;
1472
  value_ = rhs.value_;
1473
1474
  byte* tmp = nullptr;
1475
  if (rhs.sizeDataArea_ > 0) {
1476
    tmp = new byte[rhs.sizeDataArea_];
1477
    std::memcpy(tmp, rhs.pDataArea_, rhs.sizeDataArea_);
1478
  }
1479
  delete[] pDataArea_;
1480
  pDataArea_ = tmp;
1481
  sizeDataArea_ = rhs.sizeDataArea_;
1482
1483
  return *this;
1484
}
1485
1486
template <typename T>
1487
22.1M
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1488
22.1M
  value_.clear();
1489
22.1M
  size_t ts = TypeInfo::typeSize(typeId());
1490
22.1M
  if (ts > 0 && len % ts != 0)
1491
2.28k
    len = (len / ts) * ts;
1492
61.3M
  for (size_t i = 0; i < len; i += ts) {
1493
39.1M
    value_.push_back(getValue<T>(buf + i, byteOrder));
1494
39.1M
  }
1495
22.1M
  return 0;
1496
22.1M
}
Exiv2::ValueType<unsigned short>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1487
19.3M
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1488
19.3M
  value_.clear();
1489
19.3M
  size_t ts = TypeInfo::typeSize(typeId());
1490
19.3M
  if (ts > 0 && len % ts != 0)
1491
1.00k
    len = (len / ts) * ts;
1492
39.5M
  for (size_t i = 0; i < len; i += ts) {
1493
20.2M
    value_.push_back(getValue<T>(buf + i, byteOrder));
1494
20.2M
  }
1495
19.3M
  return 0;
1496
19.3M
}
Exiv2::ValueType<unsigned int>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1487
218k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1488
218k
  value_.clear();
1489
218k
  size_t ts = TypeInfo::typeSize(typeId());
1490
218k
  if (ts > 0 && len % ts != 0)
1491
124
    len = (len / ts) * ts;
1492
2.07M
  for (size_t i = 0; i < len; i += ts) {
1493
1.85M
    value_.push_back(getValue<T>(buf + i, byteOrder));
1494
1.85M
  }
1495
218k
  return 0;
1496
218k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1487
33.8k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1488
33.8k
  value_.clear();
1489
33.8k
  size_t ts = TypeInfo::typeSize(typeId());
1490
33.8k
  if (ts > 0 && len % ts != 0)
1491
0
    len = (len / ts) * ts;
1492
253k
  for (size_t i = 0; i < len; i += ts) {
1493
219k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1494
219k
  }
1495
33.8k
  return 0;
1496
33.8k
}
Exiv2::ValueType<short>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1487
2.53M
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1488
2.53M
  value_.clear();
1489
2.53M
  size_t ts = TypeInfo::typeSize(typeId());
1490
2.53M
  if (ts > 0 && len % ts != 0)
1491
332
    len = (len / ts) * ts;
1492
9.82M
  for (size_t i = 0; i < len; i += ts) {
1493
7.29M
    value_.push_back(getValue<T>(buf + i, byteOrder));
1494
7.29M
  }
1495
2.53M
  return 0;
1496
2.53M
}
Exiv2::ValueType<int>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1487
40.7k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1488
40.7k
  value_.clear();
1489
40.7k
  size_t ts = TypeInfo::typeSize(typeId());
1490
40.7k
  if (ts > 0 && len % ts != 0)
1491
826
    len = (len / ts) * ts;
1492
8.82M
  for (size_t i = 0; i < len; i += ts) {
1493
8.78M
    value_.push_back(getValue<T>(buf + i, byteOrder));
1494
8.78M
  }
1495
40.7k
  return 0;
1496
40.7k
}
Exiv2::ValueType<std::__1::pair<int, int> >::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1487
22.7k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1488
22.7k
  value_.clear();
1489
22.7k
  size_t ts = TypeInfo::typeSize(typeId());
1490
22.7k
  if (ts > 0 && len % ts != 0)
1491
0
    len = (len / ts) * ts;
1492
601k
  for (size_t i = 0; i < len; i += ts) {
1493
579k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1494
579k
  }
1495
22.7k
  return 0;
1496
22.7k
}
Exiv2::ValueType<float>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1487
6.49k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1488
6.49k
  value_.clear();
1489
6.49k
  size_t ts = TypeInfo::typeSize(typeId());
1490
6.49k
  if (ts > 0 && len % ts != 0)
1491
0
    len = (len / ts) * ts;
1492
124k
  for (size_t i = 0; i < len; i += ts) {
1493
117k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1494
117k
  }
1495
6.49k
  return 0;
1496
6.49k
}
Exiv2::ValueType<double>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1487
5.27k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1488
5.27k
  value_.clear();
1489
5.27k
  size_t ts = TypeInfo::typeSize(typeId());
1490
5.27k
  if (ts > 0 && len % ts != 0)
1491
0
    len = (len / ts) * ts;
1492
16.7k
  for (size_t i = 0; i < len; i += ts) {
1493
11.4k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1494
11.4k
  }
1495
5.27k
  return 0;
1496
5.27k
}
1497
1498
template <typename T>
1499
3.36k
int ValueType<T>::read(const std::string& buf) {
1500
3.36k
  std::istringstream is(buf);
1501
3.36k
  T tmp;
1502
3.36k
  ValueList val;
1503
7.56k
  while (is >> tmp)
1504
4.19k
    val.push_back(tmp);
1505
3.36k
  if (!is.eof())
1506
9
    return 1;
1507
3.36k
  value_ = std::move(val);
1508
3.36k
  return 0;
1509
3.36k
}
Exiv2::ValueType<unsigned short>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
1499
681
int ValueType<T>::read(const std::string& buf) {
1500
681
  std::istringstream is(buf);
1501
681
  T tmp;
1502
681
  ValueList val;
1503
1.32k
  while (is >> tmp)
1504
639
    val.push_back(tmp);
1505
681
  if (!is.eof())
1506
9
    return 1;
1507
672
  value_ = std::move(val);
1508
672
  return 0;
1509
681
}
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&)
Exiv2::ValueType<short>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
1499
2.68k
int ValueType<T>::read(const std::string& buf) {
1500
2.68k
  std::istringstream is(buf);
1501
2.68k
  T tmp;
1502
2.68k
  ValueList val;
1503
6.24k
  while (is >> tmp)
1504
3.56k
    val.push_back(tmp);
1505
2.68k
  if (!is.eof())
1506
0
    return 1;
1507
2.68k
  value_ = std::move(val);
1508
2.68k
  return 0;
1509
2.68k
}
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&)
1510
1511
template <typename T>
1512
79.1k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1513
79.1k
  size_t offset = 0;
1514
996k
  for (const auto& val : value_) {
1515
996k
    offset += toData(buf + offset, val, byteOrder);
1516
996k
  }
1517
79.1k
  return offset;
1518
79.1k
}
Exiv2::ValueType<unsigned short>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1512
12.3k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1513
12.3k
  size_t offset = 0;
1514
306k
  for (const auto& val : value_) {
1515
306k
    offset += toData(buf + offset, val, byteOrder);
1516
306k
  }
1517
12.3k
  return offset;
1518
12.3k
}
Exiv2::ValueType<unsigned int>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1512
27.1k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1513
27.1k
  size_t offset = 0;
1514
42.0k
  for (const auto& val : value_) {
1515
42.0k
    offset += toData(buf + offset, val, byteOrder);
1516
42.0k
  }
1517
27.1k
  return offset;
1518
27.1k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1512
17.6k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1513
17.6k
  size_t offset = 0;
1514
314k
  for (const auto& val : value_) {
1515
314k
    offset += toData(buf + offset, val, byteOrder);
1516
314k
  }
1517
17.6k
  return offset;
1518
17.6k
}
Exiv2::ValueType<short>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1512
5.01k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1513
5.01k
  size_t offset = 0;
1514
133k
  for (const auto& val : value_) {
1515
133k
    offset += toData(buf + offset, val, byteOrder);
1516
133k
  }
1517
5.01k
  return offset;
1518
5.01k
}
Exiv2::ValueType<int>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1512
2.66k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1513
2.66k
  size_t offset = 0;
1514
15.5k
  for (const auto& val : value_) {
1515
15.5k
    offset += toData(buf + offset, val, byteOrder);
1516
15.5k
  }
1517
2.66k
  return offset;
1518
2.66k
}
Exiv2::ValueType<std::__1::pair<int, int> >::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1512
6.38k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1513
6.38k
  size_t offset = 0;
1514
47.5k
  for (const auto& val : value_) {
1515
47.5k
    offset += toData(buf + offset, val, byteOrder);
1516
47.5k
  }
1517
6.38k
  return offset;
1518
6.38k
}
Exiv2::ValueType<float>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1512
3.46k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1513
3.46k
  size_t offset = 0;
1514
113k
  for (const auto& val : value_) {
1515
113k
    offset += toData(buf + offset, val, byteOrder);
1516
113k
  }
1517
3.46k
  return offset;
1518
3.46k
}
Exiv2::ValueType<double>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1512
4.39k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1513
4.39k
  size_t offset = 0;
1514
23.2k
  for (const auto& val : value_) {
1515
23.2k
    offset += toData(buf + offset, val, byteOrder);
1516
23.2k
  }
1517
4.39k
  return offset;
1518
4.39k
}
1519
1520
template <typename T>
1521
31.4M
size_t ValueType<T>::count() const {
1522
31.4M
  return value_.size();
1523
31.4M
}
Exiv2::ValueType<unsigned short>::count() const
Line
Count
Source
1521
19.6M
size_t ValueType<T>::count() const {
1522
19.6M
  return value_.size();
1523
19.6M
}
Exiv2::ValueType<unsigned int>::count() const
Line
Count
Source
1521
321k
size_t ValueType<T>::count() const {
1522
321k
  return value_.size();
1523
321k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::count() const
Line
Count
Source
1521
72.6k
size_t ValueType<T>::count() const {
1522
72.6k
  return value_.size();
1523
72.6k
}
Exiv2::ValueType<short>::count() const
Line
Count
Source
1521
11.2M
size_t ValueType<T>::count() const {
1522
11.2M
  return value_.size();
1523
11.2M
}
Exiv2::ValueType<int>::count() const
Line
Count
Source
1521
68.0k
size_t ValueType<T>::count() const {
1522
68.0k
  return value_.size();
1523
68.0k
}
Exiv2::ValueType<std::__1::pair<int, int> >::count() const
Line
Count
Source
1521
61.5k
size_t ValueType<T>::count() const {
1522
61.5k
  return value_.size();
1523
61.5k
}
Exiv2::ValueType<float>::count() const
Line
Count
Source
1521
15.6k
size_t ValueType<T>::count() const {
1522
15.6k
  return value_.size();
1523
15.6k
}
Exiv2::ValueType<double>::count() const
Line
Count
Source
1521
12.2k
size_t ValueType<T>::count() const {
1522
12.2k
  return value_.size();
1523
12.2k
}
1524
1525
template <typename T>
1526
341k
size_t ValueType<T>::size() const {
1527
341k
  return TypeInfo::typeSize(typeId()) * value_.size();
1528
341k
}
Exiv2::ValueType<unsigned short>::size() const
Line
Count
Source
1526
65.3k
size_t ValueType<T>::size() const {
1527
65.3k
  return TypeInfo::typeSize(typeId()) * value_.size();
1528
65.3k
}
Exiv2::ValueType<unsigned int>::size() const
Line
Count
Source
1526
150k
size_t ValueType<T>::size() const {
1527
150k
  return TypeInfo::typeSize(typeId()) * value_.size();
1528
150k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::size() const
Line
Count
Source
1526
48.7k
size_t ValueType<T>::size() const {
1527
48.7k
  return TypeInfo::typeSize(typeId()) * value_.size();
1528
48.7k
}
Exiv2::ValueType<short>::size() const
Line
Count
Source
1526
17.7k
size_t ValueType<T>::size() const {
1527
17.7k
  return TypeInfo::typeSize(typeId()) * value_.size();
1528
17.7k
}
Exiv2::ValueType<int>::size() const
Line
Count
Source
1526
12.6k
size_t ValueType<T>::size() const {
1527
12.6k
  return TypeInfo::typeSize(typeId()) * value_.size();
1528
12.6k
}
Exiv2::ValueType<std::__1::pair<int, int> >::size() const
Line
Count
Source
1526
19.4k
size_t ValueType<T>::size() const {
1527
19.4k
  return TypeInfo::typeSize(typeId()) * value_.size();
1528
19.4k
}
Exiv2::ValueType<float>::size() const
Line
Count
Source
1526
13.2k
size_t ValueType<T>::size() const {
1527
13.2k
  return TypeInfo::typeSize(typeId()) * value_.size();
1528
13.2k
}
Exiv2::ValueType<double>::size() const
Line
Count
Source
1526
13.8k
size_t ValueType<T>::size() const {
1527
13.8k
  return TypeInfo::typeSize(typeId()) * value_.size();
1528
13.8k
}
1529
1530
template <typename T>
1531
44.5M
ValueType<T>* ValueType<T>::clone_() const {
1532
44.5M
  return new ValueType<T>(*this);
1533
44.5M
}
Exiv2::ValueType<unsigned short>::clone_() const
Line
Count
Source
1531
38.6M
ValueType<T>* ValueType<T>::clone_() const {
1532
38.6M
  return new ValueType<T>(*this);
1533
38.6M
}
Exiv2::ValueType<unsigned int>::clone_() const
Line
Count
Source
1531
490k
ValueType<T>* ValueType<T>::clone_() const {
1532
490k
  return new ValueType<T>(*this);
1533
490k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::clone_() const
Line
Count
Source
1531
89.6k
ValueType<T>* ValueType<T>::clone_() const {
1532
89.6k
  return new ValueType<T>(*this);
1533
89.6k
}
Exiv2::ValueType<short>::clone_() const
Line
Count
Source
1531
5.07M
ValueType<T>* ValueType<T>::clone_() const {
1532
5.07M
  return new ValueType<T>(*this);
1533
5.07M
}
Exiv2::ValueType<int>::clone_() const
Line
Count
Source
1531
85.6k
ValueType<T>* ValueType<T>::clone_() const {
1532
85.6k
  return new ValueType<T>(*this);
1533
85.6k
}
Exiv2::ValueType<std::__1::pair<int, int> >::clone_() const
Line
Count
Source
1531
54.0k
ValueType<T>* ValueType<T>::clone_() const {
1532
54.0k
  return new ValueType<T>(*this);
1533
54.0k
}
Exiv2::ValueType<float>::clone_() const
Line
Count
Source
1531
17.6k
ValueType<T>* ValueType<T>::clone_() const {
1532
17.6k
  return new ValueType<T>(*this);
1533
17.6k
}
Exiv2::ValueType<double>::clone_() const
Line
Count
Source
1531
16.8k
ValueType<T>* ValueType<T>::clone_() const {
1532
16.8k
  return new ValueType<T>(*this);
1533
16.8k
}
1534
1535
template <typename T>
1536
105k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1537
105k
  auto end = value_.end();
1538
105k
  auto i = value_.begin();
1539
1.05M
  while (i != end) {
1540
944k
    os << std::setprecision(15) << *i;
1541
944k
    if (++i != end)
1542
840k
      os << " ";
1543
944k
  }
1544
105k
  return os;
1545
105k
}
Exiv2::ValueType<unsigned short>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1536
39.6k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1537
39.6k
  auto end = value_.end();
1538
39.6k
  auto i = value_.begin();
1539
350k
  while (i != end) {
1540
310k
    os << std::setprecision(15) << *i;
1541
310k
    if (++i != end)
1542
271k
      os << " ";
1543
310k
  }
1544
39.6k
  return os;
1545
39.6k
}
Exiv2::ValueType<unsigned int>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1536
45.1k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1537
45.1k
  auto end = value_.end();
1538
45.1k
  auto i = value_.begin();
1539
357k
  while (i != end) {
1540
312k
    os << std::setprecision(15) << *i;
1541
312k
    if (++i != end)
1542
267k
      os << " ";
1543
312k
  }
1544
45.1k
  return os;
1545
45.1k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1536
3.20k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1537
3.20k
  auto end = value_.end();
1538
3.20k
  auto i = value_.begin();
1539
28.2k
  while (i != end) {
1540
25.0k
    os << std::setprecision(15) << *i;
1541
25.0k
    if (++i != end)
1542
22.0k
      os << " ";
1543
25.0k
  }
1544
3.20k
  return os;
1545
3.20k
}
Exiv2::ValueType<short>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1536
8.88k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1537
8.88k
  auto end = value_.end();
1538
8.88k
  auto i = value_.begin();
1539
192k
  while (i != end) {
1540
183k
    os << std::setprecision(15) << *i;
1541
183k
    if (++i != end)
1542
174k
      os << " ";
1543
183k
  }
1544
8.88k
  return os;
1545
8.88k
}
Exiv2::ValueType<int>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1536
2.76k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1537
2.76k
  auto end = value_.end();
1538
2.76k
  auto i = value_.begin();
1539
37.0k
  while (i != end) {
1540
34.3k
    os << std::setprecision(15) << *i;
1541
34.3k
    if (++i != end)
1542
31.6k
      os << " ";
1543
34.3k
  }
1544
2.76k
  return os;
1545
2.76k
}
Exiv2::ValueType<std::__1::pair<int, int> >::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1536
3.94k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1537
3.94k
  auto end = value_.end();
1538
3.94k
  auto i = value_.begin();
1539
25.3k
  while (i != end) {
1540
21.3k
    os << std::setprecision(15) << *i;
1541
21.3k
    if (++i != end)
1542
17.4k
      os << " ";
1543
21.3k
  }
1544
3.94k
  return os;
1545
3.94k
}
Exiv2::ValueType<float>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1536
1.39k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1537
1.39k
  auto end = value_.end();
1538
1.39k
  auto i = value_.begin();
1539
56.2k
  while (i != end) {
1540
54.8k
    os << std::setprecision(15) << *i;
1541
54.8k
    if (++i != end)
1542
53.4k
      os << " ";
1543
54.8k
  }
1544
1.39k
  return os;
1545
1.39k
}
Exiv2::ValueType<double>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1536
612
std::ostream& ValueType<T>::write(std::ostream& os) const {
1537
612
  auto end = value_.end();
1538
612
  auto i = value_.begin();
1539
3.05k
  while (i != end) {
1540
2.44k
    os << std::setprecision(15) << *i;
1541
2.44k
    if (++i != end)
1542
1.91k
      os << " ";
1543
2.44k
  }
1544
612
  return os;
1545
612
}
1546
1547
template <typename T>
1548
1.18k
std::string ValueType<T>::toString(size_t n) const {
1549
1.18k
  ok_ = true;
1550
1.18k
  return Exiv2::toString<T>(value_.at(n));
1551
1.18k
}
Exiv2::ValueType<unsigned short>::toString(unsigned long) const
Line
Count
Source
1548
664
std::string ValueType<T>::toString(size_t n) const {
1549
664
  ok_ = true;
1550
664
  return Exiv2::toString<T>(value_.at(n));
1551
664
}
Exiv2::ValueType<unsigned int>::toString(unsigned long) const
Line
Count
Source
1548
146
std::string ValueType<T>::toString(size_t n) const {
1549
146
  ok_ = true;
1550
146
  return Exiv2::toString<T>(value_.at(n));
1551
146
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::toString(unsigned long) const
Line
Count
Source
1548
206
std::string ValueType<T>::toString(size_t n) const {
1549
206
  ok_ = true;
1550
206
  return Exiv2::toString<T>(value_.at(n));
1551
206
}
Exiv2::ValueType<short>::toString(unsigned long) const
Line
Count
Source
1548
56
std::string ValueType<T>::toString(size_t n) const {
1549
56
  ok_ = true;
1550
56
  return Exiv2::toString<T>(value_.at(n));
1551
56
}
Exiv2::ValueType<int>::toString(unsigned long) const
Line
Count
Source
1548
38
std::string ValueType<T>::toString(size_t n) const {
1549
38
  ok_ = true;
1550
38
  return Exiv2::toString<T>(value_.at(n));
1551
38
}
Exiv2::ValueType<std::__1::pair<int, int> >::toString(unsigned long) const
Line
Count
Source
1548
22
std::string ValueType<T>::toString(size_t n) const {
1549
22
  ok_ = true;
1550
22
  return Exiv2::toString<T>(value_.at(n));
1551
22
}
Exiv2::ValueType<float>::toString(unsigned long) const
Line
Count
Source
1548
18
std::string ValueType<T>::toString(size_t n) const {
1549
18
  ok_ = true;
1550
18
  return Exiv2::toString<T>(value_.at(n));
1551
18
}
Exiv2::ValueType<double>::toString(unsigned long) const
Line
Count
Source
1548
34
std::string ValueType<T>::toString(size_t n) const {
1549
34
  ok_ = true;
1550
34
  return Exiv2::toString<T>(value_.at(n));
1551
34
}
1552
1553
// Default implementation
1554
template <typename T>
1555
9.04M
int64_t ValueType<T>::toInt64(size_t n) const {
1556
9.04M
  ok_ = true;
1557
9.04M
  return static_cast<int64_t>(value_.at(n));
1558
9.04M
}
Exiv2::ValueType<unsigned short>::toInt64(unsigned long) const
Line
Count
Source
1555
317k
int64_t ValueType<T>::toInt64(size_t n) const {
1556
317k
  ok_ = true;
1557
317k
  return static_cast<int64_t>(value_.at(n));
1558
317k
}
Exiv2::ValueType<unsigned int>::toInt64(unsigned long) const
Line
Count
Source
1555
24.7k
int64_t ValueType<T>::toInt64(size_t n) const {
1556
24.7k
  ok_ = true;
1557
24.7k
  return static_cast<int64_t>(value_.at(n));
1558
24.7k
}
Exiv2::ValueType<short>::toInt64(unsigned long) const
Line
Count
Source
1555
8.68M
int64_t ValueType<T>::toInt64(size_t n) const {
1556
8.68M
  ok_ = true;
1557
8.68M
  return static_cast<int64_t>(value_.at(n));
1558
8.68M
}
Exiv2::ValueType<int>::toInt64(unsigned long) const
Line
Count
Source
1555
16.7k
int64_t ValueType<T>::toInt64(size_t n) const {
1556
16.7k
  ok_ = true;
1557
16.7k
  return static_cast<int64_t>(value_.at(n));
1558
16.7k
}
1559
template <typename T>
1560
29.3k
uint32_t ValueType<T>::toUint32(size_t n) const {
1561
29.3k
  ok_ = true;
1562
29.3k
  return static_cast<uint32_t>(value_.at(n));
1563
29.3k
}
Exiv2::ValueType<unsigned short>::toUint32(unsigned long) const
Line
Count
Source
1560
13.5k
uint32_t ValueType<T>::toUint32(size_t n) const {
1561
13.5k
  ok_ = true;
1562
13.5k
  return static_cast<uint32_t>(value_.at(n));
1563
13.5k
}
Exiv2::ValueType<unsigned int>::toUint32(unsigned long) const
Line
Count
Source
1560
4.24k
uint32_t ValueType<T>::toUint32(size_t n) const {
1561
4.24k
  ok_ = true;
1562
4.24k
  return static_cast<uint32_t>(value_.at(n));
1563
4.24k
}
Exiv2::ValueType<short>::toUint32(unsigned long) const
Line
Count
Source
1560
9.57k
uint32_t ValueType<T>::toUint32(size_t n) const {
1561
9.57k
  ok_ = true;
1562
9.57k
  return static_cast<uint32_t>(value_.at(n));
1563
9.57k
}
Exiv2::ValueType<int>::toUint32(unsigned long) const
Line
Count
Source
1560
1.94k
uint32_t ValueType<T>::toUint32(size_t n) const {
1561
1.94k
  ok_ = true;
1562
1.94k
  return static_cast<uint32_t>(value_.at(n));
1563
1.94k
}
1564
// #55 crash when value_.at(n).first == LONG_MIN
1565
#define LARGE_INT 1000000
1566
// Specialization for double
1567
template <>
1568
1.18k
inline int64_t ValueType<double>::toInt64(size_t n) const {
1569
1.18k
  return float_to_integer_helper<int64_t>(n);
1570
1.18k
}
1571
1572
template <>
1573
1.19k
inline uint32_t ValueType<double>::toUint32(size_t n) const {
1574
1.19k
  return float_to_integer_helper<uint32_t>(n);
1575
1.19k
}
1576
// Specialization for float
1577
template <>
1578
4.71k
inline int64_t ValueType<float>::toInt64(size_t n) const {
1579
4.71k
  return float_to_integer_helper<int64_t>(n);
1580
4.71k
}
1581
template <>
1582
1.18k
inline uint32_t ValueType<float>::toUint32(size_t n) const {
1583
1.18k
  return float_to_integer_helper<uint32_t>(n);
1584
1.18k
}
1585
// Specialization for rational
1586
template <>
1587
40.4k
inline int64_t ValueType<Rational>::toInt64(size_t n) const {
1588
40.4k
  return rational_to_integer_helper<int64_t>(n);
1589
40.4k
}
1590
template <>
1591
18.2k
inline uint32_t ValueType<Rational>::toUint32(size_t n) const {
1592
18.2k
  return rational_to_integer_helper<uint32_t>(n);
1593
18.2k
}
1594
// Specialization for unsigned rational
1595
template <>
1596
13.3k
inline int64_t ValueType<URational>::toInt64(size_t n) const {
1597
13.3k
  return rational_to_integer_helper<int64_t>(n);
1598
13.3k
}
1599
template <>
1600
2.21k
inline uint32_t ValueType<URational>::toUint32(size_t n) const {
1601
2.21k
  return rational_to_integer_helper<uint32_t>(n);
1602
2.21k
}
1603
// Default implementation
1604
template <typename T>
1605
7.50k
float ValueType<T>::toFloat(size_t n) const {
1606
7.50k
  ok_ = true;
1607
7.50k
  return static_cast<float>(value_.at(n));
1608
7.50k
}
Exiv2::ValueType<unsigned short>::toFloat(unsigned long) const
Line
Count
Source
1605
7.03k
float ValueType<T>::toFloat(size_t n) const {
1606
7.03k
  ok_ = true;
1607
7.03k
  return static_cast<float>(value_.at(n));
1608
7.03k
}
Exiv2::ValueType<unsigned int>::toFloat(unsigned long) const
Line
Count
Source
1605
149
float ValueType<T>::toFloat(size_t n) const {
1606
149
  ok_ = true;
1607
149
  return static_cast<float>(value_.at(n));
1608
149
}
Exiv2::ValueType<short>::toFloat(unsigned long) const
Line
Count
Source
1605
143
float ValueType<T>::toFloat(size_t n) const {
1606
143
  ok_ = true;
1607
143
  return static_cast<float>(value_.at(n));
1608
143
}
Exiv2::ValueType<int>::toFloat(unsigned long) const
Line
Count
Source
1605
58
float ValueType<T>::toFloat(size_t n) const {
1606
58
  ok_ = true;
1607
58
  return static_cast<float>(value_.at(n));
1608
58
}
Exiv2::ValueType<float>::toFloat(unsigned long) const
Line
Count
Source
1605
45
float ValueType<T>::toFloat(size_t n) const {
1606
45
  ok_ = true;
1607
45
  return static_cast<float>(value_.at(n));
1608
45
}
Exiv2::ValueType<double>::toFloat(unsigned long) const
Line
Count
Source
1605
77
float ValueType<T>::toFloat(size_t n) const {
1606
77
  ok_ = true;
1607
77
  return static_cast<float>(value_.at(n));
1608
77
}
1609
// Specialization for rational
1610
template <>
1611
524
inline float ValueType<Rational>::toFloat(size_t n) const {
1612
524
  ok_ = (value_.at(n).second != 0);
1613
524
  if (!ok_)
1614
6
    return 0.0f;
1615
518
  return static_cast<float>(value_.at(n).first) / value_.at(n).second;
1616
524
}
1617
// Specialization for unsigned rational
1618
template <>
1619
2.76k
inline float ValueType<URational>::toFloat(size_t n) const {
1620
2.76k
  ok_ = (value_.at(n).second != 0);
1621
2.76k
  if (!ok_)
1622
15
    return 0.0f;
1623
2.74k
  return static_cast<float>(value_.at(n).first) / value_.at(n).second;
1624
2.76k
}
1625
// Default implementation
1626
template <typename T>
1627
504
Rational ValueType<T>::toRational(size_t n) const {
1628
504
  ok_ = true;
1629
504
  return {value_.at(n), 1};
1630
504
}
Exiv2::ValueType<unsigned short>::toRational(unsigned long) const
Line
Count
Source
1627
44
Rational ValueType<T>::toRational(size_t n) const {
1628
44
  ok_ = true;
1629
44
  return {value_.at(n), 1};
1630
44
}
Exiv2::ValueType<unsigned int>::toRational(unsigned long) const
Line
Count
Source
1627
268
Rational ValueType<T>::toRational(size_t n) const {
1628
268
  ok_ = true;
1629
268
  return {value_.at(n), 1};
1630
268
}
Exiv2::ValueType<short>::toRational(unsigned long) const
Line
Count
Source
1627
90
Rational ValueType<T>::toRational(size_t n) const {
1628
90
  ok_ = true;
1629
90
  return {value_.at(n), 1};
1630
90
}
Exiv2::ValueType<int>::toRational(unsigned long) const
Line
Count
Source
1627
102
Rational ValueType<T>::toRational(size_t n) const {
1628
102
  ok_ = true;
1629
102
  return {value_.at(n), 1};
1630
102
}
1631
// Specialization for rational
1632
template <>
1633
2.62k
inline Rational ValueType<Rational>::toRational(size_t n) const {
1634
2.62k
  ok_ = true;
1635
2.62k
  return {value_.at(n).first, value_.at(n).second};
1636
2.62k
}
1637
// Specialization for unsigned rational
1638
template <>
1639
12.7k
inline Rational ValueType<URational>::toRational(size_t n) const {
1640
12.7k
  ok_ = true;
1641
12.7k
  return {value_.at(n).first, value_.at(n).second};
1642
12.7k
}
1643
// Specialization for float.
1644
template <>
1645
1.60k
inline Rational ValueType<float>::toRational(size_t n) const {
1646
1.60k
  ok_ = true;
1647
  // Warning: This is a very simple conversion, see floatToRationalCast()
1648
1.60k
  return floatToRationalCast(value_.at(n));
1649
1.60k
}
1650
// Specialization for double.
1651
template <>
1652
474
inline Rational ValueType<double>::toRational(size_t n) const {
1653
474
  ok_ = true;
1654
  // Warning: This is a very simple conversion, see floatToRationalCast()
1655
474
  return floatToRationalCast(static_cast<float>(value_.at(n)));
1656
474
}
1657
1658
template <typename T>
1659
5.24k
size_t ValueType<T>::sizeDataArea() const {
1660
5.24k
  return sizeDataArea_;
1661
5.24k
}
Exiv2::ValueType<unsigned short>::sizeDataArea() const
Line
Count
Source
1659
811
size_t ValueType<T>::sizeDataArea() const {
1660
811
  return sizeDataArea_;
1661
811
}
Exiv2::ValueType<unsigned int>::sizeDataArea() const
Line
Count
Source
1659
919
size_t ValueType<T>::sizeDataArea() const {
1660
919
  return sizeDataArea_;
1661
919
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::sizeDataArea() const
Line
Count
Source
1659
338
size_t ValueType<T>::sizeDataArea() const {
1660
338
  return sizeDataArea_;
1661
338
}
Exiv2::ValueType<short>::sizeDataArea() const
Line
Count
Source
1659
2.35k
size_t ValueType<T>::sizeDataArea() const {
1660
2.35k
  return sizeDataArea_;
1661
2.35k
}
Exiv2::ValueType<int>::sizeDataArea() const
Line
Count
Source
1659
79
size_t ValueType<T>::sizeDataArea() const {
1660
79
  return sizeDataArea_;
1661
79
}
Exiv2::ValueType<std::__1::pair<int, int> >::sizeDataArea() const
Line
Count
Source
1659
524
size_t ValueType<T>::sizeDataArea() const {
1660
524
  return sizeDataArea_;
1661
524
}
Exiv2::ValueType<float>::sizeDataArea() const
Line
Count
Source
1659
146
size_t ValueType<T>::sizeDataArea() const {
1660
146
  return sizeDataArea_;
1661
146
}
Exiv2::ValueType<double>::sizeDataArea() const
Line
Count
Source
1659
74
size_t ValueType<T>::sizeDataArea() const {
1660
74
  return sizeDataArea_;
1661
74
}
1662
1663
template <typename T>
1664
367
DataBuf ValueType<T>::dataArea() const {
1665
367
  return {pDataArea_, sizeDataArea_};
1666
367
}
Exiv2::ValueType<unsigned short>::dataArea() const
Line
Count
Source
1664
53
DataBuf ValueType<T>::dataArea() const {
1665
53
  return {pDataArea_, sizeDataArea_};
1666
53
}
Exiv2::ValueType<unsigned int>::dataArea() const
Line
Count
Source
1664
189
DataBuf ValueType<T>::dataArea() const {
1665
189
  return {pDataArea_, sizeDataArea_};
1666
189
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::dataArea() const
Line
Count
Source
1664
29
DataBuf ValueType<T>::dataArea() const {
1665
29
  return {pDataArea_, sizeDataArea_};
1666
29
}
Exiv2::ValueType<short>::dataArea() const
Line
Count
Source
1664
36
DataBuf ValueType<T>::dataArea() const {
1665
36
  return {pDataArea_, sizeDataArea_};
1666
36
}
Exiv2::ValueType<int>::dataArea() const
Line
Count
Source
1664
19
DataBuf ValueType<T>::dataArea() const {
1665
19
  return {pDataArea_, sizeDataArea_};
1666
19
}
Exiv2::ValueType<std::__1::pair<int, int> >::dataArea() const
Line
Count
Source
1664
27
DataBuf ValueType<T>::dataArea() const {
1665
27
  return {pDataArea_, sizeDataArea_};
1666
27
}
Exiv2::ValueType<float>::dataArea() const
Line
Count
Source
1664
10
DataBuf ValueType<T>::dataArea() const {
1665
10
  return {pDataArea_, sizeDataArea_};
1666
10
}
Exiv2::ValueType<double>::dataArea() const
Line
Count
Source
1664
4
DataBuf ValueType<T>::dataArea() const {
1665
4
  return {pDataArea_, sizeDataArea_};
1666
4
}
1667
1668
template <typename T>
1669
2.30k
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1670
2.30k
  byte* tmp = nullptr;
1671
2.30k
  if (len > 0) {
1672
1.55k
    tmp = new byte[len];
1673
1.55k
    std::memcpy(tmp, buf, len);
1674
1.55k
  }
1675
2.30k
  delete[] pDataArea_;
1676
2.30k
  pDataArea_ = tmp;
1677
2.30k
  sizeDataArea_ = len;
1678
2.30k
  return 0;
1679
2.30k
}
Exiv2::ValueType<unsigned short>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1669
195
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1670
195
  byte* tmp = nullptr;
1671
195
  if (len > 0) {
1672
162
    tmp = new byte[len];
1673
162
    std::memcpy(tmp, buf, len);
1674
162
  }
1675
195
  delete[] pDataArea_;
1676
195
  pDataArea_ = tmp;
1677
195
  sizeDataArea_ = len;
1678
195
  return 0;
1679
195
}
Exiv2::ValueType<unsigned int>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1669
310
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1670
310
  byte* tmp = nullptr;
1671
310
  if (len > 0) {
1672
229
    tmp = new byte[len];
1673
229
    std::memcpy(tmp, buf, len);
1674
229
  }
1675
310
  delete[] pDataArea_;
1676
310
  pDataArea_ = tmp;
1677
310
  sizeDataArea_ = len;
1678
310
  return 0;
1679
310
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1669
131
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1670
131
  byte* tmp = nullptr;
1671
131
  if (len > 0) {
1672
66
    tmp = new byte[len];
1673
66
    std::memcpy(tmp, buf, len);
1674
66
  }
1675
131
  delete[] pDataArea_;
1676
131
  pDataArea_ = tmp;
1677
131
  sizeDataArea_ = len;
1678
131
  return 0;
1679
131
}
Exiv2::ValueType<short>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1669
230
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1670
230
  byte* tmp = nullptr;
1671
230
  if (len > 0) {
1672
154
    tmp = new byte[len];
1673
154
    std::memcpy(tmp, buf, len);
1674
154
  }
1675
230
  delete[] pDataArea_;
1676
230
  pDataArea_ = tmp;
1677
230
  sizeDataArea_ = len;
1678
230
  return 0;
1679
230
}
Exiv2::ValueType<int>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1669
119
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1670
119
  byte* tmp = nullptr;
1671
119
  if (len > 0) {
1672
61
    tmp = new byte[len];
1673
61
    std::memcpy(tmp, buf, len);
1674
61
  }
1675
119
  delete[] pDataArea_;
1676
119
  pDataArea_ = tmp;
1677
119
  sizeDataArea_ = len;
1678
119
  return 0;
1679
119
}
Exiv2::ValueType<std::__1::pair<int, int> >::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1669
883
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1670
883
  byte* tmp = nullptr;
1671
883
  if (len > 0) {
1672
637
    tmp = new byte[len];
1673
637
    std::memcpy(tmp, buf, len);
1674
637
  }
1675
883
  delete[] pDataArea_;
1676
883
  pDataArea_ = tmp;
1677
883
  sizeDataArea_ = len;
1678
883
  return 0;
1679
883
}
Exiv2::ValueType<float>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1669
284
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1670
284
  byte* tmp = nullptr;
1671
284
  if (len > 0) {
1672
157
    tmp = new byte[len];
1673
157
    std::memcpy(tmp, buf, len);
1674
157
  }
1675
284
  delete[] pDataArea_;
1676
284
  pDataArea_ = tmp;
1677
284
  sizeDataArea_ = len;
1678
284
  return 0;
1679
284
}
Exiv2::ValueType<double>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1669
157
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1670
157
  byte* tmp = nullptr;
1671
157
  if (len > 0) {
1672
88
    tmp = new byte[len];
1673
88
    std::memcpy(tmp, buf, len);
1674
88
  }
1675
157
  delete[] pDataArea_;
1676
157
  pDataArea_ = tmp;
1677
157
  sizeDataArea_ = len;
1678
157
  return 0;
1679
157
}
1680
}  // namespace Exiv2
1681
1682
#endif  // EXIV2_VALUE_HPP