1
/* typecast_binary.c - binary typecasting functions to python types
3
* Copyright (C) 2001-2003 Federico Di Gregorio <fog@debian.org>
5
* This file is part of the psycopg module.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 2,
10
* or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
#include "typecast_binary.h"
28
/* Python object holding a memory chunk. The memory is deallocated when
29
the object is destroyed. This type is used to let users directly access
30
memory chunks holding unescaped binary data through the buffer interface.
34
chunk_dealloc(chunkObject *self)
36
Dprintf("chunk_dealloc: deallocating memory at %p, size %d",
37
self->base, self->len);
39
self->ob_type->tp_free((PyObject *) self);
43
chunk_repr(chunkObject *self)
45
return PyString_FromFormat("<memory chunk at %p size %d>",
46
self->base, self->len);
50
chunk_getreadbuffer(chunkObject *self, int segment, void **ptr)
54
PyErr_SetString(PyExc_SystemError,
55
"acessing non-existant buffer segment");
63
chunk_getsegcount(chunkObject *self, int *lenp)
70
static PyBufferProcs chunk_as_buffer =
72
(getreadbufferproc) chunk_getreadbuffer,
73
(getwritebufferproc) NULL,
74
(getsegcountproc) chunk_getsegcount,
75
(getcharbufferproc) NULL
78
#define chunk_doc "memory chunk"
80
PyTypeObject chunkType = {
81
PyObject_HEAD_INIT(NULL)
83
"psycopg2._psycopg.chunk", /* tp_name */
84
sizeof(chunkObject), /* tp_basicsize */
86
(destructor) chunk_dealloc, /* tp_dealloc*/
91
(reprfunc) chunk_repr, /* tp_repr */
93
0, /* tp_as_sequence */
94
0, /* tp_as_mapping */
100
&chunk_as_buffer, /* tp_as_buffer */
101
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
102
chunk_doc /* tp_doc */
105
/* the function typecast_BINARY_cast_unescape is used when libpq does not
106
provide PQunescapeBytea: it convert all the \xxx octal sequences to the
109
#ifdef PSYCOPG_OWN_QUOTING
110
static unsigned char *
111
typecast_BINARY_cast_unescape(unsigned char *str, size_t *to_length)
113
char *dstptr, *dststr;
117
dststr = (char*)calloc(len, sizeof(char));
120
if (dststr == NULL) return NULL;
122
Py_BEGIN_ALLOW_THREADS;
124
for (i = 0; i < len; i++) {
125
if (str[i] == '\\') {
127
if (str[i] == '\\') {
132
*dstptr |= (str[i++] & 7) << 6;
133
*dstptr |= (str[i++] & 7) << 3;
134
*dstptr |= (str[i] & 7);
144
Py_END_ALLOW_THREADS;
146
*to_length = (size_t)(dstptr-dststr);
151
#define PQunescapeBytea typecast_BINARY_cast_unescape
155
typecast_BINARY_cast(char *s, int l, PyObject *curs)
159
char *str, *buffer = NULL;
162
if (s == NULL) {Py_INCREF(Py_None); return Py_None;}
164
/* PQunescapeBytea absolutely wants a 0-terminated string and we don't
165
want to copy the whole buffer, right? Wrong, but there isn't any other
168
if ((buffer = PyMem_Malloc(l+1)) == NULL)
170
strncpy(buffer, s, l);
174
str = (char*)PQunescapeBytea((unsigned char*)s, &len);
175
Dprintf("typecast_BINARY_cast: unescaped %d bytes", len);
176
if (buffer) PyMem_Free(buffer);
178
chunk = (chunkObject *) PyObject_New(chunkObject, &chunkType);
179
if (chunk == NULL) return NULL;
183
if ((res = PyBuffer_FromObject((PyObject *)chunk, 0, len)) == NULL)
186
/* PyBuffer_FromObject() created a new reference. Release our reference so
187
that the memory can be freed once the buffer is garbage collected. */