Coverage Report

Created: 2026-07-10 06:09

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
10.2M
  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
6.39M
  TypeId typeId() const {
86
6.39M
    return type_;
87
6.39M
  }
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
7.99M
  UniquePtr clone() const {
94
7.99M
    return UniquePtr(clone_());
95
7.99M
  }
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
102k
  bool ok() const {
182
102k
    return ok_;
183
102k
  }
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
7.36M
  Value(const Value&) = default;
226
  /*!
227
    @brief Assignment operator. Protected so that it can only be used
228
           by subclasses but not directly.
229
   */
230
  Value& operator=(const Value&) = default;
231
  // DATA
232
  mutable bool ok_{true};  //!< Indicates the status of the previous to<Type> conversion
233
234
 private:
235
  //! Internal virtual copy constructor.
236
  virtual Value* clone_() const = 0;
237
  // DATA
238
  TypeId type_;  //!< Type of the data
239
};
240
241
//! Output operator for Value types
242
0
inline std::ostream& operator<<(std::ostream& os, const Value& value) {
243
0
  return value.write(os);
244
0
}
245
246
//! %Value for an undefined data type.
247
class EXIV2API DataValue : public Value {
248
 public:
249
  //! Shortcut for a %DataValue auto pointer.
250
  using UniquePtr = std::unique_ptr<DataValue>;
251
252
  explicit DataValue(TypeId typeId = undefined);
253
254
  DataValue(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder, TypeId typeId = undefined);
255
256
  //! @name Manipulators
257
  //@{
258
  int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
259
  //! Set the data from a string of integer values (e.g., "0 1 2 3")
260
  int read(const std::string& buf) override;
261
  //@}
262
263
  //! @name Accessors
264
  //@{
265
0
  UniquePtr clone() const {
266
0
    return UniquePtr(clone_());
267
0
  }
268
  /*!
269
    @brief Write value to a character data buffer.
270
271
    @note The byte order is required by the interface but not used by this
272
          method, so just use the default.
273
274
    The user must ensure that the buffer has enough memory. Otherwise
275
    the call results in undefined behaviour.
276
277
    @param buf Data buffer to write to.
278
    @param byteOrder Byte order. Not needed.
279
    @return Number of characters written.
280
  */
281
  size_t copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
282
  size_t count() const override;
283
  size_t size() const override;
284
  std::ostream& write(std::ostream& os) const override;
285
  /*!
286
    @brief Return the <EM>n</EM>-th component of the value as a string.
287
           The behaviour of this method may be undefined if there is no
288
           <EM>n</EM>-th component.
289
   */
290
  std::string toString(size_t n) const override;
291
  int64_t toInt64(size_t n = 0) const override;
292
  uint32_t toUint32(size_t n = 0) const override;
293
  float toFloat(size_t n = 0) const override;
294
  Rational toRational(size_t n = 0) const override;
295
  //@}
296
297
 private:
298
  //! Internal virtual copy constructor.
299
  DataValue* clone_() const override;
300
301
 public:
302
  //! Type used to store the data.
303
  using ValueType = std::vector<byte>;
304
  // DATA
305
  ValueType value_;  //!< Stores the data value
306
307
};  // class DataValue
308
309
/*!
310
  @brief Abstract base class for a string based %Value type.
311
312
  Uses a std::string to store the value and implements defaults for
313
  most operations.
314
 */
315
class EXIV2API StringValueBase : public Value {
316
  using Value::Value;
317
318
 public:
319
  //! Shortcut for a %StringValueBase auto pointer.
320
  using UniquePtr = std::unique_ptr<StringValueBase>;
321
322
  //! @name Creators
323
  //@{
324
  //! Constructor for subclasses
325
  StringValueBase(TypeId typeId, const std::string& buf);
326
  //@}
327
328
  //! @name Manipulators
329
  //@{
330
  //! Read the value from buf. This default implementation uses buf as it is.
331
  int read(const std::string& buf) override;
332
  int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
333
  //@}
334
335
  //! @name Accessors
336
  //@{
337
0
  UniquePtr clone() const {
338
0
    return UniquePtr(clone_());
339
0
  }
340
  /*!
341
    @brief Write value to a character data buffer.
342
343
    The user must ensure that the buffer has enough memory. Otherwise
344
    the call results in undefined behaviour.
345
346
    @note The byte order is required by the interface but not used by this
347
          method, so just use the default.
348
349
    @param buf Data buffer to write to.
350
    @param byteOrder Byte order. Not used.
351
    @return Number of characters written.
352
  */
353
  size_t copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
354
  size_t count() const override;
355
  size_t size() const override;
356
  int64_t toInt64(size_t n = 0) const override;
357
  uint32_t toUint32(size_t n = 0) const override;
358
  float toFloat(size_t n = 0) const override;
359
  Rational toRational(size_t n = 0) const override;
360
  std::ostream& write(std::ostream& os) const override;
361
  //@}
362
363
 protected:
364
  //! Internal virtual copy constructor.
365
  StringValueBase* clone_() const override = 0;
366
367
 public:
368
  // DATA
369
  std::string value_;  //!< Stores the string value.
370
371
};  // class StringValueBase
372
373
/*!
374
  @brief %Value for string type.
375
376
  This can be a plain Ascii string or a multiple byte encoded string. It is
377
  left to caller to decode and encode the string to and from readable
378
  text if that is required.
379
*/
380
class EXIV2API StringValue : public StringValueBase {
381
 public:
382
  //! Shortcut for a %StringValue auto pointer.
383
  using UniquePtr = std::unique_ptr<StringValue>;
384
385
  //! @name Creators
386
  //@{
387
  //! Default constructor.
388
  StringValue();
389
  //! Constructor
390
  explicit StringValue(const std::string& buf);
391
  //@}
392
393
  //! @name Accessors
394
  //@{
395
0
  UniquePtr clone() const {
396
0
    return UniquePtr(clone_());
397
0
  }
398
  //@}
399
400
 private:
401
  //! Internal virtual copy constructor.
402
  StringValue* clone_() const override;
403
404
};  // class StringValue
405
406
/*!
407
  @brief %Value for an Ascii string type.
408
409
  This class is for null terminated single byte Ascii strings.
410
  This class also ensures that the string is null terminated.
411
 */
412
class EXIV2API AsciiValue : public StringValueBase {
413
 public:
414
  //! Shortcut for a %AsciiValue auto pointer.
415
  using UniquePtr = std::unique_ptr<AsciiValue>;
416
417
  //! @name Creators
418
  //@{
419
  //! Default constructor.
420
  AsciiValue();
421
  //! Constructor
422
  explicit AsciiValue(const std::string& buf);
423
  //@}
424
425
  //! @name Manipulators
426
  //@{
427
  using StringValueBase::read;
428
  /*!
429
    @brief Set the value to that of the string buf. Overrides base class
430
           to append a terminating '\\0' character if buf doesn't end
431
           with '\\0'.
432
   */
433
  int read(const std::string& buf) override;
434
  //@}
435
436
  //! @name Accessors
437
  //@{
438
0
  UniquePtr clone() const {
439
0
    return UniquePtr(clone_());
440
0
  }
441
  /*!
442
    @brief Write the ASCII value up to the first '\\0' character to an
443
           output stream.  Any further characters are ignored and not
444
           written to the output stream.
445
  */
446
  std::ostream& write(std::ostream& os) const override;
447
  //@}
448
449
 private:
450
  //! Internal virtual copy constructor.
451
  AsciiValue* clone_() const override;
452
453
};  // class AsciiValue
454
455
/*!
456
  @brief %Value for an Exif comment.
457
458
  This can be a plain Ascii string or a multiple byte encoded string. The
459
  comment is expected to be encoded in the character set indicated (default
460
  undefined), but this is not checked. It is left to caller to decode and
461
  encode the string to and from readable text if that is required.
462
*/
463
class EXIV2API CommentValue : public StringValueBase {
464
 public:
465
  //! Character set identifiers for the character sets defined by %Exif
466
  enum CharsetId { ascii, jis, unicode, undefined, invalidCharsetId, lastCharsetId };
467
  //! Information pertaining to the defined character sets
468
  struct CharsetTable {
469
    CharsetId charsetId_;  //!< Charset id
470
    const char* name_;     //!< Name of the charset
471
    const char* code_;     //!< Code of the charset
472
  };
473
474
  //! Charset information lookup functions. Implemented as a static class.
475
  class EXIV2API CharsetInfo {
476
   public:
477
    //! Return the name for a charset id
478
    static const char* name(CharsetId charsetId);
479
    //! Return the code for a charset id
480
    static const char* code(CharsetId charsetId);
481
    //! Return the charset id for a name
482
    static CharsetId charsetIdByName(const std::string& name);
483
    //! Return the charset id for a code
484
    static CharsetId charsetIdByCode(const std::string& code);
485
486
   private:
487
    static const CharsetTable charsetTable_[];
488
  };  // class CharsetInfo
489
490
  //! Shortcut for a %CommentValue auto pointer.
491
  using UniquePtr = std::unique_ptr<CommentValue>;
492
493
  //! @name Creators
494
  //@{
495
  //! Default constructor.
496
  CommentValue();
497
  //! Constructor, uses read(const std::string& comment)
498
  explicit CommentValue(const std::string& comment);
499
  //@}
500
501
  //! @name Manipulators
502
  //@{
503
  /*!
504
    @brief Read the value from a comment
505
506
    The format of \em comment is:
507
    <BR>
508
    <CODE>[charset=["]Ascii|Jis|Unicode|Undefined["] ]comment</CODE>
509
    <BR>
510
    The default charset is Undefined.
511
512
    @return 0 if successful<BR>
513
            1 if an invalid character set is encountered
514
  */
515
  int read(const std::string& comment) override;
516
  int read(const byte* buf, size_t len, ByteOrder byteOrder) override;
517
  //@}
518
519
  //! @name Accessors
520
  //@{
521
0
  UniquePtr clone() const {
522
0
    return UniquePtr(clone_());
523
0
  }
524
  size_t copy(byte* buf, ByteOrder byteOrder) const override;
525
  /*!
526
    @brief Write the comment in a format which can be read by
527
    read(const std::string& comment).
528
   */
529
  std::ostream& write(std::ostream& os) const override;
530
  /*!
531
    @brief Return the comment (without a charset="..." prefix)
532
533
    The comment is decoded to UTF-8. For Exif UNICODE comments, the
534
    function makes an attempt to correctly determine the character
535
    encoding of the value. Alternatively, the optional \em encoding
536
    parameter can be used to specify it.
537
538
    @param encoding Optional argument to specify the character encoding
539
        that the comment is encoded in, as an iconv(3) name. Only used
540
        for Exif UNICODE comments.
541
542
    @return A string containing the comment converted to UTF-8.
543
   */
544
  std::string comment(const char* encoding = nullptr) const;
545
  /*!
546
    @brief Determine the character encoding that was used to encode the
547
        UNICODE comment value as an iconv(3) name.
548
549
    If the comment \em c starts with a BOM, the BOM is interpreted and
550
    removed from the string.
551
552
    Todo: Implement rules to guess if the comment is UTF-8 encoded.
553
   */
554
  const char* detectCharset(std::string& c) const;
555
  //! Return the Exif charset id of the comment
556
  CharsetId charsetId() const;
557
  //@}
558
559
 private:
560
  //! Internal virtual copy constructor.
561
  CommentValue* clone_() const override;
562
563
 public:
564
  // DATA
565
  ByteOrder byteOrder_{littleEndian};  //!< Byte order of the comment string that was read
566
567
};  // class CommentValue
568
569
/*!
570
  @brief Base class for all Exiv2 values used to store XMP property values.
571
 */
572
class EXIV2API XmpValue : public Value {
573
  using Value::Value;
574
575
 public:
576
  //! Shortcut for a %XmpValue auto pointer.
577
  using UniquePtr = std::unique_ptr<XmpValue>;
578
579
  //! XMP array types.
580
  enum XmpArrayType { xaNone, xaAlt, xaBag, xaSeq };
581
  //! XMP structure indicator.
582
  enum XmpStruct { xsNone, xsStruct };
583
584
  //! @name Accessors
585
  //@{
586
  //! Return XMP array type, indicates if an XMP value is an array.
587
  XmpArrayType xmpArrayType() const;
588
  //! Return XMP struct, indicates if an XMP value is a structure.
589
  XmpStruct xmpStruct() const;
590
  size_t size() const override;
591
  /*!
592
    @brief Write value to a character data buffer.
593
594
    The user must ensure that the buffer has enough memory. Otherwise
595
    the call results in undefined behaviour.
596
597
    @note The byte order is required by the interface but not used by this
598
          method, so just use the default.
599
600
    @param buf Data buffer to write to.
601
    @param byteOrder Byte order. Not used.
602
    @return Number of characters written.
603
  */
604
  size_t copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
605
  //@}
606
607
  //! @name Manipulators
608
  //@{
609
  //! Set the XMP array type to indicate that an XMP value is an array.
610
  void setXmpArrayType(XmpArrayType xmpArrayType);
611
  //! Set the XMP struct type to indicate that an XMP value is a structure.
612
  void setXmpStruct(XmpStruct xmpStruct = xsStruct);
613
614
  /// @note Uses read(const std::string& buf)
615
  int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
616
  int read(const std::string& buf) override = 0;
617
  //@}
618
619
  /*!
620
    @brief Return XMP array type for an array Value TypeId, xaNone if
621
           \em typeId is not an XMP array value type.
622
   */
623
  static XmpArrayType xmpArrayType(TypeId typeId);
624
625
 private:
626
  // DATA
627
  XmpArrayType xmpArrayType_{xaNone};  //!< Type of XMP array
628
  XmpStruct xmpStruct_{xsNone};        //!< XMP structure indicator
629
630
};  // class XmpValue
631
632
/*!
633
  @brief %Value type suitable for simple XMP properties and
634
         XMP nodes of complex types which are not parsed into
635
         specific values.
636
637
  Uses a std::string to store the value.
638
 */
639
class EXIV2API XmpTextValue : public XmpValue {
640
 public:
641
  //! Shortcut for a %XmpTextValue auto pointer.
642
  using UniquePtr = std::unique_ptr<XmpTextValue>;
643
644
  //! @name Creators
645
  //@{
646
  //! Constructor.
647
  XmpTextValue();
648
  //! Constructor, reads the value from a string.
649
  explicit XmpTextValue(const std::string& buf);
650
  //@}
651
652
  //! @name Manipulators
653
  //@{
654
  using XmpValue::read;
655
  /*!
656
    @brief Read a simple property value from \em buf to set the value.
657
658
    Sets the value to the contents of \em buf. A optional keyword,
659
    \em type is supported to set the XMP value type. This is useful for
660
    complex value types for which Exiv2 does not have direct support.
661
662
    The format of \em buf is:
663
    <BR>
664
    <CODE>[type=["]Alt|Bag|Seq|Struct["] ]text</CODE>
665
    <BR>
666
667
    @return 0 if successful.
668
   */
669
670
  int read(const std::string& buf) override;
671
  //@}
672
673
  //! @name Accessors
674
  //@{
675
  UniquePtr clone() const;
676
  size_t size() const override;
677
  size_t count() const override;
678
  /*!
679
    @brief Convert the value to an int64_t.
680
           The optional parameter \em n is not used and is ignored.
681
682
    @return The converted value.
683
   */
684
  int64_t toInt64(size_t n = 0) const override;
685
  /*!
686
    @brief Convert the value to an uint32_t.
687
           The optional parameter \em n is not used and is ignored.
688
689
    @return The converted value.
690
   */
691
  uint32_t toUint32(size_t n = 0) const override;
692
  /*!
693
    @brief Convert the value to a float.
694
           The optional parameter \em n is not used and is ignored.
695
696
    @return The converted value.
697
   */
698
  float toFloat(size_t n = 0) const override;
699
  /*!
700
    @brief Convert the value to a Rational.
701
           The optional parameter \em n is not used and is ignored.
702
703
    @return The converted value.
704
   */
705
  Rational toRational(size_t n = 0) const override;
706
  std::ostream& write(std::ostream& os) const override;
707
  //@}
708
709
 private:
710
  //! Internal virtual copy constructor.
711
  XmpTextValue* clone_() const override;
712
713
 public:
714
  // DATA
715
  std::string value_;  //!< Stores the string values.
716
717
};  // class XmpTextValue
718
719
/*!
720
  @brief %Value type for simple arrays. Each item in the array is a simple
721
         value, without qualifiers. The array may be an ordered (\em seq),
722
         unordered (\em bag) or alternative array (\em alt). The array
723
         items must not contain qualifiers. For language alternatives use
724
         LangAltValue.
725
726
  Uses a vector of std::string to store the value(s).
727
 */
728
class EXIV2API XmpArrayValue : public XmpValue {
729
 public:
730
  //! Shortcut for a %XmpArrayValue auto pointer.
731
  using UniquePtr = std::unique_ptr<XmpArrayValue>;
732
733
  //! @name Creators
734
  //@{
735
  //! Constructor. \em typeId can be one of xmpBag, xmpSeq or xmpAlt.
736
  explicit XmpArrayValue(TypeId typeId = xmpBag);
737
  //@}
738
739
  //! @name Manipulators
740
  //@{
741
  using XmpValue::read;
742
  /*!
743
    @brief Read a simple property value from \em buf and append it
744
           to the value.
745
746
    Appends \em buf to the value after the last existing array element.
747
    Subsequent calls will therefore populate multiple array elements in
748
    the order they are read.
749
750
    @return 0 if successful.
751
   */
752
  int read(const std::string& buf) override;
753
  //@}
754
755
  //! @name Accessors
756
  //@{
757
  UniquePtr clone() const;
758
  size_t count() const override;
759
  /*!
760
    @brief Return the <EM>n</EM>-th component of the value as a string.
761
           The behaviour of this method may be undefined if there is no
762
           <EM>n</EM>-th component.
763
   */
764
  std::string toString(size_t n) const override;
765
  int64_t toInt64(size_t n = 0) const override;
766
  uint32_t toUint32(size_t n = 0) const override;
767
  float toFloat(size_t n = 0) const override;
768
  Rational toRational(size_t n = 0) const override;
769
  /*!
770
    @brief Write all elements of the value to \em os, separated by commas.
771
772
    @note The output of this method cannot directly be used as the parameter
773
          for read().
774
   */
775
  std::ostream& write(std::ostream& os) const override;
776
  //@}
777
778
 private:
779
  //! Internal virtual copy constructor.
780
  XmpArrayValue* clone_() const override;
781
782
  std::vector<std::string> value_;  //!< Stores the string values.
783
784
};  // class XmpArrayValue
785
786
/*!
787
  @brief %LangAltValueComparator
788
789
  #1058
790
  https://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart1.pdf
791
  XMP spec chapter B.4 (page 42) the xml:lang qualifier is to be compared case insensitive.
792
  */
793
struct LangAltValueComparator {
794
  //! LangAltValueComparator comparison case insensitive function
795
14.9k
  bool operator()(const std::string& str1, const std::string& str2) const {
796
14.9k
    if (str1.size() != str2.size())
797
9.63k
      return str1.size() > str2.size();
798
799
214k
    auto f = [](unsigned char a, unsigned char b) { return std::tolower(a) > std::tolower(b); };
800
5.31k
    return std::lexicographical_compare(str1.begin(), str1.end(), str2.begin(), str2.end(), f);
801
14.9k
  }
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
41.5k
inline TypeId getType<uint16_t>() {
1084
41.5k
  return unsignedShort;
1085
41.5k
}
1086
//! Specialization for an unsigned long
1087
template <>
1088
2.91k
inline TypeId getType<uint32_t>() {
1089
2.91k
  return unsignedLong;
1090
2.91k
}
1091
//! Specialization for an unsigned rational
1092
template <>
1093
8.38k
inline TypeId getType<URational>() {
1094
8.38k
  return unsignedRational;
1095
8.38k
}
1096
//! Specialization for a signed short
1097
template <>
1098
17.3k
inline TypeId getType<int16_t>() {
1099
17.3k
  return signedShort;
1100
17.3k
}
1101
//! Specialization for a signed long
1102
template <>
1103
53.1k
inline TypeId getType<int32_t>() {
1104
53.1k
  return signedLong;
1105
53.1k
}
1106
//! Specialization for a signed rational
1107
template <>
1108
7.85k
inline TypeId getType<Rational>() {
1109
7.85k
  return signedRational;
1110
7.85k
}
1111
//! Specialization for a float
1112
template <>
1113
5.61k
inline TypeId getType<float>() {
1114
5.61k
  return tiffFloat;
1115
5.61k
}
1116
//! Specialization for a double
1117
template <>
1118
8.38k
inline TypeId getType<double>() {
1119
8.38k
  return tiffDouble;
1120
8.38k
}
1121
1122
// No default implementation: let the compiler/linker complain
1123
// template<typename T> inline TypeId getType() { return invalid; }
1124
1125
/*!
1126
  @brief Template for a %Value of a basic type. This is used for unsigned
1127
         and signed short, long and rationals.
1128
 */
1129
template <typename T>
1130
class ValueType : public Value {
1131
  using Value::Value;
1132
1133
 public:
1134
  //! Shortcut for a %ValueType\<T\> auto pointer.
1135
  using UniquePtr = std::unique_ptr<ValueType<T>>;
1136
1137
  //! @name Creators
1138
  //@{
1139
  //! Default Constructor.
1140
  ValueType();
1141
  //! Constructor.
1142
  ValueType(const byte* buf, size_t len, ByteOrder byteOrder, TypeId typeId = getType<T>());
1143
  //! Constructor.
1144
  explicit ValueType(const T& val, TypeId typeId = getType<T>());
1145
  //! Copy constructor
1146
  ValueType(const ValueType<T>& rhs);
1147
  //@}
1148
1149
  //! @name Manipulators
1150
  //@{
1151
  //! Assignment operator.
1152
  ValueType<T>& operator=(const ValueType<T>& rhs);
1153
  int read(const byte* buf, size_t len, ByteOrder byteOrder) override;
1154
  /*!
1155
    @brief Set the data from a string of values of type T (e.g.,
1156
           "0 1 2 3" or "1/2 1/3 1/4" depending on what T is).
1157
           Generally, the accepted input format is the same as that
1158
           produced by the write() method.
1159
   */
1160
  int read(const std::string& buf) override;
1161
  /*!
1162
    @brief Set the data area. This method copies (clones) the buffer
1163
           pointed to by buf.
1164
   */
1165
  int setDataArea(const byte* buf, size_t len) override;
1166
  //@}
1167
1168
  //! @name Accessors
1169
  //@{
1170
  UniquePtr clone() const {
1171
    return UniquePtr(clone_());
1172
  }
1173
  size_t copy(byte* buf, ByteOrder byteOrder) const override;
1174
  size_t count() const override;
1175
  size_t size() const override;
1176
  std::ostream& write(std::ostream& os) const override;
1177
  /*!
1178
    @brief Return the <EM>n</EM>-th component of the value as a string.
1179
           The behaviour of this method may be undefined if there is no
1180
           <EM>n</EM>-th
1181
           component.
1182
   */
1183
  std::string toString(size_t n) const override;
1184
  int64_t toInt64(size_t n = 0) const override;
1185
  uint32_t toUint32(size_t n = 0) const override;
1186
  float toFloat(size_t n = 0) const override;
1187
  Rational toRational(size_t n = 0) const override;
1188
  //! Return the size of the data area.
1189
  size_t sizeDataArea() const override;
1190
  /*!
1191
    @brief Return a copy of the data area in a DataBuf. The caller owns
1192
           this copy and DataBuf ensures that it will be deleted.
1193
   */
1194
  DataBuf dataArea() const override;
1195
  //@}
1196
1197
  //! Container for values
1198
  using ValueList = std::vector<T>;
1199
1200
  // DATA
1201
  /*!
1202
    @brief The container for all values. In your application, if you know
1203
           what subclass of Value you're dealing with (and possibly the T)
1204
           then you can access this STL container through the usual
1205
           standard library functions.
1206
   */
1207
  ValueList value_;
1208
1209
 private:
1210
  //! Utility for toInt64, toUint32, etc.
1211
  template <typename I>
1212
20.0k
  I float_to_integer_helper(size_t n) const {
1213
20.0k
    const auto v = value_.at(n);
1214
20.0k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
15.4k
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
13.0k
      return static_cast<I>(std::lround(v));
1217
13.0k
    }
1218
6.95k
    return 0;
1219
20.0k
  }
long Exiv2::ValueType<double>::float_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1212
1.08k
  I float_to_integer_helper(size_t n) const {
1213
1.08k
    const auto v = value_.at(n);
1214
1.08k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
999
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
777
      return static_cast<I>(std::lround(v));
1217
777
    }
1218
306
    return 0;
1219
1.08k
  }
unsigned int Exiv2::ValueType<double>::float_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1212
5.19k
  I float_to_integer_helper(size_t n) const {
1213
5.19k
    const auto v = value_.at(n);
1214
5.19k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
4.58k
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
3.97k
      return static_cast<I>(std::lround(v));
1217
3.97k
    }
1218
1.22k
    return 0;
1219
5.19k
  }
long Exiv2::ValueType<float>::float_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1212
5.30k
  I float_to_integer_helper(size_t n) const {
1213
5.30k
    const auto v = value_.at(n);
1214
5.30k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
4.50k
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
3.64k
      return static_cast<I>(std::lround(v));
1217
3.64k
    }
1218
1.66k
    return 0;
1219
5.30k
  }
unsigned int Exiv2::ValueType<float>::float_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1212
8.44k
  I float_to_integer_helper(size_t n) const {
1213
8.44k
    const auto v = value_.at(n);
1214
8.44k
    if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
1215
5.33k
        v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
1216
4.68k
      return static_cast<I>(std::lround(v));
1217
4.68k
    }
1218
3.76k
    return 0;
1219
8.44k
  }
1220
1221
  //! Utility for toInt64, toUint32, etc.
1222
  template <typename I>
1223
44.7k
  I rational_to_integer_helper(size_t n) const {
1224
44.7k
    auto a = value_.at(n).first;
1225
44.7k
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
44.7k
    if (b <= 0) {
1229
6.79k
      return 0;
1230
6.79k
    }
1231
1232
    // Check for integer overflow.
1233
37.9k
#ifdef __cpp_if_constexpr
1234
37.9k
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
24.6k
      const auto imin = std::numeric_limits<I>::min();
1240
24.6k
      const auto imax = std::numeric_limits<I>::max();
1241
24.6k
      if (imax < b || a < imin || imax < a) {
1242
0
        return 0;
1243
0
      }
1244
24.6k
#ifdef __cpp_if_constexpr
1245
24.6k
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
6.21k
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
6.21k
      if (imax < b || imax < a) {
1252
0
        return 0;
1253
0
      }
1254
7.13k
    } else {
1255
      // conversion is from signed to unsigned
1256
7.13k
      const auto imax = std::numeric_limits<I>::max();
1257
7.13k
      if (a < 0) {
1258
483
        return 0;
1259
483
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
6.65k
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
6.65k
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
6.65k
      if (imax < b_u || imax < a_u) {
1264
0
        return 0;
1265
0
      }
1266
6.65k
    }
1267
1268
37.4k
    return static_cast<I>(a) / static_cast<I>(b);
1269
44.7k
  }
long Exiv2::ValueType<std::__1::pair<int, int> >::rational_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1223
5.19k
  I rational_to_integer_helper(size_t n) const {
1224
5.19k
    auto a = value_.at(n).first;
1225
5.19k
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
5.19k
    if (b <= 0) {
1229
1.81k
      return 0;
1230
1.81k
    }
1231
1232
    // Check for integer overflow.
1233
3.37k
#ifdef __cpp_if_constexpr
1234
3.37k
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
3.37k
      const auto imin = std::numeric_limits<I>::min();
1240
3.37k
      const auto imax = std::numeric_limits<I>::max();
1241
3.37k
      if (imax < b || a < imin || imax < a) {
1242
0
        return 0;
1243
0
      }
1244
3.37k
#ifdef __cpp_if_constexpr
1245
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
      if (imax < b || imax < a) {
1252
        return 0;
1253
      }
1254
    } else {
1255
      // conversion is from signed to unsigned
1256
      const auto imax = std::numeric_limits<I>::max();
1257
      if (a < 0) {
1258
        return 0;
1259
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
      if (imax < b_u || imax < a_u) {
1264
        return 0;
1265
      }
1266
    }
1267
1268
3.37k
    return static_cast<I>(a) / static_cast<I>(b);
1269
5.19k
  }
unsigned int Exiv2::ValueType<std::__1::pair<int, int> >::rational_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1223
9.55k
  I rational_to_integer_helper(size_t n) const {
1224
9.55k
    auto a = value_.at(n).first;
1225
9.55k
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
9.55k
    if (b <= 0) {
1229
2.41k
      return 0;
1230
2.41k
    }
1231
1232
    // Check for integer overflow.
1233
7.13k
#ifdef __cpp_if_constexpr
1234
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
      const auto imin = std::numeric_limits<I>::min();
1240
      const auto imax = std::numeric_limits<I>::max();
1241
      if (imax < b || a < imin || imax < a) {
1242
        return 0;
1243
      }
1244
#ifdef __cpp_if_constexpr
1245
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
      if (imax < b || imax < a) {
1252
        return 0;
1253
      }
1254
7.13k
    } else {
1255
      // conversion is from signed to unsigned
1256
7.13k
      const auto imax = std::numeric_limits<I>::max();
1257
7.13k
      if (a < 0) {
1258
483
        return 0;
1259
483
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
6.65k
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
6.65k
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
6.65k
      if (imax < b_u || imax < a_u) {
1264
0
        return 0;
1265
0
      }
1266
6.65k
    }
1267
1268
6.65k
    return static_cast<I>(a) / static_cast<I>(b);
1269
9.55k
  }
long Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::rational_to_integer_helper<long>(unsigned long) const
Line
Count
Source
1223
7.09k
  I rational_to_integer_helper(size_t n) const {
1224
7.09k
    auto a = value_.at(n).first;
1225
7.09k
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
7.09k
    if (b <= 0) {
1229
876
      return 0;
1230
876
    }
1231
1232
    // Check for integer overflow.
1233
6.21k
#ifdef __cpp_if_constexpr
1234
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
      const auto imin = std::numeric_limits<I>::min();
1240
      const auto imax = std::numeric_limits<I>::max();
1241
      if (imax < b || a < imin || imax < a) {
1242
        return 0;
1243
      }
1244
#ifdef __cpp_if_constexpr
1245
6.21k
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
6.21k
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
6.21k
      if (imax < b || imax < a) {
1252
0
        return 0;
1253
0
      }
1254
    } else {
1255
      // conversion is from signed to unsigned
1256
      const auto imax = std::numeric_limits<I>::max();
1257
      if (a < 0) {
1258
        return 0;
1259
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
      if (imax < b_u || imax < a_u) {
1264
        return 0;
1265
      }
1266
    }
1267
1268
6.21k
    return static_cast<I>(a) / static_cast<I>(b);
1269
7.09k
  }
unsigned int Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::rational_to_integer_helper<unsigned int>(unsigned long) const
Line
Count
Source
1223
22.9k
  I rational_to_integer_helper(size_t n) const {
1224
22.9k
    auto a = value_.at(n).first;
1225
22.9k
    auto b = value_.at(n).second;
1226
1227
    // Protect against divide-by-zero.
1228
22.9k
    if (b <= 0) {
1229
1.68k
      return 0;
1230
1.68k
    }
1231
1232
    // Check for integer overflow.
1233
21.2k
#ifdef __cpp_if_constexpr
1234
21.2k
    if constexpr (std::is_signed_v<I> == std::is_signed_v<decltype(a)>) {
1235
#else
1236
    if (std::is_signed<I>::value == std::is_signed<decltype(a)>::value) {
1237
#endif
1238
      // conversion does not change sign
1239
21.2k
      const auto imin = std::numeric_limits<I>::min();
1240
21.2k
      const auto imax = std::numeric_limits<I>::max();
1241
21.2k
      if (imax < b || a < imin || imax < a) {
1242
0
        return 0;
1243
0
      }
1244
21.2k
#ifdef __cpp_if_constexpr
1245
    } else if constexpr (std::is_signed_v<I>) {
1246
#else
1247
    } else if (std::is_signed<I>::value) {
1248
#endif
1249
      // conversion is from unsigned to signed
1250
      const auto imax = static_cast<std::make_unsigned_t<I>>(std::numeric_limits<I>::max());
1251
      if (imax < b || imax < a) {
1252
        return 0;
1253
      }
1254
    } else {
1255
      // conversion is from signed to unsigned
1256
      const auto imax = std::numeric_limits<I>::max();
1257
      if (a < 0) {
1258
        return 0;
1259
      }
1260
      // Inputs are not negative so convert them to unsigned.
1261
      const auto a_u = static_cast<std::make_unsigned_t<decltype(a)>>(a);
1262
      const auto b_u = static_cast<std::make_unsigned_t<decltype(b)>>(b);
1263
      if (imax < b_u || imax < a_u) {
1264
        return 0;
1265
      }
1266
    }
1267
1268
21.2k
    return static_cast<I>(a) / static_cast<I>(b);
1269
22.9k
  }
1270
1271
  //! Internal virtual copy constructor.
1272
  ValueType<T>* clone_() const override;
1273
1274
  // DATA
1275
  //! Pointer to the buffer, nullptr if none has been allocated
1276
  Blob pDataArea_;
1277
};  // class ValueType
1278
1279
//! Unsigned short value type
1280
using UShortValue = ValueType<uint16_t>;
1281
//! Unsigned long value type
1282
using ULongValue = ValueType<uint32_t>;
1283
//! Unsigned rational value type
1284
using URationalValue = ValueType<URational>;
1285
//! Signed short value type
1286
using ShortValue = ValueType<int16_t>;
1287
//! Signed long value type
1288
using LongValue = ValueType<int32_t>;
1289
//! Signed rational value type
1290
using RationalValue = ValueType<Rational>;
1291
//! Float value type
1292
using FloatValue = ValueType<float>;
1293
//! Double value type
1294
using DoubleValue = ValueType<double>;
1295
1296
// *****************************************************************************
1297
// free functions, template and inline definitions
1298
1299
/*!
1300
  @brief Read a value of type T from the data buffer.
1301
1302
  We need this template function for the ValueType template classes.
1303
  There are only specializations of this function available; no default
1304
  implementation is provided.
1305
1306
  @param buf Pointer to the data buffer to read from.
1307
  @param byteOrder Applicable byte order (little or big endian).
1308
  @return A value of type T.
1309
 */
1310
template <typename T>
1311
T getValue(const byte* buf, ByteOrder byteOrder);
1312
// Specialization for a 2 byte unsigned short value.
1313
template <>
1314
830k
inline uint16_t getValue(const byte* buf, ByteOrder byteOrder) {
1315
830k
  return getUShort(buf, byteOrder);
1316
830k
}
1317
// Specialization for a 4 byte unsigned long value.
1318
template <>
1319
1.83M
inline uint32_t getValue(const byte* buf, ByteOrder byteOrder) {
1320
1.83M
  return getULong(buf, byteOrder);
1321
1.83M
}
1322
// Specialization for an 8 byte unsigned rational value.
1323
template <>
1324
714k
inline URational getValue(const byte* buf, ByteOrder byteOrder) {
1325
714k
  return getURational(buf, byteOrder);
1326
714k
}
1327
// Specialization for a 2 byte signed short value.
1328
template <>
1329
98.6k
inline int16_t getValue(const byte* buf, ByteOrder byteOrder) {
1330
98.6k
  return getShort(buf, byteOrder);
1331
98.6k
}
1332
// Specialization for a 4 byte signed long value.
1333
template <>
1334
444k
inline int32_t getValue(const byte* buf, ByteOrder byteOrder) {
1335
444k
  return getLong(buf, byteOrder);
1336
444k
}
1337
// Specialization for an 8 byte signed rational value.
1338
template <>
1339
357k
inline Rational getValue(const byte* buf, ByteOrder byteOrder) {
1340
357k
  return getRational(buf, byteOrder);
1341
357k
}
1342
// Specialization for a 4 byte float value.
1343
template <>
1344
44.5k
inline float getValue(const byte* buf, ByteOrder byteOrder) {
1345
44.5k
  return getFloat(buf, byteOrder);
1346
44.5k
}
1347
// Specialization for a 8 byte double value.
1348
template <>
1349
133k
inline double getValue(const byte* buf, ByteOrder byteOrder) {
1350
133k
  return getDouble(buf, byteOrder);
1351
133k
}
1352
1353
/*!
1354
  @brief Convert a value of type T to data, write the data to the data buffer.
1355
1356
  We need this template function for the ValueType template classes.
1357
  There are only specializations of this function available; no default
1358
  implementation is provided.
1359
1360
  @param buf Pointer to the data buffer to write to.
1361
  @param t Value to be converted.
1362
  @param byteOrder Applicable byte order (little or big endian).
1363
  @return The number of bytes written to the buffer.
1364
 */
1365
template <typename T>
1366
size_t toData(byte* buf, T t, ByteOrder byteOrder);
1367
/*!
1368
  @brief Specialization to write an unsigned short to the data buffer.
1369
         Return the number of bytes written.
1370
 */
1371
template <>
1372
556k
inline size_t toData(byte* buf, uint16_t t, ByteOrder byteOrder) {
1373
556k
  return us2Data(buf, t, byteOrder);
1374
556k
}
1375
/*!
1376
  @brief Specialization to write an unsigned long to the data buffer.
1377
         Return the number of bytes written.
1378
 */
1379
template <>
1380
1.10M
inline size_t toData(byte* buf, uint32_t t, ByteOrder byteOrder) {
1381
1.10M
  return ul2Data(buf, t, byteOrder);
1382
1.10M
}
1383
/*!
1384
  @brief Specialization to write an unsigned rational to the data buffer.
1385
         Return the number of bytes written.
1386
 */
1387
template <>
1388
625k
inline size_t toData(byte* buf, URational t, ByteOrder byteOrder) {
1389
625k
  return ur2Data(buf, t, byteOrder);
1390
625k
}
1391
/*!
1392
  @brief Specialization to write a signed short to the data buffer.
1393
         Return the number of bytes written.
1394
 */
1395
template <>
1396
113k
inline size_t toData(byte* buf, int16_t t, ByteOrder byteOrder) {
1397
113k
  return s2Data(buf, t, byteOrder);
1398
113k
}
1399
/*!
1400
  @brief Specialization to write a signed long to the data buffer.
1401
         Return the number of bytes written.
1402
 */
1403
template <>
1404
272k
inline size_t toData(byte* buf, int32_t t, ByteOrder byteOrder) {
1405
272k
  return l2Data(buf, t, byteOrder);
1406
272k
}
1407
/*!
1408
  @brief Specialization to write a signed rational to the data buffer.
1409
         Return the number of bytes written.
1410
 */
1411
template <>
1412
212k
inline size_t toData(byte* buf, Rational t, ByteOrder byteOrder) {
1413
212k
  return r2Data(buf, t, byteOrder);
1414
212k
}
1415
/*!
1416
  @brief Specialization to write a float to the data buffer.
1417
         Return the number of bytes written.
1418
 */
1419
template <>
1420
56.6k
inline size_t toData(byte* buf, float t, ByteOrder byteOrder) {
1421
56.6k
  return f2Data(buf, t, byteOrder);
1422
56.6k
}
1423
/*!
1424
  @brief Specialization to write a double to the data buffer.
1425
         Return the number of bytes written.
1426
 */
1427
template <>
1428
117k
inline size_t toData(byte* buf, double t, ByteOrder byteOrder) {
1429
117k
  return d2Data(buf, t, byteOrder);
1430
117k
}
1431
1432
template <typename T>
1433
145k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
145k
}
Exiv2::ValueType<unsigned short>::ValueType()
Line
Count
Source
1433
41.5k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
41.5k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::ValueType()
Line
Count
Source
1433
8.38k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
8.38k
}
Exiv2::ValueType<short>::ValueType()
Line
Count
Source
1433
17.3k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
17.3k
}
Exiv2::ValueType<int>::ValueType()
Line
Count
Source
1433
53.1k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
53.1k
}
Exiv2::ValueType<std::__1::pair<int, int> >::ValueType()
Line
Count
Source
1433
7.85k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
7.85k
}
Exiv2::ValueType<float>::ValueType()
Line
Count
Source
1433
5.61k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
5.61k
}
Exiv2::ValueType<double>::ValueType()
Line
Count
Source
1433
8.38k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
8.38k
}
Exiv2::ValueType<unsigned int>::ValueType()
Line
Count
Source
1433
2.91k
ValueType<T>::ValueType() : Value(getType<T>()) {
1434
2.91k
}
1435
1436
template <typename T>
1437
ValueType<T>::ValueType(const byte* buf, size_t len, ByteOrder byteOrder, TypeId typeId) : Value(typeId) {
1438
  read(buf, len, byteOrder);
1439
}
1440
1441
template <typename T>
1442
ValueType<T>::ValueType(const T& val, TypeId typeId) : Value(typeId) {
1443
  value_.push_back(val);
1444
}
1445
1446
template <typename T>
1447
630k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
630k
  if (!rhs.pDataArea_.empty())
1449
6.90k
    pDataArea_ = rhs.pDataArea_;
1450
630k
}
Exiv2::ValueType<unsigned short>::ValueType(Exiv2::ValueType<unsigned short> const&)
Line
Count
Source
1447
105k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
105k
  if (!rhs.pDataArea_.empty())
1449
1.56k
    pDataArea_ = rhs.pDataArea_;
1450
105k
}
Exiv2::ValueType<unsigned int>::ValueType(Exiv2::ValueType<unsigned int> const&)
Line
Count
Source
1447
246k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
246k
  if (!rhs.pDataArea_.empty())
1449
304
    pDataArea_ = rhs.pDataArea_;
1450
246k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::ValueType(Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> > const&)
Line
Count
Source
1447
25.7k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
25.7k
  if (!rhs.pDataArea_.empty())
1449
513
    pDataArea_ = rhs.pDataArea_;
1450
25.7k
}
Exiv2::ValueType<short>::ValueType(Exiv2::ValueType<short> const&)
Line
Count
Source
1447
37.8k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
37.8k
  if (!rhs.pDataArea_.empty())
1449
848
    pDataArea_ = rhs.pDataArea_;
1450
37.8k
}
Exiv2::ValueType<int>::ValueType(Exiv2::ValueType<int> const&)
Line
Count
Source
1447
147k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
147k
  if (!rhs.pDataArea_.empty())
1449
626
    pDataArea_ = rhs.pDataArea_;
1450
147k
}
Exiv2::ValueType<std::__1::pair<int, int> >::ValueType(Exiv2::ValueType<std::__1::pair<int, int> > const&)
Line
Count
Source
1447
24.7k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
24.7k
  if (!rhs.pDataArea_.empty())
1449
627
    pDataArea_ = rhs.pDataArea_;
1450
24.7k
}
Exiv2::ValueType<float>::ValueType(Exiv2::ValueType<float> const&)
Line
Count
Source
1447
19.1k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
19.1k
  if (!rhs.pDataArea_.empty())
1449
1.65k
    pDataArea_ = rhs.pDataArea_;
1450
19.1k
}
Exiv2::ValueType<double>::ValueType(Exiv2::ValueType<double> const&)
Line
Count
Source
1447
23.1k
ValueType<T>::ValueType(const ValueType<T>& rhs) : Value(rhs.typeId()), value_(rhs.value_) {
1448
23.1k
  if (!rhs.pDataArea_.empty())
1449
770
    pDataArea_ = rhs.pDataArea_;
1450
23.1k
}
1451
1452
template <typename T>
1453
ValueType<T>& ValueType<T>::operator=(const ValueType<T>& rhs) {
1454
  if (this == &rhs)
1455
    return *this;
1456
  value_ = rhs.value_;
1457
1458
  if (!rhs.pDataArea_.empty())
1459
    pDataArea_ = rhs.pDataArea_;
1460
  else
1461
    pDataArea_.clear();
1462
1463
  return *this;
1464
}
1465
1466
template <typename T>
1467
218k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
218k
  value_.clear();
1469
218k
  size_t ts = TypeInfo::typeSize(typeId());
1470
218k
  if (ts > 0 && len % ts != 0)
1471
367
    len = (len / ts) * ts;
1472
4.67M
  for (size_t i = 0; i < len; i += ts) {
1473
4.45M
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
4.45M
  }
1475
218k
  return 0;
1476
218k
}
Exiv2::ValueType<unsigned short>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
40.1k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
40.1k
  value_.clear();
1469
40.1k
  size_t ts = TypeInfo::typeSize(typeId());
1470
40.1k
  if (ts > 0 && len % ts != 0)
1471
243
    len = (len / ts) * ts;
1472
871k
  for (size_t i = 0; i < len; i += ts) {
1473
830k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
830k
  }
1475
40.1k
  return 0;
1476
40.1k
}
Exiv2::ValueType<unsigned int>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
83.4k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
83.4k
  value_.clear();
1469
83.4k
  size_t ts = TypeInfo::typeSize(typeId());
1470
83.4k
  if (ts > 0 && len % ts != 0)
1471
50
    len = (len / ts) * ts;
1472
1.91M
  for (size_t i = 0; i < len; i += ts) {
1473
1.83M
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
1.83M
  }
1475
83.4k
  return 0;
1476
83.4k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
8.04k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
8.04k
  value_.clear();
1469
8.04k
  size_t ts = TypeInfo::typeSize(typeId());
1470
8.04k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
722k
  for (size_t i = 0; i < len; i += ts) {
1473
714k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
714k
  }
1475
8.04k
  return 0;
1476
8.04k
}
Exiv2::ValueType<short>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
12.1k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
12.1k
  value_.clear();
1469
12.1k
  size_t ts = TypeInfo::typeSize(typeId());
1470
12.1k
  if (ts > 0 && len % ts != 0)
1471
24
    len = (len / ts) * ts;
1472
110k
  for (size_t i = 0; i < len; i += ts) {
1473
98.6k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
98.6k
  }
1475
12.1k
  return 0;
1476
12.1k
}
Exiv2::ValueType<int>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
53.1k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
53.1k
  value_.clear();
1469
53.1k
  size_t ts = TypeInfo::typeSize(typeId());
1470
53.1k
  if (ts > 0 && len % ts != 0)
1471
50
    len = (len / ts) * ts;
1472
498k
  for (size_t i = 0; i < len; i += ts) {
1473
444k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
444k
  }
1475
53.1k
  return 0;
1476
53.1k
}
Exiv2::ValueType<std::__1::pair<int, int> >::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
7.85k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
7.85k
  value_.clear();
1469
7.85k
  size_t ts = TypeInfo::typeSize(typeId());
1470
7.85k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
365k
  for (size_t i = 0; i < len; i += ts) {
1473
357k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
357k
  }
1475
7.85k
  return 0;
1476
7.85k
}
Exiv2::ValueType<float>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
5.61k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
5.61k
  value_.clear();
1469
5.61k
  size_t ts = TypeInfo::typeSize(typeId());
1470
5.61k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
50.2k
  for (size_t i = 0; i < len; i += ts) {
1473
44.5k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
44.5k
  }
1475
5.61k
  return 0;
1476
5.61k
}
Exiv2::ValueType<double>::read(unsigned char const*, unsigned long, Exiv2::ByteOrder)
Line
Count
Source
1467
8.38k
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
1468
8.38k
  value_.clear();
1469
8.38k
  size_t ts = TypeInfo::typeSize(typeId());
1470
8.38k
  if (ts > 0 && len % ts != 0)
1471
0
    len = (len / ts) * ts;
1472
141k
  for (size_t i = 0; i < len; i += ts) {
1473
133k
    value_.push_back(getValue<T>(buf + i, byteOrder));
1474
133k
  }
1475
8.38k
  return 0;
1476
8.38k
}
1477
1478
template <typename T>
1479
6.60k
int ValueType<T>::read(const std::string& buf) {
1480
6.60k
  std::istringstream is(buf);
1481
6.60k
  T tmp;
1482
6.60k
  ValueList val;
1483
18.3k
  while (is >> tmp)
1484
11.7k
    val.push_back(tmp);
1485
6.60k
  if (!is.eof())
1486
3
    return 1;
1487
6.60k
  value_ = std::move(val);
1488
6.60k
  return 0;
1489
6.60k
}
Exiv2::ValueType<unsigned short>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
1479
1.32k
int ValueType<T>::read(const std::string& buf) {
1480
1.32k
  std::istringstream is(buf);
1481
1.32k
  T tmp;
1482
1.32k
  ValueList val;
1483
2.38k
  while (is >> tmp)
1484
1.05k
    val.push_back(tmp);
1485
1.32k
  if (!is.eof())
1486
3
    return 1;
1487
1.32k
  value_ = std::move(val);
1488
1.32k
  return 0;
1489
1.32k
}
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
1479
5.28k
int ValueType<T>::read(const std::string& buf) {
1480
5.28k
  std::istringstream is(buf);
1481
5.28k
  T tmp;
1482
5.28k
  ValueList val;
1483
15.9k
  while (is >> tmp)
1484
10.6k
    val.push_back(tmp);
1485
5.28k
  if (!is.eof())
1486
0
    return 1;
1487
5.28k
  value_ = std::move(val);
1488
5.28k
  return 0;
1489
5.28k
}
Unexecuted instantiation: Exiv2::ValueType<int>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<int, int> >::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<float>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: Exiv2::ValueType<double>::read(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
1490
1491
template <typename T>
1492
178k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
178k
  size_t offset = 0;
1494
3.05M
  for (const auto& val : value_) {
1495
3.05M
    offset += toData(buf + offset, val, byteOrder);
1496
3.05M
  }
1497
178k
  return offset;
1498
178k
}
Exiv2::ValueType<unsigned short>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
30.6k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
30.6k
  size_t offset = 0;
1494
556k
  for (const auto& val : value_) {
1495
556k
    offset += toData(buf + offset, val, byteOrder);
1496
556k
  }
1497
30.6k
  return offset;
1498
30.6k
}
Exiv2::ValueType<unsigned int>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
73.3k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
73.3k
  size_t offset = 0;
1494
1.10M
  for (const auto& val : value_) {
1495
1.10M
    offset += toData(buf + offset, val, byteOrder);
1496
1.10M
  }
1497
73.3k
  return offset;
1498
73.3k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
7.22k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
7.22k
  size_t offset = 0;
1494
625k
  for (const auto& val : value_) {
1495
625k
    offset += toData(buf + offset, val, byteOrder);
1496
625k
  }
1497
7.22k
  return offset;
1498
7.22k
}
Exiv2::ValueType<short>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
5.38k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
5.38k
  size_t offset = 0;
1494
113k
  for (const auto& val : value_) {
1495
113k
    offset += toData(buf + offset, val, byteOrder);
1496
113k
  }
1497
5.38k
  return offset;
1498
5.38k
}
Exiv2::ValueType<int>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
48.3k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
48.3k
  size_t offset = 0;
1494
272k
  for (const auto& val : value_) {
1495
272k
    offset += toData(buf + offset, val, byteOrder);
1496
272k
  }
1497
48.3k
  return offset;
1498
48.3k
}
Exiv2::ValueType<std::__1::pair<int, int> >::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
6.18k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
6.18k
  size_t offset = 0;
1494
212k
  for (const auto& val : value_) {
1495
212k
    offset += toData(buf + offset, val, byteOrder);
1496
212k
  }
1497
6.18k
  return offset;
1498
6.18k
}
Exiv2::ValueType<float>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
3.75k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
3.75k
  size_t offset = 0;
1494
56.6k
  for (const auto& val : value_) {
1495
56.6k
    offset += toData(buf + offset, val, byteOrder);
1496
56.6k
  }
1497
3.75k
  return offset;
1498
3.75k
}
Exiv2::ValueType<double>::copy(unsigned char*, Exiv2::ByteOrder) const
Line
Count
Source
1492
3.33k
size_t ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const {
1493
3.33k
  size_t offset = 0;
1494
117k
  for (const auto& val : value_) {
1495
117k
    offset += toData(buf + offset, val, byteOrder);
1496
117k
  }
1497
3.33k
  return offset;
1498
3.33k
}
1499
1500
template <typename T>
1501
689k
size_t ValueType<T>::count() const {
1502
689k
  return value_.size();
1503
689k
}
Exiv2::ValueType<unsigned short>::count() const
Line
Count
Source
1501
179k
size_t ValueType<T>::count() const {
1502
179k
  return value_.size();
1503
179k
}
Exiv2::ValueType<unsigned int>::count() const
Line
Count
Source
1501
230k
size_t ValueType<T>::count() const {
1502
230k
  return value_.size();
1503
230k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::count() const
Line
Count
Source
1501
35.7k
size_t ValueType<T>::count() const {
1502
35.7k
  return value_.size();
1503
35.7k
}
Exiv2::ValueType<short>::count() const
Line
Count
Source
1501
38.1k
size_t ValueType<T>::count() const {
1502
38.1k
  return value_.size();
1503
38.1k
}
Exiv2::ValueType<int>::count() const
Line
Count
Source
1501
131k
size_t ValueType<T>::count() const {
1502
131k
  return value_.size();
1503
131k
}
Exiv2::ValueType<std::__1::pair<int, int> >::count() const
Line
Count
Source
1501
22.9k
size_t ValueType<T>::count() const {
1502
22.9k
  return value_.size();
1503
22.9k
}
Exiv2::ValueType<float>::count() const
Line
Count
Source
1501
29.3k
size_t ValueType<T>::count() const {
1502
29.3k
  return value_.size();
1503
29.3k
}
Exiv2::ValueType<double>::count() const
Line
Count
Source
1501
21.3k
size_t ValueType<T>::count() const {
1502
21.3k
  return value_.size();
1503
21.3k
}
1504
1505
template <typename T>
1506
1.13M
size_t ValueType<T>::size() const {
1507
1.13M
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
1.13M
}
Exiv2::ValueType<unsigned short>::size() const
Line
Count
Source
1506
137k
size_t ValueType<T>::size() const {
1507
137k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
137k
}
Exiv2::ValueType<unsigned int>::size() const
Line
Count
Source
1506
517k
size_t ValueType<T>::size() const {
1507
517k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
517k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::size() const
Line
Count
Source
1506
18.8k
size_t ValueType<T>::size() const {
1507
18.8k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
18.8k
}
Exiv2::ValueType<short>::size() const
Line
Count
Source
1506
20.8k
size_t ValueType<T>::size() const {
1507
20.8k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
20.8k
}
Exiv2::ValueType<int>::size() const
Line
Count
Source
1506
406k
size_t ValueType<T>::size() const {
1507
406k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
406k
}
Exiv2::ValueType<std::__1::pair<int, int> >::size() const
Line
Count
Source
1506
18.1k
size_t ValueType<T>::size() const {
1507
18.1k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
18.1k
}
Exiv2::ValueType<float>::size() const
Line
Count
Source
1506
9.55k
size_t ValueType<T>::size() const {
1507
9.55k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
9.55k
}
Exiv2::ValueType<double>::size() const
Line
Count
Source
1506
10.4k
size_t ValueType<T>::size() const {
1507
10.4k
  return TypeInfo::typeSize(typeId()) * value_.size();
1508
10.4k
}
1509
1510
template <typename T>
1511
630k
ValueType<T>* ValueType<T>::clone_() const {
1512
630k
  return new ValueType<T>(*this);
1513
630k
}
Exiv2::ValueType<unsigned short>::clone_() const
Line
Count
Source
1511
105k
ValueType<T>* ValueType<T>::clone_() const {
1512
105k
  return new ValueType<T>(*this);
1513
105k
}
Exiv2::ValueType<unsigned int>::clone_() const
Line
Count
Source
1511
246k
ValueType<T>* ValueType<T>::clone_() const {
1512
246k
  return new ValueType<T>(*this);
1513
246k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::clone_() const
Line
Count
Source
1511
25.7k
ValueType<T>* ValueType<T>::clone_() const {
1512
25.7k
  return new ValueType<T>(*this);
1513
25.7k
}
Exiv2::ValueType<short>::clone_() const
Line
Count
Source
1511
37.8k
ValueType<T>* ValueType<T>::clone_() const {
1512
37.8k
  return new ValueType<T>(*this);
1513
37.8k
}
Exiv2::ValueType<int>::clone_() const
Line
Count
Source
1511
147k
ValueType<T>* ValueType<T>::clone_() const {
1512
147k
  return new ValueType<T>(*this);
1513
147k
}
Exiv2::ValueType<std::__1::pair<int, int> >::clone_() const
Line
Count
Source
1511
24.7k
ValueType<T>* ValueType<T>::clone_() const {
1512
24.7k
  return new ValueType<T>(*this);
1513
24.7k
}
Exiv2::ValueType<float>::clone_() const
Line
Count
Source
1511
19.1k
ValueType<T>* ValueType<T>::clone_() const {
1512
19.1k
  return new ValueType<T>(*this);
1513
19.1k
}
Exiv2::ValueType<double>::clone_() const
Line
Count
Source
1511
23.1k
ValueType<T>* ValueType<T>::clone_() const {
1512
23.1k
  return new ValueType<T>(*this);
1513
23.1k
}
1514
1515
template <typename T>
1516
5.81k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
5.81k
  auto end = value_.end();
1518
5.81k
  auto i = value_.begin();
1519
595k
  while (i != end) {
1520
589k
    os << std::setprecision(15) << *i;
1521
589k
    if (++i != end)
1522
585k
      os << " ";
1523
589k
  }
1524
5.81k
  return os;
1525
5.81k
}
Exiv2::ValueType<unsigned short>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
380
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
380
  auto end = value_.end();
1518
380
  auto i = value_.begin();
1519
4.79k
  while (i != end) {
1520
4.41k
    os << std::setprecision(15) << *i;
1521
4.41k
    if (++i != end)
1522
4.13k
      os << " ";
1523
4.41k
  }
1524
380
  return os;
1525
380
}
Exiv2::ValueType<unsigned int>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
2.73k
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
2.73k
  auto end = value_.end();
1518
2.73k
  auto i = value_.begin();
1519
79.6k
  while (i != end) {
1520
76.9k
    os << std::setprecision(15) << *i;
1521
76.9k
    if (++i != end)
1522
74.5k
      os << " ";
1523
76.9k
  }
1524
2.73k
  return os;
1525
2.73k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
456
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
456
  auto end = value_.end();
1518
456
  auto i = value_.begin();
1519
6.35k
  while (i != end) {
1520
5.90k
    os << std::setprecision(15) << *i;
1521
5.90k
    if (++i != end)
1522
5.70k
      os << " ";
1523
5.90k
  }
1524
456
  return os;
1525
456
}
Exiv2::ValueType<short>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
326
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
326
  auto end = value_.end();
1518
326
  auto i = value_.begin();
1519
1.98k
  while (i != end) {
1520
1.65k
    os << std::setprecision(15) << *i;
1521
1.65k
    if (++i != end)
1522
1.47k
      os << " ";
1523
1.65k
  }
1524
326
  return os;
1525
326
}
Exiv2::ValueType<int>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
442
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
442
  auto end = value_.end();
1518
442
  auto i = value_.begin();
1519
431k
  while (i != end) {
1520
431k
    os << std::setprecision(15) << *i;
1521
431k
    if (++i != end)
1522
430k
      os << " ";
1523
431k
  }
1524
442
  return os;
1525
442
}
Exiv2::ValueType<std::__1::pair<int, int> >::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
768
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
768
  auto end = value_.end();
1518
768
  auto i = value_.begin();
1519
2.74k
  while (i != end) {
1520
1.97k
    os << std::setprecision(15) << *i;
1521
1.97k
    if (++i != end)
1522
1.58k
      os << " ";
1523
1.97k
  }
1524
768
  return os;
1525
768
}
Exiv2::ValueType<float>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
487
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
487
  auto end = value_.end();
1518
487
  auto i = value_.begin();
1519
67.8k
  while (i != end) {
1520
67.3k
    os << std::setprecision(15) << *i;
1521
67.3k
    if (++i != end)
1522
67.0k
      os << " ";
1523
67.3k
  }
1524
487
  return os;
1525
487
}
Exiv2::ValueType<double>::write(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const
Line
Count
Source
1516
222
std::ostream& ValueType<T>::write(std::ostream& os) const {
1517
222
  auto end = value_.end();
1518
222
  auto i = value_.begin();
1519
965
  while (i != end) {
1520
743
    os << std::setprecision(15) << *i;
1521
743
    if (++i != end)
1522
556
      os << " ";
1523
743
  }
1524
222
  return os;
1525
222
}
1526
1527
template <typename T>
1528
0
std::string ValueType<T>::toString(size_t n) const {
1529
0
  ok_ = true;
1530
0
  return Exiv2::toString<T>(value_.at(n));
1531
0
}
Unexecuted instantiation: Exiv2::ValueType<unsigned short>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<short>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<int>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<std::__1::pair<int, int> >::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<float>::toString(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<double>::toString(unsigned long) const
1532
1533
// Default implementation
1534
template <typename T>
1535
112k
int64_t ValueType<T>::toInt64(size_t n) const {
1536
112k
  ok_ = true;
1537
112k
  return static_cast<int64_t>(value_.at(n));
1538
112k
}
Exiv2::ValueType<unsigned short>::toInt64(unsigned long) const
Line
Count
Source
1535
96.1k
int64_t ValueType<T>::toInt64(size_t n) const {
1536
96.1k
  ok_ = true;
1537
96.1k
  return static_cast<int64_t>(value_.at(n));
1538
96.1k
}
Exiv2::ValueType<unsigned int>::toInt64(unsigned long) const
Line
Count
Source
1535
5.73k
int64_t ValueType<T>::toInt64(size_t n) const {
1536
5.73k
  ok_ = true;
1537
5.73k
  return static_cast<int64_t>(value_.at(n));
1538
5.73k
}
Exiv2::ValueType<short>::toInt64(unsigned long) const
Line
Count
Source
1535
3.63k
int64_t ValueType<T>::toInt64(size_t n) const {
1536
3.63k
  ok_ = true;
1537
3.63k
  return static_cast<int64_t>(value_.at(n));
1538
3.63k
}
Exiv2::ValueType<int>::toInt64(unsigned long) const
Line
Count
Source
1535
6.49k
int64_t ValueType<T>::toInt64(size_t n) const {
1536
6.49k
  ok_ = true;
1537
6.49k
  return static_cast<int64_t>(value_.at(n));
1538
6.49k
}
1539
template <typename T>
1540
274k
uint32_t ValueType<T>::toUint32(size_t n) const {
1541
274k
  ok_ = true;
1542
274k
  return static_cast<uint32_t>(value_.at(n));
1543
274k
}
Exiv2::ValueType<unsigned short>::toUint32(unsigned long) const
Line
Count
Source
1540
105k
uint32_t ValueType<T>::toUint32(size_t n) const {
1541
105k
  ok_ = true;
1542
105k
  return static_cast<uint32_t>(value_.at(n));
1543
105k
}
Exiv2::ValueType<unsigned int>::toUint32(unsigned long) const
Line
Count
Source
1540
74.5k
uint32_t ValueType<T>::toUint32(size_t n) const {
1541
74.5k
  ok_ = true;
1542
74.5k
  return static_cast<uint32_t>(value_.at(n));
1543
74.5k
}
Exiv2::ValueType<short>::toUint32(unsigned long) const
Line
Count
Source
1540
84.6k
uint32_t ValueType<T>::toUint32(size_t n) const {
1541
84.6k
  ok_ = true;
1542
84.6k
  return static_cast<uint32_t>(value_.at(n));
1543
84.6k
}
Exiv2::ValueType<int>::toUint32(unsigned long) const
Line
Count
Source
1540
10.1k
uint32_t ValueType<T>::toUint32(size_t n) const {
1541
10.1k
  ok_ = true;
1542
10.1k
  return static_cast<uint32_t>(value_.at(n));
1543
10.1k
}
1544
// #55 crash when value_.at(n).first == LONG_MIN
1545
#define LARGE_INT 1000000
1546
// Specialization for double
1547
template <>
1548
1.08k
inline int64_t ValueType<double>::toInt64(size_t n) const {
1549
1.08k
  return float_to_integer_helper<int64_t>(n);
1550
1.08k
}
1551
1552
template <>
1553
5.19k
inline uint32_t ValueType<double>::toUint32(size_t n) const {
1554
5.19k
  return float_to_integer_helper<uint32_t>(n);
1555
5.19k
}
1556
// Specialization for float
1557
template <>
1558
5.30k
inline int64_t ValueType<float>::toInt64(size_t n) const {
1559
5.30k
  return float_to_integer_helper<int64_t>(n);
1560
5.30k
}
1561
template <>
1562
8.44k
inline uint32_t ValueType<float>::toUint32(size_t n) const {
1563
8.44k
  return float_to_integer_helper<uint32_t>(n);
1564
8.44k
}
1565
// Specialization for rational
1566
template <>
1567
5.19k
inline int64_t ValueType<Rational>::toInt64(size_t n) const {
1568
5.19k
  return rational_to_integer_helper<int64_t>(n);
1569
5.19k
}
1570
template <>
1571
9.55k
inline uint32_t ValueType<Rational>::toUint32(size_t n) const {
1572
9.55k
  return rational_to_integer_helper<uint32_t>(n);
1573
9.55k
}
1574
// Specialization for unsigned rational
1575
template <>
1576
7.09k
inline int64_t ValueType<URational>::toInt64(size_t n) const {
1577
7.09k
  return rational_to_integer_helper<int64_t>(n);
1578
7.09k
}
1579
template <>
1580
22.9k
inline uint32_t ValueType<URational>::toUint32(size_t n) const {
1581
22.9k
  return rational_to_integer_helper<uint32_t>(n);
1582
22.9k
}
1583
// Default implementation
1584
template <typename T>
1585
0
float ValueType<T>::toFloat(size_t n) const {
1586
0
  ok_ = true;
1587
0
  return static_cast<float>(value_.at(n));
1588
0
}
Unexecuted instantiation: Exiv2::ValueType<unsigned short>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<short>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<int>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<float>::toFloat(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<double>::toFloat(unsigned long) const
1589
// Specialization for rational
1590
template <>
1591
0
inline float ValueType<Rational>::toFloat(size_t n) const {
1592
0
  ok_ = (value_.at(n).second != 0);
1593
0
  if (!ok_)
1594
0
    return 0.0f;
1595
0
  return static_cast<float>(value_.at(n).first) / value_.at(n).second;
1596
0
}
1597
// Specialization for unsigned rational
1598
template <>
1599
0
inline float ValueType<URational>::toFloat(size_t n) const {
1600
0
  ok_ = (value_.at(n).second != 0);
1601
0
  if (!ok_)
1602
0
    return 0.0f;
1603
0
  return static_cast<float>(value_.at(n).first) / value_.at(n).second;
1604
0
}
1605
// Default implementation
1606
template <typename T>
1607
0
Rational ValueType<T>::toRational(size_t n) const {
1608
0
  ok_ = true;
1609
0
  return {value_.at(n), 1};
1610
0
}
Unexecuted instantiation: Exiv2::ValueType<unsigned short>::toRational(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<unsigned int>::toRational(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<short>::toRational(unsigned long) const
Unexecuted instantiation: Exiv2::ValueType<int>::toRational(unsigned long) const
1611
// Specialization for rational
1612
template <>
1613
0
inline Rational ValueType<Rational>::toRational(size_t n) const {
1614
0
  ok_ = true;
1615
0
  return {value_.at(n).first, value_.at(n).second};
1616
0
}
1617
// Specialization for unsigned rational
1618
template <>
1619
0
inline Rational ValueType<URational>::toRational(size_t n) const {
1620
0
  ok_ = true;
1621
0
  return {value_.at(n).first, value_.at(n).second};
1622
0
}
1623
// Specialization for float.
1624
template <>
1625
0
inline Rational ValueType<float>::toRational(size_t n) const {
1626
0
  ok_ = true;
1627
  // Warning: This is a very simple conversion, see floatToRationalCast()
1628
0
  return floatToRationalCast(value_.at(n));
1629
0
}
1630
// Specialization for double.
1631
template <>
1632
0
inline Rational ValueType<double>::toRational(size_t n) const {
1633
0
  ok_ = true;
1634
  // Warning: This is a very simple conversion, see floatToRationalCast()
1635
0
  return floatToRationalCast(static_cast<float>(value_.at(n)));
1636
0
}
1637
1638
template <typename T>
1639
23.9k
size_t ValueType<T>::sizeDataArea() const {
1640
23.9k
  return pDataArea_.size();
1641
23.9k
}
Exiv2::ValueType<unsigned short>::sizeDataArea() const
Line
Count
Source
1639
2.73k
size_t ValueType<T>::sizeDataArea() const {
1640
2.73k
  return pDataArea_.size();
1641
2.73k
}
Exiv2::ValueType<unsigned int>::sizeDataArea() const
Line
Count
Source
1639
8.29k
size_t ValueType<T>::sizeDataArea() const {
1640
8.29k
  return pDataArea_.size();
1641
8.29k
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::sizeDataArea() const
Line
Count
Source
1639
1.28k
size_t ValueType<T>::sizeDataArea() const {
1640
1.28k
  return pDataArea_.size();
1641
1.28k
}
Exiv2::ValueType<short>::sizeDataArea() const
Line
Count
Source
1639
1.30k
size_t ValueType<T>::sizeDataArea() const {
1640
1.30k
  return pDataArea_.size();
1641
1.30k
}
Exiv2::ValueType<int>::sizeDataArea() const
Line
Count
Source
1639
2.57k
size_t ValueType<T>::sizeDataArea() const {
1640
2.57k
  return pDataArea_.size();
1641
2.57k
}
Exiv2::ValueType<std::__1::pair<int, int> >::sizeDataArea() const
Line
Count
Source
1639
1.18k
size_t ValueType<T>::sizeDataArea() const {
1640
1.18k
  return pDataArea_.size();
1641
1.18k
}
Exiv2::ValueType<float>::sizeDataArea() const
Line
Count
Source
1639
4.38k
size_t ValueType<T>::sizeDataArea() const {
1640
4.38k
  return pDataArea_.size();
1641
4.38k
}
Exiv2::ValueType<double>::sizeDataArea() const
Line
Count
Source
1639
2.17k
size_t ValueType<T>::sizeDataArea() const {
1640
2.17k
  return pDataArea_.size();
1641
2.17k
}
1642
1643
template <typename T>
1644
2.82k
DataBuf ValueType<T>::dataArea() const {
1645
2.82k
  return {pDataArea_.data(), pDataArea_.size()};
1646
2.82k
}
Exiv2::ValueType<unsigned short>::dataArea() const
Line
Count
Source
1644
568
DataBuf ValueType<T>::dataArea() const {
1645
568
  return {pDataArea_.data(), pDataArea_.size()};
1646
568
}
Exiv2::ValueType<unsigned int>::dataArea() const
Line
Count
Source
1644
842
DataBuf ValueType<T>::dataArea() const {
1645
842
  return {pDataArea_.data(), pDataArea_.size()};
1646
842
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::dataArea() const
Line
Count
Source
1644
144
DataBuf ValueType<T>::dataArea() const {
1645
144
  return {pDataArea_.data(), pDataArea_.size()};
1646
144
}
Exiv2::ValueType<short>::dataArea() const
Line
Count
Source
1644
387
DataBuf ValueType<T>::dataArea() const {
1645
387
  return {pDataArea_.data(), pDataArea_.size()};
1646
387
}
Exiv2::ValueType<int>::dataArea() const
Line
Count
Source
1644
277
DataBuf ValueType<T>::dataArea() const {
1645
277
  return {pDataArea_.data(), pDataArea_.size()};
1646
277
}
Exiv2::ValueType<std::__1::pair<int, int> >::dataArea() const
Line
Count
Source
1644
72
DataBuf ValueType<T>::dataArea() const {
1645
72
  return {pDataArea_.data(), pDataArea_.size()};
1646
72
}
Exiv2::ValueType<float>::dataArea() const
Line
Count
Source
1644
287
DataBuf ValueType<T>::dataArea() const {
1645
287
  return {pDataArea_.data(), pDataArea_.size()};
1646
287
}
Exiv2::ValueType<double>::dataArea() const
Line
Count
Source
1644
249
DataBuf ValueType<T>::dataArea() const {
1645
249
  return {pDataArea_.data(), pDataArea_.size()};
1646
249
}
1647
1648
template <typename T>
1649
6.50k
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
6.50k
  if (len > 0)
1651
3.92k
    pDataArea_ = Blob(buf, buf + len);
1652
2.58k
  else
1653
2.58k
    pDataArea_.clear();
1654
6.50k
  return 0;
1655
6.50k
}
Exiv2::ValueType<unsigned short>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1649
1.49k
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
1.49k
  if (len > 0)
1651
734
    pDataArea_ = Blob(buf, buf + len);
1652
763
  else
1653
763
    pDataArea_.clear();
1654
1.49k
  return 0;
1655
1.49k
}
Exiv2::ValueType<unsigned int>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1649
412
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
412
  if (len > 0)
1651
267
    pDataArea_ = Blob(buf, buf + len);
1652
145
  else
1653
145
    pDataArea_.clear();
1654
412
  return 0;
1655
412
}
Exiv2::ValueType<std::__1::pair<unsigned int, unsigned int> >::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1649
442
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
442
  if (len > 0)
1651
221
    pDataArea_ = Blob(buf, buf + len);
1652
221
  else
1653
221
    pDataArea_.clear();
1654
442
  return 0;
1655
442
}
Exiv2::ValueType<short>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1649
722
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
722
  if (len > 0)
1651
430
    pDataArea_ = Blob(buf, buf + len);
1652
292
  else
1653
292
    pDataArea_.clear();
1654
722
  return 0;
1655
722
}
Exiv2::ValueType<int>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1649
643
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
643
  if (len > 0)
1651
323
    pDataArea_ = Blob(buf, buf + len);
1652
320
  else
1653
320
    pDataArea_.clear();
1654
643
  return 0;
1655
643
}
Exiv2::ValueType<std::__1::pair<int, int> >::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1649
796
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
796
  if (len > 0)
1651
368
    pDataArea_ = Blob(buf, buf + len);
1652
428
  else
1653
428
    pDataArea_.clear();
1654
796
  return 0;
1655
796
}
Exiv2::ValueType<float>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1649
1.44k
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
1.44k
  if (len > 0)
1651
1.17k
    pDataArea_ = Blob(buf, buf + len);
1652
264
  else
1653
264
    pDataArea_.clear();
1654
1.44k
  return 0;
1655
1.44k
}
Exiv2::ValueType<double>::setDataArea(unsigned char const*, unsigned long)
Line
Count
Source
1649
549
int ValueType<T>::setDataArea(const byte* buf, size_t len) {
1650
549
  if (len > 0)
1651
402
    pDataArea_ = Blob(buf, buf + len);
1652
147
  else
1653
147
    pDataArea_.clear();
1654
549
  return 0;
1655
549
}
1656
}  // namespace Exiv2
1657
1658
#endif  // EXIV2_VALUE_HPP