Skip to content

Commit f5e3b1c

Browse files
Add sq_ass_item slot macro
1 parent c330f28 commit f5e3b1c

File tree

4 files changed

+1956
-1097
lines changed

4 files changed

+1956
-1097
lines changed

src/interface/shared/slots.i

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,50 @@ static PyObject* __getitem__%mangle(type)_closure(
4646
%enddef // SQ_ITEM
4747

4848

49+
// Macro to add sq_ass_item slot and functions
50+
%define SQ_ASS_ITEM(type, item_type, setfunc, delfunc)
51+
// Use %inline so SWIG generates wrappers with type conversions.
52+
// Names start with '_' so it's invisible in normal use.
53+
%noexception __setitem__%mangle(Exiv2::ValueType<item_type>);
54+
%noexception __delitem__%mangle(Exiv2::ValueType<item_type>);
55+
%inline %{
56+
static void __setitem__%mangle(Exiv2::ValueType<item_type>)(
57+
Exiv2::ValueType<item_type>* self, size_t idx, item_type value) {
58+
setfunc;
59+
};
60+
static void __delitem__%mangle(Exiv2::ValueType<item_type>)(
61+
Exiv2::ValueType<item_type>* self, size_t idx) {
62+
delfunc;
63+
};
64+
%}
65+
%fragment("__setitem__"{type}, "header") {
66+
extern "C" {
67+
static PyObject* _wrap___setitem__%mangle(type)(PyObject*, PyObject*);
68+
static PyObject* _wrap___delitem__%mangle(type)(PyObject*, PyObject*);
69+
}
70+
static int __setitem__%mangle(type)_closure(
71+
PyObject* self, Py_ssize_t idx, PyObject* value) {
72+
PyObject* args;
73+
PyObject* result;
74+
if (value) {
75+
args = Py_BuildValue("(OnO)", self, idx, value);
76+
result = _wrap___setitem__%mangle(type)(self, args);
77+
} else {
78+
args = Py_BuildValue("(On)", self, idx);
79+
result = _wrap___delitem__%mangle(type)(self, args);
80+
}
81+
Py_DECREF(args);
82+
if (!result)
83+
return -1;
84+
Py_DECREF(result);
85+
return 0;
86+
};
87+
}
88+
%fragment("__setitem__"{type});
89+
%feature("python:sq_ass_item") type QUOTE(__setitem__%mangle(type)_closure);
90+
%enddef // SQ_ASS_ITEM
91+
92+
4993
// Macro to add sq_length slot and function
5094
%define SQ_LENGTH(type, func)
5195
%fragment("__len__"{type}, "header") {

src/interface/value.i

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,6 @@ DEPRECATED_ENUM(XmpValue, XmpStruct)
236236
%ignore type_name::copy(byte *) const;
237237
%ignore type_name::read(byte const *, BUFLEN_T);
238238
%noexception type_name::~part_name;
239-
%noexception type_name::__setitem__;
240239
%noexception type_name::append;
241240
%noexception type_name::count;
242241
%noexception type_name::size;
@@ -276,15 +275,9 @@ VALUE_SUBCLASS(Exiv2::ValueType<item_type>, type_name)
276275
std::pair< unsigned int,unsigned int > const &);
277276
// Access values as a list
278277
SQ_ITEM(Exiv2::ValueType<item_type>, item_type, self->value_[idx])
279-
#if SWIG_VERSION >= 0x040201
280-
%feature("python:slot", "sq_ass_item", functype="ssizeobjargproc")
281-
Exiv2::ValueType<item_type>::__setitem__;
282-
#else
283-
// sq_ass_item segfaults when used to delete element
284-
// See https://github.com/swig/swig/pull/2771
285-
%feature("python:slot", "mp_ass_subscript", functype="objobjargproc")
286-
Exiv2::ValueType<item_type>::__setitem__;
287-
#endif // SWIG_VERSION
278+
SQ_ASS_ITEM(Exiv2::ValueType<item_type>, item_type,
279+
self->value_[idx] = value,
280+
self->value_.erase(self->value_.begin() + idx))
288281
%feature("docstring") Exiv2::ValueType<item_type>
289282
"Sequence of " #item_type " values.\n"
290283
"The data components can be accessed like a Python list."
@@ -299,12 +292,6 @@ SQ_ITEM(Exiv2::ValueType<item_type>, item_type, self->value_[idx])
299292
result->value_ = value;
300293
return result;
301294
}
302-
void __setitem__(size_t idx, const item_type* INPUT) {
303-
if (INPUT)
304-
$self->value_[idx] = *INPUT;
305-
else
306-
$self->value_.erase($self->value_.begin() + idx);
307-
}
308295
void append(item_type value) {
309296
$self->value_.push_back(value);
310297
}

0 commit comments

Comments
 (0)