Index: generic/tclTestObj.c ================================================================== --- generic/tclTestObj.c +++ generic/tclTestObj.c @@ -23,10 +23,11 @@ #else # include "tclTomMath.h" #endif #include "tclStringRep.h" +#include /* * Forward declarations for functions defined later in this file: */ @@ -40,10 +41,11 @@ static Tcl_ObjCmdProc TestindexobjCmd; static Tcl_ObjCmdProc TestintobjCmd; static Tcl_ObjCmdProc TestlistobjCmd; static Tcl_ObjCmdProc TestobjCmd; static Tcl_ObjCmdProc TeststringobjCmd; +static Tcl_ObjCmdProc TestbigdataCmd; #define VARPTR_KEY "TCLOBJTEST_VARPTR" #define NUMBER_OF_OBJECT_VARS 20 static void VarPtrDeleteProc(void *clientData, TCL_UNUSED(Tcl_Interp *)) @@ -114,10 +116,12 @@ NULL, NULL); Tcl_CreateObjCommand(interp, "testlistobj", TestlistobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd, + NULL, NULL); + Tcl_CreateObjCommand(interp, "testbigdata", TestbigdataCmd, NULL, NULL); return TCL_OK; } /* @@ -1516,10 +1520,139 @@ } return TCL_OK; } +/* + *------------------------------------------------------------------------ + * + * TestbigdataCmd -- + * + * Implements the Tcl command testbigdata + * testbigdata string ?LEN? ?SPLIT? + * testbigdata bytearray ?LEN? ?SPLIT? + * If no arguments given, returns the pattern used to generate strings. + * If SPLIT is specified, the character at that position is set to "X". + * + * Results: + * TCL_OK - Success. + * TCL_ERROR - Error. + * + * Side effects: + * Interpreter result holds result or error message. + * + *------------------------------------------------------------------------ + */ +static int +TestbigdataCmd ( + ClientData notUsed, + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + static const char *const subcmds[] = { + "string", "bytearray", "list", NULL + }; + enum options { + BIGDATA_STRING, BIGDATA_BYTEARRAY, BIGDATA_LIST + } idx; + char *s; + unsigned char *p; + Tcl_WideInt i, len, split; + Tcl_DString ds; + Tcl_Obj *objPtr; +#define PATTERN_LEN 10 + Tcl_Obj *patternObjs[PATTERN_LEN]; + + if (objc < 2 || objc > 4) { + Tcl_WrongNumArgs(interp, 1, objv, "command ?len?"); + return TCL_ERROR; + } + if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0, + &idx) != TCL_OK) { + return TCL_ERROR; + } + split = -1; + if (objc == 2) { + len = PATTERN_LEN; + } else { + if (Tcl_GetWideIntFromObj(interp, objv[2], &len) != TCL_OK) { + return TCL_ERROR; + } + if (objc == 4) { + if (Tcl_GetWideIntFromObj(interp, objv[3], &split) != TCL_OK) { + return TCL_ERROR; + } + if (split >= len) { + split = len - 1; /* Last position */ + } + } + } + /* Need one byte for nul terminator */ + Tcl_WideInt limit = + sizeof(Tcl_Size) == sizeof(Tcl_WideInt) ? WIDE_MAX-1 : INT_MAX-1; + if (len < 0 || len > limit) { + Tcl_SetObjResult( + interp, + Tcl_ObjPrintf( + "%s is greater than max permitted length %" TCL_LL_MODIFIER "d", + Tcl_GetString(objv[2]), + limit)); + return TCL_ERROR; + } + + switch (idx) { + case BIGDATA_STRING: + Tcl_DStringInit(&ds); + Tcl_DStringSetLength(&ds, len);/* Also stores \0 at index len+1 */ + s = Tcl_DStringValue(&ds); + for (i = 0; i < len; ++i) { + s[i] = '0' + (i % PATTERN_LEN); + } + if (split >= 0) { + assert(split < len); + s[split] = 'X'; + } + Tcl_DStringResult(interp, &ds); + break; + case BIGDATA_BYTEARRAY: + objPtr = Tcl_NewByteArrayObj(NULL, len); + p = Tcl_GetByteArrayFromObj(objPtr, &len); + for (i = 0; i < len; ++i) { + p[i] = '0' + (i % PATTERN_LEN); + } + if (split >= 0) { + assert(split < len); + p[split] = 'X'; + } + Tcl_SetObjResult(interp, objPtr); + break; + case BIGDATA_LIST: + for (i = 0; i < PATTERN_LEN; ++i) { + patternObjs[i] = Tcl_NewIntObj(i); + Tcl_IncrRefCount(patternObjs[i]); + } + objPtr = Tcl_NewListObj(len, NULL); + for (i = 0; i < len; ++i) { + Tcl_ListObjAppendElement( + interp, objPtr, patternObjs[i % PATTERN_LEN]); + } + if (split >= 0) { + assert(split < len); + Tcl_Obj *splitMarker = Tcl_NewStringObj("X", 1); + Tcl_ListObjReplace(interp, objPtr, split, 1, 1, &splitMarker); + } + for (i = 0; i < PATTERN_LEN; ++i) { + patternObjs[i] = Tcl_NewIntObj(i); + Tcl_DecrRefCount(patternObjs[i]); + } + Tcl_SetObjResult(interp, objPtr); + break; + } + return TCL_OK; +} + /* *---------------------------------------------------------------------- * * SetVarToObj -- *