Coverage Report

Created: 2026-10-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/exiv2/include/exiv2/xmp_exiv2.hpp
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
#ifndef EXIV2_XMP_EXIV2_HPP
4
#define EXIV2_XMP_EXIV2_HPP
5
6
// *****************************************************************************
7
#include "exiv2lib_export.h"
8
9
// included header files
10
#include "datasets.hpp"
11
#include "metadatum.hpp"
12
#include "params.hpp"
13
#include "properties.hpp"
14
15
#include <atomic>
16
#include <map>
17
18
// *****************************************************************************
19
// namespace extensions
20
namespace Exiv2 {
21
// *****************************************************************************
22
// class declarations
23
class ExifData;
24
class XmpKey;
25
26
// *****************************************************************************
27
// class definitions
28
29
/*!
30
  @brief Information related to an XMP property. An XMP metadatum consists
31
         of an XmpKey and a Value and provides methods to manipulate these.
32
 */
33
class EXIV2API Xmpdatum : public Metadatum {
34
 public:
35
  //! @name Creators
36
  //@{
37
  /*!
38
    @brief Constructor for new tags created by an application. The
39
           %Xmpdatum is created from a key / value pair. %Xmpdatum
40
           copies (clones) the value if one is provided. Alternatively, a
41
           program can create an 'empty' %Xmpdatum with only a key and
42
           set the value using setValue().
43
44
    @param key The key of the %Xmpdatum.
45
    @param pValue Pointer to a %Xmpdatum value.
46
    @throw Error if the key cannot be parsed and converted
47
           to a known schema namespace prefix and property name.
48
   */
49
  explicit Xmpdatum(const XmpKey& key, const Value* pValue = nullptr);
50
  //! Copy constructor
51
  Xmpdatum(const Xmpdatum& rhs);
52
  //! Destructor
53
  ~Xmpdatum() override;
54
  //@}
55
56
  //! @name Manipulators
57
  //@{
58
  //! Assignment operator
59
  Xmpdatum& operator=(const Xmpdatum& rhs);
60
  /*!
61
    @brief Assign std::string \em value to the %Xmpdatum.
62
           Calls setValue(const std::string&).
63
   */
64
  template <typename T>
65
  Xmpdatum& operator=(const T& value);
66
  /*!
67
    @brief Assign Value \em value to the %Xmpdatum.
68
           Calls setValue(const Value*).
69
   */
70
  void setValue(const Value* pValue) override;
71
  /*!
72
    @brief Set the value to the string \em value. Uses Value::read(const
73
           std::string&).  If the %Xmpdatum does not have a Value yet,
74
           then a %Value of the correct type for this %Xmpdatum is
75
           created. If the key is unknown, a XmpTextValue is used as
76
           default. Return 0 if the value was read successfully.
77
   */
78
  int setValue(const std::string& value) override;
79
  //@}
80
81
  //! @name Accessors
82
  //@{
83
  //! Not implemented. Calling this method will raise an exception.
84
  size_t copy(byte* buf, ByteOrder byteOrder) const override;
85
  std::ostream& write(std::ostream& os, const ExifData* pMetadata = nullptr) const override;
86
  /*!
87
    @brief Return the key of the Xmpdatum. The key is of the form
88
           '<b>Xmp</b>.prefix.property'. Note however that the
89
           key is not necessarily unique, i.e., an XmpData object may
90
           contain multiple metadata with the same key.
91
   */
92
  [[nodiscard]] std::string key() const override;
93
  [[nodiscard]] const char* familyName() const override;
94
  //! Return the (preferred) schema namespace prefix.
95
  [[nodiscard]] std::string groupName() const override;
96
  //! Return the property name.
97
  [[nodiscard]] std::string tagName() const override;
98
  [[nodiscard]] std::string tagLabel() const override;
99
  [[nodiscard]] std::string tagDesc() const override;
100
  //! Properties don't have a tag number. Return 0.
101
  [[nodiscard]] uint16_t tag() const override;
102
  [[nodiscard]] TypeId typeId() const override;
103
  [[nodiscard]] const char* typeName() const override;
104
  // Todo: Remove this method from the baseclass
105
  //! The Exif typeSize doesn't make sense here. Return 0.
106
  [[nodiscard]] size_t typeSize() const override;
107
  [[nodiscard]] size_t count() const override;
108
  [[nodiscard]] size_t size() const override;
109
  [[nodiscard]] std::string toString() const override;
110
  [[nodiscard]] std::string toString(size_t n) const override;
111
  [[nodiscard]] int64_t toInt64(size_t n = 0) const override;
112
  [[nodiscard]] float toFloat(size_t n = 0) const override;
113
  [[nodiscard]] Rational toRational(size_t n = 0) const override;
114
  [[nodiscard]] std::unique_ptr<Value> getValue() const override;
115
  [[nodiscard]] const Value& value() const override;
116
  //@}
117
118
 private:
119
  // Pimpl idiom
120
  struct Impl;
121
  std::unique_ptr<Impl> p_;
122
123
};  // class Xmpdatum
124
125
//! Container type to hold all metadata
126
using XmpMetadata = std::vector<Xmpdatum>;
127
128
/*!
129
  @brief A container for XMP data. This is a top-level class of
130
         the %Exiv2 library.
131
132
  Provide high-level access to the XMP data of an image:
133
  - read XMP information from an XML block
134
  - access metadata through keys and standard C++ iterators
135
  - add, modify and delete metadata
136
  - serialize XMP data to an XML block
137
*/
138
class EXIV2API XmpData {
139
 public:
140
  //! Default constructor
141
95.1k
  XmpData() = default;
142
143
  //! XmpMetadata iterator type
144
  using iterator = XmpMetadata::iterator;
145
  //! XmpMetadata const iterator type
146
  using const_iterator = XmpMetadata::const_iterator;
147
148
  //! @name Manipulators
149
  //@{
150
  /*!
151
    @brief Returns a reference to the %Xmpdatum that is associated with a
152
           particular \em key. If %XmpData does not already contain such
153
           an %Xmpdatum, operator[] adds object \em Xmpdatum(key).
154
155
    @note  Since operator[] might insert a new element, it can't be a const
156
           member function.
157
   */
158
  Xmpdatum& operator[](const std::string& key);
159
  /*!
160
    @brief Add an %Xmpdatum from the supplied key and value pair. This
161
           method copies (clones) the value.
162
    @return 0 if successful.
163
   */
164
  int add(const XmpKey& key, const Value* value);
165
  /*!
166
    @brief Add a copy of the Xmpdatum to the XMP metadata.
167
    @return 0 if successful.
168
   */
169
  int add(const Xmpdatum& xmpDatum);
170
  /*
171
  @brief Delete the Xmpdatum at iterator position pos, return the
172
          position of the next Xmpdatum.
173
174
  @note  Iterators into the metadata, including pos, are potentially
175
          invalidated by this call.
176
  @brief Delete the Xmpdatum at iterator position pos and update pos
177
  */
178
  iterator erase(XmpData::iterator pos);
179
  /*!
180
    @brief Delete the Xmpdatum at iterator position pos and update pos
181
           erases all following keys from the same family
182
           See: https://github.com/Exiv2/exiv2/issues/521
183
   */
184
  void eraseFamily(XmpData::iterator& pos);
185
  //! Delete all Xmpdatum instances resulting in an empty container.
186
  void clear();
187
  //! Sort metadata by key
188
  void sortByKey();
189
  //! Begin of the metadata
190
  iterator begin();
191
  //! End of the metadata
192
  iterator end();
193
  /*!
194
    @brief Find the first Xmpdatum with the given key, return an iterator
195
           to it.
196
   */
197
  iterator findKey(const XmpKey& key);
198
  //@}
199
200
  //! @name Accessors
201
  //@{
202
  //! Begin of the metadata
203
  [[nodiscard]] const_iterator begin() const;
204
  //! End of the metadata
205
  [[nodiscard]] const_iterator end() const;
206
  /*!
207
    @brief Find the first Xmpdatum with the given key, return a const
208
           iterator to it.
209
   */
210
  [[nodiscard]] const_iterator findKey(const XmpKey& key) const;
211
  //! Return true if there is no XMP metadata
212
  [[nodiscard]] bool empty() const;
213
  //! Get the number of metadata entries
214
  [[nodiscard]] long count() const;
215
216
  //! are we to use the packet?
217
0
  [[nodiscard]] bool usePacket() const {
218
0
    return usePacket_;
219
0
  }
220
221
  //! set usePacket_
222
178k
  bool usePacket(bool b) {
223
178k
    bool r = usePacket_;
224
178k
    usePacket_ = b;
225
178k
    return r;
226
178k
  }
227
  //! setPacket
228
178k
  void setPacket(std::string xmpPacket) {
229
178k
    xmpPacket_ = std::move(xmpPacket);
230
178k
    usePacket(false);
231
178k
  }
232
  // ! getPacket
233
0
  [[nodiscard]] const std::string& xmpPacket() const {
234
0
    return xmpPacket_;
235
0
  }
236
237
  //@}
238
239
 private:
240
  // DATA
241
  XmpMetadata xmpMetadata_;
242
  std::string xmpPacket_;
243
  bool usePacket_{};
244
  //! Per-instance prefix-to-URI namespace bindings, see nsBindings().
245
  std::map<std::string, std::string> nsBindings_;
246
247
  /*!
248
    @brief Namespace prefix-to-URI bindings captured from this object's own
249
           source packet at decode time.
250
251
    XMP namespace prefixes are document-scoped: two images may legitimately
252
    bind the same prefix to different URIs.  Exiv2 keys are prefix-based and
253
    the URI is otherwise re-derived from a process-global registry at encode
254
    time, which lets one image's binding (including a corrupted one) leak into
255
    another.  These per-instance bindings let encode() resolve each property's
256
    URI from the data it actually came from, falling back to the global
257
    registry only for keys that were added without a source packet.
258
259
    @note Internal: read by XmpParser::resolveNamespace() during encode().
260
   */
261
0
  [[nodiscard]] const std::map<std::string, std::string>& nsBindings() const {
262
0
    return nsBindings_;
263
0
  }
264
265
  int addUnlocked(const XmpKey& key, const Value* value, const XmpProperties::XmpLock&);
266
  int addUnlocked(const Xmpdatum& xmpDatum, const XmpProperties::XmpLock&);
267
  bool emptyUnlocked(const XmpProperties::XmpLock&) const;
268
  long countUnlocked(const XmpProperties::XmpLock&) const;
269
  void sortByKeyUnlocked(const XmpProperties::XmpLock&);
270
  void clearUnlocked(const XmpProperties::XmpLock&);
271
  friend class XmpParser;
272
};  // class XmpData
273
274
/*!
275
  @brief Stateless parser class for XMP packets. Images use this
276
         class to parse and serialize XMP packets. The parser uses
277
         the XMP toolkit to do the job.
278
 */
279
class EXIV2API XmpParser {
280
 public:
281
  //! Options to control the format of the serialized XMP packet.
282
  enum XmpFormatFlags {
283
    omitPacketWrapper = 0x0010UL,    //!< Omit the XML packet wrapper.
284
    readOnlyPacket = 0x0020UL,       //!< Default is a writeable packet.
285
    useCompactFormat = 0x0040UL,     //!< Use a compact form of RDF.
286
    includeThumbnailPad = 0x0100UL,  //!< Include a padding allowance for a thumbnail image.
287
    exactPacketLength = 0x0200UL,    //!< The padding parameter is the overall packet length.
288
    writeAliasComments = 0x0400UL,   //!< Show aliases as XML comments.
289
    omitAllFormatting = 0x0800UL     //!< Omit all formatting whitespace.
290
  };
291
  /*!
292
    @brief Decode XMP metadata from an XMP packet \em xmpPacket into
293
           \em xmpData. The format of the XMP packet must follow the
294
           XMP specification. This method clears any previous contents
295
           of \em xmpData.
296
297
    @param xmpData   Container for the decoded XMP properties
298
    @param xmpPacket The raw XMP packet to decode
299
    @return 0 if successful;<BR>
300
            1 if XMP support has not been compiled-in;<BR>
301
            2 if the XMP toolkit failed to initialize;<BR>
302
            3 if the XMP toolkit failed and raised an XMP_Error
303
  */
304
  static int decode(XmpData& xmpData, const std::string& xmpPacket, const DecodeParams& dp);
305
  /*!
306
    @brief Encode (serialize) XMP metadata from \em xmpData into a
307
           string xmpPacket. The XMP packet returned in the string
308
           follows the XMP specification. This method only modifies
309
           \em xmpPacket if the operations succeeds (return code 0).
310
311
    @param xmpPacket   Reference to a string to hold the encoded XMP
312
                       packet.
313
    @param xmpData     XMP properties to encode.
314
    @param formatFlags Flags that control the format of the XMP packet,
315
                       see enum XmpFormatFlags.
316
    @param padding     Padding length.
317
    @return 0 if successful;<BR>
318
            1 if XMP support has not been compiled-in;<BR>
319
            2 if the XMP toolkit failed to initialize;<BR>
320
            3 if the XMP toolkit failed and raised an XMP_Error
321
  */
322
  static int encode(std::string& xmpPacket, const XmpData& xmpData, uint16_t formatFlags = useCompactFormat,
323
                    uint32_t padding = 0);
324
325
  /*!
326
    @deprecated This function is no longer needed and does absolutely nothing.
327
                XMP Toolkit initialization is handled automatically.
328
                Arguments are ignored.
329
330
    @return Always returns true.
331
   */
332
  [[deprecated(
333
      "XmpParser::initialize is deprecated and does nothing. The XMP Toolkit is initialized "
334
      "automatically.")]] static bool
335
  initialize(void (*)(void*, bool) = nullptr, void* = nullptr);
336
337
  /*!
338
    @deprecated This function is no longer needed and does absolutely nothing.
339
                XMP Toolkit termination is handled automatically.
340
   */
341
  [[deprecated(
342
      "XmpParser::terminate is deprecated and does nothing. The XMP Toolkit termination is handled "
343
      "automatically.")]] static void
344
  terminate();
345
  /*!
346
    @brief Clear all custom namespaces registered with the XMP Toolkit.
347
           This is useful for resetting the registry state in tests.
348
   */
349
  static void clearCustomNamespaces();
350
351
 private:
352
  /*!
353
    @brief Register a namespace with the XMP Toolkit.
354
   */
355
  static void registerNs(const std::string& ns, const std::string& prefix);
356
  /*!
357
    @brief Delete a namespace from the XMP Toolkit.
358
359
    XmpProperties::unregisterNs calls this to synchronize namespaces.
360
  */
361
  static void unregisterNs(const std::string& ns);
362
363
  /*!
364
    @brief Register a namespace with the XMP Toolkit without locking.
365
           Assumes the lock obtained via XmpProperties::XmpLock is already held by caller.
366
   */
367
  static void registerNsImpl(const std::string& ns, const std::string& prefix);
368
369
  static void registeredNamespacesUnlocked(Exiv2::Dictionary&, const XmpProperties::XmpLock&);
370
371
  /*!
372
    @brief Get namespaces registered with XMPsdk
373
   */
374
  static void registeredNamespaces(Exiv2::Dictionary&);
375
376
  friend class XmpProperties;  // permit XmpProperties -> registerNs() and registeredNamespaces()
377
378
  static std::unique_ptr<XmpKey> makeXmpKey(const std::string& schemaNs, const std::string& propPath,
379
                                            const XmpProperties::XmpLock&);
380
381
  /*!
382
    @brief Resolve a namespace prefix to its URI for serialization, preferring the
383
           binding declared by \em xmpData's own source packet and falling back to
384
           the process-global registry for keys added without one.
385
           Assumes the lock obtained via XmpProperties::XmpLock is held by caller.
386
   */
387
  static std::string resolveNamespace(const XmpData& xmpData, const std::string& prefix, const XmpProperties::XmpLock&);
388
389
};  // class XmpParser
390
391
// *****************************************************************************
392
// free functions, template and inline definitions
393
394
#if __cpp_if_constexpr
395
template <typename T>
396
36.6k
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
0
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
14.9k
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
0
    setValue(&value);
403
  else
404
21.7k
    setValue(Exiv2::toString(value));
405
36.6k
  return *this;
406
36.6k
}
Unexecuted instantiation: Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<Exiv2::Value>(Exiv2::Value const&)
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
396
12.7k
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
12.7k
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
    setValue(Exiv2::toString(value));
405
12.7k
  return *this;
406
12.7k
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<double>(double const&)
Line
Count
Source
396
7.16k
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
7.16k
    setValue(Exiv2::toString(value));
405
7.16k
  return *this;
406
7.16k
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<unsigned long>(unsigned long const&)
Line
Count
Source
396
4.75k
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
4.75k
    setValue(Exiv2::toString(value));
405
4.75k
  return *this;
406
4.75k
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<unsigned int>(unsigned int const&)
Line
Count
Source
396
5.88k
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
5.88k
    setValue(Exiv2::toString(value));
405
5.88k
  return *this;
406
5.88k
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<unsigned char const*>(unsigned char const* const&)
Line
Count
Source
396
649
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
649
    setValue(Exiv2::toString(value));
405
649
  return *this;
406
649
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<char [4]>(char const (&) [4])
Line
Count
Source
396
232
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
232
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
    setValue(Exiv2::toString(value));
405
232
  return *this;
406
232
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<long>(long const&)
Line
Count
Source
396
170
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
170
    setValue(Exiv2::toString(value));
405
170
  return *this;
406
170
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<float>(float const&)
Line
Count
Source
396
2.07k
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
2.07k
    setValue(Exiv2::toString(value));
405
2.07k
  return *this;
406
2.07k
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<char [18]>(char const (&) [18])
Line
Count
Source
396
6
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
6
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
    setValue(Exiv2::toString(value));
405
6
  return *this;
406
6
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<unsigned short>(unsigned short const&)
Line
Count
Source
396
542
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
542
    setValue(Exiv2::toString(value));
405
542
  return *this;
406
542
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<short>(short const&)
Line
Count
Source
396
103
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
103
    setValue(Exiv2::toString(value));
405
103
  return *this;
406
103
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<unsigned char*>(unsigned char* const&)
Line
Count
Source
396
307
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
307
    setValue(Exiv2::toString(value));
405
307
  return *this;
406
307
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<char const*>(char const* const&)
Line
Count
Source
396
1.98k
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
1.98k
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
    setValue(Exiv2::toString(value));
405
1.98k
  return *this;
406
1.98k
}
Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<int>(int const&)
Line
Count
Source
396
82
Xmpdatum& Xmpdatum::operator=(const T& value) {
397
  if constexpr (std::is_same_v<T, bool>)
398
    setValue(value ? "True" : "False");
399
  else if constexpr (std::is_convertible_v<T, std::string>)
400
    setValue(value);
401
  else if constexpr (std::is_base_of_v<Value, T>)
402
    setValue(&value);
403
  else
404
82
    setValue(Exiv2::toString(value));
405
82
  return *this;
406
82
}
Unexecuted instantiation: Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<char [12]>(char const (&) [12])
Unexecuted instantiation: Exiv2::Xmpdatum& Exiv2::Xmpdatum::operator=<bool>(bool const&)
407
#else
408
template <typename T>
409
std::enable_if_t<std::is_convertible<T, std::string>::value> operatorHelper(Xmpdatum* xmp, const T& value) {
410
  xmp->setValue(value);
411
}
412
413
template <typename T>
414
std::enable_if_t<std::is_base_of<Value, T>::value> operatorHelper(Xmpdatum* xmp, const T& value) {
415
  xmp->setValue(&value);
416
}
417
418
template <typename T>
419
std::enable_if_t<std::is_same<T, bool>::value> operatorHelper(Xmpdatum* xmp, const T& value) {
420
  xmp->setValue(value ? "True" : "False");
421
}
422
423
template <typename T>
424
std::enable_if_t<!(std::is_convertible<T, std::string>::value || std::is_base_of<Value, T>::value ||
425
                   std::is_same<T, bool>::value)>
426
operatorHelper(Xmpdatum* xmp, const T& value) {
427
  xmp->setValue(Exiv2::toString(value));
428
}
429
430
template <typename T>
431
Xmpdatum& Xmpdatum::operator=(const T& value) {
432
  operatorHelper(this, value);
433
  return *this;
434
}
435
#endif
436
}  // namespace Exiv2
437
438
#endif  // EXIV2_XMP_EXIV2_HPP