aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jim.c89
-rw-r--r--test.tcl49
2 files changed, 138 insertions, 0 deletions
diff --git a/jim.c b/jim.c
index 559289d..8aa65bc 100644
--- a/jim.c
+++ b/jim.c
@@ -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;
diff --git a/test.tcl b/test.tcl
index 011fa21..aa2ef61 100644
--- a/test.tcl
+++ b/test.tcl
@@ -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
################################################################################