Skip to content

Commit b3bd773

Browse files
author
James William Pye
committed
Use the buffer API.
The direct use of bytes, while desirable for speed, limits the number of types the unpack routines can work with. Eventually, we may be using memoryviews more often, so it's imperative to support the buffer APIs. [Didn't see much, if any, slow down on the single int test either.] Also, relax the check on the buffer's size to only require that *at least* 2, 4, or 8 bytes exist in the buffer. This further aligns the implementation with Struct.unpack_from.
1 parent cd0bad4 commit b3bd773

1 file changed

Lines changed: 58 additions & 69 deletions

File tree

postgresql/port/optimized/structlib.c

Lines changed: 58 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/*
2-
* copyright 2009, James William Pye
3-
* http://python.projects.postgresql.org
2+
* .port.optimized - pack and unpack int2, int4, and int8.
43
*/
54

65
/*
@@ -130,6 +129,7 @@ int2_pack(PyObject *self, PyObject *arg)
130129
s = (short) l;
131130
return(PyBytes_FromStringAndSize((const char *) &s, 2));
132131
}
132+
133133
static PyObject *
134134
swap_int2_pack(PyObject *self, PyObject *arg)
135135
{
@@ -159,14 +159,12 @@ int2_unpack(PyObject *self, PyObject *arg)
159159
Py_ssize_t len;
160160
PyObject *rob;
161161

162-
c = PyBytes_AsString(arg);
163-
if (PyErr_Occurred())
162+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
164163
return(NULL);
165164

166-
len = PyBytes_Size(arg);
167-
if (len != 2)
165+
if (len < 2)
168166
{
169-
PyErr_SetString(PyExc_ValueError, "invalid size of data for int2_unpack");
167+
PyErr_SetString(PyExc_ValueError, "not enough data for int2_unpack");
170168
return(NULL);
171169
}
172170

@@ -175,6 +173,7 @@ int2_unpack(PyObject *self, PyObject *arg)
175173
rob = PyLong_FromLong(l);
176174
return(rob);
177175
}
176+
178177
static PyObject *
179178
swap_int2_unpack(PyObject *self, PyObject *arg)
180179
{
@@ -184,14 +183,12 @@ swap_int2_unpack(PyObject *self, PyObject *arg)
184183
Py_ssize_t len;
185184
PyObject *rob;
186185

187-
c = PyBytes_AsString(arg);
188-
if (PyErr_Occurred())
186+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
189187
return(NULL);
190188

191-
len = PyBytes_Size(arg);
192-
if (len != 2)
189+
if (len < 2)
193190
{
194-
PyErr_SetString(PyExc_ValueError, "invalid size of data for swap_int2_unpack");
191+
PyErr_SetString(PyExc_ValueError, "not enough data for swap_int2_unpack");
195192
return(NULL);
196193
}
197194

@@ -221,6 +218,7 @@ int4_pack(PyObject *self, PyObject *arg)
221218
i = (int32_t) l;
222219
return(PyBytes_FromStringAndSize((const char *) &i, 4));
223220
}
221+
224222
static PyObject *
225223
swap_int4_pack(PyObject *self, PyObject *arg)
226224
{
@@ -249,35 +247,32 @@ int4_unpack(PyObject *self, PyObject *arg)
249247
int32_t i;
250248
Py_ssize_t len;
251249

252-
c = PyBytes_AsString(arg);
253-
if (PyErr_Occurred())
250+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
254251
return(NULL);
255252

256-
len = PyBytes_Size(arg);
257-
if (len != 4)
253+
if (len < 4)
258254
{
259-
PyErr_SetString(PyExc_ValueError, "invalid size of data for int4_unpack");
255+
PyErr_SetString(PyExc_ValueError, "not enough data for int4_unpack");
260256
return(NULL);
261257
}
262258
i = *((int32_t *) c);
263259

264260
return(PyLong_FromLong((long) i));
265261
}
262+
266263
static PyObject *
267264
swap_int4_unpack(PyObject *self, PyObject *arg)
268265
{
269266
char *c;
270267
int32_t i;
271268
Py_ssize_t len;
272269

273-
c = PyBytes_AsString(arg);
274-
if (PyErr_Occurred())
270+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
275271
return(NULL);
276272

277-
len = PyBytes_Size(arg);
278-
if (len != 4)
273+
if (len < 4)
279274
{
280-
PyErr_SetString(PyExc_ValueError, "invalid size of data for swap_int4_unpack");
275+
PyErr_SetString(PyExc_ValueError, "not enough data for swap_int4_unpack");
281276
return(NULL);
282277
}
283278

@@ -307,6 +302,7 @@ uint2_pack(PyObject *self, PyObject *arg)
307302
s = (unsigned short) l;
308303
return(PyBytes_FromStringAndSize((const char *) &s, 2));
309304
}
305+
310306
static PyObject *
311307
swap_uint2_pack(PyObject *self, PyObject *arg)
312308
{
@@ -339,14 +335,12 @@ uint2_unpack(PyObject *self, PyObject *arg)
339335
Py_ssize_t len;
340336
PyObject *rob;
341337

342-
c = PyBytes_AsString(arg);
343-
if (PyErr_Occurred())
338+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
344339
return(NULL);
345340

346-
len = PyBytes_GET_SIZE(arg);
347-
if (len != 2)
341+
if (len < 2)
348342
{
349-
PyErr_SetString(PyExc_ValueError, "invalid size of data for uint2_unpack");
343+
PyErr_SetString(PyExc_ValueError, "not enough data for uint2_unpack");
350344
return(NULL);
351345
}
352346

@@ -355,6 +349,7 @@ uint2_unpack(PyObject *self, PyObject *arg)
355349
rob = PyLong_FromLong(l);
356350
return(rob);
357351
}
352+
358353
static PyObject *
359354
swap_uint2_unpack(PyObject *self, PyObject *arg)
360355
{
@@ -364,14 +359,11 @@ swap_uint2_unpack(PyObject *self, PyObject *arg)
364359
Py_ssize_t len;
365360
PyObject *rob;
366361

367-
c = PyBytes_AsString(arg);
368-
if (PyErr_Occurred())
362+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
369363
return(NULL);
370-
371-
len = PyBytes_GET_SIZE(arg);
372-
if (len != 2)
364+
if (len < 2)
373365
{
374-
PyErr_SetString(PyExc_ValueError, "invalid size of data for swap_uint2_unpack");
366+
PyErr_SetString(PyExc_ValueError, "not enough data for swap_uint2_unpack");
375367
return(NULL);
376368
}
377369

@@ -402,6 +394,7 @@ uint4_pack(PyObject *self, PyObject *arg)
402394
i = (uint32_t) l;
403395
return(PyBytes_FromStringAndSize((const char *) &i, 4));
404396
}
397+
405398
static PyObject *
406399
swap_uint4_pack(PyObject *self, PyObject *arg)
407400
{
@@ -431,36 +424,32 @@ uint4_unpack(PyObject *self, PyObject *arg)
431424
uint32_t i;
432425
Py_ssize_t len;
433426

434-
len = PyBytes_Size(arg);
435-
if (len != 4)
427+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
428+
return(NULL);
429+
430+
if (len < 4)
436431
{
437-
PyErr_SetString(PyExc_ValueError,
438-
"invalid size of data for uint4_unpack");
432+
PyErr_SetString(PyExc_ValueError, "not enough data for uint4_unpack");
439433
return(NULL);
440434
}
441-
c = PyBytes_AsString(arg);
442-
if (PyErr_Occurred())
443-
return(NULL);
444-
i = *((uint32_t *) c);
445435

436+
i = *((uint32_t *) c);
446437
return(PyLong_FromUnsignedLong((unsigned long) i));
447438
}
439+
448440
static PyObject *
449441
swap_uint4_unpack(PyObject *self, PyObject *arg)
450442
{
451443
char *c;
452444
uint32_t i;
453445
Py_ssize_t len;
454446

455-
c = PyBytes_AsString(arg);
456-
if (PyErr_Occurred())
447+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
457448
return(NULL);
458-
459-
len = PyBytes_Size(arg);
460-
if (len != 4)
449+
if (len < 4)
461450
{
462451
PyErr_SetString(PyExc_ValueError,
463-
"invalid size of data for swap_uint4_unpack");
452+
"not enough data for swap_uint4_unpack");
464453
return(NULL);
465454
}
466455

@@ -485,6 +474,7 @@ int8_pack(PyObject *self, PyObject *arg)
485474

486475
return(PyBytes_FromStringAndSize((const char *) &l, 8));
487476
}
477+
488478
static PyObject *
489479
swap_int8_pack(PyObject *self, PyObject *arg)
490480
{
@@ -509,6 +499,7 @@ uint8_pack(PyObject *self, PyObject *arg)
509499

510500
return(PyBytes_FromStringAndSize((const char *) &l, 8));
511501
}
502+
512503
static PyObject *
513504
swap_uint8_pack(PyObject *self, PyObject *arg)
514505
{
@@ -526,85 +517,83 @@ static PyObject *
526517
uint8_unpack(PyObject *self, PyObject *arg)
527518
{
528519
char *c;
520+
Py_ssize_t len;
529521
unsigned PY_LONG_LONG i;
530522

531-
if (PyBytes_Size(arg) != 8)
523+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
524+
return(NULL);
525+
if (len < 8)
532526
{
533-
PyErr_SetString(PyExc_ValueError,
534-
"invalid size of data for uint8_unpack");
527+
PyErr_SetString(PyExc_ValueError, "not enough data for uint8_unpack");
535528
return(NULL);
536529
}
537530

538-
c = PyBytes_AsString(arg);
539-
if (PyErr_Occurred())
540-
return(NULL);
541-
542531
i = *((unsigned PY_LONG_LONG *) c);
543-
544532
return(PyLong_FromUnsignedLongLong(i));
545533
}
546534
static PyObject *
547535
swap_uint8_unpack(PyObject *self, PyObject *arg)
548536
{
549537
char *c;
538+
Py_ssize_t len;
550539
unsigned PY_LONG_LONG i;
551540

552-
c = PyBytes_AsString(arg);
553-
if (PyErr_Occurred())
541+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
554542
return(NULL);
555-
556-
if (PyBytes_Size(arg) != 8)
543+
if (len < 8)
557544
{
558545
PyErr_SetString(PyExc_ValueError,
559-
"invalid size of data for swap_uint8_unpack");
546+
"not enough data for swap_uint8_unpack");
560547
return(NULL);
561548
}
562549

563550
i = *((unsigned PY_LONG_LONG *) c);
564551
swap8(((char *) &i));
565-
566552
return(PyLong_FromUnsignedLongLong(i));
567553
}
568554

569555
static PyObject *
570556
int8_unpack(PyObject *self, PyObject *arg)
571557
{
572558
char *c;
559+
Py_ssize_t len;
573560
PY_LONG_LONG i;
574561

575-
if (PyBytes_Size(arg) != 8)
562+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
563+
return(NULL);
564+
if (len < 8)
576565
{
577566
PyErr_SetString(PyExc_ValueError,
578-
"invalid size of data for int8_unpack");
567+
"not enough data for int8_unpack");
579568
return(NULL);
580569
}
581-
c = PyBytes_AsString(arg);
582-
if (PyErr_Occurred())
583-
return(NULL);
584570

585571
i = *((PY_LONG_LONG *) c);
586572
return(PyLong_FromLongLong((PY_LONG_LONG) i));
587573
}
574+
588575
static PyObject *
589576
swap_int8_unpack(PyObject *self, PyObject *arg)
590577
{
591578
char *c;
579+
Py_ssize_t len;
592580
PY_LONG_LONG i;
593581

594582
c = PyBytes_AsString(arg);
595583
if (PyErr_Occurred())
596584
return(NULL);
597585

598-
if (PyBytes_Size(arg) != 8)
586+
if (PyObject_AsReadBuffer(arg, (const void **) &c, &len))
587+
return(NULL);
588+
if (len < 8)
599589
{
600590
PyErr_SetString(PyExc_ValueError,
601-
"invalid size of data for swap_int8_unpack");
591+
"not enough data for swap_int8_unpack");
602592
return(NULL);
603593
}
604594

605595
i = *((PY_LONG_LONG *) c);
606596
swap8(((char *) &i));
607-
608597
return(PyLong_FromLongLong(i));
609598
}
610599
#endif /* longlong_funcs */

0 commit comments

Comments
 (0)