diff options
-rw-r--r-- | jim.c | 89 | ||||
-rw-r--r-- | test.tcl | 49 |
2 files changed, 138 insertions, 0 deletions
@@ -8036,6 +8036,75 @@ static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, return JIM_OK; } +/* does the [string map] operation. On error NULL is returned, + * otherwise a new string object with the result, having refcount = 0, + * is returned. */ +static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr, + Jim_Obj *objPtr, int nocase) +{ + int numMaps; + const char **key, *str, *noMatchStart = NULL; + Jim_Obj **value; + int *keyLen, strLen, i; + Jim_Obj *resultObjPtr; + + Jim_ListLength(interp, mapListObjPtr, &numMaps); + if (numMaps % 2) { + Jim_SetResultString(interp, + "list must contain an even number of elements", -1); + return NULL; + } + /* Initialization */ + numMaps /= 2; + key = Jim_Alloc(sizeof(char*)*numMaps); + keyLen = Jim_Alloc(sizeof(int)*numMaps); + value = Jim_Alloc(sizeof(Jim_Obj*)*numMaps); + resultObjPtr = Jim_NewStringObj(interp, "", 0); + for (i = 0; i < numMaps; i++) { + Jim_Obj *eleObjPtr; + + Jim_ListIndex(interp, mapListObjPtr, i*2, &eleObjPtr, JIM_NONE); + key[i] = Jim_GetString(eleObjPtr, &keyLen[i]); + Jim_ListIndex(interp, mapListObjPtr, i*2+1, &eleObjPtr, JIM_NONE); + value[i] = eleObjPtr; + } + str = Jim_GetString(objPtr, &strLen); + /* Map it */ + while(strLen) { + for (i = 0; i < numMaps; i++) { + if (strLen >= keyLen[i] && keyLen[i]) { + if (!JimStringCompare(str, keyLen[i], key[i], keyLen[i], + nocase)) + { + if (noMatchStart) { + Jim_AppendString(interp, resultObjPtr, + noMatchStart, str-noMatchStart); + noMatchStart = NULL; + } + Jim_AppendObj(interp, resultObjPtr, value[i]); + str += keyLen[i]; + strLen -= keyLen[i]; + break; + } + } + } + if (i == numMaps) { /* no match */ + if (noMatchStart == NULL) + noMatchStart = str; + str ++; + strLen --; + } + } + if (noMatchStart) { + Jim_AppendString(interp, resultObjPtr, + noMatchStart, str-noMatchStart); + } + Jim_Free(key); + Jim_Free(keyLen); + Jim_Free(value); + return resultObjPtr; +} + /* [string] */ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) @@ -8108,6 +8177,26 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, return JIM_ERR; Jim_SetResult(interp, objPtr); return JIM_OK; + } else if (Jim_CompareStringImmediate(interp, argv[1], "map")) { + int nocase = 0; + Jim_Obj *objPtr; + + if ((argc != 4 && argc != 5) || + (argc == 5 && Jim_CompareStringImmediate(interp, + argv[2], "-nocase") == 0)) { + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? mapList " + "string"); + return JIM_ERR; + } + if (argc == 5) { + nocase = 1; + argv++; + } + objPtr = JimStringMap(interp, argv[2], argv[3], nocase); + if (objPtr == NULL) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; } else if (Jim_CompareStringImmediate(interp, argv[1], "repeat")) { Jim_Obj *objPtr; jim_wide count; @@ -2237,6 +2237,55 @@ test string-9.3 {string length} { foo } 15 +# string map + +test string-10.4 {string map} { + string map {a b} abba +} {bbbb} +test string-10.5 {string map} { + string map {a b} a +} {b} +test string-10.6 {string map -nocase} { + string map -nocase {a b} Abba +} {bbbb} +test string-10.7 {string map} { + string map {abc 321 ab * a A} aabcabaababcab +} {A321*A*321*} +test string-10.8 {string map -nocase} { + string map -nocase {aBc 321 Ab * a A} aabcabaababcab +} {A321*A*321*} +test string-10.10 {string map} { + list [catch {string map {a b c} abba} msg] $msg +} {1 {list must contain an even number of elements}} +test string-10.11 {string map, nulls} { + string map {\x00 NULL blah \x00nix} {qwerty} +} {qwerty} +test string-10.12 {string map, unicode} { + string map [list \374 ue UE \334] "a\374ueUE\000EU" +} aueue\334\0EU +test string-10.13 {string map, -nocase unicode} { + string map -nocase [list \374 ue UE \334] "a\374ueUE\000EU" +} aue\334\334\0EU +test string-10.14 {string map, -nocase null arguments} { + string map -nocase {{} abc} foo +} foo +test string-10.15 {string map, one pair case} { + string map -nocase {abc 32} aAbCaBaAbAbcAb +} {a32aBaAb32Ab} +test string-10.16 {string map, one pair case} { + string map -nocase {ab 4321} aAbCaBaAbAbcAb +} {a4321C4321a43214321c4321} +test string-10.17 {string map, one pair case} { + string map {Ab 4321} aAbCaBaAbAbcAb +} {a4321CaBa43214321c4321} +test string-10.18 {string map, empty argument} { + string map -nocase {{} abc} foo +} foo +test string-10.19 {string map, empty arguments} { + string map -nocase {{} abc f bar {} def} foo +} baroo + + ################################################################################ # FINAL REPORT ################################################################################ |