switch to using buffer.c/h from Ruby

This commit is contained in:
Mike Dirolf 2010-09-14 10:01:44 -04:00
parent 789296c6ef
commit 56699b9ff2
6 changed files with 330 additions and 171 deletions

View File

@ -14,33 +14,22 @@
* limitations under the License.
*/
#ifndef _CBSON_H
#define _CBSON_H
#include <Python.h>
#include "buffer.h"
/* A buffer representing some data being encoded to BSON. */
typedef struct {
char* buffer;
int size;
int position;
} bson_buffer;
bson_buffer* buffer_new(void);
int buffer_save_bytes(bson_buffer* buffer, int size);
int buffer_write_bytes(bson_buffer* buffer, const char* bytes, int size);
void buffer_free(bson_buffer* buffer);
int write_dict(bson_buffer* buffer, PyObject* dict,
int write_dict(buffer_t buffer, PyObject* dict,
unsigned char check_keys, unsigned char top_level);
PyObject* elements_to_dict(const char* string, int max,
PyObject* as_class, unsigned char tz_aware);
PyObject* elements_to_dict(const char* string, int max, PyObject* as_class,
unsigned char tz_aware);
int write_pair(bson_buffer* buffer, const char* name,
Py_ssize_t name_length, PyObject* value,
unsigned char check_keys, unsigned char allow_id);
int write_pair(buffer_t buffer, const char* name, Py_ssize_t name_length,
PyObject* value, unsigned char check_keys, unsigned char allow_id);
int decode_and_write_pair(bson_buffer* buffer,
PyObject* key, PyObject* value,
int decode_and_write_pair(buffer_t buffer, PyObject* key, PyObject* value,
unsigned char check_keys, unsigned char top_level);
#endif

View File

@ -26,6 +26,7 @@
#include <datetime.h>
#include "_cbson.h"
#include "buffer.h"
#include "time64.h"
#include "encoding_helpers.h"
@ -55,8 +56,6 @@ typedef int Py_ssize_t;
PyErr_WarnEx((category), (message), 1)
#endif
#define INITIAL_BUFFER_SIZE 256
/* Maximum number of regex flags */
#define FLAGS_SIZE 7
@ -127,81 +126,17 @@ static long long millis_from_datetime(PyObject* datetime) {
return millis;
}
bson_buffer* buffer_new(void) {
bson_buffer* buffer;
buffer = (bson_buffer*)malloc(sizeof(bson_buffer));
if (!buffer) {
PyErr_NoMemory();
return NULL;
}
buffer->size = INITIAL_BUFFER_SIZE;
buffer->position = 0;
buffer->buffer = (char*)malloc(INITIAL_BUFFER_SIZE);
if (!buffer->buffer) {
PyErr_NoMemory();
return NULL;
}
return buffer;
}
void buffer_free(bson_buffer* buffer) {
if (buffer == NULL) {
return;
}
free(buffer->buffer);
free(buffer);
}
/* returns zero on failure */
static int buffer_resize(bson_buffer* buffer, int min_length) {
int size = buffer->size;
if (size >= min_length) {
return 1;
}
while (size < min_length) {
size *= 2;
}
buffer->buffer = (char*)realloc(buffer->buffer, size);
if (!buffer->buffer) {
/* Just make this compatible w/ the old API. */
static inline int buffer_write_bytes(buffer_t buffer, const char* data, int size) {
if (buffer_write(buffer, data, size)) {
PyErr_NoMemory();
return 0;
}
buffer->size = size;
return 1;
}
/* returns zero on failure */
static int buffer_assure_space(bson_buffer* buffer, int size) {
if (buffer->position + size <= buffer->size) {
return 1;
}
return buffer_resize(buffer, buffer->position + size);
}
/* returns offset for writing, or -1 on failure */
int buffer_save_bytes(bson_buffer* buffer, int size) {
int position;
if (!buffer_assure_space(buffer, size)) {
return -1;
}
position = buffer->position;
buffer->position += size;
return position;
}
/* returns zero on failure */
int buffer_write_bytes(bson_buffer* buffer, const char* bytes, int size) {
if (!buffer_assure_space(buffer, size)) {
return 0;
}
memcpy(buffer->buffer + buffer->position, bytes, size);
buffer->position += size;
return 1;
}
/* returns 0 on failure */
static int write_string(bson_buffer* buffer, PyObject* py_string) {
static int write_string(buffer_t buffer, PyObject* py_string) {
Py_ssize_t string_length;
const char* string = PyString_AsString(py_string);
if (!string) {
@ -280,11 +215,11 @@ static int _reload_python_objects(void) {
* space has already been reserved.
*
* returns 0 on failure */
static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject* value, unsigned char check_keys, unsigned char first_attempt) {
static int write_element_to_buffer(buffer_t buffer, int type_byte, PyObject* value, unsigned char check_keys, unsigned char first_attempt) {
if (PyBool_Check(value)) {
const long bool = PyInt_AsLong(value);
const char c = bool ? 0x01 : 0x00;
*(buffer->buffer + type_byte) = 0x08;
*(buffer_get_buffer(buffer) + type_byte) = 0x08;
return buffer_write_bytes(buffer, &c, 1);
}
else if (PyInt_Check(value) || PyLong_Check(value)) {
@ -299,20 +234,20 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
"MongoDB can only handle up to 8-byte ints");
return 0;
}
*(buffer->buffer + type_byte) = 0x12;
*(buffer_get_buffer(buffer) + type_byte) = 0x12;
return buffer_write_bytes(buffer, (const char*)&long_long_value, 8);
}
*(buffer->buffer + type_byte) = 0x10;
*(buffer_get_buffer(buffer) + type_byte) = 0x10;
return buffer_write_bytes(buffer, (const char*)&int_value, 4);
} else if (PyFloat_Check(value)) {
const double d = PyFloat_AsDouble(value);
*(buffer->buffer + type_byte) = 0x01;
*(buffer_get_buffer(buffer) + type_byte) = 0x01;
return buffer_write_bytes(buffer, (const char*)&d, 8);
} else if (value == Py_None) {
*(buffer->buffer + type_byte) = 0x0A;
*(buffer_get_buffer(buffer) + type_byte) = 0x0A;
return 1;
} else if (PyDict_Check(value)) {
*(buffer->buffer + type_byte) = 0x03;
*(buffer_get_buffer(buffer) + type_byte) = 0x03;
return write_dict(buffer, value, check_keys, 0);
} else if (PyList_Check(value) || PyTuple_Check(value)) {
int start_position,
@ -322,22 +257,24 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
i;
char zero = 0;
*(buffer->buffer + type_byte) = 0x04;
start_position = buffer->position;
*(buffer_get_buffer(buffer) + type_byte) = 0x04;
start_position = buffer_get_position(buffer);
/* save space for length */
length_location = buffer_save_bytes(buffer, 4);
length_location = buffer_save_space(buffer, 4);
if (length_location == -1) {
PyErr_NoMemory();
return 0;
}
items = PySequence_Size(value);
for(i = 0; i < items; i++) {
int list_type_byte = buffer_save_bytes(buffer, 1);
int list_type_byte = buffer_save_space(buffer, 1);
char* name;
PyObject* item_value;
if (type_byte == -1) {
if (list_type_byte == -1) {
PyErr_NoMemory();
return 0;
}
if (INT2STRING(&name, i) < 0 || !name) {
@ -362,13 +299,13 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
if (!buffer_write_bytes(buffer, &zero, 1)) {
return 0;
}
length = buffer->position - start_position;
memcpy(buffer->buffer + length_location, &length, 4);
length = buffer_get_position(buffer) - start_position;
memcpy(buffer_get_buffer(buffer) + length_location, &length, 4);
return 1;
} else if (PyObject_IsInstance(value, Binary)) {
PyObject* subtype_object;
*(buffer->buffer + type_byte) = 0x05;
*(buffer_get_buffer(buffer) + type_byte) = 0x05;
subtype_object = PyObject_GetAttrString(value, "subtype");
if (!subtype_object) {
return 0;
@ -416,7 +353,7 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
PyObject* bytes;
*(buffer->buffer + type_byte) = 0x05;
*(buffer_get_buffer(buffer) + type_byte) = 0x05;
if (!buffer_write_bytes(buffer, (const char*)&length, 4)) {
return 0;
}
@ -440,12 +377,13 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
length;
PyObject* scope;
*(buffer->buffer + type_byte) = 0x0F;
*(buffer_get_buffer(buffer) + type_byte) = 0x0F;
start_position = buffer->position;
start_position = buffer_get_position(buffer);
/* save space for length */
length_location = buffer_save_bytes(buffer, 4);
length_location = buffer_save_space(buffer, 4);
if (length_location == -1) {
PyErr_NoMemory();
return 0;
}
@ -463,14 +401,14 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
}
Py_DECREF(scope);
length = buffer->position - start_position;
memcpy(buffer->buffer + length_location, &length, 4);
length = buffer_get_position(buffer) - start_position;
memcpy(buffer_get_buffer(buffer) + length_location, &length, 4);
return 1;
} else if (PyString_Check(value)) {
int result;
result_t status;
*(buffer->buffer + type_byte) = 0x02;
*(buffer_get_buffer(buffer) + type_byte) = 0x02;
status = check_string((const unsigned char*)PyString_AsString(value),
PyString_Size(value), 1, 0);
if (status == NOT_UTF_8) {
@ -486,7 +424,7 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
PyObject* encoded;
int result;
*(buffer->buffer + type_byte) = 0x02;
*(buffer_get_buffer(buffer) + type_byte) = 0x02;
encoded = PyUnicode_AsUTF8String(value);
if (!encoded) {
return 0;
@ -508,7 +446,7 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
} else {
millis = millis_from_datetime(value);
}
*(buffer->buffer + type_byte) = 0x09;
*(buffer_get_buffer(buffer) + type_byte) = 0x09;
return buffer_write_bytes(buffer, (const char*)&millis, 8);
} else if (PyObject_IsInstance(value, ObjectId)) {
PyObject* pystring = PyObject_GetAttrString(value, "_ObjectId__id");
@ -526,7 +464,7 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
return 0;
}
Py_DECREF(pystring);
*(buffer->buffer + type_byte) = 0x07;
*(buffer_get_buffer(buffer) + type_byte) = 0x07;
}
return 1;
} else if (PyObject_IsInstance(value, DBRef)) {
@ -539,7 +477,7 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
return 0;
}
Py_DECREF(as_doc);
*(buffer->buffer + type_byte) = 0x03;
*(buffer_get_buffer(buffer) + type_byte) = 0x03;
return 1;
} else if (PyObject_IsInstance(value, Timestamp)) {
PyObject* obj;
@ -565,7 +503,7 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
return 0;
}
*(buffer->buffer + type_byte) = 0x11;
*(buffer_get_buffer(buffer) + type_byte) = 0x11;
return 1;
}
else if (PyObject_TypeCheck(value, REType)) {
@ -651,13 +589,13 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
if (!buffer_write_bytes(buffer, flags, flags_length)) {
return 0;
}
*(buffer->buffer + type_byte) = 0x0B;
*(buffer_get_buffer(buffer) + type_byte) = 0x0B;
return 1;
} else if (PyObject_IsInstance(value, MinKey)) {
*(buffer->buffer + type_byte) = 0xFF;
*(buffer_get_buffer(buffer) + type_byte) = 0xFF;
return 1;
} else if (PyObject_IsInstance(value, MaxKey)) {
*(buffer->buffer + type_byte) = 0x7F;
*(buffer_get_buffer(buffer) + type_byte) = 0x7F;
return 1;
} else if (first_attempt) {
/* Try reloading the modules and having one more go at it. */
@ -712,7 +650,7 @@ static int check_key_name(const char* name,
/* Write a (key, value) pair to the buffer.
*
* Returns 0 on failure */
int write_pair(bson_buffer* buffer, const char* name, Py_ssize_t name_length, PyObject* value, unsigned char check_keys, unsigned char allow_id) {
int write_pair(buffer_t buffer, const char* name, Py_ssize_t name_length, PyObject* value, unsigned char check_keys, unsigned char allow_id) {
int type_byte;
/* Don't write any _id elements unless we're explicitly told to -
@ -722,8 +660,9 @@ int write_pair(bson_buffer* buffer, const char* name, Py_ssize_t name_length, Py
return 1;
}
type_byte = buffer_save_bytes(buffer, 1);
type_byte = buffer_save_space(buffer, 1);
if (type_byte == -1) {
PyErr_NoMemory();
return 0;
}
if (check_keys && !check_key_name(name, name_length)) {
@ -738,7 +677,7 @@ int write_pair(bson_buffer* buffer, const char* name, Py_ssize_t name_length, Py
return 1;
}
int decode_and_write_pair(bson_buffer* buffer,
int decode_and_write_pair(buffer_t buffer,
PyObject* key, PyObject* value,
unsigned char check_keys, unsigned char top_level) {
PyObject* encoded;
@ -802,7 +741,7 @@ int decode_and_write_pair(bson_buffer* buffer,
}
/* returns 0 on failure */
int write_dict(bson_buffer* buffer, PyObject* dict, unsigned char check_keys, unsigned char top_level) {
int write_dict(buffer_t buffer, PyObject* dict, unsigned char check_keys, unsigned char top_level) {
PyObject* key;
PyObject* iter;
char zero = 0;
@ -818,8 +757,9 @@ int write_dict(bson_buffer* buffer, PyObject* dict, unsigned char check_keys, un
return 0;
}
length_location = buffer_save_bytes(buffer, 4);
length_location = buffer_save_space(buffer, 4);
if (length_location == -1) {
PyErr_NoMemory();
return 0;
}
@ -854,7 +794,7 @@ int write_dict(bson_buffer* buffer, PyObject* dict, unsigned char check_keys, un
if (!buffer_write_bytes(buffer, &zero, 1)) {
return 0;
}
length = buffer->position - length_location;
length = buffer_get_position(buffer) - length_location;
if (length > 4 * 1024 * 1024) {
PyObject* InvalidDocument = _error("InvalidDocument");
PyErr_SetString(InvalidDocument, "document too large - "
@ -862,7 +802,7 @@ int write_dict(bson_buffer* buffer, PyObject* dict, unsigned char check_keys, un
Py_DECREF(InvalidDocument);
return 0;
}
memcpy(buffer->buffer + length_location, &length, 4);
memcpy(buffer_get_buffer(buffer) + length_location, &length, 4);
return 1;
}
@ -870,7 +810,7 @@ static PyObject* _cbson_dict_to_bson(PyObject* self, PyObject* args) {
PyObject* dict;
PyObject* result;
unsigned char check_keys;
bson_buffer* buffer;
buffer_t buffer;
if (!PyArg_ParseTuple(args, "Ob", &dict, &check_keys)) {
return NULL;
@ -878,6 +818,7 @@ static PyObject* _cbson_dict_to_bson(PyObject* self, PyObject* args) {
buffer = buffer_new();
if (!buffer) {
PyErr_NoMemory();
return NULL;
}
@ -887,7 +828,8 @@ static PyObject* _cbson_dict_to_bson(PyObject* self, PyObject* args) {
}
/* objectify buffer */
result = Py_BuildValue("s#", buffer->buffer, buffer->position);
result = Py_BuildValue("s#", buffer_get_buffer(buffer),
buffer_get_position(buffer));
buffer_free(buffer);
return result;
}

135
bson/buffer.c Normal file
View File

@ -0,0 +1,135 @@
/*
* Copyright 2009-2010 10gen, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <string.h>
#include "buffer.h"
#define INITIAL_BUFFER_SIZE 256
struct buffer {
char* buffer;
int size;
int position;
};
/* Allocate and return a new buffer.
* Return NULL on allocation failure. */
buffer_t buffer_new(void) {
buffer_t buffer;
buffer = (buffer_t)malloc(sizeof(struct buffer));
if (buffer == NULL) {
return NULL;
}
buffer->size = INITIAL_BUFFER_SIZE;
buffer->position = 0;
buffer->buffer = (char*)malloc(sizeof(char) * INITIAL_BUFFER_SIZE);
if (buffer->buffer == NULL) {
free(buffer);
return NULL;
}
return buffer;
}
/* Free the memory allocated for `buffer`.
* Return non-zero on failure. */
int buffer_free(buffer_t buffer) {
if (buffer == NULL) {
return 1;
}
free(buffer->buffer);
free(buffer);
return 0;
}
/* Grow `buffer` to at least `min_length`.
* Return non-zero on allocation failure. */
static int buffer_grow(buffer_t buffer, int min_length) {
int size = buffer->size;
char* old_buffer = buffer->buffer;
if (size >= min_length) {
return 0;
}
while (size < min_length) {
size *= 2;
}
buffer->buffer = (char*)realloc(buffer->buffer, sizeof(char) * size);
if (buffer->buffer == NULL) {
free(old_buffer);
free(buffer);
return 1;
}
buffer->size = size;
return 0;
}
/* Assure that `buffer` has at least `size` free bytes (and grow if needed).
* Return non-zero on allocation failure. */
static int buffer_assure_space(buffer_t buffer, int size) {
if (buffer->position + size <= buffer->size) {
return 0;
}
return buffer_grow(buffer, buffer->position + size);
}
/* Save `size` bytes from the current position in `buffer` (and grow if needed).
* Return offset for writing, or -1 on allocation failure. */
buffer_position buffer_save_space(buffer_t buffer, int size) {
int position = buffer->position;
if (buffer_assure_space(buffer, size) != 0) {
return -1;
}
buffer->position += size;
return position;
}
/* Write `size` bytes from `data` to `buffer` (and grow if needed).
* Return non-zero on allocation failure. */
int buffer_write(buffer_t buffer, const char* data, int size) {
if (buffer_assure_space(buffer, size) != 0) {
return 1;
}
memcpy(buffer->buffer + buffer->position, data, size);
buffer->position += size;
return 0;
}
/* Write `size` bytes from `data` to `buffer` at position `position`.
* Does not change the internal position of `buffer`.
* Return non-zero if buffer isn't large enough for write. */
int buffer_write_at_position(buffer_t buffer, buffer_position position,
const char* data, int size) {
if (position + size > buffer->size) {
buffer_free(buffer);
return 1;
}
memcpy(buffer->buffer + position, data, size);
return 0;
}
int buffer_get_position(buffer_t buffer) {
return buffer->position;
}
char* buffer_get_buffer(buffer_t buffer) {
return buffer->buffer;
}

55
bson/buffer.h Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright 2009-2010 10gen, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BUFFER_H
#define BUFFER_H
/* Note: if any of these functions return a failure condition then the buffer
* has already been freed. */
/* A buffer */
typedef struct buffer* buffer_t;
/* A position in the buffer */
typedef int buffer_position;
/* Allocate and return a new buffer.
* Return NULL on allocation failure. */
buffer_t buffer_new(void);
/* Free the memory allocated for `buffer`.
* Return non-zero on failure. */
int buffer_free(buffer_t buffer);
/* Save `size` bytes from the current position in `buffer` (and grow if needed).
* Return offset for writing, or -1 on allocation failure. */
buffer_position buffer_save_space(buffer_t buffer, int size);
/* Write `size` bytes from `data` to `buffer` (and grow if needed).
* Return non-zero on allocation failure. */
int buffer_write(buffer_t buffer, const char* data, int size);
/* Write `size` bytes from `data` to `buffer` at position `position`.
* Does not change the internal position of `buffer`.
* Return non-zero if buffer isn't large enough for write. */
int buffer_write_at_position(buffer_t buffer, buffer_position position, const char* data, int size);
/* Getters for the internals of a buffer_t.
* Should try to avoid using these as much as possible
* since they break the abstraction. */
buffer_position buffer_get_position(buffer_t buffer);
char* buffer_get_buffer(buffer_t buffer);
#endif

View File

@ -23,6 +23,7 @@
#include <Python.h>
#include "_cbson.h"
#include "buffer.h"
/*#include <stdio.h>
#include <datetime.h>
@ -30,6 +31,15 @@
#include "time64.h"
#include "encoding_helpers.h"*/
/* Just make this compatible w/ the old API. */
static inline int buffer_write_bytes(buffer_t buffer, const char* data, int size) {
if (buffer_write(buffer, data, size)) {
PyErr_NoMemory();
return 0;
}
return 1;
}
/* Get an error class from the pymongo.errors module.
*
* Returns a new ref */
@ -46,7 +56,7 @@ static PyObject* _error(char* name) {
/* add a lastError message on the end of the buffer.
* returns 0 on failure */
static int add_last_error(bson_buffer* buffer, int request_id, PyObject* args) {
static int add_last_error(buffer_t buffer, int request_id, PyObject* args) {
int message_start;
int document_start;
int message_length;
@ -56,8 +66,9 @@ static int add_last_error(bson_buffer* buffer, int request_id, PyObject* args) {
Py_ssize_t pos = 0;
PyObject* one;
message_start = buffer_save_bytes(buffer, 4);
message_start = buffer_save_space(buffer, 4);
if (message_start == -1) {
PyErr_NoMemory();
return 0;
}
if (!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
@ -73,8 +84,9 @@ static int add_last_error(bson_buffer* buffer, int request_id, PyObject* args) {
}
/* save space for length */
document_start = buffer_save_bytes(buffer, 4);
document_start = buffer_save_space(buffer, 4);
if (document_start == -1) {
PyErr_NoMemory();
return 0;
}
@ -98,8 +110,8 @@ static int add_last_error(bson_buffer* buffer, int request_id, PyObject* args) {
return 0;
}
message_length = buffer->position - message_start;
document_length = buffer->position - document_start;
message_length = buffer_get_position(buffer) - message_start;
document_length = buffer_get_position(buffer) - document_start;
if (document_length > 4 * 1024 * 1024) {
PyObject* InvalidDocument = _error("InvalidDocument");
PyErr_SetString(InvalidDocument, "document too large - "
@ -107,8 +119,8 @@ static int add_last_error(bson_buffer* buffer, int request_id, PyObject* args) {
Py_DECREF(InvalidDocument);
return 0;
}
memcpy(buffer->buffer + message_start, &message_length, 4);
memcpy(buffer->buffer + document_start, &document_length, 4);
memcpy(buffer_get_buffer(buffer) + message_start, &message_length, 4);
memcpy(buffer_get_buffer(buffer) + document_start, &document_length, 4);
return 1;
}
@ -123,7 +135,7 @@ static PyObject* _cbson_insert_message(PyObject* self, PyObject* args) {
unsigned char check_keys;
unsigned char safe;
PyObject* last_error_args;
bson_buffer* buffer;
buffer_t buffer;
int length_location;
PyObject* result;
@ -137,14 +149,19 @@ static PyObject* _cbson_insert_message(PyObject* self, PyObject* args) {
buffer = buffer_new();
if (!buffer) {
PyErr_NoMemory();
PyMem_Free(collection_name);
return NULL;
}
// save space for message length
length_location = buffer_save_bytes(buffer, 4);
if (length_location == -1 ||
!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
length_location = buffer_save_space(buffer, 4);
if (length_location == -1) {
PyMem_Free(collection_name);
PyErr_NoMemory();
return NULL;
}
if (!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
!buffer_write_bytes(buffer,
"\x00\x00\x00\x00"
"\xd2\x07\x00\x00"
@ -176,7 +193,8 @@ static PyObject* _cbson_insert_message(PyObject* self, PyObject* args) {
}
}
memcpy(buffer->buffer + length_location, &buffer->position, 4);
memcpy(buffer_get_buffer(buffer) + length_location,
buffer_get_buffer(buffer) + buffer_get_position(buffer), 4);
if (safe) {
if (!add_last_error(buffer, request_id, last_error_args)) {
@ -187,7 +205,8 @@ static PyObject* _cbson_insert_message(PyObject* self, PyObject* args) {
/* objectify buffer */
result = Py_BuildValue("is#", request_id,
buffer->buffer, buffer->position);
buffer_get_buffer(buffer),
buffer_get_position(buffer));
buffer_free(buffer);
return result;
}
@ -204,7 +223,7 @@ static PyObject* _cbson_update_message(PyObject* self, PyObject* args) {
unsigned char safe;
PyObject* last_error_args;
int options;
bson_buffer* buffer;
buffer_t buffer;
int length_location;
PyObject* result;
@ -226,14 +245,19 @@ static PyObject* _cbson_update_message(PyObject* self, PyObject* args) {
}
buffer = buffer_new();
if (!buffer) {
PyErr_NoMemory();
PyMem_Free(collection_name);
return NULL;
}
// save space for message length
length_location = buffer_save_bytes(buffer, 4);
if (length_location == -1 ||
!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
length_location = buffer_save_space(buffer, 4);
if (length_location == -1) {
PyMem_Free(collection_name);
PyErr_NoMemory();
return NULL;
}
if (!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
!buffer_write_bytes(buffer,
"\x00\x00\x00\x00"
"\xd1\x07\x00\x00"
@ -252,7 +276,8 @@ static PyObject* _cbson_update_message(PyObject* self, PyObject* args) {
PyMem_Free(collection_name);
memcpy(buffer->buffer + length_location, &buffer->position, 4);
memcpy(buffer_get_buffer(buffer) + length_location,
buffer_get_buffer(buffer) + buffer_get_position(buffer), 4);
if (safe) {
if (!add_last_error(buffer, request_id, last_error_args)) {
@ -263,7 +288,8 @@ static PyObject* _cbson_update_message(PyObject* self, PyObject* args) {
/* objectify buffer */
result = Py_BuildValue("is#", request_id,
buffer->buffer, buffer->position);
buffer_get_buffer(buffer),
buffer_get_position(buffer));
buffer_free(buffer);
return result;
}
@ -278,7 +304,7 @@ static PyObject* _cbson_query_message(PyObject* self, PyObject* args) {
int num_to_return;
PyObject* query;
PyObject* field_selector = Py_None;
bson_buffer* buffer;
buffer_t buffer;
int length_location;
PyObject* result;
@ -293,20 +319,22 @@ static PyObject* _cbson_query_message(PyObject* self, PyObject* args) {
}
buffer = buffer_new();
if (!buffer) {
PyErr_NoMemory();
PyMem_Free(collection_name);
return NULL;
}
// save space for message length
length_location = buffer_save_bytes(buffer, 4);
if (length_location == -1 ||
!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
!buffer_write_bytes(buffer,
"\x00\x00\x00\x00"
"\xd4\x07\x00\x00", 8) ||
length_location = buffer_save_space(buffer, 4);
if (length_location == -1) {
PyMem_Free(collection_name);
PyErr_NoMemory();
return NULL;
}
if (!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
!buffer_write_bytes(buffer, "\x00\x00\x00\x00\xd4\x07\x00\x00", 8) ||
!buffer_write_bytes(buffer, (const char*)&options, 4) ||
!buffer_write_bytes(buffer,
collection_name,
!buffer_write_bytes(buffer, collection_name,
collection_name_length + 1) ||
!buffer_write_bytes(buffer, (const char*)&num_to_skip, 4) ||
!buffer_write_bytes(buffer, (const char*)&num_to_return, 4) ||
@ -320,11 +348,13 @@ static PyObject* _cbson_query_message(PyObject* self, PyObject* args) {
PyMem_Free(collection_name);
memcpy(buffer->buffer + length_location, &buffer->position, 4);
memcpy(buffer_get_buffer(buffer) + length_location,
buffer_get_buffer(buffer) + buffer_get_position(buffer), 4);
/* objectify buffer */
result = Py_BuildValue("is#", request_id,
buffer->buffer, buffer->position);
buffer_get_buffer(buffer),
buffer_get_position(buffer));
buffer_free(buffer);
return result;
}
@ -336,7 +366,7 @@ static PyObject* _cbson_get_more_message(PyObject* self, PyObject* args) {
int collection_name_length;
int num_to_return;
long long cursor_id;
bson_buffer* buffer;
buffer_t buffer;
int length_location;
PyObject* result;
@ -350,14 +380,19 @@ static PyObject* _cbson_get_more_message(PyObject* self, PyObject* args) {
}
buffer = buffer_new();
if (!buffer) {
PyErr_NoMemory();
PyMem_Free(collection_name);
return NULL;
}
// save space for message length
length_location = buffer_save_bytes(buffer, 4);
if (length_location == -1 ||
!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
length_location = buffer_save_space(buffer, 4);
if (length_location == -1) {
PyMem_Free(collection_name);
PyErr_NoMemory();
return NULL;
}
if (!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
!buffer_write_bytes(buffer,
"\x00\x00\x00\x00"
"\xd5\x07\x00\x00"
@ -374,11 +409,13 @@ static PyObject* _cbson_get_more_message(PyObject* self, PyObject* args) {
PyMem_Free(collection_name);
memcpy(buffer->buffer + length_location, &buffer->position, 4);
memcpy(buffer_get_buffer(buffer) + length_location,
buffer_get_buffer(buffer) + buffer_get_position(buffer), 4);
/* objectify buffer */
result = Py_BuildValue("is#", request_id,
buffer->buffer, buffer->position);
buffer_get_buffer(buffer),
buffer_get_position(buffer));
buffer_free(buffer);
return result;
}

View File

@ -132,6 +132,7 @@ c_ext = Feature(
include_dirs=['bson'],
sources=['bson/_cbsonmodule.c',
'bson/time64.c',
'bson/buffer.c',
'bson/encoding_helpers.c']),
Extension('pymongo._cmessage',
include_dirs=['bson', 'pymongo'],
@ -142,11 +143,11 @@ if "--no_ext" in sys.argv:
features = {}
elif sys.byteorder == "big":
print """
***************************************************
The optional C extension is currently not supported
*****************************************************
The optional C extensions are currently not supported
on big endian platforms and will not be built.
Performance may be degraded.
***************************************************
*****************************************************
"""
features = {}
else: