X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/2398a6a73fafe52e34a8aa158cb1003a30bf31f1..f4206a23cb0e9c218713ca1a0c980b9c65ff4710:/src/xbt/xbt_str.c diff --git a/src/xbt/xbt_str.c b/src/xbt/xbt_str.c index 399b9ad4ea..b2593e5f1f 100644 --- a/src/xbt/xbt_str.c +++ b/src/xbt/xbt_str.c @@ -191,14 +191,21 @@ void xbt_str_subst(char *str, char from, char to, int occurence) /** @brief Replaces a set of variables by their values * - * @param str where to apply the change - * @param patterns what to change + * @param str The input of the replacement process + * @param patterns The changes to apply * @return The string modified * - * Check xbt_strbuff_varsubst() for more details, and remember that the string may be reallocated (moved) in the process. + * Both '$toto' and '${toto}' are valid (and the two writing are equivalent). + * + * If the variable name contains spaces, use the brace version (ie, ${toto tutu}) + * + * You can provide a default value to use if the variable is not set in the dict by using + * '${var:=default}' or '${var:-default}'. These two forms are equivalent, even if they + * shouldn't to respect the shell standard (:= form should set the value in the dict, + * but does not) (BUG). */ -char *xbt_str_varsubst(char *str, xbt_dict_t patterns) +char *xbt_str_varsubst(const char *str, xbt_dict_t patterns) { xbt_strbuff_t buff = xbt_strbuff_new_from(str); char *res; @@ -572,11 +579,10 @@ static XBT_INLINE int diff_get(xbt_matrix_t C, int i, int j) return (i == -1 || j == -1) ? 0 : xbt_matrix_get_as(C, i, j, int); } -static xbt_matrix_t diff_build_LCS(xbt_dynar_t da, xbt_dynar_t db) +static xbt_matrix_t diff_build_LCS(xbt_dynar_t da, xbt_dynar_t db, + int len_a, int len_b) { - xbt_matrix_t C = - xbt_matrix_new(xbt_dynar_length(da), xbt_dynar_length(db), - sizeof(int), NULL); + xbt_matrix_t C = xbt_matrix_new(len_a, len_b, sizeof(int), NULL); int i, j; /* Compute the LCS */ @@ -595,8 +601,8 @@ static xbt_matrix_t diff_build_LCS(xbt_dynar_t da, xbt_dynar_t db) C[i,j] := max(C[i,j-1], C[i-1,j]) return C[m,n] */ - for (i = 0; i < (int)xbt_dynar_length(da); i++) - for (j = 0; j < (int)xbt_dynar_length(db); j++) { + for (i = 0; i < len_a; i++) + for (j = 0; j < len_b; j++) { if (!strcmp(xbt_dynar_get_as(da, i, char *), xbt_dynar_get_as(db, j, char *))) @@ -654,32 +660,55 @@ char *xbt_str_diff(const char *a, const char *b) xbt_dynar_t diff; char *res; size_t len; + unsigned length_da; + + diff = xbt_dynar_new(sizeof(char *), &xbt_free_ref); /* Clean empty lines at the end of da and db */ len = strlen(a); - if (len > 0 && a[len - 1] == '\n') { - char *str; - xbt_dynar_pop(da, &str); - free(str); - } + if (len > 0 && a[len - 1] == '\n') + xbt_dynar_pop(da, NULL); len = strlen(b); - if (len > 0 && b[len - 1] == '\n') { - char *str; - xbt_dynar_pop(db, &str); - free(str); + if (len > 0 && b[len - 1] == '\n') + xbt_dynar_pop(db, NULL); + + /* Find the common suffix, do it before extracting the prefix, + * as xbt_dynar_pop costs less than xbt_dynar_shift */ + length_da = xbt_dynar_length(da); + while (length_da > 0 && xbt_dynar_length(db) > 0 && + !strcmp(xbt_dynar_get_as(da, length_da - 1, char *), + xbt_dynar_getlast_as(db, char *))) { + xbt_dynar_pop(db, NULL); + length_da--; } - C = diff_build_LCS(da, db); - diff = xbt_dynar_new(sizeof(char *), &xbt_free_ref); + /* Extract the common prefix */ + while (length_da > 0 && xbt_dynar_length(db) > 0 && + !strcmp(xbt_dynar_getfirst_as(da, char *), + xbt_dynar_getfirst_as(db, char *))) { + char *topush = bprintf(" %s", xbt_dynar_getfirst_as(da, char *)); + xbt_dynar_push(diff, &topush); + xbt_dynar_shift(da, NULL); + xbt_dynar_shift(db, NULL); + length_da--; + } - diff_build_diff(diff, C, da, db, xbt_dynar_length(da) - 1, - xbt_dynar_length(db) - 1); - res = xbt_str_join(diff, "\n"); + /* Compute the diff for the remaining */ + C = diff_build_LCS(da, db, length_da, xbt_dynar_length(db)); + diff_build_diff(diff, C, da, db, length_da - 1, xbt_dynar_length(db) - 1); + xbt_matrix_free(C); + xbt_dynar_free(&db); + /* Add the common suffix */ + for (; length_da < xbt_dynar_length(da); length_da++) { + char *topush = bprintf(" %s", xbt_dynar_get_as(da, length_da, char *)); + xbt_dynar_push(diff, &topush); + } xbt_dynar_free(&da); - xbt_dynar_free(&db); + + /* Build the final result */ + res = xbt_str_join(diff, "\n"); xbt_dynar_free(&diff); - xbt_matrix_free(C); return res; } @@ -765,10 +794,11 @@ XBT_TEST_UNIT("xbt_str_split_str", test_split_str, "test the function xbt_str_sp mytest_str("Basic test", "toto##tutu", "##", "totoXXXtutu"); } -#define mytest_diff(name, s1, s2, diff) \ +/* Last args are format string and parameters for xbt_test_add */ +#define mytest_diff(s1, s2, diff, ...) \ do { \ char *mytest_diff_res; \ - xbt_test_add(name); \ + xbt_test_add(__VA_ARGS__); \ mytest_diff_res = xbt_str_diff(s1, s2); \ xbt_test_assert(!strcmp(mytest_diff_res, diff), \ "Wrong output:\n--- got:\n%s\n--- expected:\n%s\n---", \ @@ -781,58 +811,57 @@ XBT_TEST_UNIT("xbt_str_diff", test_diff, "test the function xbt_str_diff") unsigned i; /* Trivial cases */ - mytest_diff("1 word, no difference", "a", "a", " a"); - mytest_diff("1 word, different", "a", "A", "- a\n+ A"); - mytest_diff("1 line, no difference", "a\n", "a\n", " a"); - mytest_diff("1 line, different", "a\n", "A\n", "- a\n+ A"); + mytest_diff("a", "a", " a", "1 word, no difference"); + mytest_diff("a", "A", "- a\n+ A", "1 word, different"); + mytest_diff("a\n", "a\n", " a", "1 line, no difference"); + mytest_diff("a\n", "A\n", "- a\n+ A", "1 line, different"); /* Empty strings */ - mytest_diff("empty strings", "", "", ""); - mytest_diff("1 word, added", "", "a", "+ a"); - mytest_diff("1 word, removed", "a", "", "- a"); - mytest_diff("1 line, added", "", "a\n", "+ a"); - mytest_diff("1 line, removed", "a\n", "", "- a"); - mytest_diff("4 lines, all added", "", "a\nb\nc\n", "+ a\n+ b\n+ c"); - mytest_diff("4 lines, all removed", "a\nb\nc\n", "", "- a\n- b\n- c"); + mytest_diff("", "", "", "empty strings"); + mytest_diff("", "a", "+ a", "1 word, added"); + mytest_diff("a", "", "- a", "1 word, removed"); + mytest_diff("", "a\n", "+ a", "1 line, added"); + mytest_diff("a\n", "", "- a", "1 line, removed"); + mytest_diff("", "a\nb\nc\n", "+ a\n+ b\n+ c", "4 lines, all added"); + mytest_diff("a\nb\nc\n", "", "- a\n- b\n- c", "4 lines, all removed"); /* Empty lines */ - mytest_diff("empty lines", "\n", "\n", " "); - mytest_diff("empty line, added", "", "\n", "+ "); - mytest_diff("empty line, removed", "\n", "", "- "); - - mytest_diff("empty line added before word", "a", "\na", "+ \n a"); - mytest_diff("empty line added after word", "a", "a\n\n", " a\n+ "); - mytest_diff("empty line removed before word", "\na", "a", "- \n a"); - mytest_diff("empty line removed after word", "a\n\n", "a", " a\n- "); - - mytest_diff("empty line added before line", "a\n", "\na\n", "+ \n a"); - mytest_diff("empty line added after line", "a\n", "a\n\n", " a\n+ "); - mytest_diff("empty line removed before line", "\na\n", "a\n", "- \n a"); - mytest_diff("empty line removed after line", "a\n\n", "a\n", " a\n- "); - - mytest_diff("empty line added before 4 lines", - "a\nb\nc\nd\n", "\na\nb\nc\nd\n", "+ \n a\n b\n c\n d"); - mytest_diff("empty line added after 4 lines", - "a\nb\nc\nd\n", "a\nb\nc\nd\n\n", " a\n b\n c\n d\n+ "); - mytest_diff("empty line removed before 4 lines", - "\na\nb\nc\nd\n", "a\nb\nc\nd\n", "- \n a\n b\n c\n d"); - mytest_diff("empty line removed after 4 lines", - "a\nb\nc\nd\n\n", "a\nb\nc\nd\n", " a\n b\n c\n d\n- "); + mytest_diff("\n", "\n", " ", "empty lines"); + mytest_diff("", "\n", "+ ", "empty line, added"); + mytest_diff("\n", "", "- ", "empty line, removed"); + + mytest_diff("a", "\na", "+ \n a", "empty line added before word"); + mytest_diff("a", "a\n\n", " a\n+ ", "empty line added after word"); + mytest_diff("\na", "a", "- \n a", "empty line removed before word"); + mytest_diff("a\n\n", "a", " a\n- ", "empty line removed after word"); + + mytest_diff("a\n", "\na\n", "+ \n a", "empty line added before line"); + mytest_diff("a\n", "a\n\n", " a\n+ ", "empty line added after line"); + mytest_diff("\na\n", "a\n", "- \n a", "empty line removed before line"); + mytest_diff("a\n\n", "a\n", " a\n- ", "empty line removed after line"); + + mytest_diff("a\nb\nc\nd\n", "\na\nb\nc\nd\n", "+ \n a\n b\n c\n d", + "empty line added before 4 lines"); + mytest_diff("a\nb\nc\nd\n", "a\nb\nc\nd\n\n", " a\n b\n c\n d\n+ ", + "empty line added after 4 lines"); + mytest_diff("\na\nb\nc\nd\n", "a\nb\nc\nd\n", "- \n a\n b\n c\n d", + "empty line removed before 4 lines"); + mytest_diff("a\nb\nc\nd\n\n", "a\nb\nc\nd\n", " a\n b\n c\n d\n- ", + "empty line removed after 4 lines"); /* Missing newline at the end of one of the strings */ - mytest_diff("1 line, 1 word, no difference", "a\n", "a", " a"); - mytest_diff("1 word, 1 line, no difference", "a", "a\n", " a"); - mytest_diff("1 line, 1 word, different", "a\n", "A", "- a\n+ A"); - mytest_diff("1 word, 1 line, different", "a", "A\n", "- a\n+ A"); + mytest_diff("a\n", "a", " a", "1 line, 1 word, no difference"); + mytest_diff("a", "a\n", " a", "1 word, 1 line, no difference"); + mytest_diff("a\n", "A", "- a\n+ A", "1 line, 1 word, different"); + mytest_diff("a", "A\n", "- a\n+ A", "1 word, 1 line, different"); - mytest_diff("4 lines, no newline on first", - "a\nb\nc\nd", "a\nb\nc\nd\n", " a\n b\n c\n d"); - mytest_diff("4 lines, no newline on second", - "a\nb\nc\nd\n", "a\nb\nc\nd", " a\n b\n c\n d"); + mytest_diff("a\nb\nc\nd", "a\nb\nc\nd\n", " a\n b\n c\n d", + "4 lines, no newline on first"); + mytest_diff("a\nb\nc\nd\n", "a\nb\nc\nd", " a\n b\n c\n d", + "4 lines, no newline on second"); /* Four lines, all combinations of differences */ for (i = 0 ; i < (1U << 4) ; i++) { - char descr[80]; char d2[4 + 1]; char s2[4 * 2 + 1]; char res[4 * 8 + 1]; @@ -858,13 +887,12 @@ XBT_TEST_UNIT("xbt_str_diff", test_diff, "test the function xbt_str_diff") } *pd = '\0'; *--pr = '\0'; /* strip last '\n' from expected result */ - sprintf(descr, "compare (abcd) with changed (%s)", d2); - mytest_diff(descr, "a\nb\nc\nd\n", s2, res); + mytest_diff("a\nb\nc\nd\n", s2, res, + "compare (abcd) with changed (%s)", d2); } /* Subsets of four lines, do not test for empty subset */ for (i = 1 ; i < (1U << 4) ; i++) { - char descr[80]; char d2[4 + 1]; char s2[4 * 2 + 1]; char res[4 * 8 + 1]; @@ -884,14 +912,14 @@ XBT_TEST_UNIT("xbt_str_diff", test_diff, "test the function xbt_str_diff") } *pd = '\0'; *--pr = '\0'; /* strip last '\n' from expected result */ - sprintf(descr, "compare (abcd) with subset (%s)", d2); - mytest_diff(descr, "a\nb\nc\nd\n", s2, res); + mytest_diff("a\nb\nc\nd\n", s2, res, + "compare (abcd) with subset (%s)", d2); for (pr = res ; *pr != '\0' ; pr++) if (*pr == '-') *pr = '+'; - sprintf(descr, "compare subset (%s) with (abcd)", d2); - mytest_diff(descr, s2, "a\nb\nc\nd\n", res); + mytest_diff(s2, "a\nb\nc\nd\n", res, + "compare subset (%s) with (abcd)", d2); } }