X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/01468b426eb004d5fbdbbf6ef89374c5dd1e06fd..cff262f0a0384a8aaf0d719a32792fcc7ff89293:/src/xbt/xbt_str.c diff --git a/src/xbt/xbt_str.c b/src/xbt/xbt_str.c index aa61389215..18fb8eda78 100644 --- a/src/xbt/xbt_str.c +++ b/src/xbt/xbt_str.c @@ -18,6 +18,11 @@ #include "xbt/sysdep.h" #include "xbt/str.h" /* headers of these functions */ #include "portable.h" +#include "xbt/matrix.h" /* for the diff */ + +static void free_string(void *d){ + free(*(void**)d); +} /** @brief Strip whitespace (or other characters) from the end of a string. * @@ -181,6 +186,89 @@ xbt_str_strip_spaces(char *s) { end: *s = '\0'; } + +/** @brief Splits a string into a dynar of strings + * + * @param s: the string to split + * @param sep: a string of all chars to consider as separator. + * + * By default (with sep=NULL), these characters are used as separator: + * + * - " " (ASCII 32 (0x20)) space. + * - "\t" (ASCII 9 (0x09)) tab. + * - "\n" (ASCII 10 (0x0A)) line feed. + * - "\r" (ASCII 13 (0x0D)) carriage return. + * - "\0" (ASCII 0 (0x00)) NULL. + * - "\x0B" (ASCII 11 (0x0B)) vertical tab. + */ + +xbt_dynar_t xbt_str_split(char *s, const char *sep) { + char *str=xbt_strdup(s); + xbt_dynar_t res = xbt_dynar_new(sizeof(char*), free_string); + char *p, *q; + int done; + const char* sep_dflt = " \t\n\r\x0B"; + char is_sep[256] = {1,0}; + + /* check what are the separators */ + memset(is_sep,0,sizeof(is_sep)); + if (!sep) { + while (*sep_dflt) + is_sep[(unsigned char) *sep_dflt++] = 1; + } else { + while (*sep) + is_sep[(unsigned char) *sep++] = 1; + } + is_sep[0] = 1; /* End of string is also separator */ + + /* Do the job */ + p=q=str; + done=0; + while (!done) { + char *topush; + while (!is_sep[(unsigned char)*q]) { + q++; + } + if (*q == '\0') { +#ifdef UNDEF + if (p==q) { + /* do not push last empty line */ + free(str); + return res; + } +#endif + done = 1; + } else { + *q='\0'; + } + topush=xbt_strdup(p); + xbt_dynar_push(res,&topush); + p = ++q; + } + free (str); + return res; +} + +/** @brief Join a set of strings as a single string */ + +char *xbt_str_join(xbt_dynar_t dyn, const char*sep) { + int len=2; + int cpt; + char *cursor; + char *res,*p; + /* compute the length */ + xbt_dynar_foreach(dyn,cpt,cursor) { + len+=strlen(cursor); + } + len+=strlen(sep)*(xbt_dynar_length(dyn)-1); + /* Do the job */ + res = xbt_malloc(len); + p=res; + xbt_dynar_foreach(dyn,cpt,cursor) { + p+=sprintf(p,"%s%s",cursor,sep); + } + return res; +} #ifndef HAVE_GETLINE long getline(char **buf, size_t *n, FILE *stream) { @@ -218,3 +306,104 @@ long getline(char **buf, size_t *n, FILE *stream) { } #endif /* HAVE_GETLINE */ + +/* + * Diff related functions + */ +static xbt_matrix_t diff_build_LCS(xbt_dynar_t da, xbt_dynar_t db) { + xbt_matrix_t C = xbt_matrix_new(xbt_dynar_length(da),xbt_dynar_length(db), + sizeof(int),NULL); + int i,j; + /* Compute the LCS */ + /* + C = array(0..m, 0..n) + for i := 0..m + C[i,0] = 0 + for j := 1..n + C[0,j] = 0 + for i := 1..m + for j := 1..n + if X[i] = Y[j] + C[i,j] := C[i-1,j-1] + 1 + else: + C[i,j] := max(C[i,j-1], C[i-1,j]) + return C[m,n] + */ + for (i=0; i 0 and j > 0 and X[i] = Y[j] + printDiff(C, X, Y, i-1, j-1) + print " " + X[i] + else + if j > 0 and (i = 0 or C[i,j-1] >= C[i-1,j]) + printDiff(C, X, Y, i, j-1) + print "+ " + Y[j] + else if i > 0 and (j = 0 or C[i,j-1] < C[i-1,j]) + printDiff(C, X, Y, i-1, j) + print "- " + X[i] + */ + + if (i>=0 && j >= 0 && !strcmp(xbt_dynar_get_as(da,i,char*), + xbt_dynar_get_as(db,j,char*))) { + diff_build_diff(res,C,da,db,i-1,j-1); + topush = bprintf(" %s",xbt_dynar_get_as(da,i,char*)); + xbt_dynar_push(res, &topush); + } else if (j>=0 && + (i<0 || xbt_matrix_get_as(C,i,j-1,int) >= xbt_matrix_get_as(C,i-1,j,int))) { + diff_build_diff(res,C,da,db,i,j-1); + topush = bprintf("+ %s",xbt_dynar_get_as(db,j,char*)); + xbt_dynar_push(res,&topush); + } else if (i>=0 && + (j<0 || xbt_matrix_get_as(C,i,j-1,int) < xbt_matrix_get_as(C,i-1,j,int))) { + diff_build_diff(res,C,da,db,i-1,j); + topush = bprintf("- %s",xbt_dynar_get_as(da,i,char*)); + xbt_dynar_push(res,&topush); + } else if (i<0 && j<0) { + return; + } else { + THROW_IMPOSSIBLE; + } +} + +/** @brief Compute the unified diff of two strings */ +char *xbt_str_diff(char *a, char *b) { + xbt_dynar_t da = xbt_str_split(a, "\n"); + xbt_dynar_t db = xbt_str_split(b, "\n"); + + xbt_matrix_t C = diff_build_LCS(da,db); + xbt_dynar_t diff = xbt_dynar_new(sizeof(char*),free_string); + char *res=NULL; + + diff_build_diff(diff, C, da,db, xbt_dynar_length(da)-1, xbt_dynar_length(db)-1); + res = xbt_str_join(diff, "\n"); + + xbt_dynar_free(&da); + xbt_dynar_free(&db); + xbt_dynar_free(&diff); + xbt_matrix_free(C); + + return res; +}