() = evalfile ("inc.sl"); testing_feature ("string functions"); % Usage: test (&fun, args, expected_ans); static define test () { variable ans = (); variable args = __pop_args (_NARGS-2); variable fun = (); variable result = (@fun) (__push_args(args)); if (ans != result) { variable fmt = String_Type[_NARGS-2]; fmt[*] = "%S"; fmt = sprintf ("%%S(%s) ==> %%S!=%%S", strjoin (fmt, ",")); failed (fmt, fun, __push_args(args), result, ans); } } %test (&str_delete_chars, "foo\xAAbar", "\xAA", "foobar"); private variable s; s = " \t hello world\n\t"; if ("hello world" != strtrim (s)) failed ("strtrim"); if ("hello world\n\t" != strtrim_beg (s)) failed ("strtrim_beg"); if (" \t hello world" != strtrim_end (s)) failed ("strtrim_beg"); if ("hello wor" != strtrim (s, " \t\nld")) failed ("strtrim with whitespace"); if ("" != strcat ("", "")) failed ("strcat 0"); if ("1" != strcat ("", "1")) failed ("strcat 1"); if ("abcdefg" != strcat ("a", "b", "c", "d", "e", "f", "g")) failed ("strcat"); if ("abcdefg" != strcat ("abcdefg")) failed ("strcat 2"); if ((strtok (s)[0] != "hello") or (strtok(s)[1] != "world") or (strtok (s, "^a-z")[0] != "hello") or (strtok (s, "^a-z")[1] != "world") or (2 != length (strtok (s))) or (2 != length (strtok (s, "^a-z")))) failed ("strtok"); define test_create_delimited_string () { variable n = (); variable args = __pop_args (_NARGS - 3); variable delim = (); variable eresult = (); variable result; result = create_delimited_string (delim, __push_args (args), n); if (eresult != result) failed ("create_delimited_string: expected: %s, got: %s", eresult, result); if (n) result = strjoin ([__push_args (args)], delim); else result = strjoin (String_Type[0], delim); if (eresult != result) failed ("strjoin: expected: %s, got: %s", eresult, result); } test_create_delimited_string ("aXXbXXcXXdXXe", "XX", "a", "b", "c", "d", "e", 5); test_create_delimited_string ("", "", "", 1); test_create_delimited_string ("a", ",", "a", 1); test_create_delimited_string (",", ",", "", "", 2); test_create_delimited_string (",,", ",", "", "", "", 3); test_create_delimited_string ("", "XXX", 0); static define test_str_delete_chars (str, del_set, ans) { variable s1 = str_delete_chars (str, del_set); if (ans != s1) failed ("str_delete_chars(\"%s\", \"%s\") --> \"%s\"", str, del_set, s1); variable a, b, b1, i = [1,3,4]; a = String_Type[5]; b = @a; a[i] = str; b[i] = ans; b1 = str_delete_chars (a, del_set); if (any(b1 != b)) failed ("str_delete_chars(\"%S\", \"%S\") --> \"%S\"", a, del_set, b1); } test_str_delete_chars ("abcdefg", "bdf", "aceg"); test_str_delete_chars ("abcdefg", "^bdf", "bdf"); test_str_delete_chars ("abcdefg", "bdfg", "ace"); test_str_delete_chars ("abcdefg", "ag", "bcdef"); test_str_delete_chars ("abcdefg", "^ag", "ag"); test_str_delete_chars ("abcdefg", "a-z", ""); test_str_delete_chars ("abcdefgABCDEF", "\l"R, "ABCDEF"); test_str_delete_chars ("abcdefgABCDEF", "^\l"R, "abcdefg"); test_str_delete_chars (",1,", `\,`, "1"); test_str_delete_chars (",", `\,`, ""); test_str_delete_chars ("1,", `\,`, "1"); test_str_delete_chars ("1,,,1", `\,`, "11"); test_str_delete_chars ("\\", "\\", ""); test_str_delete_chars ("\\n", "\\", "n"); test_str_delete_chars ("12,a,3,b", "\\a", "12,,3,"); test_str_delete_chars ("12\t,a\n, 3,b", "\\g", "\t\n "); test_str_delete_chars ("12\t,a\ng, 3,b", "\\x", "\t,\ng, ,"); static define test_strtrans (s, from, to, ans) { variable s1; try { s1 = strtrans (s, from, to); if (ans == NULL) failed ("Expected strtrans('%s', '%s', '%s') to fail", s, from, to); } catch AnyError: { if (ans == NULL) return; throw; } if (ans != s1) failed ("strtrans(%s, %s, %s) --> %s", s, from, to, s1); variable a, b, b1, i = [1,3,4]; a = String_Type[5]; b = @a; a[i] = s; b[i] = ans; b1 = strtrans (a, from, to); if (any(b1 != b)) failed ("strtrans(%S, %S, %S) --> %S", a, from, to, b1); if ((to == "X") && (from[0] != '^')) { % we can double the from and get the same result from = from + from; s1 = strtrans (s, from, to); if (ans != s1) failed ("strtrans(%s, \"%s\", \"%s\") --> \"%s\"", s, from, to, s1); to = "XX"; s1 = strtrans (s, from, to); if (ans != s1) failed ("strtrans(%s, \"%s\", \"%s\") --> \"%s\"", s, from, to, s1); } } test_strtrans ("hello world", "^a-zA-Z", "X", "helloXworld"); test_strtrans ("hello world", "^\a"R, "X", "helloXworld"); test_strtrans ("hello", "", "xxxx", "hello"); test_strtrans ("hello", "l", "", "heo"); test_strtrans ("hello", "helo", "abcd", "abccd"); test_strtrans ("hello", "hl", "X", "XeXXo"); test_strtrans ("", "hl", "X", ""); test_strtrans ("hello", "a-z", "A-Z", "HELLO"); test_strtrans ("he\\o"R, "\\\\", "x", "hexxo"); test_strtrans ("hello", "\l"R, "\u"R, "HELLO"); test_strtrans ("hello", "a-mn-z", "A-MN-Z", "HELLO"); test_strtrans ("hello", "a-mn-z", "\\u", "HELLO"); test_strtrans ("hello", "a-mn-z", "\\u\\l", "HELLo"); test_strtrans ("abcdefg", "a-z", "Z-A", "ZYXWVUT"); %test_strtrans ("hejklo", "k-l", "L---", "hejL-o"); test_strtrans ("hejklo", "k-l", "\\u", "hejKLo"); test_strtrans ("hello", "he", "-+", "-+llo"); test_strtrans ("hello", "", "", "hello"); test_strtrans ("hello", "helo", "", ""); test_strtrans ("hello", "o", "", "hell"); test_strtrans ("hello", "hlo", "", "e"); test_strtrans ("", "hlo", "", ""); test_strtrans ("HeLLo", "A-Ze", "", "o"); test_strtrans ("HeLLo", "^A-Z", "", "HLL"); test_strtrans ("HeLLo", "\\l\\u", "aA", "AaAAa"); test_strtrans ("He11o", "\l\u\d"R, "aAx", "Aaxxa"); test_strtrans (",1,", `\,`, "X", "X1X"); test_strtrans (",", `\,`, "X", "X"); test_strtrans ("1,", `\,`, "X", "1X"); test_strtrans ("1,,,1", `\,`, "X", "1XXX1"); test_strtrans ("\\", "\\", "X", "X"); test_strtrans ("\\n", "\\", "X", "Xn"); test_strtrans ("12,a,X3,b", "\\a", "X", "12,X,X3,X"); test_strtrans ("12\t,a\n, 3,b", "\\g", "X", "XX\tXX\nX XXX"); test_strtrans ("12\t,a\n, 3,b", "\\c", "X", "12X,aX, 3,b"); test_strtrans ("12\t,a\n, 3,b", "\\p", "X", "XX\tXX\nXXXXX"); test_strtrans ("12\t,a\n, 3,b", "\\b", "X", "12X,a\n,X3,b"); test_strtrans ("12\t,A\ng, 3,b", "\\x", "X", "XX\t,X\ng, X,X"); test_strtrans ("12\t,A\ng, 3,b", "\\w", "X", "XX\t,X\nX, X,X"); test_strtrans (",1,", "[:punct:]", "X", "X1X"); test_strtrans (",", "[:punct:]", "X", "X"); test_strtrans ("1,", "[:punct:]", "X", "1X"); test_strtrans ("1,,,1", "[:punct:]", "X", "1XXX1"); test_strtrans ("12,a,X3,b", "[:alpha:]", "X", "12,X,X3,X"); test_strtrans ("12\t,a\n, 3,b", "[:print:]", "X", "XX\tXX\nXXXXX"); test_strtrans ("12\t,a\n, 3,b", "[:blank:]", "X", "12X,a\n,X3,b"); test_strtrans ("12\t,a\n, 3,b", "[:graph:]", "X", "XX\tXX\nX XXX"); test_strtrans ("12\t,A\ng, 3,b", "[:xdigit:]", "X", "XX\t,X\ng, X,X"); #ifeval _slang_utf8_ok test_strtrans ("|\u{EF}\u{100}\u{80}|", "^\\7", "X", "|XXX|"); test_strtrans ("|\u{EF}\u{100}\u{80}|", "\\7", "X", "X\u{EF}\u{100}\u{80}X"); test_strtrans ("|\u{100}|", "^\\7", "X", "|X|"); test_strtrans ("|\u{FF}|", "\\7", "\u{1234}", "\u{1234}\u{FF}\u{1234}"); test_strtrans ("|\u{FF}|", "^\\7", "X", "|X|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\u{100}", "X", "|\u{FF}X\u{101}|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "^\u{100}\\7", "X", "|X\u{100}X|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "^\u{100}\\7", "\u{1000}", "|\u{1000}\u{100}\u{1000}|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\u{100}-\u{101}", "X", "|\u{FF}XX|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\u{FF}-\u{100}", "X", "|XX\u{101}|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\u{100}-\u{101}", "\u{FF}-\u{100}", "|\u{FF}\u{FF}\u{100}|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\u{100}-\u{101}", "\\u", "|\u{FF}\u{100}\u{100}|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\u{100}-\u{101}", "\\l", "|\u{FF}\u{101}\u{101}|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "^\\7", "\\u", "|\u{178}\u{100}\u{100}|"); test_strtrans ("|\u{1000}|", "^\\7", "\\l", "|\u{1000}|"); test_strtrans ("|\u{1000}|", "^\\7", "\\u", "|\u{1000}|"); test_strtrans ("|\u{1000}|", "\u{999}-\u{1000}", "\\u", "|\u{1000}|"); test_strtrans ("|\u{1000}|", "\u{999}-\u{1000}\u{2000}-\u{3000}", "\\u", "|\u{1000}|"); test_strtrans ("|\u{1000}|", "\u{7f}-\u{1500}\u{2000}", "", "||"); test_strtrans ("|\u{1000}x", "^\u{999}-\u{1000}", "\\u", "|\u{1000}X"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\u{100}-\u{101}", "\u{FF}-\u{100}", "|\u{FF}\u{FF}\u{100}|"); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\\c", "X", "|\u{FF}\u{100}\u{101}|"); % Bad cases test_strtrans ("|\u{FF}\u{100}\u{101}|", "^\u{100}-\u{101}", "\u{FF}-\u{100}", NULL); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\u{100}-\u{101}", "^\u{FF}-\u{100}", NULL); test_strtrans ("|\u{FF}\u{100}\u{101}|", "\u{100}-\u{101}", "\\7", NULL); private define test_long_range () { variable r1 = ""; variable r2 = ""; _for (1000, 1067, 1) { variable i = (); r1 = strcat (r1, char(i)); r2 = strcat (r2, char(i+1)); } test_strtrans (r1, r1, r2, r2); test_strtrans (r1, r2, "", substr(r1,1,1)); } test_long_range(); #endif test_strtrans (",1,", "[:Xpunct:]", "X", NULL); private define test_strcompress (str, white, ans) { variable ans1 = strcompress (str, white); if (ans != ans1) failed ("%S != %S = strcompress(%S, %S)", ans, ans1, str, white); variable a, b, b1, i = [1,3,4]; a = String_Type[5]; b = @a; a[i] = str; b[i] = ans; b1 = strcompress (a, white); if (any(b1 != b)) failed ("strcompress(%S, %S) --> %S", a, white, b1); } test_strcompress ("3)x", "_ #&<>\t()-", "3_x"); test_strcompress (" \t \tA\n\ntest\t", " \t\n", "A test"); test_strcompress ("../afoo/bfoo/cbard/ooohbhar/", "/", "../afoo/bfoo/cbard/ooohbhar"); define test_str_replace_all (a, b, c, result, n) { variable new; variable m; (new, m) = strreplace (a, b, c, n); if (new != result) failed ("strreplace (%s, %s, %s, %d) ==> %s!=%s", a, b, c, n, new, result); if (n == 1) { n = str_replace (a, b, c); !if (n) a; new = (); if (new != result) failed ("str_replace (%s, %s, %s) ==> %s!=", a, b, c, new, result); } } define test_str_replace (a, b, c, result, n) { variable new; variable m; (new, m) = strreplace (a, b, c, n); if (new != result) failed ("strreplace (%s, %s, %s, %d) ==> %s!=%s", a, b, c, n, new, result); if (n == 1) { n = str_replace (a, b, c); !if (n) a; new = (); if (new != result) failed ("str_replace (%s, %s, %s) ==> %s!=%S", a, b, c, new, result); } % Alternate interface variable new1 = strreplace (a, b, c); (new,) = strreplace (a, b, c, strbytelen (a)); if (new1 != new) failed ("str_replace (%s, %s, %s) ==> %s!=%s", a, b, c, new, new1); } test_str_replace ("a", "b", "x", "a", 1); test_str_replace ("a", "b", "x", "a", -1); test_str_replace ("a", "b", "x", "a", -10); test_str_replace ("a", "b", "x", "a", 10); test_str_replace ("a", "b", "x", "a", 0); test_str_replace ("blafoofbarfoobar", "", "xyyy", "blafoofbarfoobar", 0); test_str_replace ("blafoofbarfoobar", "", "xyyy", "blafoofbarfoobar", 1); test_str_replace ("blafoofbarfoobar", "", "xyyy", "blafoofbarfoobar", -1); test_str_replace ("blafoofbarfoobar", "", "xyyy", "blafoofbarfoobar", -10); test_str_replace ("blafoofbarfoobar", "foo", "XY", "blafoofbarfoobar", 0); test_str_replace ("blafoofbarfoobar", "foo", "XY", "blaXYfbarfoobar", 1); test_str_replace ("blafoofbarfoobar", "foo", "XY", "blaXYfbarXYbar", 2); test_str_replace ("blafoofbarfoobar", "foo", "XY", "blaXYfbarXYbar", 10); test_str_replace ("blafoofbarfoobar", "foo", "XY", "blafoofbarXYbar", -1); test_str_replace ("blafoofbarfoobar", "foo", "XY", "blaXYfbarXYbar", -2); test_str_replace ("blafoofbarfoobar", "r", "", "blafoofbarfoobar", 0); test_str_replace ("blafoofbarfoobar", "r", "", "blafoofbafoobar", 1); test_str_replace ("blafoofbarfoobar", "r", "", "blafoofbafooba", 2); test_str_replace ("blafoofbarfoobar", "r", "", "blafoofbarfooba", -1); test_str_replace ("blafoofbarfoobar", "r", "", "blafoofbafooba", -2); test_str_replace ("bla", "bla", "", "", -2); test_str_replace ("bla", "bla", "foo", "foo", -2); test_str_replace ("bla", "bla", "foo", "foo", 1); define test_strcat () { % This test generates a combined byte-code. It is used for leak checking variable a = "hello"; variable b = "world"; loop (20) { variable c = a + b; a = c; } } test_strcat (); static define test_str_uncomment_string (s, beg, end, result) { variable r = str_uncomment_string (s, beg, end); if (r != result) { failed ("str_uncomment_string(%s,%s,%s)==>%s!=%s", s, beg, end, r, result); } } test_str_uncomment_string ("Ab(cd)e", "(",")", "Abe"); test_str_uncomment_string ("(Ab(cd)e", "(",")", "e"); test_str_uncomment_string ("(Abcde)", "(",")", ""); test_str_uncomment_string ("(Ab[cde)[def]g", "([",")]", "g"); static define test_str_quote_string (str, qlis, quote, result) { variable r = str_quote_string (str, qlis, quote); if (r != result) { failed ("str_quote_string (%s,%s,%d)==>%s!=%s", str, qlis, quote, r, result); } } test_str_quote_string ("hello", "lh", 'X', "XheXlXlo"); #ifeval _slang_utf8_ok test_str_quote_string ("hel\u{1234}o", "lh\u{1234}", 0x2345, "\u{2345}he\u{2345}l\u{2345}\u{1234}o"); #endif private variable D, S; foreach D ([',', 0xAB, 0xABCD]) { if ((D > 0xFF) and (_slang_utf8_ok == 0)) continue; S = "foo0,bar1,baz2,,bing4,5,,,8,"; test_str_replace ((S, ",", sprintf ("%c", D), sprintf ("foo0%sbar1%sbaz2%s%sbing4%s5%s%s%s8%s", char(D),char(D),char(D),char(D),char(D),char(D), char(D),char(D),char(D)), strlen (S))); (S,) = strreplace (S, ",", sprintf ("%c", D), strlen (S)); test (&extract_element,(S,0,,D,), "foo0"); test (&extract_element,(S,1,,D,), "bar1"); test (&extract_element,(S,3,,D,), ""); test (&extract_element,(S,4,,D,), "bing4"); test (&extract_element,(S,5,,D,), "5"); test (&extract_element,(S,6,,D,), ""); test (&extract_element,(S,7,,D,), ""); test (&extract_element,(S,8,,D,), "8"); test (&extract_element,(S,9,,D,), ""); test(&is_list_element, (S, "bar1", ,D,), 1+1); test(&is_list_element, (S, "goo", ,D,), 0); test(&is_list_element, (S, "8", ,D,), 8+1); test(&is_list_element, (S, "", ,D,), 3+1); S = ",1,"; (S,) = strreplace (S, ",", sprintf ("%c", D), strlen (S)); test (&extract_element,(S,0,,D,), ""); test (&extract_element,(S,1,,D,), "1"); test (&extract_element,(S,2,,D,), ""); S = ""; (S,) = strreplace (S, ",", sprintf ("%c", D), strlen (S)); test (&extract_element,(S,0,,D,), ""); test (&extract_element,(S,1,,D,), NULL); S = ",1"; (S,) = strreplace (S, ",", sprintf ("%lc", D), strlen (S)); test (&extract_element,(S,0,,D,), ""); test (&extract_element,(S,1,,D,), "1"); } static define test_strncmp (a, b, n, ans) { variable ans1 = strncmp (a, b, n); if (ans1 != ans) failed ("strncmp (%s,%s,%s)", a, b, n); variable aa, bb; aa = [a,a,a], bb = b; ans1 = strncmp (aa, bb, n); if ((length (ans1) != length (aa)) || not all (ans1 == ans)) failed ("%S = strncmp (%S, %S, %S)", ans1, aa, bb, n); aa = a, bb = [b,b]; ans1 = strncmp (aa, bb, n); if ((length (ans1) != length (bb)) || not all (ans1 == ans)) failed ("%S = strncmp (%S, %S, %S)", ans1, aa, bb, n); aa = [a,a,a,a], bb = [b,b,b,b]; ans1 = strncmp (aa, bb, n); if ((length (ans1) != length (aa)) || not all (ans1 == ans)) failed ("%S = strncmp (%S, %S, %S)", ans1, aa, bb, n); } test_strncmp ("ignore_all", "ign", 3, 0); test_strncmp ("ign", "ignore_all", 3, 0); static define test_strnbytecmp (a, b, n, ans) { variable ans1 = strnbytecmp (a, b, n); if (ans1 != ans) failed ("strnbytecmp (%s,%s,%s)", a, b, n); variable aa, bb; aa = [a,a,a], bb = b; ans1 = strnbytecmp (aa, bb, n); if ((length (ans1) != length (aa)) || not all (ans1 == ans)) failed ("%S = strnbytecmp (%S, %S, %S)", ans1, aa, bb, n); aa = a, bb = [b,b]; ans1 = strnbytecmp (aa, bb, n); if ((length (ans1) != length (bb)) || not all (ans1 == ans)) failed ("%S = strnbytecmp (%S, %S, %S)", ans1, aa, bb, n); aa = [a,a,a,a], bb = [b,b,b,b]; ans1 = strnbytecmp (aa, bb, n); if ((length (ans1) != length (aa)) || not all (ans1 == ans)) failed ("%S = strnbytecmp (%S, %S, %S)", ans1, aa, bb, n); aa = String_Type[0]; bb = b; ans1 = strnbytecmp (aa, bb, n); if (length (ans1) != length (aa)) failed ("%S = strnbytecmp (%S, %S, %S)", ans1, aa, bb, n); } test_strnbytecmp ("ignore_all", "ign", 3, 0); test_strnbytecmp ("ign", "ignore_all", 3, 0); static define test_strcmp (a, b, ans) { variable ans1 = sign(strcmp (a, b)); if (ans1 != ans) failed ("strcmp (%s,%s)", a, b); variable aa, bb; aa = [a,a,a], bb = b; ans1 = sign(strcmp (aa, bb)); if ((length (ans1) != length (aa)) || not all (ans1 == ans)) failed ("%S = strcmp (%S, %S)", ans1, aa, bb); aa = a, bb = [b,b]; ans1 = sign(strcmp (aa, bb)); if ((length (ans1) != length (bb)) || not all (ans1 == ans)) failed ("%S = strcmp (%S, %S)", ans1, aa, bb); aa = [a,a,a,a], bb = [b,b,b,b]; ans1 = sign(strcmp (aa, bb)); if ((length (ans1) != length (aa)) || not all (ans1 == ans)) failed ("%S = strcmp (%S, %S)", ans1, aa, bb); } test_strcmp ("ignore_all", "ign", 1); test_strcmp ("ign", "ignore_all", -1); test_strcmp ("silly", "silly", 0); private define test_strchop (s, d, len, nth, nth_val) { variable a = strchop (s, d, 0); if (length (a) != len) failed ("strchop (%S,%S,0) ==> %S", s,d,a); if (a[nth] != nth_val) failed ("strchop (%S,%S,0)[%d] ==> %S, not %S", s,d,nth,a[nth],nth_val); variable b = strchopr (s, d, 0); ifnot (_eqs (b[[-1::-1]], a)) failed ("strchopr (%S,%S,0)", s,d); } test_strchop ("{{{\r}}}\r\rX", '\r', 4, 0, "{{{"); test_strchop ("{{{\r}}}\r\rX", '\r', 4, 1, "}}}"); test_strchop ("{{{\r}}}\r\rX", '\r', 4, 2, ""); test_strchop ("{{{\r}}}\r\rX", '\r', 4, 3, "X"); test_strchop ("\r{{{\r}}}\r\rX", '\r', 5, 0, ""); test_strchop ("\r{{{\r}}}\r\rX", '\r', 5, 1, "{{{"); test_strchop ("", '\r', 1, 0, ""); test_strchop ("\r", '\r', 2, 0, ""); test_strchop ("\r", '\r', 2, 1, ""); static define test_substr (fun, s, n, len, ret) { variable ret1 = (@fun) (s, n, len); if (ret1 != ret) failed ("$fun($s,$n,$len)==>$ret1 not $ret"$); } test_substr (&substr, "To be or not to be", 7, 5, "or no"); test_substr (&substr, "", 1, -1, ""); test_substr (&substr, "A", 1, -1, "A"); test_substr (&substr, "A", 1, 0, ""); test_substr (&substr, "A", 2, 1, ""); test_substr (&substrbytes, "To be or not to be", 7, 5, "or no"); test_substr (&substrbytes, "", 1, -1, ""); test_substr (&substrbytes, "A", 1, -1, "A"); test_substr (&substrbytes, "A", 1, 0, ""); test_substr (&substrbytes, "A", 2, 1, ""); static define test_strsub (fun, s, pos, ch, ret) { variable ret1 = (@fun)(s, pos, ch); if (ret1 != ret) failed ("$fun($s,$pos,$ch) ==> $ret1 not $ret"$); } test_strsub (&strsub, "A", 1, 0, ""); test_strsub (&strsub, "AB", 1, 'a', "aB"); test_strsub (&strsub, "AB", 2, 0, "A"); test_strsub (&strbytesub, "A", 1, 0, ""); test_strsub (&strbytesub, "AB", 1, 'a', "aB"); test_strsub (&strbytesub, "AB", 2, 0, "A"); private define test_foreach () { variable X = "ab\xAA\x{BB}"; variable utf8_X = {'a', 'b', -0xAA, 0xBB}; % Note that \x{BB} varies according to the UTF-8 mode variable xi; foreach xi (X) { if (typeof (xi) != UChar_Type) failed ("foreach (String_Type) failed to produce UChar_Types"); } foreach (X) using ("bytes") { xi = (); if (typeof (xi) != UChar_Type) failed ("foreach (String_Type) using bytes failed to produce UChar_Types"); } variable i = 0; foreach xi (X) using ("chars") { if (_slang_utf8_ok) { if (xi != utf8_X[i]) failed ("foreach (String_Type) using chars failed at i=%d", i); } else if (xi != X[i]) failed ("foreach (String_Type) using chars failed at i=%d", i); i++; } } test_foreach (); define test_char (c, s) { variable cs = char (c); variable ss = sprintf ("%b", -c); if (s != cs) failed ("char(%d) ==> %s, not %s as expected", c, cs, s); if (s != ss) failed ("sprintf using %%b with %d ==> %s, not %s as expected", -c, cs, s); } test_char (-0x78, "\x78"); test_char (-0xAB, "\xAB"); #ifexists Double_Type foreach $1 ([0,1,2,5,10,20,50,100,200,500,1000,2000,5000]) { () = sprintf ("%f", 10^$1); () = sprintf ("%f", -10^$1); () = sprintf ("%f", 10^-$1); () = sprintf ("%f", -10^-$1); } #endif define test_count_occur (func, s, ch, ans) { variable n = (@func) (s, ch); if (ans != n) { failed ("%S failed on %s: expected %u, got %u", func, s, ans, n); } } test_count_occur (&count_char_occurrences, "", 'A', 0); test_count_occur (&count_char_occurrences, "A", 'A', 1); test_count_occur (&count_char_occurrences, " A", 'A', 1); test_count_occur (&count_char_occurrences, "A ", 'A', 1); test_count_occur (&count_char_occurrences, "A A", 'A', 2); test_count_occur (&count_char_occurrences, "A A ", 'A', 2); test_count_occur (&count_byte_occurrences, "", 'A', 0); test_count_occur (&count_byte_occurrences, "A", 'A', 1); test_count_occur (&count_byte_occurrences, " A\0", 'A', 1); test_count_occur (&count_byte_occurrences, "A ", 'A', 1); test_count_occur (&count_byte_occurrences, "A \0A", 'A', 2); test_count_occur (&count_byte_occurrences, "A \0 A ", 'A', 2); if (_slang_utf8_ok) { test_count_occur (&count_char_occurrences, "", 0xFF, 0); test_count_occur (&count_char_occurrences, "\u{00FF}", 0xFF, 1); test_count_occur (&count_char_occurrences, " \u{00FF}", 0xFF, 1); test_count_occur (&count_char_occurrences, "\u{00FF} ", 0xFF, 1); test_count_occur (&count_char_occurrences, "\u{00FF} \u{00FF}", 0xFF, 2); test_count_occur (&count_char_occurrences, "\u{00FF} \u{00FF} ", 0xFF, 2); } private define test_strskipbytes (args, ans) { variable n1 = strskipbytes (__push_list(args)); if (n1 != ans) { failed ("strskipbytes failed, expected %d, got %d", ans, n1); } } test_strskipbytes ({"abc def", "a-z", 4}, 7); test_strskipbytes ({"abc def", "a-z", 4, -1}, 6); test_strskipbytes ({"abc def", "a-z"}, 3); test_strskipbytes ({"abc def", "a-z", 0}, 3); test_strskipbytes ({"abc def", "a-z", 1}, 3); test_strskipbytes ({"abc def", "a-z", 2}, 3); test_strskipbytes ({"abc def", "a-z", 3}, 3); test_strskipbytes ({"abc def", "a-z", 5}, 7); test_strskipbytes ({"abc def", "a-z", 6}, 7); test_strskipbytes ({"abc def", "a-z", 7}, 7); test_strskipbytes ({"abc def", "a-z", 0, 0}, 0); test_strskipbytes ({"abc def", "a-z", 0, 1}, 1); test_strskipbytes ({"abc def", "a-z", 0, 2}, 2); test_strskipbytes ({"abc def", "a-z", 0, 4}, 3); test_strskipbytes ({"abc def", "a-z", 0, -1}, 3); test_strskipbytes ({"abc def", "a-z", -3, -1}, 6); private define test_strup (a, b) { variable c = strup (a); if (b != c) failed ("strup %s produced %s, expected %s", a, c, b); a = [a, a+a, a+a+a]; b = [b, b+b, b+b+b]; c = strup (a); ifnot (_eqs (b, c)) failed ("strup on an array"); ifnot (_eqs (String_Type[0], strup(String_Type[0]))) failed ("strup on empty array"); } test_strup("", ""); test_strup("a", "A"); test_strup("ab", "AB"); test_strup("abC", "ABC"); private define test_strlow (a, b) { variable c = strlow (a); if (b != c) failed ("strlow %s produced %s", a, c); a = [a, a+a, a+a+a]; b = [b, b+b, b+b+b]; c = strlow (a); ifnot (_eqs (b, c)) failed ("strlow on an array"); ifnot (_eqs (String_Type[0], strlow(String_Type[0]))) failed ("strlow on empty array"); } test_strlow("", ""); test_strlow("A", "a"); test_strlow("AB", "ab"); test_strlow("ABc", "abc"); private define test_strlen (func, s, ans) { variable ans1 = (@func)(s); if (ans1 != ans) failed ("%S != %S = %S (%S)", ans, ans1, func, s); variable ss = [s,s,s,s]; ans1 = (@func)(ss); if (all (ans1 != ans)) failed ("%S != %S = %S (%S)", ans, ans1, func, s); ans = Int_Type[5] + ans; ans[1] = 0; ans[-1] = 0; ss = String_Type[5]; ss[[0,2,3]] = s; ans1 = (@func)(ss); if (all (ans1 != ans)) failed ("%S != %S = %S (%S)", ans, ans1, func, s); } test_strlen (&strlen, "foobar", 6); test_strlen (&strbytelen, "foobar", 6); test_strlen (&strcharlen, "foobar", 6); private define test_strtrim (func, in, out, white) { variable out1; variable a, b, b1; if (white == NULL) { out1 = (@func)(in); if (out != out1) failed ("%S != %S = %S(%S)", out, out1, func, in); a = [in, in, in]; b = [out, out, out]; b1 = (@func)(a); if (any(b != b1)) failed ("%S != %S = %S(%S)", b, b1, func, a); return; } out1 = (@func)(in, white); if (out != out1) failed ("%S != %S = %S(%S,%S)", out, out1, func, in, white); a = String_Type[5]; b = String_Type[5]; a[[1,3,4]] = in; b[[1,3,4]] = out; b1 = (@func)(a, white); if (any(b != b1)) failed ("%S != %S = %S(%S,%S)", b, b1, func, a, white); } $1 = " \t hello world\n\t"; test_strtrim (&strtrim, $1, "hello world", NULL); test_strtrim (&strtrim_beg, $1, "hello world\n\t", NULL); test_strtrim (&strtrim_end, $1, " \t hello world", NULL); test_strtrim (&strtrim, $1, "hello wor", " \t\nld"); #ifeval _slang_utf8_ok test_strtrim (&strtrim, "\u{FF}X\u{FF}Y\u{100}", "X\u{FF}Y", "\u{FF}\u{100}"); test_strtrim (&strtrim, "\u{FF}X\u{FF}Y\u{100}", "X\u{FF}Y", "\u{FF}-\u{100}"); test_strtrim (&strtrim, "\u{FF}X\u{FF}Y\u{100}", "\u{FF}X\u{FF}Y", "\u{100}-\u{101}"); test_strtrim (&strtrim, "\u{FF}X\u{FF}Y\u{100}\u{101}", "X\u{FF}Y\u{100}\u{101}", "\u{FF}-\u{100}"); test_strtrim (&strtrim, "\u{FF}X\u{FF}Y\u{100}\u{101}", "\u{FF}X\u{FF}Y\u{100}", "^\u{FF}-\u{100}"); test_strtrim (&strtrim, "\u{FF}X\u{FF}Y\u{100}", "X\u{FF}Y", "^\\7"); #endif private define test_strtrim_bad () { try { () = strtrim ("asasasc", "\\n"); % --> \ + n is invalid character class failed ("%s", "Expected strtrim to choke on invalid char class"); } catch InvalidParmError; } test_strtrim_bad (); private define test_string_to_wchars (str, ans) { ifnot (_eqs (ans, string_to_wchars (str))) { failed ("string_to_wchars (%S)", str); } ifnot (_eqs (str, wchars_to_string (ans))) { failed ("wchars_to_string: expected to produce %S", str); } ans = [random_integer(1024), random_integer(1024)-255, random_integer(1024), random_integer(1024), random_integer(1024), random_integer(1024)-255]; ans[where(-127 <= ans <= 0)] += 512; str = wchars_to_string (ans); variable ans1 = string_to_wchars(str); if (_eqs (ans, ans1)) return; variable msg = ""; if (length(ans) == length(ans1)) { msg = "\n"; _for (0, length(ans)-1, 1) { variable i = (); msg = sprintf ("%s%d: in=%d, out=%d\n", msg, i, ans[i], ans1[i]); } } failed ("string_to_wchars <-> wchars_to_string: %S -> %S -> %S%S", ans, str, ans1, msg); } test_string_to_wchars ("", Int_Type[0]); test_string_to_wchars ("a", ['a']); test_string_to_wchars ("\xEE", [-0xEE]); test_string_to_wchars ("\u{1234}", [0x1234]); test_string_to_wchars ("a\xEE", ['a', -0xEE]); test_string_to_wchars ("\xEEa", [-0xEE, 'a']); test_string_to_wchars ("\xEE\u{1234}", [-0xEE, 0x1234]); test_string_to_wchars ("\u{1234}\xEE", [0x1234, -0xEE]); test_string_to_wchars ("\u{1234}\xEEa", [0x1234, -0xEE, 'a']); test_string_to_wchars ("b\u{1234}\xEEa", ['b', 0x1234, -0xEE, 'a']); test_string_to_wchars ("b\u{1234}\u{EE}\xEEa", ['b', 0x1234, 0xEE, -0xEE, 'a']); private define _string_to_array (str) { variable n = strcharlen (str); variable a = ULong_Type[n]; variable p = 0; _for (0, n-1, 1) { variable i = (); variable wch; (p, a[i]) = strskipchar (str, p, 0); } return a; } private define string_to_array_b (str) { variable n = strcharlen (str); variable a = ULong_Type[n]; variable p = strbytelen (str); _for (n-1, 0, -1) { variable i = (); variable wch; (p, a[i]) = strbskipchar (str, p, 0); } return a; } private define test_wchar_funcs () { variable str = "123";%ABCdef"; variable i; _for i (225, 260, -1) str = strcat (str, char(i), char(10*i)); variable astr = string_to_array_b (str); variable lstr = _string_to_array (strlow (str)); variable ustr = _string_to_array (strup (str)); _for i (0, strcharlen(str)-1, 1) { variable wch = astr[i]; if ((isupper (wch)) && (wch != ustr[i])) failed ("isupper"); if (islower (wch) && (wch != lstr[i])) failed ("islower"); if (tolower (wch) != lstr[i]) failed ("tolower"); if (toupper (wch) != ustr[i]) failed ("toupper"); } variable s = char (32), d = '1', p = ','; if ((0 == isspace(s)) || isspace (d)) failed ("ispace"); if ((0 == isblank(s)) || isblank (d)) failed ("isblank"); if ((0 == ispunct (p)) || ispunct (d)) failed ("ispunct"); if ((0 == iscntrl (1)) || iscntrl (' ')) failed ("iscntrl"); if ((0 == isxdigit (d)) || isxdigit ('g')) failed ("isxdigit"); if ((0 == isgraph ("x")) || isgraph (' ')) failed ("isgraph"); if ((0 == isprint (' ')) || isprint (1)) failed ("isprint"); if ((0 == isascii (' ')) || isascii (255)) failed ("isascii"); if ((0 == isalpha ('a')) || isalpha ('6')) failed ("isalpha"); if ((0 == isalnum ('6')) || isalnum ('/')) failed ("isalnum"); } test_wchar_funcs (); if (any (typecast (["foo", "", NULL, "bar"], Int_Type) != ['f',0,0,'b'])) failed ("typecast of string[] to integer"); private define test_string_sort () { variable a = ["1", "2", "3", "33", "22", "11"]; variable i = array_sort (a); if (any (i != [0,5,1,4,2,3])) failed ("string sort"); } test_string_sort (); #ifexists Double_Type private define test_get_set_float_format (fmt, x) { variable dfmt = get_float_format (); set_float_format (fmt); if (string (x) != sprintf (fmt, x)) failed ("set_float_format %S", fmt); set_float_format (dfmt); } test_get_set_float_format ("%e", PI); test_get_set_float_format ("%f", PI); test_get_set_float_format ("%g", PI); test_get_set_float_format ("%+ f", PI); test_get_set_float_format ("%+f", PI); test_get_set_float_format ("%+.5f", PI); test_get_set_float_format ("%+3.5f", PI); test_get_set_float_format ("% 3.5f", PI); #endif private define test_sprintf (fmt, x, ans) { foreach ([Char_Type, UChar_Type, Short_Type, UShort_Type, Int_Type, UInt_Type, Long_Type, ULong_Type, #ifexists LLong_Type LLong_Type, ULLong_Type #endif ]) { variable t = (); if (ans != sprintf (fmt, typecast (x, t))) failed ("%S != sprintf (%S, (%S)%x)", ans, fmt, t); } } test_sprintf ("%B", 7, "111"); test_sprintf ("%5B", 7, " 111"); test_sprintf ("%5.5B", 7, "00111"); test_sprintf ("%.7B", 7, "0000111"); test_sprintf ("%8.7B", 7, " 0000111"); % Reuse function name private define test_sprintf () { variable c = typecast (-55, Char_Type); variable u = typecast (-55, UChar_Type); variable cs = sprintf ("%c", c); variable us = sprintf ("%c", u); if (us != cs) failed ("sprintf %%c with signed and unsigned char"); variable ans = " 6"; variable s = sprintf ("%*d", 4, 6); if (s != ans) failed ("sprintf (%%*d, 4, 6) ==> \"%S\", expected \"%S\"", s, ans); ans = "0006"; if (ans != sprintf ("%0*d", 4, 6)) failed ("sprintf (%%0*d, 4, 6)"); } test_sprintf (); private define test_issubstr () { variable a = String_Type[4]; a[2] = "foobar"; a[3] = "oo"; variable i = where(is_substr (a, "foo")); ifnot (_eqs (i, [2])) failed ("test_issubstr: foo"); i = where (is_substr ("oo", a)); ifnot (_eqs (i, [3])) failed ("test_issubstr: oo"); } test_issubstr (); print ("Ok\n"); exit (0);