<commit_before>/*
 * mongotcl - Tcl interface to MongoDB
 *
 * Copyright (C) 2014 FlightAware LLC
 *
 * freely redistributable under the Berkeley license
 */

#include "mongotcl.h"
#include <assert.h>



/*
 *--------------------------------------------------------------
 *
 * mongotcl_bsonObjectDelete -- command deletion callback routine.
 *
 * Results:
 *      ...frees the bson object.
 *      ...frees memory
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */
void
mongotcl_bsonObjectDelete (ClientData clientData)
{
    mongotcl_bsonClientData *bd = (mongotcl_bsonClientData *)clientData;

    assert (bd->bson_magic == MONGOTCL_BSON_MAGIC);

    bson_destroy(bd->bson);
    ckfree((char *)bd->bson);
    ckfree((char *)clientData);
}

int
mongotcl_setBsonError (Tcl_Interp *interp, bson *bson) {
    Tcl_Obj *list = Tcl_NewObj();
    Tcl_Obj *errorCodeList = Tcl_NewObj();

    if (bson->err & BSON_NOT_UTF8) {
	Tcl_AddErrorInfo (interp, "bson not utf8");
	Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj("NOT_UTF8",-1));
    }

    if (bson->err & BSON_FIELD_HAS_DOT) {
	Tcl_AddErrorInfo (interp, "bson field has dot");
	Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj("HAS_DOT",-1));
    }

    if (bson->err & BSON_FIELD_INIT_DOLLAR) {
	Tcl_AddErrorInfo (interp, "bson field has initial dollar sign");
	Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj("INIT_DOLLAR",-1));
    }

    if (bson->err & BSON_ALREADY_FINISHED) {
	Tcl_AddErrorInfo (interp, "bson already finished");
	Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj("ALREADY_FINISHED",-1));
    }

    Tcl_ListObjAppendElement(interp, errorCodeList, Tcl_NewStringObj("BSON",-1));
    Tcl_ListObjAppendElement(interp, errorCodeList, list);

    Tcl_SetObjErrorCode (interp, errorCodeList);

    return TCL_ERROR;
}



/*
 *----------------------------------------------------------------------
 *
 * mongotcl_cmdNameObjToBson --
 *
 *    Take a command name, find the Tcl command info structure, return
 *    a pointer to the bson embedded in the clientData of the object.
 *
 *----------------------------------------------------------------------
 */
static int
mongotcl_cmdNameObjToBson (Tcl_Interp *interp, Tcl_Obj *commandNameObj, bson *bson) {
    Tcl_CmdInfo	cmdInfo;

    if (!Tcl_GetCommandInfo (interp, Tcl_GetString(commandNameObj), &cmdInfo)) {
	return TCL_ERROR;
    }

    if (cmdInfo.objClientData == NULL || ((mongotcl_bsonClientData *)cmdInfo.objClientData)->bson_magic != MONGOTCL_BSON_MAGIC) {
	Tcl_AppendResult (interp, "Error: '", Tcl_GetString (commandNameObj), "' is not a bson object", NULL);
	return TCL_ERROR;
    }

    bson = ((mongotcl_bsonClientData *)cmdInfo.objClientData)->bson;
    return TCL_OK;
}



/*
 *----------------------------------------------------------------------
 *
 * mongotcl_bsonObjectObjCmd --
 *
 *    dispatches the subcommands of a bson object command
 *
 * Results:
 *    stuff
 *
 *----------------------------------------------------------------------
 */
int
mongotcl_bsonObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
    int         optIndex;
    mongotcl_bsonClientData *bd = (mongotcl_bsonClientData *)cData;

    static CONST char *options[] = {
        "init",
        "string",
        "int",
        "start_array",
        "finish_array",
	"start_object",
	"finish_object",
	"finish",
        NULL
    };

    enum options {
        OPT_INIT,
        OPT_APPEND_STRING,
        OPT_APPEND_INT,
        OPT_START_ARRAY,
        OPT_FINISH_ARRAY,
        OPT_START_OBJECT,
        OPT_FINISH_OBJECT,
        OPT_FINISH
    };

    /* basic validation of command line arguments */
    if (objc < 2) {
        Tcl_WrongNumArgs (interp, 1, objv, "subcommand ?args?");
        return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj (interp, objv[1], options, "option",
	TCL_EXACT, &optIndex) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) optIndex) {
      case OPT_INIT: {
	if (objc != 2) {
	    Tcl_WrongNumArgs (interp, 1, objv, "init");
	    return TCL_ERROR;
	}

	bson_init (bd->bson);
	break;
      }

      case OPT_APPEND_STRING: {
	if (objc != 4) {
	    Tcl_WrongNumArgs (interp, 2, objv, "key value");
	    return TCL_ERROR;
	}

	if (bson_append_string (bd->bson, Tcl_GetString (objv[2]), Tcl_GetString (objv[3])) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
	break;
      }

      case OPT_APPEND_INT: {
	int num;

	if (objc != 4) {
	    Tcl_WrongNumArgs (interp, 2, objv, "key value");
	    return TCL_ERROR;
	}

	if (Tcl_GetIntFromObj (interp, objv[3], &num) == TCL_ERROR) {
	    return TCL_ERROR;
	}

	if (bson_append_int (bd->bson, Tcl_GetString (objv[2]), num) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
	break;
      }

      case OPT_START_ARRAY: {
	if (objc != 3) {
	    Tcl_WrongNumArgs (interp, 2, objv, "name");
	    return TCL_ERROR;
	}

	if (bson_append_start_array (bd->bson, Tcl_GetString (objv[2])) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }

      case OPT_FINISH_ARRAY: {
	if (objc != 2) {
	    Tcl_WrongNumArgs (interp, 1, objv, "finish_array");
	    return TCL_ERROR;
	}

	if (bson_append_finish_array (bd->bson) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }

      case OPT_START_OBJECT: {
        break;
      }

      case OPT_FINISH_OBJECT: {
	if (objc != 2) {
	    Tcl_WrongNumArgs (interp, 1, objv, "finish_object");
	    return TCL_ERROR;
	}

	if (bson_append_finish_object (bd->bson) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }

      case OPT_FINISH: {
	if (objc != 2) {
	    Tcl_WrongNumArgs (interp, 1, objv, "finish");
	    return TCL_ERROR;
	}

	if (bson_append_finish_object (bd->bson) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }
    }

    return TCL_OK;
}



/*
 *----------------------------------------------------------------------
 *<commit_msg>Add method for bson_append_new_oid. Normalize bson option enums to be closer to the functions they represent. BUGZID:<commit_after>/*
 * mongotcl - Tcl interface to MongoDB
 *
 * Copyright (C) 2014 FlightAware LLC
 *
 * freely redistributable under the Berkeley license
 */

#include "mongotcl.h"
#include <assert.h>



/*
 *--------------------------------------------------------------
 *
 * mongotcl_bsonObjectDelete -- command deletion callback routine.
 *
 * Results:
 *      ...frees the bson object.
 *      ...frees memory
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */
void
mongotcl_bsonObjectDelete (ClientData clientData)
{
    mongotcl_bsonClientData *bd = (mongotcl_bsonClientData *)clientData;

    assert (bd->bson_magic == MONGOTCL_BSON_MAGIC);

    bson_destroy(bd->bson);
    ckfree((char *)bd->bson);
    ckfree((char *)clientData);
}

int
mongotcl_setBsonError (Tcl_Interp *interp, bson *bson) {
    Tcl_Obj *list = Tcl_NewObj();
    Tcl_Obj *errorCodeList = Tcl_NewObj();

    if (bson->err & BSON_NOT_UTF8) {
	Tcl_AddErrorInfo (interp, "bson not utf8");
	Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj("NOT_UTF8",-1));
    }

    if (bson->err & BSON_FIELD_HAS_DOT) {
	Tcl_AddErrorInfo (interp, "bson field has dot");
	Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj("HAS_DOT",-1));
    }

    if (bson->err & BSON_FIELD_INIT_DOLLAR) {
	Tcl_AddErrorInfo (interp, "bson field has initial dollar sign");
	Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj("INIT_DOLLAR",-1));
    }

    if (bson->err & BSON_ALREADY_FINISHED) {
	Tcl_AddErrorInfo (interp, "bson already finished");
	Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj("ALREADY_FINISHED",-1));
    }

    Tcl_ListObjAppendElement(interp, errorCodeList, Tcl_NewStringObj("BSON",-1));
    Tcl_ListObjAppendElement(interp, errorCodeList, list);

    Tcl_SetObjErrorCode (interp, errorCodeList);

    return TCL_ERROR;
}



/*
 *----------------------------------------------------------------------
 *
 * mongotcl_cmdNameObjToBson --
 *
 *    Take a command name, find the Tcl command info structure, return
 *    a pointer to the bson embedded in the clientData of the object.
 *
 *----------------------------------------------------------------------
 */
static int
mongotcl_cmdNameObjToBson (Tcl_Interp *interp, Tcl_Obj *commandNameObj, bson *bson) {
    Tcl_CmdInfo	cmdInfo;

    if (!Tcl_GetCommandInfo (interp, Tcl_GetString(commandNameObj), &cmdInfo)) {
	return TCL_ERROR;
    }

    if (cmdInfo.objClientData == NULL || ((mongotcl_bsonClientData *)cmdInfo.objClientData)->bson_magic != MONGOTCL_BSON_MAGIC) {
	Tcl_AppendResult (interp, "Error: '", Tcl_GetString (commandNameObj), "' is not a bson object", NULL);
	return TCL_ERROR;
    }

    bson = ((mongotcl_bsonClientData *)cmdInfo.objClientData)->bson;
    return TCL_OK;
}



/*
 *----------------------------------------------------------------------
 *
 * mongotcl_bsonObjectObjCmd --
 *
 *    dispatches the subcommands of a bson object command
 *
 * Results:
 *    stuff
 *
 *----------------------------------------------------------------------
 */
int
mongotcl_bsonObjectObjCmd(ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
    int         optIndex;
    mongotcl_bsonClientData *bd = (mongotcl_bsonClientData *)cData;

    static CONST char *options[] = {
        "init",
        "string",
        "int",
        "start_array",
        "finish_array",
	"start_object",
	"finish_object",
	"new_oid",
	"finish",
        NULL
    };

    enum options {
        OPT_INIT,
        OPT_APPEND_STRING,
        OPT_APPEND_INT,
        OPT_APPEND_START_ARRAY,
        OPT_APPEND_FINISH_ARRAY,
        OPT_APPEND_START_OBJECT,
        OPT_APPEND_FINISH_OBJECT,
	OPT_APPEND_NEW_OID,
        OPT_FINISH
    };

    /* basic validation of command line arguments */
    if (objc < 2) {
        Tcl_WrongNumArgs (interp, 1, objv, "subcommand ?args?");
        return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj (interp, objv[1], options, "option",
	TCL_EXACT, &optIndex) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) optIndex) {
      case OPT_INIT: {
	if (objc != 2) {
	    Tcl_WrongNumArgs (interp, 1, objv, "init");
	    return TCL_ERROR;
	}

	bson_init (bd->bson);
	break;
      }

      case OPT_APPEND_STRING: {
	if (objc != 4) {
	    Tcl_WrongNumArgs (interp, 2, objv, "key value");
	    return TCL_ERROR;
	}

	if (bson_append_string (bd->bson, Tcl_GetString (objv[2]), Tcl_GetString (objv[3])) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
	break;
      }

      case OPT_APPEND_INT: {
	int num;

	if (objc != 4) {
	    Tcl_WrongNumArgs (interp, 2, objv, "key value");
	    return TCL_ERROR;
	}

	if (Tcl_GetIntFromObj (interp, objv[3], &num) == TCL_ERROR) {
	    return TCL_ERROR;
	}

	if (bson_append_int (bd->bson, Tcl_GetString (objv[2]), num) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
	break;
      }

      case OPT_APPEND_START_ARRAY: {
	if (objc != 3) {
	    Tcl_WrongNumArgs (interp, 2, objv, "name");
	    return TCL_ERROR;
	}

	if (bson_append_start_array (bd->bson, Tcl_GetString (objv[2])) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }

      case OPT_APPEND_FINISH_ARRAY: {
	if (objc != 2) {
	    Tcl_WrongNumArgs (interp, 1, objv, "finish_array");
	    return TCL_ERROR;
	}

	if (bson_append_finish_array (bd->bson) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }

      case OPT_APPEND_START_OBJECT: {
	if (objc != 3) {
	    Tcl_WrongNumArgs (interp, 2, objv, "name");
	    return TCL_ERROR;
	}

	if (bson_append_start_object (bd->bson, Tcl_GetString (objv[2])) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }

      case OPT_APPEND_FINISH_OBJECT: {
	if (objc != 2) {
	    Tcl_WrongNumArgs (interp, 1, objv, "finish_object");
	    return TCL_ERROR;
	}

	if (bson_append_finish_object (bd->bson) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }

      case OPT_APPEND_NEW_OID: {
	if (objc != 3) {
	    Tcl_WrongNumArgs (interp, 2, objv, "name");
	    return TCL_ERROR;
	}

	if (bson_append_new_oid (bd->bson, Tcl_GetString (objv[2])) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }

      case OPT_FINISH: {
	if (objc != 2) {
	    Tcl_WrongNumArgs (interp, 1, objv, "finish");
	    return TCL_ERROR;
	}

	if (bson_append_finish_object (bd->bson) != BSON_OK) {
	    return mongotcl_setBsonError (interp, bd->bson);
	}
        break;
      }
    }

    return TCL_OK;
}



/*
 *----------------------------------------------------------------------
 *
{'fraction_non_alphanumeric': 0.18895146979399738, 'fraction_numerical': 0.005709436000308618, 'mean_word_length': 2.3994230264883294, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4288752', 'n_tokens_mistral': 4856, 'n_tokens_neox': 4678, 'n_words': 945}