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. */