Skip to content

Commit 23a511a

Browse files
Removed EXTEND_METADATUM macro
Its contents have been put in more logical places, which makes everything easier to read and maintain.
1 parent c21b2ea commit 23a511a

22 files changed

+1665
-1360
lines changed

src/interface/exif.i

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ KEEP_REFERENCE_EX(Exiv2::ExifThumb*, args)
5252

5353
INPUT_BUFFER_RO(const Exiv2::byte* buf, BUFLEN_T size)
5454

55-
EXTEND_METADATUM(Exifdatum)
56-
5755
METADATUM_WRAPPERS(ExifData, Exifdatum)
5856

5957
// Get the current (or default if not set) type id of a datum

src/interface/image.i

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ WINDOWS_PATH(const std::string& path)
6767

6868
// Declare metadatum wrapper classes
6969
DECLARE_METADATUM_WRAPPERS(ExifData, Exifdatum)
70+
DECLARE_METADATUM_WRAPPERS(IptcData, Iptcdatum)
71+
DECLARE_METADATUM_WRAPPERS(XmpData, Xmpdatum)
7072

7173
// Simplify handling of default parameters
7274
%typemap(default) bool useCurl {$1 = true;}

src/interface/iptc.i

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ IMPORT_ENUM(TypeId)
3838
// Catch all C++ exceptions
3939
EXCEPTION()
4040

41-
EXTEND_METADATUM(Iptcdatum)
42-
4341
METADATUM_WRAPPERS(IptcData, Iptcdatum)
4442

4543
// Get the current (or default if not set) type id of a datum

src/interface/metadatum.i

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
%include "shared/preamble.i"
2727
%include "shared/containers.i"
28-
%include "shared/keep_reference.i"
2928

3029
%import "value.i"
3130

@@ -54,84 +53,6 @@ UNIQUE_PTR(key_type);
5453

5554
EXTEND_KEY(Exiv2::Key);
5655

57-
// Macro for Metadatum subclasses
58-
%define EXTEND_METADATUM(datum_type)
59-
// Ignore overloaded default parameter version
60-
%ignore Exiv2::datum_type::write(std::ostream &) const;
61-
// Keep a reference to Metadatum when calling value()
62-
KEEP_REFERENCE(const Exiv2::Value&)
63-
// Keep a reference to any object that returns a reference to a datum.
64-
KEEP_REFERENCE(Exiv2::datum_type&)
65-
// Set the datum's value from a Python object. The datum's current or default
66-
// type is used to create an Exiv2::Value object (via Python) from the Python
67-
// object.
68-
%fragment("set_value_from_py"{Exiv2::datum_type}, "header",
69-
fragment="get_type_object",
70-
fragment="get_type_id"{Exiv2::datum_type}) {
71-
static PyObject* set_value_from_py(Exiv2::datum_type* datum,
72-
PyObject* py_value) {
73-
swig_type_info* ty_info = get_type_object(get_type_id(datum));
74-
SwigPyClientData *cl_data = (SwigPyClientData*)ty_info->clientdata;
75-
// Call type object to invoke constructor
76-
PyObject* swig_obj = PyObject_CallFunctionObjArgs(
77-
(PyObject*)cl_data->pytype, py_value, NULL);
78-
if (!swig_obj)
79-
return NULL;
80-
// Convert constructed object to Exiv2::Value
81-
Exiv2::Value* value = 0;
82-
if (!SWIG_IsOK(SWIG_ConvertPtr(swig_obj, (void**)&value, ty_info, 0))) {
83-
PyErr_SetString(
84-
PyExc_RuntimeError, "set_value_from_py: invalid conversion");
85-
Py_DECREF(swig_obj);
86-
return NULL;
87-
}
88-
// Set value
89-
datum->setValue(value);
90-
Py_DECREF(swig_obj);
91-
return SWIG_Py_Void();
92-
};
93-
}
94-
%extend Exiv2::datum_type {
95-
bool operator==(const Exiv2::datum_type &other) const {
96-
return &other == self;
97-
}
98-
bool operator!=(const Exiv2::datum_type &other) const {
99-
return &other != self;
100-
}
101-
// Extend Metadatum to allow getting value as a specific type.
102-
Exiv2::Value::SMART_PTR getValue(Exiv2::TypeId as_type) {
103-
// deprecated since 2023-12-07
104-
PyErr_WarnEx(PyExc_DeprecationWarning, "Requested type ignored.", 1);
105-
return $self->getValue();
106-
}
107-
const Exiv2::Value& value(Exiv2::TypeId as_type) {
108-
// deprecated since 2023-12-07
109-
PyErr_WarnEx(PyExc_DeprecationWarning, "Requested type ignored.", 1);
110-
return $self->value();
111-
}
112-
// Set the value from a Python object. The datum's current or default
113-
// type is used to create an Exiv2::Value object (via Python) from the
114-
// Python object.
115-
%fragment("set_value_from_py"{Exiv2::datum_type});
116-
PyObject* setValue(PyObject* py_value) {
117-
return set_value_from_py($self, py_value);
118-
}
119-
// Old _print method for compatibility
120-
std::string _print(const Exiv2::ExifData* pMetadata) const {
121-
// deprecated since 2024-01-29
122-
PyErr_WarnEx(PyExc_DeprecationWarning,
123-
"'_print' has been replaced by 'print'", 1);
124-
return $self->print(pMetadata);
125-
}
126-
// toString parameter does not default to 0, so bypass default typemap
127-
std::string toString() const { return self->toString(); }
128-
std::string toString(BUFLEN_T i) const { return self->toString(i); }
129-
}
130-
// Deprecate some methods since 2025-08-25
131-
DEPRECATE_FUNCTION(Exiv2::datum_type::copy, true)
132-
DEPRECATE_FUNCTION(Exiv2::datum_type::write, true)
133-
%enddef // EXTEND_METADATUM
134-
13556
// Deprecate some base class methods since 2025-08-25
13657
DEPRECATE_FUNCTION(Exiv2::Metadatum::copy, true)
13758
DEPRECATE_FUNCTION(Exiv2::Metadatum::write, true)

src/interface/preview.i

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ WINDOWS_PATH_OUT(extension)
6161

6262
// Declare metadatum wrapper classes
6363
DECLARE_METADATUM_WRAPPERS(ExifData, Exifdatum)
64+
DECLARE_METADATUM_WRAPPERS(IptcData, Iptcdatum)
65+
DECLARE_METADATUM_WRAPPERS(XmpData, Xmpdatum)
6466

6567
// Convert getPreviewProperties result to a Python tuple
6668
%template() std::vector<Exiv2::PreviewProperties>;

src/interface/shared/containers.i

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
base_class::__contains__;
3838
%extend base_class {
3939
%fragment("get_type_id"{datum_type});
40-
%fragment("set_value_from_py"{datum_type});
4140
datum_type& __getitem__(const std::string& key) {
4241
return (*$self)[key];
4342
}
@@ -56,10 +55,6 @@
5655
value.c_str());
5756
return SWIG_Py_Void();
5857
}
59-
PyObject* __setitem__(const std::string& key, PyObject* py_value) {
60-
datum_type* datum = &(*$self)[key];
61-
return set_value_from_py(datum, py_value);
62-
}
6358
#if SWIG_VERSION >= 0x040400
6459
PyObject* __setitem__(PyObject* py_self, const std::string& key) {
6560
#else
@@ -80,4 +75,47 @@
8075
return $self->findKey(key_type(key)) != $self->end();
8176
}
8277
}
78+
79+
// Set the datum's value from a Python object. The datum's current or default
80+
// type is used to create an Exiv2::Value object (via Python) from the Python
81+
// object.
82+
%fragment("set_value_from_py"{datum_type}, "header",
83+
fragment="get_type_object",
84+
fragment="get_type_id"{datum_type}) {
85+
static PyObject* set_value_from_py(datum_type* datum,
86+
PyObject* py_value) {
87+
swig_type_info* ty_info = get_type_object(get_type_id(datum));
88+
SwigPyClientData *cl_data = (SwigPyClientData*)ty_info->clientdata;
89+
// Call type object to invoke constructor
90+
PyObject* swig_obj = PyObject_CallFunctionObjArgs(
91+
(PyObject*)cl_data->pytype, py_value, NULL);
92+
if (!swig_obj)
93+
return NULL;
94+
// Convert constructed object to Exiv2::Value
95+
Exiv2::Value* value = 0;
96+
if (!SWIG_IsOK(SWIG_ConvertPtr(swig_obj, (void**)&value, ty_info, 0))) {
97+
PyErr_SetString(
98+
PyExc_RuntimeError, "set_value_from_py: invalid conversion");
99+
Py_DECREF(swig_obj);
100+
return NULL;
101+
}
102+
// Set value
103+
datum->setValue(value);
104+
Py_DECREF(swig_obj);
105+
return SWIG_Py_Void();
106+
};
107+
}
108+
%extend datum_type {
109+
%fragment("set_value_from_py"{datum_type});
110+
PyObject* setValue(PyObject* py_value) {
111+
return set_value_from_py($self, py_value);
112+
}
113+
}
114+
%extend base_class {
115+
%fragment("set_value_from_py"{datum_type});
116+
PyObject* __setitem__(const std::string& key, PyObject* py_value) {
117+
datum_type* datum = &(*$self)[key];
118+
return set_value_from_py(datum, py_value);
119+
}
120+
}
83121
%enddef // DATA_CONTAINER

src/interface/shared/metadatum_wrappers.i

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class datum_type##_reference;
3636
// Macro to wrap metadatum iterators and pointers
3737
%define METADATUM_WRAPPERS(container_type, datum_type)
3838

39+
// Keep a reference to any object that returns a reference to a datum.
40+
KEEP_REFERENCE(Exiv2::datum_type&)
41+
3942
// Invalidate pointers when data is deleted
4043
POINTER_STORE(container_type, datum_type)
4144

@@ -158,6 +161,31 @@ public:
158161
}
159162
};
160163
%}
164+
165+
// Metadata reference wrapper
166+
%ignore datum_type##_reference::##datum_type##_reference;
167+
%ignore datum_type##_reference::operator*;
168+
%feature("docstring") datum_type##_reference "
169+
Python wrapper for an :class:`" #datum_type "` reference. It has most of
170+
the methods of :class:`" #datum_type "` allowing easy access to the
171+
data it points to."
172+
%inline %{
173+
class datum_type##_reference: public datum_type##_pointer {
174+
private:
175+
Exiv2::datum_type* ptr;
176+
public:
177+
datum_type##_reference(Exiv2::datum_type* ptr): ptr(ptr) {
178+
name = "pointer";
179+
}
180+
Exiv2::datum_type* operator*() const {
181+
if (invalidated)
182+
throw std::runtime_error("datum_type reference is invalid");
183+
return ptr;
184+
}
185+
};
186+
%}
187+
188+
// typemaps
161189
%typemap(in) Exiv2::container_type::iterator
162190
(container_type##_iterator *argp=NULL) %{
163191
{
@@ -178,6 +206,15 @@ public:
178206
it = argp->_ptr();
179207
$1 = &it;
180208
}
209+
%typemap(in) const Exiv2::datum_type& {
210+
datum_type##_pointer* tmp = NULL;
211+
if (SWIG_IsOK(SWIG_ConvertPtr(
212+
$input, (void**)&tmp, $descriptor(datum_type##_pointer*), 0)))
213+
$1 = **tmp;
214+
else {
215+
$typemap(in, Exiv2::datum_type&)
216+
}
217+
}
181218
%typemap(out) Exiv2::container_type::iterator {
182219
$result = SWIG_NewPointerObj(
183220
SWIG_as_voidptr(new container_type##_iterator($1, arg1->end())),
@@ -189,40 +226,6 @@ public:
189226
}
190227
#endif // SWIG_VERSION
191228
}
192-
193-
// Metadata reference wrapper
194-
%ignore datum_type##_reference::##datum_type##_reference;
195-
%ignore datum_type##_reference::operator*;
196-
%feature("docstring") datum_type##_reference "
197-
Python wrapper for an :class:`" #datum_type "` reference. It has most of
198-
the methods of :class:`" #datum_type "` allowing easy access to the
199-
data it points to."
200-
// Keep a reference to the data being referred to
201-
KEEP_REFERENCE(Exiv2::datum_type&)
202-
%inline %{
203-
class datum_type##_reference: public datum_type##_pointer {
204-
private:
205-
Exiv2::datum_type* ptr;
206-
public:
207-
datum_type##_reference(Exiv2::datum_type* ptr): ptr(ptr) {
208-
name = "pointer";
209-
}
210-
Exiv2::datum_type* operator*() const {
211-
if (invalidated)
212-
throw std::runtime_error("datum_type reference is invalid");
213-
return ptr;
214-
}
215-
};
216-
%}
217-
%typemap(in) const Exiv2::datum_type& {
218-
datum_type##_reference* tmp = NULL;
219-
if (SWIG_IsOK(SWIG_ConvertPtr(
220-
$input, (void**)&tmp, $descriptor(datum_type##_reference*), 0)))
221-
$1 = **tmp;
222-
else {
223-
$typemap(in, Exiv2::datum_type&)
224-
}
225-
}
226229
%typemap(out) Exiv2::datum_type& {
227230
$result = SWIG_NewPointerObj(
228231
SWIG_as_voidptr(new datum_type##_reference($1)),
@@ -235,4 +238,41 @@ public:
235238
#endif // SWIG_VERSION
236239
}
237240

241+
// Deprecate some methods since 2025-08-25
242+
DEPRECATE_FUNCTION(Exiv2::datum_type::copy, true)
243+
DEPRECATE_FUNCTION(Exiv2::datum_type::write, true)
244+
// Ignore overloaded default parameter version
245+
%ignore Exiv2::datum_type::write(std::ostream &) const;
246+
247+
// Extend datum type
248+
%extend Exiv2::datum_type {
249+
bool operator==(const Exiv2::datum_type &other) const {
250+
return &other == self;
251+
}
252+
bool operator!=(const Exiv2::datum_type &other) const {
253+
return &other != self;
254+
}
255+
// Extend Metadatum to allow getting value as a specific type.
256+
Exiv2::Value::SMART_PTR getValue(Exiv2::TypeId as_type) {
257+
// deprecated since 2023-12-07
258+
PyErr_WarnEx(PyExc_DeprecationWarning, "Requested type ignored.", 1);
259+
return $self->getValue();
260+
}
261+
const Exiv2::Value& value(Exiv2::TypeId as_type) {
262+
// deprecated since 2023-12-07
263+
PyErr_WarnEx(PyExc_DeprecationWarning, "Requested type ignored.", 1);
264+
return $self->value();
265+
}
266+
// Old _print method for compatibility
267+
std::string _print(const Exiv2::ExifData* pMetadata) const {
268+
// deprecated since 2024-01-29
269+
PyErr_WarnEx(PyExc_DeprecationWarning,
270+
"'_print' has been replaced by 'print'", 1);
271+
return $self->print(pMetadata);
272+
}
273+
// toString parameter does not default to 0, so bypass default typemap
274+
std::string toString() const { return self->toString(); }
275+
std::string toString(BUFLEN_T i) const { return self->toString(i); }
276+
}
277+
238278
%enddef // METADATUM_WRAPPERS

src/interface/value.i

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
%include "shared/preamble.i"
2929
%include "shared/buffers.i"
30+
%include "shared/keep_reference.i"
3031
%include "shared/private_data.i"
3132
%include "shared/struct_dict.i"
3233

@@ -46,6 +47,9 @@ EXCEPTION()
4647

4748
UNIQUE_PTR(Exiv2::Value);
4849

50+
// Keep a reference to any object that returns a reference to a value.
51+
KEEP_REFERENCE(const Exiv2::Value&)
52+
4953
// Remove exception handler for some methods known to be safe
5054
%noexception Exiv2::Value::~Value;
5155
%noexception Exiv2::Value::count;

src/interface/xmp.i

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ IMPORT_ENUM(TypeId)
3838
// Catch all C++ exceptions
3939
EXCEPTION()
4040

41-
EXTEND_METADATUM(Xmpdatum)
42-
4341
METADATUM_WRAPPERS(XmpData, Xmpdatum)
4442

4543
// Get the current (or default if not set) type id of a datum

0 commit comments

Comments
 (0)