Skip to content

Commit

Permalink
Add a new to_array method to cursors and bson objects. Requires an ar…
Browse files Browse the repository at this point in the history
…ray name, takes an optional type array name. The array is filled with key-value pairs from the bson object. If present, the type array is filled with the datatype.

subobjects and subarrays are returned as bson to_list-style.
  • Loading branch information
lehenbauer committed Feb 18, 2014
1 parent 61455a5 commit 1b06b0e
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 4 deletions.
199 changes: 195 additions & 4 deletions generic/bson.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ mongotcl_bsontolist_raw (Tcl_Interp *interp, Tcl_Obj *listObj, const char *data

key = bson_iterator_key (&i);

switch (t) {
switch (t) {
case BSON_DOUBLE: {
append_list_type_object (interp, listObj, "double", key, Tcl_NewDoubleObj (bson_iterator_double (&i)));
break;
}
append_list_type_object (interp, listObj, "double", key, Tcl_NewDoubleObj (bson_iterator_double (&i)));
break;
}

case BSON_STRING: {
append_list_type_object (interp, listObj, "string", key, Tcl_NewStringObj (bson_iterator_string (&i), -1));
Expand Down Expand Up @@ -152,6 +152,174 @@ mongotcl_bsontolist(Tcl_Interp *interp, const bson *b) {
return mongotcl_bsontolist_raw (interp, listObj, b->data , 0);
}

int
mongotcl_bsontoarray_raw (Tcl_Interp *interp, char *arrayName, char *typeArrayName, const char *data , int depth) {
bson_iterator i;
const char *key;
bson_timestamp_t ts;
char oidhex[25];
Tcl_Obj *obj;
char *type;

if (data == NULL) {
return TCL_OK;
}

bson_iterator_from_buffer(&i, data);

while (bson_iterator_next (&i)) {
bson_type t = bson_iterator_type (&i);
if (t == 0) {
break;
}

key = bson_iterator_key (&i);

switch (t) {
case BSON_DOUBLE: {
obj = Tcl_NewDoubleObj (bson_iterator_double (&i));
type = "double";
break;
}

case BSON_SYMBOL: {
obj = Tcl_NewStringObj (bson_iterator_string (&i), -1);
type = "symbol";
break;
}

case BSON_STRING: {
obj = Tcl_NewStringObj (bson_iterator_string (&i), -1);
type = "string";
break;
}

case BSON_OID: {
bson_oid_to_string( bson_iterator_oid( &i ), oidhex );
obj = Tcl_NewStringObj (oidhex, -1);
type = "oid";
break;
}

case BSON_BOOL: {
obj = Tcl_NewBooleanObj (bson_iterator_bool (&i));
type = "bool";
break;
}

case BSON_DATE: {
obj = Tcl_NewLongObj ((long) bson_iterator_date(&i));
type = "date";
break;
}

case BSON_BINDATA: {
unsigned char *bindata = (unsigned char *)bson_iterator_bin_data (&i);
int binlen = bson_iterator_bin_len (&i);

obj = Tcl_NewByteArrayObj (bindata, binlen);
type = "bin";
break;
}

case BSON_UNDEFINED: {
obj = Tcl_NewObj ();
type = "undefined";
break;
}

case BSON_NULL: {
obj = Tcl_NewObj ();
type = "null";
break;
}

case BSON_REGEX: {
obj = Tcl_NewStringObj (bson_iterator_regex (&i), -1);
type = "regex";
break;
}

case BSON_CODE: {
obj = Tcl_NewStringObj (bson_iterator_code (&i), -1);
type = "code";
break;
}

case BSON_CODEWSCOPE: {
// bson_printf( "BSON_CODE_W_SCOPE: %s", bson_iterator_code( &i ) );
/* bson_init( &scope ); */ /* review - stepped on by bson_iterator_code_scope? */
// bson_iterator_code_scope( &i, &scope );
// bson_printf( "\n\t SCOPE: " );
// bson_print( &scope );
/* bson_destroy( &scope ); */ /* review - causes free error */
break;
}

case BSON_INT: {
obj = Tcl_NewIntObj (bson_iterator_int (&i));
type = "int";
break;
}

case BSON_LONG: {
obj = Tcl_NewLongObj ((uint64_t)bson_iterator_long (&i));
type = "long";
break;
}

case BSON_TIMESTAMP: {
char string[64];

ts = bson_iterator_timestamp (&i);
snprintf(string, sizeof(string), "%d:%d", ts.i, ts.t);
obj = Tcl_NewStringObj (bson_iterator_string (&i), -1);
type = "timestamp";
break;
}

case BSON_ARRAY: {
obj = Tcl_NewObj();
obj = mongotcl_bsontolist_raw (interp, obj, bson_iterator_value (&i), depth + 1);
type = "array";

break;
}

case BSON_OBJECT: {
Tcl_Obj *subList = Tcl_NewObj ();

obj = mongotcl_bsontolist_raw (interp, subList, bson_iterator_value (&i), depth + 1);
type = "object";
break;
}

default: {
obj = Tcl_NewIntObj (t);
type = "unknown";
break;
}
}

if (Tcl_SetVar2Ex (interp, arrayName, key, obj, TCL_LEAVE_ERR_MSG) == NULL) {
return TCL_ERROR;
}

if (typeArrayName != NULL) {
if (Tcl_SetVar2Ex (interp, typeArrayName, key, Tcl_NewStringObj (type, -1), TCL_LEAVE_ERR_MSG) == NULL) {
return TCL_ERROR;
}
}
}
return TCL_OK;
}

int
mongotcl_bsontoarray(Tcl_Interp *interp, char *arrayName, char *typeArrayName, const bson *b) {
return mongotcl_bsontoarray_raw (interp, arrayName, typeArrayName, b->data , 0);
}



/*
*--------------------------------------------------------------
Expand Down Expand Up @@ -327,6 +495,7 @@ mongotcl_bsonObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_Ob
"finish_object",
"new_oid",
"to_list",
"to_array",
"finish",
"print",
NULL
Expand All @@ -350,6 +519,7 @@ mongotcl_bsonObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_Ob
OPT_APPEND_FINISH_OBJECT,
OPT_APPEND_NEW_OID,
OPT_TO_LIST,
OPT_TO_ARRAY,
OPT_FINISH,
OPT_PRINT
};
Expand Down Expand Up @@ -687,6 +857,27 @@ mongotcl_bsonObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_Ob
break;
}

case OPT_TO_ARRAY: {
char *arrayName;
char *typeArrayName;

if (objc < 3 || objc > 4) {
Tcl_WrongNumArgs (interp, 1, objv, "to_array arrayName ?typeArrayName?");
return TCL_ERROR;
}

arrayName = Tcl_GetString (objv[2]);

if (objc == 3) {
typeArrayName = NULL;
} else {
typeArrayName = Tcl_GetString (objv[3]);
}

return mongotcl_bsontoarray(interp, arrayName, typeArrayName, bd->bson);
break;
}

case OPT_FINISH: {
if (bson_finish (bd->bson) != BSON_OK) {
return mongotcl_setBsonError (interp, bd->bson);
Expand Down
22 changes: 22 additions & 0 deletions generic/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ mongotcl_cursorObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_
static CONST char *options[] = {
"next",
"to_list",
"to_array",
"init",
"set_query",
"set_fields",
Expand All @@ -223,6 +224,7 @@ mongotcl_cursorObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_
enum options {
OPT_CURSOR_NEXT,
OPT_CURSOR_TO_LIST,
OPT_CURSOR_TO_ARRAY,
OPT_CURSOR_INIT,
OPT_CURSOR_SET_QUERY,
OPT_CURSOR_SET_FIELDS,
Expand Down Expand Up @@ -408,6 +410,26 @@ mongotcl_cursorObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_
break;
}

case OPT_CURSOR_TO_ARRAY: {
char *arrayName;
char *typeArrayName;

if (objc < 3 || objc > 4) {
Tcl_WrongNumArgs (interp, 1, objv, "to_array array ?typeArray?");
return TCL_ERROR;
}

arrayName = Tcl_GetString (objv[2]);

if (objc == 3) {
typeArrayName = NULL;
} else {
typeArrayName = Tcl_GetString (objv[3]);
}

return mongotcl_bsontoarray (interp, arrayName, typeArrayName, mongo_cursor_bson (mc->cursor));
}

case OPT_CURSOR_NEXT: {
if (mongo_cursor_next (mc->cursor) == MONGO_OK) {
Tcl_SetObjResult (interp, Tcl_NewBooleanObj (1));
Expand Down
20 changes: 20 additions & 0 deletions generic/mongotcl.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ mongotcl_mongoObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_O
"update",
"insert_batch",
"cursor",
"search",
"find",
"count",
"init",
Expand Down Expand Up @@ -208,6 +209,7 @@ mongotcl_mongoObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_O
OPT_UPDATE,
OPT_INSERT_BATCH,
OPT_CURSOR,
OPT_SEARCH,
OPT_MONGO_FIND,
OPT_COUNT,
OPT_INIT,
Expand Down Expand Up @@ -497,6 +499,24 @@ mongotcl_mongoObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_O
break;
}

case OPT_SEARCH: {
int i;
int result;
Tcl_Obj **searchObjv = (Tcl_Obj **)ckalloc(sizeof (Tcl_Obj *) * objc);

searchObjv[0] = Tcl_NewStringObj ("mongo::_search", -1);
Tcl_IncrRefCount (searchObjv[0]);
searchObjv[1] = objv[0];

for (i = 2; i < objc; i++) {
searchObjv[i] = objv[i];
}
result = Tcl_EvalObjv (interp, objc, searchObjv, 0);
Tcl_DecrRefCount (searchObjv[0]);
ckfree((char *)searchObjv);
return result;
}

case OPT_MONGO_FIND: {
char *ns;
bson *bsonQuery;
Expand Down
2 changes: 2 additions & 0 deletions generic/mongotcl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ mongotcl_cmdNameObjSetBson (Tcl_Interp *interp, Tcl_Obj *commandNameObj, bson *n
extern Tcl_Obj *
mongotcl_bsontolist(Tcl_Interp *interp, const bson *b);

extern int
mongotcl_bsontoarray(Tcl_Interp *interp, char *arrayName, char *typeArrayName, const bson *b);

extern int
mongotcl_mongoObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objvp[]);
Expand Down

0 comments on commit 1b06b0e

Please sign in to comment.