c version of _element_to_bson for unicode. use the c version whenever it supports an element type

This commit is contained in:
Mike Dirolf 2009-02-03 15:53:48 -05:00
parent f716ea6f38
commit fa1eb0da08
2 changed files with 53 additions and 6 deletions

View File

@ -23,6 +23,8 @@
#include <Python.h>
#include <string.h>
static PyObject* CBSONError;
static char* shuffle_oid(char* oid) {
char* shuffled = (char*) malloc(12);
int i;
@ -66,8 +68,10 @@ static PyObject* _cbson_shuffle_oid(PyObject* self, PyObject* args) {
return result;
}
/* TODO our platform better be little-endian w/ 4-byte ints! */
static PyObject* _cbson_element_to_bson(PyObject* self, PyObject* args) {
const char* name;
const char* type;
int name_length;
PyObject* value;
@ -75,9 +79,38 @@ static PyObject* _cbson_element_to_bson(PyObject* self, PyObject* args) {
return NULL;
}
printf(value->ob_type->tp_name);
printf("\n");
return Py_BuildValue("s#", name, name_length);
/* TODO this isn't quite the same as the Python version:
* here we check for type equivalence, not isinstance. */
type = value->ob_type->tp_name;
if (PyUnicode_Check(value)) {
PyObject* encoded = PyUnicode_AsUTF8String(value);
if (!encoded) {
return NULL;
}
const char* encoded_bytes = PyString_AsString(encoded);
if (!encoded_bytes) {
return NULL;
}
int bytes_length = strlen(encoded_bytes) + 1;
int return_value_length = 5 + name_length + bytes_length;
char* to_return = (char*)malloc(return_value_length);
if (!to_return) {
PyErr_NoMemory();
return NULL;
}
to_return[0] = 0x02;
memcpy(to_return + 1, name, name_length);
memcpy(to_return + 1 + name_length, &bytes_length, 4);
memcpy(to_return + 5 + name_length, encoded_bytes, bytes_length);
PyObject* result = Py_BuildValue("s#", to_return, return_value_length);
free(to_return);
return result;
}
PyErr_SetString(CBSONError, "no c encoder for this type yet");
return NULL;
}
static PyMethodDef _CBSONMethods[] = {
@ -89,5 +122,13 @@ static PyMethodDef _CBSONMethods[] = {
};
PyMODINIT_FUNC init_cbson(void) {
(void) Py_InitModule("_cbson", _CBSONMethods);
PyObject *m;
m = Py_InitModule("_cbson", _CBSONMethods);
if (m == NULL) {
return;
}
CBSONError = PyErr_NewException("_cbson.error", NULL, NULL);
Py_INCREF(CBSONError);
PyModule_AddObject(m, "error", CBSONError);
}

View File

@ -351,8 +351,14 @@ def _element_to_bson(name, value):
ns = _make_c_string(value.collection())
return "\x0C" + name + struct.pack("<i", len(ns)) + ns + _shuffle_oid(str(value.id()))
raise InvalidDocument("cannot convert value of type %s to bson" % type(value))
# if _use_c:
# _element_to_bson = _cbson._element_to_bson
if _use_c:
_py_element_to_bson = _element_to_bson
_c_element_to_bson = _cbson._element_to_bson
def _element_to_bson(name, value):
try:
return _c_element_to_bson(name, value)
except _cbson.error:
return _py_element_to_bson(name, value)
def is_valid(bson):
"""Validate that the given string represents valid BSON data.