Example #1
0
PyObject *engine_buffer_setup(Evas_PyObject *o, PyObject *kwargs)
{
    Evas_Engine_Info_Buffer *einfo;
    int buflen, w, h;
    PyObject *value, *buffer;

    BENCH_START
    evas_output_method_set(o->evas, evas_render_method_lookup("buffer"));
    BENCH_END

    einfo = (Evas_Engine_Info_Buffer *) evas_engine_info_get(o->evas);
    if (!einfo) {
        PyErr_Format(PyExc_SystemError, "Evas is not built with buffer engine support.");
        return NULL;
    }

    einfo->info.func.new_update_region = NULL;
    einfo->info.func.free_update_region = NULL;
    einfo->info.use_color_key = 0;
    einfo->info.alpha_threshold = 0;

    // Class wrapper ensures these kwargs exist.
    if (!PyArg_ParseTuple(PyDict_GetItemString(kwargs, "size"), "ii", &w, &h))
        return 0;

    einfo->info.depth_type = PyLong_AsLong(PyDict_GetItemString(kwargs, "depth"));
    einfo->info.dest_buffer_row_bytes = PyLong_AsLong(PyDict_GetItemString(kwargs, "stride"));
    einfo->info.dest_buffer = 0;
    value = PyDict_GetItemString(kwargs, "buffer");
    if (!value || value == Py_None) {
        buffer = PyBuffer_New(einfo->info.dest_buffer_row_bytes * h);
        if (PyObject_AsWriteBuffer(buffer, &einfo->info.dest_buffer, &buflen) == -1)
            return 0;
    } else {
        if (PyNumber_Check(value)) {
            einfo->info.dest_buffer = (void *) PyLong_AsLong(value);
            buffer = PyBuffer_FromReadWriteMemory(einfo->info.dest_buffer, 
                                                  einfo->info.dest_buffer_row_bytes * h);
        } else {
            if (PyObject_AsWriteBuffer(value, &einfo->info.dest_buffer, &buflen) == -1)
                return 0;
            if (buflen < einfo->info.dest_buffer_row_bytes * h) {
                PyErr_SetString(PyExc_AttributeError, "Buffer not big enough");
                return 0;
            }
            buffer = value;
            Py_INCREF(buffer);
        }
    }

    BENCH_START
    evas_engine_info_set(o->evas, (Evas_Engine_Info *) einfo);
    BENCH_END
    return buffer;
}
Example #2
0
Py::Object
Image::color_conv(const Py::Tuple& args) {
  _VERBOSE("Image::color_conv");

  args.verify_length(1);
  int format = Py::Int(args[0]);

  int row_len = colsOut * 4;
  PyObject* py_buffer = PyBuffer_New(row_len * rowsOut);
  if (py_buffer ==NULL)
    throw Py::MemoryError("Image::color_conv could not allocate memory");

  void* buf;
  Py_ssize_t buffer_len;
  int ret = PyObject_AsWriteBuffer(py_buffer, &buf, &buffer_len);
  if (ret !=0)
    throw Py::MemoryError("Image::color_conv could not allocate memory");

  agg::rendering_buffer rtmp;
  rtmp.attach(reinterpret_cast<unsigned char*>(buf), colsOut, rowsOut,
	      row_len);

  switch (format) {
  case 0:
    agg::color_conv(&rtmp, rbufOut, agg::color_conv_rgba32_to_bgra32());
    break;
  case 1:
    agg::color_conv(&rtmp, rbufOut, agg::color_conv_rgba32_to_argb32());
    break;
  default:
    throw Py::ValueError("Image::color_conv unknown format");
  }
  PyObject* o = Py_BuildValue("llN", rowsOut, colsOut, py_buffer);
  return Py::asObject(o);
}
static PyObject *DoPyRead_Buffer(nsIInputStream *pI, PyObject *obBuffer, PRUint32 n)
{
	PRUint32 nread;
	void *buf;
	Py_ssize_t buf_len;
	if (PyObject_AsWriteBuffer(obBuffer, &buf, &buf_len) != 0) {
		PyErr_Clear();
		PyErr_SetString(PyExc_TypeError, "The buffer object does not have a write buffer!");
		return NULL;
	}

	if ( (buf_len & 0xFFFFFFFF) != buf_len) {
		PyErr_Clear();
		PyErr_SetString(PyExc_RuntimeError, "Python Buffer length overflows 32-bit in PyObject_AsWriteBuffer");
		return NULL;
	}

	if (n==(PRUint32)-1) {
		n = buf_len;
	} else {
		if (n > buf_len) {
			NS_WARNING("Warning: PyIInputStream::read() was passed an integer size greater than the size of the passed buffer!  Buffer size used.\n");
			n = buf_len;
		}
	}
	nsresult r;
	Py_BEGIN_ALLOW_THREADS;
	r = pI->Read((char *)buf, n, &nread);
	Py_END_ALLOW_THREADS;
	if ( NS_FAILED(r) )
		return PyXPCOM_BuildPyException(r);
	return PyInt_FromLong(nread);
}
Example #4
0
/**
 * Return a pointer to the data of a writable buffer from obj. If only a
 * read-only buffer is available and force is True, a read-write buffer based on
 * the read-only buffer is obtained. Note that this may have some surprising
 * effects on buffers which expect the data from their read-only buffer not to
 * be modified.
 */
static PyObject*
memoryview_get_buffer(PyObject *self, PyObject *args){
    PyObject *obj = NULL;
    int force = 0;
    PyObject *ret = NULL;
    void * ptr = NULL;
    const void* roptr = NULL;
    Py_ssize_t buflen;
    Py_buffer buf;

    if (!PyArg_ParseTuple(args, "O|i", &obj, &force))
        return NULL;

    if (!get_buffer(obj, &buf, force)) { /* new buffer api */
        ret = PyLong_FromVoidPtr(buf.buf);
        free_buffer(&buf);
    } else { /* old buffer api */
        PyErr_Clear();
        if (-1 == PyObject_AsWriteBuffer(obj, &ptr, &buflen)) {
          if (!force)
            return NULL;
          PyErr_Clear();
          if(-1 == PyObject_AsReadBuffer(obj, &roptr, &buflen))
            return NULL;
          ptr = (void*) roptr;
        }
        ret = PyLong_FromVoidPtr(ptr);
    }
    return ret;
}
Example #5
0
BOOL PyWinObject_AsWriteBuffer(PyObject *ob, void **buf, DWORD *buf_len, BOOL bNoneOk)
{
	if (ob==Py_None){
		if (bNoneOk){
			*buf_len=0;
			*buf=NULL;
			return TRUE;
			}
		PyErr_SetString(PyExc_TypeError, "Buffer cannot be None");
		return FALSE;
		}
	Py_ssize_t py_len;
	if (PyObject_AsWriteBuffer(ob, buf, &py_len)==-1)
		return FALSE;

#ifdef _WIN64
	if (py_len>MAXDWORD){
		PyErr_Format(PyExc_ValueError,"Buffer length can be at most %d characters", MAXDWORD);
		return FALSE;
		}
#endif

	*buf_len=(DWORD)py_len;
	return TRUE;
}
Example #6
0
static PyObject *Wiimote_read(Wiimote *self, PyObject *args, PyObject *kwds)
{
	static char *kwlist[] = { "flags", "offset", "len", NULL };
	unsigned char flags;
	unsigned int offset;
	Py_ssize_t len;
	void *buf;
	PyObject *pyRetBuf;

	if (!self->wiimote) {
		SET_CLOSED_ERROR;
		return NULL;
	}

	if (!PyArg_ParseTupleAndKeywords(args, kwds, "BII:cwiid.Wiimote.read",
	                                 kwlist, &flags, &offset, &len)) {
		return NULL;
	}

	if (!(pyRetBuf = PyBuffer_New(len))) {
		return NULL;
	}
	if (PyObject_AsWriteBuffer(pyRetBuf, &buf, &len)) {
		Py_DECREF(pyRetBuf);
		return NULL;
	}
	if (cwiid_read(self->wiimote,flags,offset,len,buf)) {
		PyErr_SetString(PyExc_RuntimeError, "Error reading wiimote data");
		Py_DECREF(pyRetBuf);
		return NULL;
	}

	return pyRetBuf;
}
/*NUMPY_API
 * Get buffer chunk from object
 *
 * this function takes a Python object which exposes the (single-segment)
 * buffer interface and returns a pointer to the data segment
 *
 * You should increment the reference count by one of buf->base
 * if you will hang on to a reference
 *
 * You only get a borrowed reference to the object. Do not free the
 * memory...
 */
NPY_NO_EXPORT int
PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
{
    Py_ssize_t buflen;

    buf->ptr = NULL;
    buf->flags = BEHAVED;
    buf->base = NULL;
    if (obj == Py_None) {
        return PY_SUCCEED;
    }
    if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) {
        PyErr_Clear();
        buf->flags &= ~WRITEABLE;
        if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr),
                                  &buflen) < 0) {
            return PY_FAIL;
        }
    }
    buf->len = (intp) buflen;

    /* Point to the base of the buffer object if present */
    if (PyBuffer_Check(obj)) {
        buf->base = ((PyArray_Chunk *)obj)->base;
    }
    if (buf->base == NULL) {
        buf->base = obj;
    }
    return PY_SUCCEED;
}
Example #8
0
/*NUMPY_API
 * Get buffer chunk from object
 *
 * this function takes a Python object which exposes the (single-segment)
 * buffer interface and returns a pointer to the data segment
 *
 * You should increment the reference count by one of buf->base
 * if you will hang on to a reference
 *
 * You only get a borrowed reference to the object. Do not free the
 * memory...
 */
NPY_NO_EXPORT int
PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
{
#if defined(NPY_PY3K)
    Py_buffer view;
#else
    Py_ssize_t buflen;
#endif

    buf->ptr = NULL;
    buf->flags = NPY_ARRAY_BEHAVED;
    buf->base = NULL;
    if (obj == Py_None) {
        return NPY_SUCCEED;
    }

#if defined(NPY_PY3K)
    if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS|PyBUF_WRITABLE) != 0) {
        PyErr_Clear();
        buf->flags &= ~NPY_ARRAY_WRITEABLE;
        if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS) != 0) {
            return NPY_FAIL;
        }
    }

    buf->ptr = view.buf;
    buf->len = (npy_intp) view.len;

    /*
     * XXX: PyObject_AsWriteBuffer does also this, but it is unsafe, as there is
     * no strict guarantee that the buffer sticks around after being released.
     */
    PyBuffer_Release(&view);

    /* Point to the base of the buffer object if present */
    if (PyMemoryView_Check(obj)) {
        buf->base = PyMemoryView_GET_BASE(obj);
    }
#else
    if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) {
        PyErr_Clear();
        buf->flags &= ~NPY_ARRAY_WRITEABLE;
        if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr),
                                  &buflen) < 0) {
            return NPY_FAIL;
        }
    }
    buf->len = (npy_intp) buflen;

    /* Point to the base of the buffer object if present */
    if (PyBuffer_Check(obj)) {
        buf->base = ((PyArray_Chunk *)obj)->base;
    }
#endif
    if (buf->base == NULL) {
        buf->base = obj;
    }
    return NPY_SUCCEED;
}
Example #9
0
NPY_NO_EXPORT npy_bool
_IsWriteable(PyArrayObject *ap)
{
    PyObject *base=PyArray_BASE(ap);
#if defined(NPY_PY3K)
    Py_buffer view;
#else
    void *dummy;
    Py_ssize_t n;
#endif

    /* If we own our own data, then no-problem */
    if ((base == NULL) || (PyArray_FLAGS(ap) & NPY_ARRAY_OWNDATA)) {
        return NPY_TRUE;
    }
    /*
     * Get to the final base object
     * If it is a writeable array, then return TRUE
     * If we can find an array object
     * or a writeable buffer object as the final base object
     * or a string object (for pickling support memory savings).
     * - this last could be removed if a proper pickleable
     * buffer was added to Python.
     *
     * MW: I think it would better to disallow switching from READONLY
     *     to WRITEABLE like this...
     */

    while(PyArray_Check(base)) {
        if (PyArray_CHKFLAGS((PyArrayObject *)base, NPY_ARRAY_OWNDATA)) {
            return (npy_bool) (PyArray_ISWRITEABLE((PyArrayObject *)base));
        }
        base = PyArray_BASE((PyArrayObject *)base);
    }

    /*
     * here so pickle support works seamlessly
     * and unpickled array can be set and reset writeable
     * -- could be abused --
     */
    if (PyString_Check(base)) {
        return NPY_TRUE;
    }
#if defined(NPY_PY3K)
    if (PyObject_GetBuffer(base, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
        PyErr_Clear();
        return NPY_FALSE;
    }
    PyBuffer_Release(&view);
#else
    if (PyObject_AsWriteBuffer(base, &dummy, &n) < 0) {
        PyErr_Clear();
        return NPY_FALSE;
    }
#endif
    return NPY_TRUE;
}
static PyObject *
image_surface_create_for_data (PyTypeObject *type, PyObject *args)
{
    cairo_surface_t *surface;
    cairo_format_t format;
    unsigned char *buffer;
    int width, height, stride = -1, res;
    Py_ssize_t buffer_len;
    PyObject *obj;

    if (!PyArg_ParseTuple(args, "Oiii|i:Surface.create_for_data",
			  &obj, &format, &width, &height, &stride))
	return NULL;

    res = PyObject_AsWriteBuffer (obj, (void **)&buffer, &buffer_len);
    if (res == -1)
	return NULL;

    if (width <= 0) {
	PyErr_SetString(PyExc_ValueError, "width must be positive");
	return NULL;
    }
    if (height <= 0) {
	PyErr_SetString(PyExc_ValueError, "height must be positive");
	return NULL;
    }
    /* if stride is missing, calculate it from width */
    if (stride < 0) {
	switch (format) {
	case CAIRO_FORMAT_ARGB32:
	case CAIRO_FORMAT_RGB24:
	    stride = width * 4;
	    break;
	case CAIRO_FORMAT_RGB16_565:
	    stride = width * 2;
	    break;
	case CAIRO_FORMAT_A8:
	    stride = width;
	    break;
	case CAIRO_FORMAT_A1: /* should be stride = (width + 31) / 32 * 4 ? */
	    stride = (width + 1) / 8;
	    break;
	default:
	    PyErr_SetString(CairoError, "Unknown format");
	    return NULL;
	}
    }
    if (height * stride > buffer_len) {
	PyErr_SetString(PyExc_TypeError, "buffer is not long enough");
	return NULL;
    }
    surface = cairo_image_surface_create_for_data (buffer, format, width,
						   height, stride);
    return PycairoSurface_FromSurface(surface, obj);
}
Example #11
0
int object_as_write_buffer(PyObject *obj, void ** buffer, Py_ssize_t * buffer_len) {
    Py_buffer *wpybuf;
    if (PyMemoryView_Check(obj)) {
        wpybuf = PyMemoryView_GET_BUFFER(obj);
		if (wpybuf->buf==NULL)
			return 1;
        buffer[0] = wpybuf->buf;
        return 0;
    }
    return PyObject_AsWriteBuffer(obj, buffer, buffer_len);
}
Example #12
0
static PyObject*
multiprocessing_address_of_buffer(PyObject *self, PyObject *obj)
{
    void *buffer;
    Py_ssize_t buffer_len;

    if (PyObject_AsWriteBuffer(obj, &buffer, &buffer_len) < 0)
        return NULL;

    return Py_BuildValue("N" F_PY_SSIZE_T,
                         PyLong_FromVoidPtr(buffer), buffer_len);
}
static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n)
{
	if (n==(PRUint32)-1) {
		nsresult r;
		Py_BEGIN_ALLOW_THREADS;
		r = pI->Available(&n);
		Py_END_ALLOW_THREADS;
		if (NS_FAILED(r))
			return PyXPCOM_BuildPyException(r);
	}
	if (n==0) { // mozilla will assert if we alloc zero bytes.
		return PyBuffer_New(0);
	}
	char *buf = (char *)nsMemory::Alloc(n);
	if (buf==NULL) {
		PyErr_NoMemory();
		return NULL;
	}
	nsresult r;
	PRUint32 nread;
	Py_BEGIN_ALLOW_THREADS;
	r = pI->Read(buf, n, &nread);
	Py_END_ALLOW_THREADS;
	PyObject *rc = NULL;
	if ( NS_SUCCEEDED(r) ) {
		rc = PyBuffer_New(nread);
		if (rc != NULL) {
			void *ob_buf;
			Py_ssize_t buf_len;
			if (PyObject_AsWriteBuffer(rc, &ob_buf, &buf_len) != 0) {
				// should never fail - we just created it!
				return NULL;
			}

			if ( (buf_len & 0xFFFFFFFF) != buf_len) {
				PyErr_SetString(PyExc_RuntimeError, "Python Buffer length overflows 32-bit in PyObject_AsWriteBuffer");
				return NULL;
			}

			if (buf_len != nread) {
				PyErr_SetString(PyExc_RuntimeError, "New buffer isn't the size we created it!");
				return NULL;
			}
			memcpy(ob_buf, buf, nread);
		}
	} else
		PyXPCOM_BuildPyException(r);
	nsMemory::Free(buf);
	return rc;
}
Example #14
0
static PyObject *
xpybCookie_reply(xpybCookie *self, PyObject *args)
{
    xcb_generic_error_t *error;
    xcb_generic_reply_t *data;
    PyObject *shim, *reply;
    int is_void;
    void *buf;
    Py_ssize_t len;

    xpybRequest_get_attributes(self->request, &is_void, NULL, NULL);

    /* Check arguments and connection. */
    if (is_void) {
        PyErr_SetString(xpybExcept_base, "Request has no reply.");
        return NULL;
    }
    if (xpybConn_invalid(self->conn))
        return NULL;

    /* Make XCB call */
    data = xcb_wait_for_reply(self->conn->conn, self->cookie.sequence, &error);
    if (xpybError_set(self->conn, error))
        return NULL;
    if (data == NULL) {
        PyErr_SetString(PyExc_IOError, "I/O error on X server connection.");
        return NULL;
    }

    /* Create a shim protocol object */
    shim = PyBuffer_New(32 + data->length * 4);
    if (shim == NULL)
        goto err1;
    if (PyObject_AsWriteBuffer(shim, &buf, &len) < 0)
        goto err2;
    memcpy(buf, data, len);
    free(data);

    /* Call the reply type object to get a new xcb.Reply instance */
    reply = PyObject_CallFunctionObjArgs((PyObject *)self->reply_type, shim, NULL);
    Py_DECREF(shim);
    return reply;

err2:
    Py_DECREF(shim);
err1:
    free(data);
    return NULL;
}
Example #15
0
File: svg.c Project: clones/kaa
PyObject *
render_svg_to_buffer(PyObject *module, PyObject *args, PyObject *kwargs)
{
    int len, w, h, i;
    guchar *svgdata;

    GError *error;
    RsvgHandle *svg;
    GdkPixbuf *pixbuf;
    gboolean res;
    size_cb_data cbdata;

    PyObject *buffer;
    guchar *buffer_ptr;
    
    if (!PyArg_ParseTuple(args, "iis#", &w, &h, &svgdata, &len))
        return NULL;

    cbdata.w = w;
    cbdata.h = h;

    svg = rsvg_handle_new();
    rsvg_handle_set_size_callback(svg, size_cb, &cbdata, NULL);
    res = rsvg_handle_write(svg, svgdata, len, &error);
    res = rsvg_handle_close(svg, &error);
    pixbuf = rsvg_handle_get_pixbuf(svg);
    rsvg_handle_free(svg);

    w = gdk_pixbuf_get_width(pixbuf);
    h = gdk_pixbuf_get_height(pixbuf);

    buffer = PyBuffer_New(w*h*4);
    PyObject_AsWriteBuffer(buffer, (void **)&buffer_ptr, &len);
    memcpy(buffer_ptr, gdk_pixbuf_get_pixels(pixbuf), w*h*4);
    g_object_unref(pixbuf);

    // RGBA to BGRA conversion.
    // FIXME: MMXify.
    for (i = 0; i < w*h*4; i+=4) {
        guchar save = buffer_ptr[i+2];
        buffer_ptr[i+2] = buffer_ptr[i];
        buffer_ptr[i] = save;
    }
    return Py_BuildValue("(iiO)", w, h, buffer);
}
Example #16
0
  void py_curand_get_scramble_constants32(py::object dst, int count)
  {
    void *buf;
    PYCUDA_BUFFER_SIZE_T len;
    int n = 0;

    if (PyObject_AsWriteBuffer(dst.ptr(), &buf, &len))
      throw py::error_already_set();
    unsigned int *vectors;
    CURAND_CALL_GUARDED(curandGetScrambleConstants32, (&vectors));
// Documentation does not mention number of dimensions
// Assuming the same as in getDirectionVectors*
    while (count > 0) {
      int size = ((count > 20000) ? 20000 : count)*sizeof(unsigned int);
      memcpy((unsigned int *)buf+n*20000, vectors, size);
      count -= size/sizeof(unsigned int);
      n++;
    }
  }
Example #17
0
    void copy_tile_data_to_py_array(const Tile& tile, bpy::object& buffer)
    {
        void* array = 0;
        Py_ssize_t len;

        const int success = PyObject_AsWriteBuffer(buffer.ptr(), &array, &len);

        if (success != 0)
            bpy::throw_error_already_set();

        if (static_cast<size_t>(len) < tile.get_size())
        {
            PyErr_SetString(PyExc_IndexError, "Buffer size is smaller than data size");
            bpy::throw_error_already_set();
        }

        std::copy(
            tile.get_storage(),
            tile.get_storage() + tile.get_size(),
            reinterpret_cast<uint8*>(array));
    }
/* Note: this has been copied verbatim from <opencv_root>/interfaces/python/cv.cpp */
static int convert_to_IplImage(PyObject *o, IplImage **dst)
{
    iplimage_t *ipl = (iplimage_t*)o;
    void *buffer;
    Py_ssize_t buffer_len;

    if (!is_iplimage(o)) {
	return -1; //failmsg("Argument must be IplImage");
    } else if (PyString_Check(ipl->data)) {
	cvSetData(ipl->a, PyString_AsString(ipl->data) + ipl->offset, ipl->a->widthStep);
	assert(cvGetErrStatus() == 0);
	*dst = ipl->a;
	return 1;
    } else if (ipl->data && PyObject_AsWriteBuffer(ipl->data, &buffer, &buffer_len) == 0) {
	cvSetData(ipl->a, (void*)((char*)buffer + ipl->offset), ipl->a->widthStep);
	assert(cvGetErrStatus() == 0);
	*dst = ipl->a;
	return 1; 
    } else {
	return -1;// failmsg("IplImage argument has no data");
    }
}
Example #19
0
  void py_curand_get_direction_vectors(
      curandDirectionVectorSet_t set, py::object dst, int count)
  {
    void *buf;
    PYCUDA_BUFFER_SIZE_T len;
    int n = 0;

    if (PyObject_AsWriteBuffer(dst.ptr(), &buf, &len))
      throw py::error_already_set();
    if (CURAND_DIRECTION_VECTORS_32_JOEKUO6 == set
#if CUDAPP_CUDA_VERSION >= 4000
      || CURAND_SCRAMBLED_DIRECTION_VECTORS_32_JOEKUO6 == set
#endif
    ) {
      curandDirectionVectors32_t *vectors;
      CURAND_CALL_GUARDED(curandGetDirectionVectors32, (&vectors, set));
      while (count > 0) {
        int size = ((count > 20000) ? 20000 : count)*sizeof(curandDirectionVectors32_t);
        memcpy((unsigned int *)buf+n*20000*sizeof(curandDirectionVectors32_t)/sizeof(unsigned int), vectors, size);
	count -= size/sizeof(curandDirectionVectors32_t);
        n++;
      }
    }
#if CUDAPP_CUDA_VERSION >= 4000
    if (CURAND_DIRECTION_VECTORS_64_JOEKUO6 == set
      || CURAND_SCRAMBLED_DIRECTION_VECTORS_64_JOEKUO6 == set) {
      curandDirectionVectors64_t *vectors;
      CURAND_CALL_GUARDED(curandGetDirectionVectors64, (&vectors, set));
      while (count > 0) {
        int size = ((count > 20000) ? 20000 : count)*sizeof(curandDirectionVectors64_t);
        memcpy((unsigned long long *)buf+n*20000*sizeof(curandDirectionVectors64_t)/sizeof(unsigned long long), vectors, size);
	count -= size/sizeof(curandDirectionVectors64_t);
        n++;
      }
    }
#endif
  }
Example #20
0
/*NUMPY_API
 * Get buffer chunk from object
 *
 * this function takes a Python object which exposes the (single-segment)
 * buffer interface and returns a pointer to the data segment
 *
 * You should increment the reference count by one of buf->base
 * if you will hang on to a reference
 *
 * You only get a borrowed reference to the object. Do not free the
 * memory...
 */
NPY_NO_EXPORT int
PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
{
    Py_ssize_t buflen;

    buf->ptr = NULL;
    buf->flags = NPY_ARRAY_BEHAVED;
    buf->base = NULL;
    if (obj == Py_None) {
        return NPY_SUCCEED;
    }
    if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) {
        PyErr_Clear();
        buf->flags &= ~NPY_ARRAY_WRITEABLE;
        if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr),
                                  &buflen) < 0) {
            return NPY_FAIL;
        }
    }
    buf->len = (npy_intp) buflen;

    /* Point to the base of the buffer object if present */
#if defined(NPY_PY3K)
    if (PyMemoryView_Check(obj)) {
        buf->base = PyMemoryView_GET_BASE(obj);
    }
#else
    if (PyBuffer_Check(obj)) {
        buf->base = ((PyArray_Chunk *)obj)->base;
    }
#endif
    if (buf->base == NULL) {
        buf->base = obj;
    }
    return NPY_SUCCEED;
}
Example #21
0
PyObject *TileEngine::getTileData(
    PyObject *tileFunction,
    PyObject *tileMap,
    int col,
    int row,
    int cols,
    int rows,
    int code,
    PyObject *tileViewCache)
{
    if ((tileFunction != Py_None) &&
	!PyCallable_Check(tileFunction)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileFunction to be a callable function or None");
	Py_INCREF(Py_None);
	return Py_None;
    }

    const int *tileMapData = NULL;
    unsigned int tileMapCount = 0;

    if (tileMap != Py_None) {

        if (!PySequence_Check(tileMap)) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap to be an array "
		"of 4 byte integers or None");
	    Py_INCREF(Py_None);
	    return Py_None;
	}

	tileMapCount = (unsigned int)PySequence_Size(tileMap);
	Py_ssize_t tileMapLength = 0;
	if (PyObject_AsReadBuffer(
	    tileMap,
	    (const void **)&tileMapData,
	    &tileMapLength) != 0) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap with read buffer");
	    Py_INCREF(Py_None);
	    return Py_None;
	}

	int tileMapDataCount = 
	    (int)tileMapLength / sizeof(unsigned int);

	if (tileMapDataCount != (int)tileMapCount) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap read buffer of 4 byte integers");
	    Py_INCREF(Py_None);
	    return Py_None;
	}
    }

    int *tileViewCacheData = NULL;
    int tileViewCacheCount = 0;

    if (tileViewCache != Py_None) {
	tileViewCacheCount =
	    (unsigned int)PySequence_Size(tileViewCache);
	Py_ssize_t tileViewCacheLength = 0;
	if ((tileViewCacheCount != (width * height)) ||
	    (PyObject_AsWriteBuffer(
	       tileViewCache,
	       (void **)&tileViewCacheData,
	       &tileViewCacheLength) != 0)) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileViewCache with write buffer");
	    Py_INCREF(Py_None);
	    return Py_None;
	}
    }

    const char *textCodeString =
	"0123456789"
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ+-";
    int tileSize = sizeof(unsigned short);
    int r, c;
    int bufSize = 0;
    char *buf = NULL;
    bool returnBuffer = false;

    switch (code) {

	case TILE_CODE_RAW_BINARY_16: {
	    bufSize = tileSize * rows * cols;
	    buf = (char *)malloc(bufSize);
	    unsigned char *dst = (unsigned char *)buf;

	    for (r = 0; r < rows; r++) {
		for (c = 0; c < cols; c++) {
		    int tile = 
			getValue(
			    col + c, 
			    row + r, 
			    tileFunction, 
			    tileMapData, 
			    tileMapCount);
		    *dst++ = (tile >> 8) & 0xff; // High byte.
		    *dst++ = tile & 0xff; // Low byte.
		}
	    }
	    break;
	}

	case TILE_CODE_COMPRESSED_TEXT: {
	    bufSize = tileSize * rows * cols * 3; // to be safe
	    buf = (char *)malloc(bufSize);
	    unsigned char *dst = (unsigned char *)buf;
	    int tileIndex = 0;
	    int tileIndexMax = rows * cols;
	    int offset = 0;
	    int skip = 0;

	    while ((tileIndex < tileIndexMax) &&
		   (offset < bufSize)) {
		int c = tileIndex % cols;
		int r = tileIndex / cols;
		int tileCacheOffset = 
		    (col + c) + ((row + r) * width);
//		printf("tileIndex %d tileCacheOffset %d tileViewCacheCount %d c %d r %d cols %d rows %d ",
//		    tileIndex,
//		    tileCacheOffset,
//		    tileViewCacheCount,
//		    c, r, cols, rows);
		int tile = 
		    getValue(
			col + c, 
			row + r, 
			tileFunction,
			tileMapData, 
			tileMapCount);
//		printf("tile %d\n", tile);
		int curTile =
		    (tileViewCacheData == NULL)
			? -1
			: tileViewCacheData[tileCacheOffset];

		if (tile == curTile) {
		    skip++;
		} else {
//		    printf("tile %d skip %d offset %d r %d c %d index %d\n", tile, skip, offset, r, c, c + (r * width));
		    if (skip) {
			if (skip == 1) {
//			    printf("skip 1\n");
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_0;
			    offset++;
			} else if (skip == 2) {
//			    printf("skip 2/1\n");
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_0;
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_0;
			    offset += 2;
			} else if (skip < 64) {
//			    printf("skip %d/64\n", skip);
			    int val = skip;
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_1;
			    *dst++ = textCodeString[val];
			    offset += 2;
			} else if (skip < 4096) {
//			    printf("skip %d/4096\n", skip);
			    int val = skip;
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_2;
			    *dst++ = textCodeString[(val >> 6) & 63]; // High.
			    *dst++ = textCodeString[val & 63]; // Low.
			    offset += 3;
			} else {
//			    printf("skip %d/999999\n", skip);
			    int val = skip;
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_3;
			    *dst++ = textCodeString[(val >> 12) & 63]; // Highest.
			    *dst++ = textCodeString[(val >> 6) & 63]; // High.
			    *dst++ = textCodeString[val & 63]; // Low.
			    offset += 4;
			}

			skip = 0;

		    }

		    if (tileViewCacheData != NULL) {
			tileViewCacheData[tileCacheOffset] = tile;
		    }

		    int low = tile & 63;
		    int high = (tile >> 6) & 63;
		    *dst++ = textCodeString[low];
		    *dst++ = textCodeString[high];

		    offset += 2;
		}

		tileIndex++;
	    }

	    bufSize = offset;

	    break;
	}
Example #22
0
void TileEngine::renderTilesLazy(
    cairo_t *ctx,
    PyObject *tileFunction,
    PyObject *tileMap,
    int tileSize,
    int renderCol,
    int renderRow,
    int renderCols,
    int renderRows,
    double alpha,
    PyObject *tileGenerator,
    PyObject *tileCache,
    PyObject *tileCacheSurfaces,
    PyObject *tileState)
{
    if ((tileFunction != Py_None) &&
	!PyCallable_Check(tileFunction)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileFunction to be a callable function or None");
	return;
    }

    // The tileMap should be None, or an array of 4 byte integers,
    // mapping virtual tiles indices to absolute tile numbers.

    const int *tileMapData = NULL;
    unsigned int tileMapCount = 0;

    if (tileMap != Py_None) {

      if (!PySequence_Check(tileMap)) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap to be an array "
		"of 4 byte integers or None");
	    return;
	}

	tileMapCount = (unsigned int)PySequence_Size(tileMap);
	Py_ssize_t tileMapLength = 0;
	if (PyObject_AsReadBuffer(
	    tileMap,
	    (const void **)&tileMapData,
	    &tileMapLength) != 0) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap with read buffer");
	    return;
	}

	int tileMapDataCount = 
	    (int)tileMapLength / sizeof(unsigned int);

	if (tileMapDataCount != (int)tileMapCount) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap read buffer of 4 byte integers");
	    return;
	}
    }

    // The tileGenerator should be a function that takes one integer
    // tile parameter, and returns a tuple of three integers: a
    // surface index, a tileX and a tileY position.
    if (!PyCallable_Check(tileGenerator)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileGenerator callable object");
	return;
    }

    // The tileCache should be an array of integers, 4 integers per
    // tile.  The first is a "cached" flag, the second is a surface
    // index, the 3rd and 4th are a tileX and tileY position.

    int *tileCacheData = NULL;
    Py_ssize_t tileCacheLength = 0;

    if (PyObject_AsWriteBuffer(
	tileCache,
	(void **)&tileCacheData,
	&tileCacheLength) != 0) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileCache array");
	return;
    }

    // The tileCacheSurfaces parameters should be a list of Cairo
    // surfaces.
    if (!PySequence_Check(tileCacheSurfaces)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileCacheSurfaces sequence");
	return;
    }

    // The tileState parameters should be None or a list of tile state
    // parameters.
    if ((tileState != Py_None) &&
	!PySequence_Check(tileState)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileState sequence or None");
	return;
    }

    int renderX = renderCol * tileSize;
    int renderY = renderRow * tileSize;

    int r;
    for (r = 0; r < renderRows; r++) {
	int c;
	for (c = 0; c  < renderCols; c++) {
	    int col = (renderCol + c) % width;
	    int row = (renderRow + r) % height;

	    unsigned long tile = 
		getValue(
		    col,
		    row,
		    tileFunction,
		    tileMapData,
		    tileMapCount);

	    double x = col * tileSize;
	    double y = row * tileSize;

	    // Get the tile surface index, tileX and tileY from the
	    // cache, or call the tileGenerator function to produce
	    // them, if they are not already cached.

	    int cacheOffset = tile * 4;
	    int tileSurfaceIndex = 0;
	    int tileX = 0;
	    int tileY = 0;

	    if (tileCacheData[cacheOffset + 0]) {

		// The tile is already cached. 
		// Get the values from the tileCache. 

		tileSurfaceIndex = tileCacheData[cacheOffset + 1];
		tileX = tileCacheData[cacheOffset + 2];
		tileY = tileCacheData[cacheOffset + 3];

	    } else {

		// The tile has not already been cached.  Call the
		// tileGenerator function to produce the tile, passing
		// it the absolute tile number as a parameter.

		// Mark the tile as cached, so we don't do this again. 
		tileCacheData[cacheOffset + 0] = 1;

		PyObject *result =
		    PyObject_CallFunction(
			tileGenerator,
			"i",
			tile);

		// The tile function returns a tuple of three numbers:
		// the surface index (into the tileCacheSurfaces array
		// of Cairo surfaces), the tileX and tileY position in
		// the surface.

		if (result == NULL) {
		    PyErr_SetString(
			PyExc_TypeError,
			"tile generator did not return a result");
		    return;
		}

		int success =
		    PyArg_ParseTuple(
			result,
			"iii",
			&tileSurfaceIndex,
			&tileX,
			&tileY);
		Py_DECREF(result);
		if (!success) {
		    PyErr_SetString(
			PyExc_TypeError,
			"tile generator return wrong number of "
		        "results in tuple");
		    return;
		}

		// Cache the returned values. 
		tileCacheData[cacheOffset + 1] = tileSurfaceIndex;
		tileCacheData[cacheOffset + 2] = tileX;
		tileCacheData[cacheOffset + 3] = tileY;
	    }

	    // Get the Python object wrapping the Cairo surface for
	    // the tile.
	    PyObject *tiles =
		PySequence_GetItem(
		    tileCacheSurfaces,
		    tileSurfaceIndex);

	    if (tiles == NULL) {
		PyErr_SetString(
		    PyExc_TypeError,
		    "tile generator returned invalid tile "
		    "surface index");
		return;
	    }

	    if (!PyObject_TypeCheck(
		  tiles,
		  &PycairoSurface_Type)) {
		PyErr_SetString(
		    PyExc_TypeError,
		    "expected cairo_surface_t objects "
		    "in tileCacheSurfaces");
		return;
	    }

	    // Get the cairo_surface_t from the Python object.
	    cairo_surface_t *tilesSurf = PycairoSurface_GET(tiles);
	    Py_DECREF(tiles);

	    // Draw a tile.

	    cairo_save(ctx);

	    cairo_translate(
		ctx,
		x - renderX,
		y - renderY);

	    cairo_rectangle(
		ctx,
		0,
		0,
		tileSize,
		tileSize);

	    cairo_clip(ctx);

	    cairo_set_source_surface(
		ctx,
		tilesSurf,
		-tileX,
		-tileY);

	    if (alpha >= 1.0) {
		cairo_paint(ctx);
	    } else {
		cairo_paint_with_alpha(ctx, alpha);
	    }

	    cairo_restore(ctx);
	}
    }
}
Example #23
0
PyObject *lightblueobex_readheaders(obex_t *obex, obex_object_t *obj)
{
    PyObject *headers;
    uint8_t hi;
    obex_headerdata_t hv;
    uint32_t hv_size;
    int r;
    PyObject *value = NULL;

    DEBUG("%s()\n", __func__);

    headers = PyDict_New();
    if (headers == NULL)
        return NULL;

    if (obex == NULL || obj == NULL || headers == NULL) {
        DEBUG("\treadheaders() got null argument\n");
        return NULL;
    }

    if (!PyDict_Check(headers)) {
        DEBUG("\treadheaders() arg must be dict\n");
        return NULL;
    }

    while (OBEX_ObjectGetNextHeader(obex, obj, &hi, &hv, &hv_size)) {
        DEBUG("\tread header: 0x%02x\n", hi);
        switch (hi & OBEX_HI_MASK) {
        case OBEX_UNICODE:
        {
            if (hv_size < 2) {
                value = PyUnicode_FromUnicode(NULL, 0);
            } else {
                /* hv_size-2 for 2-byte null terminator */
                int byteorder = OBEX_BIG_ENDIAN;
                value = PyUnicode_DecodeUTF16((const char*)hv.bs, hv_size-2,
                        NULL, &byteorder);
                if (value == NULL) {
                    DEBUG("\terror reading unicode header 0x%02x\n", hi);
                    if (PyErr_Occurred()) {
                        PyErr_Print();
                        PyErr_Clear();  /* let caller set exception */
                    }
                    return NULL;
                }
            }
            break;
        }
        case OBEX_BYTE_STREAM:
        {
            value = PyBuffer_New(hv_size);
            if (value != NULL) {
                void *buf;
                Py_ssize_t buflen;
                if (PyObject_AsWriteBuffer(value, &buf, &buflen) < 0) {
                    Py_DECREF(value);
                    DEBUG("\terror writing to buffer for header 0x%02x\n", hi);
                    return NULL;
                }
                memcpy(buf, hv.bs, buflen);
            }
            break;
        }
        case OBEX_BYTE:
        {
            value = PyInt_FromLong(hv.bq1);
            break;
        }
        case OBEX_INT:
        {
            value = PyLong_FromUnsignedLong(hv.bq4);
            break;
        }
        default:
            DEBUG("\tunknown header id encoding %d\n", (hi & OBEX_HI_MASK));
            return NULL;
        }

        if (value == NULL) {
            if (PyErr_Occurred() == NULL)
                DEBUG("\terror reading headers\n");
            return NULL;
        }
        r = PyDict_SetItem(headers, PyInt_FromLong((long)hi), value);
        Py_DECREF(value);
        if (r < 0) {
            DEBUG("\tPyDict_SetItem() error\n");
            if (PyErr_Occurred()) {
                PyErr_Print();
                PyErr_Clear();  /* let caller set exception */
            }
            return NULL;
        }
    }
    return headers;
}
Example #24
0
/*NUMPY_API
 * Get buffer chunk from object
 *
 * this function takes a Python object which exposes the (single-segment)
 * buffer interface and returns a pointer to the data segment
 *
 * You should increment the reference count by one of buf->base
 * if you will hang on to a reference
 *
 * You only get a borrowed reference to the object. Do not free the
 * memory...
 */
NPY_NO_EXPORT int
PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
{
#if defined(NPY_PY3K)
    Py_buffer view;
#else
    Py_ssize_t buflen;
#endif

    buf->ptr = NULL;
    buf->flags = NPY_ARRAY_BEHAVED;
    buf->base = NULL;
    if (obj == Py_None) {
        return NPY_SUCCEED;
    }

#if defined(NPY_PY3K)
    if (PyObject_GetBuffer(obj, &view,
                PyBUF_ANY_CONTIGUOUS|PyBUF_WRITABLE|PyBUF_SIMPLE) != 0) {
        PyErr_Clear();
        buf->flags &= ~NPY_ARRAY_WRITEABLE;
        if (PyObject_GetBuffer(obj, &view,
                PyBUF_ANY_CONTIGUOUS|PyBUF_SIMPLE) != 0) {
            return NPY_FAIL;
        }
    }

    buf->ptr = view.buf;
    buf->len = (npy_intp) view.len;

    /*
     * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
     * PyObject_AsReadBuffer that this code replaces release the buffer. It is
     * up to the object that supplies the buffer to guarantee that the buffer
     * sticks around after the release.
     */
    PyBuffer_Release(&view);
    _dealloc_cached_buffer_info(obj);

    /* Point to the base of the buffer object if present */
    if (PyMemoryView_Check(obj)) {
        buf->base = PyMemoryView_GET_BASE(obj);
    }
#else
    if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) {
        PyErr_Clear();
        buf->flags &= ~NPY_ARRAY_WRITEABLE;
        if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr),
                                  &buflen) < 0) {
            return NPY_FAIL;
        }
    }
    buf->len = (npy_intp) buflen;

    /* Point to the base of the buffer object if present */
    if (PyBuffer_Check(obj)) {
        buf->base = ((PyArray_Chunk *)obj)->base;
    }
#endif
    if (buf->base == NULL) {
        buf->base = obj;
    }
    return NPY_SUCCEED;
}
static PyObject *DoPyRead_Buffer(nsIInputStream *pI, PyObject *obBuffer, PRUint32 n)
{
	PRUint32 nread;
	void *buf;
#ifndef VBOX /* unsafe cast on 64-bit hosts. */
	PRUint32 buf_len;
	if (PyObject_AsWriteBuffer(obBuffer, &buf, (Py_ssize_t *)&buf_len) != 0) {
#else   /* VBOX */
# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
        Py_ssize_t buf_len;
# else
        int buf_len;
# endif /* VBOX */
	if (PyObject_AsWriteBuffer(obBuffer, &buf, &buf_len) != 0) {
#endif
		PyErr_Clear();
		PyErr_SetString(PyExc_TypeError, "The buffer object does not have a write buffer!");
		return NULL;
	}
	if (n==(PRUint32)-1) {
		n = buf_len;
	} else {
		if (n > buf_len) {
			NS_WARNING("Warning: PyIInputStream::read() was passed an integer size greater than the size of the passed buffer!  Buffer size used.\n");
			n = buf_len;
		}
	}
	nsresult r;
	Py_BEGIN_ALLOW_THREADS;
	r = pI->Read((char *)buf, n, &nread);
	Py_END_ALLOW_THREADS;
	if ( NS_FAILED(r) )
		return PyXPCOM_BuildPyException(r);
	return PyInt_FromLong(nread);
}

static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n)
{
	if (n==(PRUint32)-1) {
		nsresult r;
		Py_BEGIN_ALLOW_THREADS;
		r = pI->Available(&n);
		Py_END_ALLOW_THREADS;
		if (NS_FAILED(r))
			return PyXPCOM_BuildPyException(r);
	}
	if (n==0) { // mozilla will assert if we alloc zero bytes.
#if PY_MAJOR_VERSION <= 2
		return PyBuffer_New(0);
#else
		return PyBytes_FromString("");
#endif
	}
	char *buf = (char *)nsMemory::Alloc(n);
	if (buf==NULL) {
		PyErr_NoMemory();
		return NULL;
	}
	nsresult r;
	PRUint32 nread;
	Py_BEGIN_ALLOW_THREADS;
	r = pI->Read(buf, n, &nread);
	Py_END_ALLOW_THREADS;
	PyObject *rc = NULL;
	if ( NS_SUCCEEDED(r) ) {
#if PY_MAJOR_VERSION <= 2
		rc = PyBuffer_New(nread);
		if (rc != NULL) {
			void *ob_buf;
#ifndef VBOX /* unsafe cast on 64-bit hosts. */
			PRUint32 buf_len;
			if (PyObject_AsWriteBuffer(rc, &ob_buf, (Py_ssize_t *)&buf_len) != 0) {
#else   /* VBOX */
# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
                        Py_ssize_t buf_len;
# else
                        int buf_len;
# endif /* VBOX */
			if (PyObject_AsWriteBuffer(rc, &ob_buf, &buf_len) != 0) {
#endif
				// should never fail - we just created it!
				return NULL;
			}
			if (buf_len != nread) {
				PyErr_SetString(PyExc_RuntimeError, "New buffer isnt the size we create it!");
				return NULL;
			}
			memcpy(ob_buf, buf, nread);
		}
#else
        rc = PyBytes_FromStringAndSize(buf, nread);
#endif
	} else
		PyXPCOM_BuildPyException(r);
	nsMemory::Free(buf);
	return rc;
}

static PyObject *PyRead(PyObject *self, PyObject *args)
{
	PyObject *obBuffer = NULL;
	PRUint32 n = (PRUint32)-1;

	nsIInputStream *pI = GetI(self);
	if (pI==NULL)
		return NULL;
	if (PyArg_ParseTuple(args, "|i", (int *)&n))
		// This worked - no args, or just an int.
		return DoPyRead_Size(pI, n);
	// try our other supported arg format.
	PyErr_Clear();
	if (!PyArg_ParseTuple(args, "O|i", &obBuffer, (int *)&n)) {
		PyErr_Clear();
		PyErr_SetString(PyExc_TypeError, "'read()' must be called as (buffer_ob, int_size=-1) or (int_size=-1)");
		return NULL;
	}
	return DoPyRead_Buffer(pI, obBuffer, n);
}


struct PyMethodDef
PyMethods_IInputStream[] =
{
	{ "read", PyRead, 1},
	// The rest are handled as normal
	{NULL}
};