Skip to content

Commit 94407f7

Browse files
Improved OUTPUT_BUFFER_RW macro
1 parent 38473ac commit 94407f7

16 files changed

Lines changed: 284 additions & 383 deletions

CHANGELOG.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ Changes in v0.18.0:
2626
4/ Add data() method to exiv2.PreviewImage, deprecate pData() method.
2727
5/ Deprecated many BasicIo methods (read, write, seek, etc.) that should not
2828
be needed in Python scripts. Please let me know if this is a problem.
29-
6/ Deprecated 'buffer interface' to BasicIo, DataBuf, and PreviewImage. They
29+
6/ BasicIo.read (& readOrThrow) now extract count from the buffer size.
30+
7/ Deprecated 'buffer interface' to BasicIo, DataBuf, and PreviewImage. They
3031
all have 'data()' to get their contents.
31-
7/ Invalidate data iterators if data is deleted. (Requires swig >= 4.4)
32+
8/ Invalidate data iterators if data is deleted. (Requires swig >= 4.4)
3233

3334
Changes in v0.17.3:
3435
1/ Binary wheels incorporate libexiv2 v0.28.5.

src/interface/shared/buffers.i

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ _HOLD_BUFFER(hold_funcs)
7171
// Macro for output writeable byte buffer
7272
%define OUTPUT_BUFFER_RW(buf_type, count_type)
7373
%typemap(doctype) buf_type "writeable :py:term:`bytes-like object`";
74-
%typemap(in) (buf_type) (Py_buffer _global_buff) {
74+
#if #count_type != ""
75+
%typemap(in) (buf_type, count_type) (Py_buffer _global_buff) {
7576
_global_buff.obj = NULL;
7677
if (PyObject_GetBuffer(
7778
$input, &_global_buff, PyBUF_CONTIG | PyBUF_WRITABLE) < 0) {
@@ -80,18 +81,35 @@ _HOLD_BUFFER(hold_funcs)
8081
$symname, $argnum);
8182
}
8283
$1 = ($1_ltype) _global_buff.buf;
84+
$2 = ($2_ltype) _global_buff.len;
8385
}
84-
%typemap(check) (buf_type, count_type) {
85-
if ($2 > ($2_ltype) _global_buff.len) {
86+
%typemap(freearg) (buf_type, count_type) %{
87+
if (_global_buff.obj) {
88+
PyBuffer_Release(&_global_buff);
89+
}
90+
%}
91+
#else
92+
%typemap(in) (buf_type) (Py_buffer _global_buff) {
93+
_global_buff.obj = NULL;
94+
if (PyObject_GetBuffer(
95+
$input, &_global_buff, PyBUF_CONTIG | PyBUF_WRITABLE) < 0) {
96+
PyErr_Clear();
97+
%argument_fail(SWIG_TypeError, "writable bytes-like object",
98+
$symname, $argnum);
99+
}
100+
// check buffer is large enough, assumes arg1 points to self
101+
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
86102
%argument_fail(SWIG_ValueError, "buffer too small",
87103
$symname, $argnum);
88104
}
105+
$1 = ($1_ltype) _global_buff.buf;
89106
}
90107
%typemap(freearg) (buf_type) %{
91108
if (_global_buff.obj) {
92109
PyBuffer_Release(&_global_buff);
93110
}
94111
%}
112+
#endif
95113
%typemap(typecheck, precedence=SWIG_TYPECHECK_CHAR_PTR) buf_type %{
96114
$1 = PyObject_CheckBuffer($input) ? 1 : 0;
97115
%}

src/interface/value.i

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,8 @@ INPUT_BUFFER_RO(const Exiv2::byte* buf, long len)
9494
INPUT_BUFFER_RO(const Exiv2::byte* buf, size_t len)
9595
#endif
9696
// Value::copy can write to a Python buffer
97-
OUTPUT_BUFFER_RW(Exiv2::byte* buf, Exiv2::ByteOrder byteOrder)
98-
// redefine check typemap
99-
%typemap(check) (Exiv2::byte* buf, Exiv2::ByteOrder byteOrder) {
100-
// check buffer is large enough, assumes arg1 points to self
101-
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
102-
%argument_fail(SWIG_ValueError, "buffer too small",
103-
$symname, $argnum);
104-
}
105-
}
97+
OUTPUT_BUFFER_RW(Exiv2::byte* buf,)
98+
10699
// Downcast base class pointers to derived class
107100
// Convert exiv2 type id to the appropriate value class type info
108101
%fragment("get_type_object", "header") {

src/swig-0_27_7/basicio_wrap.cxx

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5276,13 +5276,10 @@ SWIGINTERN PyObject *_wrap_BasicIo_read__SWIG_1(PyObject *self, PyObject *args)
52765276
void *argp1 = 0 ;
52775277
int res1 = 0 ;
52785278
Py_buffer _global_buff ;
5279-
long val3 ;
5280-
int ecode3 = 0 ;
52815279
PyObject * obj1 = 0 ;
5282-
PyObject * obj2 = 0 ;
52835280
long result;
52845281

5285-
if (!PyArg_UnpackTuple(args, "BasicIo_read", 2, 2, &obj1, &obj2)) SWIG_fail;
5282+
if (!PyArg_UnpackTuple(args, "BasicIo_read", 1, 1, &obj1)) SWIG_fail;
52865283
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_Exiv2__BasicIo, 0 | 0 );
52875284
if (!SWIG_IsOK(res1)) {
52885285
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BasicIo_read" "', argument " "1"" of type '" "Exiv2::BasicIo *""'");
@@ -5297,23 +5294,13 @@ SWIGINTERN PyObject *_wrap_BasicIo_read__SWIG_1(PyObject *self, PyObject *args)
52975294
;
52985295
}
52995296
arg2 = (Exiv2::byte *) _global_buff.buf;
5297+
arg3 = (long) _global_buff.len;
53005298
}
5301-
ecode3 = SWIG_AsVal_long(obj2, &val3);
5302-
if (!SWIG_IsOK(ecode3)) {
5303-
SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "BasicIo_read" "', argument " "3"" of type '" "long""'");
5304-
}
5305-
arg3 = static_cast< long >(val3);
53065299
{
53075300
#ifndef NO_RELEASE_BasicIo_read
53085301
release_views(self);
53095302
#endif
53105303
}
5311-
{
5312-
if (arg3 > (long) _global_buff.len) {
5313-
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "BasicIo_read" "', argument " "2"" of type '" "buffer too small""'")
5314-
;
5315-
}
5316-
}
53175304
{
53185305
PyErr_WarnEx(PyExc_DeprecationWarning,
53195306
"Python scripts should not need to call ""Exiv2::BasicIo::read", 1);
@@ -5349,7 +5336,7 @@ SWIGINTERN PyObject *_wrap_BasicIo_read__SWIG_1(PyObject *self, PyObject *args)
53495336

53505337
SWIGINTERN PyObject *_wrap_BasicIo_read(PyObject *self, PyObject *args) {
53515338
Py_ssize_t argc;
5352-
PyObject *argv[4] = {
5339+
PyObject *argv[3] = {
53535340
0
53545341
};
53555342
Py_ssize_t ii;
@@ -5358,16 +5345,24 @@ SWIGINTERN PyObject *_wrap_BasicIo_read(PyObject *self, PyObject *args) {
53585345
if (!PyTuple_Check(args)) SWIG_fail;
53595346
argc = PyObject_Length(args);
53605347
argv[0] = self;
5361-
for (ii = 0; (ii < 2) && (ii < argc); ii++) {
5348+
for (ii = 0; (ii < 1) && (ii < argc); ii++) {
53625349
argv[ii + 1] = PyTuple_GET_ITEM(args,ii);
53635350
}
53645351
argc++;
53655352
if (argc == 2) {
5366-
PyObject *retobj = _wrap_BasicIo_read__SWIG_0(self, args);
5367-
if (!SWIG_Python_TypeErrorOccurred(retobj)) return retobj;
5368-
SWIG_fail;
5353+
int _v = 0;
5354+
{
5355+
{
5356+
int res = SWIG_AsVal_long(argv[1], NULL);
5357+
_v = SWIG_CheckState(res);
5358+
}
5359+
}
5360+
if (!_v) goto check_1;
5361+
return _wrap_BasicIo_read__SWIG_0(self, args);
53695362
}
5370-
if (argc == 3) {
5363+
check_1:
5364+
5365+
if (argc == 2) {
53715366
PyObject *retobj = _wrap_BasicIo_read__SWIG_1(self, args);
53725367
if (!SWIG_Python_TypeErrorOccurred(retobj)) return retobj;
53735368
SWIG_fail;

src/swig-0_27_7/exif_wrap.cxx

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6361,6 +6361,11 @@ SWIGINTERN PyObject *_wrap_ExifData_iterator_copy(PyObject *self, PyObject *args
63616361
SWIG_exception_fail(SWIG_ArgError(SWIG_TypeError), "in method '" "ExifData_iterator_copy" "', argument " "2"" of type '" "writable bytes-like object""'")
63626362
;
63636363
}
6364+
// check buffer is large enough, assumes arg1 points to self
6365+
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
6366+
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "ExifData_iterator_copy" "', argument " "2"" of type '" "buffer too small""'")
6367+
;
6368+
}
63646369
arg2 = (Exiv2::byte *) _global_buff.buf;
63656370
}
63666371
{
@@ -6376,13 +6381,6 @@ SWIGINTERN PyObject *_wrap_ExifData_iterator_copy(PyObject *self, PyObject *args
63766381
}
63776382
arg3 = static_cast< Exiv2::ByteOrder >(PyLong_AsLong(obj2));
63786383
}
6379-
{
6380-
// check buffer is large enough, assumes arg1 points to self
6381-
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
6382-
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "ExifData_iterator_copy" "', argument " "2"" of type '" "buffer too small""'")
6383-
;
6384-
}
6385-
}
63866384
{
63876385
try {
63886386
result = (long)(*arg1)->copy(arg2,arg3);
@@ -7832,6 +7830,11 @@ SWIGINTERN PyObject *_wrap_Exifdatum_copy(PyObject *self, PyObject *args) {
78327830
SWIG_exception_fail(SWIG_ArgError(SWIG_TypeError), "in method '" "Exifdatum_copy" "', argument " "2"" of type '" "writable bytes-like object""'")
78337831
;
78347832
}
7833+
// check buffer is large enough, assumes arg1 points to self
7834+
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
7835+
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "Exifdatum_copy" "', argument " "2"" of type '" "buffer too small""'")
7836+
;
7837+
}
78357838
arg2 = (Exiv2::byte *) _global_buff.buf;
78367839
}
78377840
{
@@ -7847,13 +7850,6 @@ SWIGINTERN PyObject *_wrap_Exifdatum_copy(PyObject *self, PyObject *args) {
78477850
}
78487851
arg3 = static_cast< Exiv2::ByteOrder >(PyLong_AsLong(obj2));
78497852
}
7850-
{
7851-
// check buffer is large enough, assumes arg1 points to self
7852-
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
7853-
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "Exifdatum_copy" "', argument " "2"" of type '" "buffer too small""'")
7854-
;
7855-
}
7856-
}
78577853
{
78587854
try {
78597855
result = (long)((Exiv2::Exifdatum const *)arg1)->copy(arg2,arg3);

src/swig-0_27_7/iptc_wrap.cxx

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6015,6 +6015,11 @@ SWIGINTERN PyObject *_wrap_IptcData_iterator_copy(PyObject *self, PyObject *args
60156015
SWIG_exception_fail(SWIG_ArgError(SWIG_TypeError), "in method '" "IptcData_iterator_copy" "', argument " "2"" of type '" "writable bytes-like object""'")
60166016
;
60176017
}
6018+
// check buffer is large enough, assumes arg1 points to self
6019+
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
6020+
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "IptcData_iterator_copy" "', argument " "2"" of type '" "buffer too small""'")
6021+
;
6022+
}
60186023
arg2 = (Exiv2::byte *) _global_buff.buf;
60196024
}
60206025
{
@@ -6030,13 +6035,6 @@ SWIGINTERN PyObject *_wrap_IptcData_iterator_copy(PyObject *self, PyObject *args
60306035
}
60316036
arg3 = static_cast< Exiv2::ByteOrder >(PyLong_AsLong(obj2));
60326037
}
6033-
{
6034-
// check buffer is large enough, assumes arg1 points to self
6035-
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
6036-
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "IptcData_iterator_copy" "', argument " "2"" of type '" "buffer too small""'")
6037-
;
6038-
}
6039-
}
60406038
{
60416039
try {
60426040
result = (long)(*arg1)->copy(arg2,arg3);
@@ -7371,6 +7369,11 @@ SWIGINTERN PyObject *_wrap_Iptcdatum_copy(PyObject *self, PyObject *args) {
73717369
SWIG_exception_fail(SWIG_ArgError(SWIG_TypeError), "in method '" "Iptcdatum_copy" "', argument " "2"" of type '" "writable bytes-like object""'")
73727370
;
73737371
}
7372+
// check buffer is large enough, assumes arg1 points to self
7373+
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
7374+
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "Iptcdatum_copy" "', argument " "2"" of type '" "buffer too small""'")
7375+
;
7376+
}
73747377
arg2 = (Exiv2::byte *) _global_buff.buf;
73757378
}
73767379
{
@@ -7386,13 +7389,6 @@ SWIGINTERN PyObject *_wrap_Iptcdatum_copy(PyObject *self, PyObject *args) {
73867389
}
73877390
arg3 = static_cast< Exiv2::ByteOrder >(PyLong_AsLong(obj2));
73887391
}
7389-
{
7390-
// check buffer is large enough, assumes arg1 points to self
7391-
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
7392-
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "Iptcdatum_copy" "', argument " "2"" of type '" "buffer too small""'")
7393-
;
7394-
}
7395-
}
73967392
{
73977393
try {
73987394
result = (long)((Exiv2::Iptcdatum const *)arg1)->copy(arg2,arg3);

src/swig-0_27_7/metadatum_wrap.cxx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5678,6 +5678,11 @@ SWIGINTERN PyObject *_wrap_Metadatum_copy(PyObject *self, PyObject *args) {
56785678
SWIG_exception_fail(SWIG_ArgError(SWIG_TypeError), "in method '" "Metadatum_copy" "', argument " "2"" of type '" "writable bytes-like object""'")
56795679
;
56805680
}
5681+
// check buffer is large enough, assumes arg1 points to self
5682+
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
5683+
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "Metadatum_copy" "', argument " "2"" of type '" "buffer too small""'")
5684+
;
5685+
}
56815686
arg2 = (Exiv2::byte *) _global_buff.buf;
56825687
}
56835688
{
@@ -5693,13 +5698,6 @@ SWIGINTERN PyObject *_wrap_Metadatum_copy(PyObject *self, PyObject *args) {
56935698
}
56945699
arg3 = static_cast< Exiv2::ByteOrder >(PyLong_AsLong(obj2));
56955700
}
5696-
{
5697-
// check buffer is large enough, assumes arg1 points to self
5698-
if ((Py_ssize_t) arg1->size() > _global_buff.len) {
5699-
SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "in method '" "Metadatum_copy" "', argument " "2"" of type '" "buffer too small""'")
5700-
;
5701-
}
5702-
}
57035701
{
57045702
try {
57055703
result = (long)((Exiv2::Metadatum const *)arg1)->copy(arg2,arg3);

0 commit comments

Comments
 (0)