Пример #1
0
// For py3k, a function that returns new memoryview object instead of buffer.
// ??? Byte array object is mutable, maybe just use that directly as a substitute ???
// Docs do not specify that you can pass NULL buffer to PyByteArray_FromStringAndSize, but it works
PyObject *PyBuffer_New(Py_ssize_t size){
	PyObject *bah = PyByteArray_FromStringAndSize(NULL, size);
	if (bah==NULL)
		return NULL;
	PyObject *ret = PyMemoryView_FromObject(bah);
	Py_DECREF(bah);	// Memory view keeps its own ref to base object
	return ret;
}
/* The function is not static and not hidden as we use ctypes to test it. */
PyObject *
typecast_BINARY_cast(const char *s, Py_ssize_t l, PyObject *curs)
{
    chunkObject *chunk = NULL;
    PyObject *res = NULL;
    char *buffer = NULL;
    Py_ssize_t len;

    if (s == NULL) { Py_RETURN_NONE; }

    if (s[0] == '\\' && s[1] == 'x') {
        /* This is a buffer escaped in hex format: libpq before 9.0 can't
         * parse it and we can't detect reliably the libpq version at runtime.
         * So the only robust option is to parse it ourselves - luckily it's
         * an easy format.
         */
        if (NULL == (buffer = psycopg_parse_hex(s, l, &len))) {
            goto exit;
        }
    }
    else {
        /* This is a buffer in the classic bytea format. So we can handle it
         * to the PQunescapeBytea to have it parsed, right? ...Wrong. We
         * could, but then we'd have to record whether buffer was allocated by
         * Python or by the libpq to dispose it properly. Furthermore the
         * PQunescapeBytea interface is not the most brilliant as it wants a
         * null-terminated string even if we have known its length thus
         * requiring a useless memcpy and strlen.
         * So we'll just have our better integrated parser, let's finish this
         * story.
         */
        if (NULL == (buffer = psycopg_parse_escape(s, l, &len))) {
            goto exit;
        }
    }

    chunk = (chunkObject *) PyObject_New(chunkObject, &chunkType);
    if (chunk == NULL) goto exit;

    /* **Transfer** ownership of buffer's memory to the chunkObject: */
    chunk->base = buffer;
    buffer = NULL;
    chunk->len = (Py_ssize_t)len;

#if PY_MAJOR_VERSION < 3
    if ((res = PyBuffer_FromObject((PyObject *)chunk, 0, chunk->len)) == NULL)
        goto exit;
#else
    if ((res = PyMemoryView_FromObject((PyObject*)chunk)) == NULL)
        goto exit;
#endif

exit:
    Py_XDECREF((PyObject *)chunk);
    PyMem_Free(buffer);

    return res;
}