X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/362df7ae97f29c6ec84ffd20d9f4643ba11d8284..fbb6b4556c347a1dec9e462574fdc2967f494002:/src/xbt/xbt_str.c diff --git a/src/xbt/xbt_str.c b/src/xbt/xbt_str.c index 81f5c1846d..9247f2dd35 100644 --- a/src/xbt/xbt_str.c +++ b/src/xbt/xbt_str.c @@ -18,12 +18,12 @@ * Strips the whitespaces from the end of s. * By default (when char_list=NULL), these characters get stripped: * - * - " " (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. + * - " " (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. * * @param s The string to strip. Modified in place. * @param char_list A string which contains the characters you want to strip. @@ -62,12 +62,12 @@ void xbt_str_rtrim(char *s, const char *char_list) * Strips the whitespaces from the begining of s. * By default (when char_list=NULL), these characters get stripped: * - * - " " (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. + * - " " (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. * * @param s The string to strip. Modified in place. * @param char_list A string which contains the characters you want to strip. @@ -103,12 +103,12 @@ void xbt_str_ltrim(char *s, const char *char_list) * Strips the whitespaces from both the beginning and the end of s. * By default (when char_list=NULL), these characters get stripped: * - * - " " (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. + * - " " (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. * * @param s The string to strip. * @param char_list A string which contains the characters you want to strip. @@ -223,12 +223,12 @@ char *xbt_str_varsubst(const char *str, xbt_dict_t patterns) * * 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. + * - " " (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(const char *s, const char *sep) @@ -305,14 +305,14 @@ xbt_dynar_t xbt_str_split_str(const char *s, const char *sep) //if substring was not found add the entire string if (NULL == q) { v = strlen(p); - to_push = malloc(v + 1); + to_push = xbt_malloc(v + 1); memcpy(to_push, p, v); to_push[v] = '\0'; xbt_dynar_push(res, &to_push); done = 1; } else { //get the appearance - to_push = malloc(q - p + 1); + to_push = xbt_malloc(q - p + 1); memcpy(to_push, p, q - p); //add string terminator to_push[q - p] = '\0'; @@ -327,11 +327,14 @@ xbt_dynar_t xbt_str_split_str(const char *s, const char *sep) * * The string passed as argument must be writable (not const) * The elements of the dynar are just parts of the string passed as argument. + * So if you don't store that argument elsewhere, you should free it in addition + * to freeing the dynar. This can be done by simply freeing the first argument + * of the dynar: + * free(xbt_dynar_get_ptr(dynar,0)); * - * To free the structure constructed by this function, free the first element and free the dynar: - * - * free(xbt_dynar_get_ptr(dynar,0)); - * xbt_dynar_free(&dynar); + * Actually this function puts a bunch of \0 in the memory area you passed as + * argument to separate the elements, and pushes the address of each chunk + * in the resulting dynar. Yes, that's uneven. Yes, that's gory. But that's efficient. */ xbt_dynar_t xbt_str_split_quoted_in_place(char *s) { xbt_dynar_t res = xbt_dynar_new(sizeof(char *), NULL); @@ -345,7 +348,7 @@ xbt_dynar_t xbt_str_split_quoted_in_place(char *s) { beg = s; - /* do not trim leading spaces: caller responsability to clean his cruft */ + /* do not trim leading spaces: caller responsibility to clean his cruft */ end = beg; while (!done) { @@ -517,66 +520,61 @@ char *xbt_str_join_array(const char *const *strs, const char *sep) return res; } -#if defined(SIMGRID_NEED_GETLINE) || defined(DOXYGEN) /** @brief Get a single line from the stream (reimplementation of the GNU getline) * - * This is a redefinition of the GNU getline function, used on platforms where it does not exists. + * This is a reimplementation of the GNU getline function, so that our code don't depends on the GNU libc. + * + * xbt_getline() reads an entire line from stream, storing the address of the + * buffer containing the text into *buf. The buffer is null-terminated and + * includes the newline character, if one was found. * - * getline() reads an entire line from stream, storing the address of the buffer - * containing the text into *buf. The buffer is null-terminated and includes - * the newline character, if one was found. + * If *buf is NULL, then xbt_getline() will allocate a buffer for storing the + * line, which should be freed by the user program. * - * If *buf is NULL, then getline() will allocate a buffer for storing the line, - * which should be freed by the user program. Alternatively, before calling getline(), - * *buf can contain a pointer to a malloc()-allocated buffer *n bytes in size. If the buffer - * is not large enough to hold the line, getline() resizes it with realloc(), updating *buf and *n - * as necessary. In either case, on a successful call, *buf and *n will be updated to - * reflect the buffer address and allocated size respectively. + * Alternatively, before calling xbt_getline(), *buf can contain a pointer to a + * malloc()-allocated buffer *n bytes in size. If the buffer is not large + * enough to hold the line, xbt_getline() resizes it with realloc(), updating + * *buf and *n as necessary. + * + * In either case, on a successful call, *buf and *n will be updated to reflect + * the buffer address and allocated size respectively. */ -long getline(char **buf, size_t * n, FILE * stream) +ssize_t xbt_getline(char **buf, size_t *n, FILE *stream) { - - size_t i; + ssize_t i; int ch; + ch = getc(stream); + if (ferror(stream) || feof(stream)) + return -1; + if (!*buf) { - *buf = xbt_malloc(512); *n = 512; + *buf = xbt_malloc(*n); } - if (feof(stream)) - return (ssize_t) - 1; - - for (i = 0; (ch = fgetc(stream)) != EOF; i++) { - - if (i >= (*n) + 1) + i = 0; + do { + if (i == *n) *buf = xbt_realloc(*buf, *n += 512); - - (*buf)[i] = ch; - - if ((*buf)[i] == '\n') { - i++; - (*buf)[i] = '\0'; - break; - } - } + (*buf)[i++] = ch; + } while (ch != '\n' && (ch = getc(stream)) != EOF); if (i == *n) *buf = xbt_realloc(*buf, *n += 1); - (*buf)[i] = '\0'; - return (ssize_t) i; + return i; } -#endif /* HAVE_GETLINE */ - /* * Diff related functions * - * Implementation of the algorithm described in "An O(NP) Sequence - * Comparison Algorithm", by Sun Wu, Udi Manber, Gene Myers, and Webb - * Miller. + * Implementation of the algorithm described in "An O(NP) Sequence Comparison + * Algorithm", by Sun Wu, Udi Manber, Gene Myers, and Webb Miller (Information + * Processing Letters 35(6):317-323, 1990), with the linear-space + * divide-and-conquer strategy described in "An O(ND) Difference Algorithm and + * Its Variations", by Eugene W. Myers (Algorithmica 1:251-266, 1986). */ struct subsequence { @@ -585,8 +583,8 @@ struct subsequence { }; static XBT_INLINE -void diff_snake(const xbt_dynar_t da, int a0, int len_a, - const xbt_dynar_t db, int b0, int len_b, +void diff_snake(const char *vec_a[], int a0, int len_a, + const char *vec_b[], int b0, int len_b, struct subsequence *seqs, int *fp, int k, int limit) { int record_seq; @@ -608,8 +606,7 @@ void diff_snake(const xbt_dynar_t da, int a0, int len_a, } else { seqs[k] = seqs[record_seq]; } - while (x < len_a && y < len_b && !strcmp(xbt_dynar_get_as(da, a0 + x, char*), - xbt_dynar_get_as(db, b0 + y, char*))) + while (x < len_a && y < len_b && !strcmp(vec_a[a0 + x], vec_b[b0 + y])) ++x, ++y; fp[k] = x; if (record_seq == k) @@ -619,8 +616,8 @@ void diff_snake(const xbt_dynar_t da, int a0, int len_a, /* Returns the length of a shortest edit script, and a common * subsequence from the middle. */ -static int diff_middle_subsequence(const xbt_dynar_t da, int a0, int len_a, - const xbt_dynar_t db, int b0, int len_b, +static int diff_middle_subsequence(const char *vec_a[], int a0, int len_a, + const char *vec_b[], int b0, int len_b, struct subsequence *subseq, struct subsequence *seqs, int *fp) { @@ -644,9 +641,9 @@ static int diff_middle_subsequence(const xbt_dynar_t da, int a0, int len_a, p++; fp[kmin - p - 1] = fp[kmax + p + 1] = -1; for (k = kmax + p; k > delta; k--) - diff_snake(da, a0, len_a, db, b0, len_b, seqs, fp, k, limit); + diff_snake(vec_a, a0, len_a, vec_b, b0, len_b, seqs, fp, k, limit); for (k = kmin - p; k <= delta; k++) - diff_snake(da, a0, len_a, db, b0, len_b, seqs, fp, k, limit); + diff_snake(vec_a, a0, len_a, vec_b, b0, len_b, seqs, fp, k, limit); } while (fp[delta] != len_a); subseq->x = a0 + seqs[delta].x; @@ -656,25 +653,34 @@ static int diff_middle_subsequence(const xbt_dynar_t da, int a0, int len_a, } /* Finds a longest common subsequence. + * Returns its length. */ -static void diff_compute_lcs(const xbt_dynar_t da, int a0, int len_a, - const xbt_dynar_t db, int b0, int len_b, - xbt_dynar_t common_sequence, - struct subsequence *seqs, int *fp) +static int diff_compute_lcs(const char *vec_a[], int a0, int len_a, + const char *vec_b[], int b0, int len_b, + xbt_dynar_t common_sequence, + struct subsequence *seqs, int *fp) { if (len_a > 0 && len_b > 0) { struct subsequence subseq; - int ses_len = diff_middle_subsequence(da, a0, len_a, db, b0, len_b, + int ses_len = diff_middle_subsequence(vec_a, a0, len_a, vec_b, b0, len_b, &subseq, seqs, fp); - if (ses_len > 1) { - int u = subseq.x + subseq.len; - int v = subseq.y + subseq.len; - diff_compute_lcs(da, a0, subseq.x - a0, db, b0, subseq.y - b0, - common_sequence, seqs, fp); + int lcs_len = (len_a + len_b - ses_len) / 2; + if (lcs_len == 0) { + return 0; + } else if (ses_len > 1) { + int lcs_len1 = subseq.len; + if (lcs_len1 < lcs_len) + lcs_len1 += diff_compute_lcs(vec_a, a0, subseq.x - a0, + vec_b, b0, subseq.y - b0, + common_sequence, seqs, fp); if (subseq.len > 0) xbt_dynar_push(common_sequence, &subseq); - diff_compute_lcs(da, u, a0 + len_a - u, db, v, b0 + len_b - v, - common_sequence, seqs, fp); + if (lcs_len1 < lcs_len) { + int u = subseq.x + subseq.len; + int v = subseq.y + subseq.len; + diff_compute_lcs(vec_a, u, a0 + len_a - u, vec_b, v, b0 + len_b - v, + common_sequence, seqs, fp); + } } else { int len = MIN(len_a, len_b) - subseq.len; if (subseq.x == a0 && subseq.y == b0) { @@ -694,21 +700,24 @@ static void diff_compute_lcs(const xbt_dynar_t da, int a0, int len_a, xbt_dynar_push(common_sequence, &subseq); } } + return lcs_len; + } else { + return 0; } } -static int diff_member(const char *s, xbt_dynar_t d, int from, int to) +static int diff_member(const char *s, const char *vec[], int from, int to) { for ( ; from < to ; from++) - if (!strcmp(s, xbt_dynar_get_as(d, from, char *))) + if (!strcmp(s, vec[from])) return 1; return 0; } /* Extract common prefix. */ -static void diff_easy_prefix(const xbt_dynar_t da, int *a0_p, int *len_a_p, - const xbt_dynar_t db, int *b0_p, int *len_b_p, +static void diff_easy_prefix(const char *vec_a[], int *a0_p, int *len_a_p, + const char *vec_b[], int *b0_p, int *len_b_p, xbt_dynar_t common_sequence) { int a0 = *a0_p; @@ -718,8 +727,7 @@ static void diff_easy_prefix(const xbt_dynar_t da, int *a0_p, int *len_a_p, while (len_a > 0 && len_b > 0) { struct subsequence subseq = {a0, b0, 0}; - while (len_a > 0 && len_b > 0 && !strcmp(xbt_dynar_get_as(da, a0, char*), - xbt_dynar_get_as(db, b0, char*))) { + while (len_a > 0 && len_b > 0 && !strcmp(vec_a[a0], vec_b[b0])) { a0++, len_a--; b0++, len_b--; subseq.len++; @@ -727,8 +735,7 @@ static void diff_easy_prefix(const xbt_dynar_t da, int *a0_p, int *len_a_p, if (subseq.len > 0) xbt_dynar_push(common_sequence, &subseq); if (len_a > 0 && len_b > 0 && - !diff_member(xbt_dynar_get_as(da, a0, char*), - db, b0 + 1, b0 + len_b)) { + !diff_member(vec_a[a0], vec_b, b0 + 1, b0 + len_b)) { a0++, len_a--; } else { break; @@ -743,8 +750,8 @@ static void diff_easy_prefix(const xbt_dynar_t da, int *a0_p, int *len_a_p, /* Extract common suffix. */ -static void diff_easy_suffix(const xbt_dynar_t da, int *a0_p, int *len_a_p, - const xbt_dynar_t db, int *b0_p, int *len_b_p, +static void diff_easy_suffix(const char *vec_a[], int *a0_p, int *len_a_p, + const char *vec_b[], int *b0_p, int *len_b_p, xbt_dynar_t common_suffix) { int a0 = *a0_p; @@ -756,8 +763,7 @@ static void diff_easy_suffix(const xbt_dynar_t da, int *a0_p, int *len_a_p, struct subsequence subseq; subseq.len = 0; while (len_a > 0 && len_b > 0 && - !strcmp(xbt_dynar_get_as(da, a0 + len_a - 1, char*), - xbt_dynar_get_as(db, b0 + len_b - 1, char*))) { + !strcmp(vec_a[a0 + len_a - 1], vec_b[b0 + len_b - 1])) { len_a--; len_b--; subseq.len++; @@ -768,8 +774,7 @@ static void diff_easy_suffix(const xbt_dynar_t da, int *a0_p, int *len_a_p, xbt_dynar_push(common_suffix, &subseq); } if (len_a > 0 && len_b > 0 && - !diff_member(xbt_dynar_get_as(db, b0 + len_b - 1, char*), - da, a0, a0 + len_a - 1)) { + !diff_member(vec_b[b0 + len_b - 1], vec_a, a0, a0 + len_a - 1)) { len_b--; } else { break; @@ -789,6 +794,7 @@ char *xbt_str_diff(const char *a, const char *b) xbt_dynar_t db = xbt_str_split(b, "\n"); xbt_dynar_t common_sequence, common_suffix; size_t len; + const char **vec_a, **vec_b; int a0, b0; int len_a, len_b; int max; @@ -809,10 +815,13 @@ char *xbt_str_diff(const char *a, const char *b) xbt_dynar_pop(db, NULL); /* Various initializations */ + /* Assume that dynar's content is contiguous */ a0 = 0; len_a = xbt_dynar_length(da); + vec_a = len_a ? xbt_dynar_get_ptr(da, 0) : NULL; b0 = 0; len_b = xbt_dynar_length(db); + vec_b = len_b ? xbt_dynar_get_ptr(db, 0) : NULL; max = MAX(len_a, len_b) + 1; fp_base = xbt_new(int, 2 * max + 1); fp = fp_base + max; /* indexes in [-max..max] */ @@ -828,9 +837,9 @@ char *xbt_str_diff(const char *a, const char *b) xbt_dynar_push(common_suffix, &subseq); /* Compute the Longest Common Subsequence */ - diff_easy_prefix(da, &a0, &len_a, db, &b0, &len_b, common_sequence); - diff_easy_suffix(da, &a0, &len_a, db, &b0, &len_b, common_suffix); - diff_compute_lcs(da, a0, len_a, db, b0, len_b, common_sequence, seqs, fp); + diff_easy_prefix(vec_a, &a0, &len_a, vec_b, &b0, &len_b, common_sequence); + diff_easy_suffix(vec_a, &a0, &len_a, vec_b, &b0, &len_b, common_suffix); + diff_compute_lcs(vec_a, a0, len_a, vec_b, b0, len_b, common_sequence, seqs, fp); while (!xbt_dynar_is_empty(common_suffix)) { xbt_dynar_pop(common_suffix, &subseq); xbt_dynar_push(common_sequence, &subseq); @@ -842,15 +851,15 @@ char *xbt_str_diff(const char *a, const char *b) y = 0; xbt_dynar_foreach(common_sequence, s, subseq) { while (x < subseq.x) { - char *topush = bprintf("- %s", xbt_dynar_get_as(da, x++, char*)); + char *topush = bprintf("- %s", vec_a[x++]); xbt_dynar_push_as(diff, char*, topush); } while (y < subseq.y) { - char *topush = bprintf("+ %s", xbt_dynar_get_as(db, y++, char*)); + char *topush = bprintf("+ %s", vec_b[y++]); xbt_dynar_push_as(diff, char*, topush); } while (x < subseq.x + subseq.len) { - char *topush = bprintf(" %s", xbt_dynar_get_as(da, x++, char*)); + char *topush = bprintf(" %s", vec_a[x++]); xbt_dynar_push_as(diff, char*, topush); y++; } @@ -890,6 +899,28 @@ char *xbt_str_from_file(FILE * file) return res; } +/* @brief Retrun 1 if string 'str' starts with string 'start' + * + * \param str a string + * \param start the string to search in str + * + * \return 1 if 'str' starts with 'start' + */ +int xbt_str_start_with(const char* str, const char* start) +{ + int i; + size_t l_str = strlen(str); + size_t l_start = strlen(start); + + if(l_start > l_str) return 0; + + for(i = 0; i< l_start; i++){ + if(str[i] != start[i]) return 0; + } + + return 1; +} + #ifdef SIMGRID_TEST #include "xbt/str.h"