/* Returns leaks, and sets errs[] */ static char *analyze_output(const char *output, char **errs) { char *leaks = tal_strdup(output, ""); unsigned int i; char **lines = tal_strsplit(output, output, "\n", STR_EMPTY_OK); *errs = tal_strdup(output, ""); for (i = 0; i < tal_count(lines) - 1; i++) { unsigned int preflen = strspn(lines[i], "=0123456789"); char *prefix, **sublines; /* Ignore erased lines, or weird stuff. */ if (preflen == 0) continue; prefix = tal_strndup(output, lines[i], preflen); sublines = extract_matching(prefix, lines); leaks = tal_strcat(output, take(leaks), take(get_leaks(sublines, errs))); } if (!leaks[0]) { tal_free(leaks); leaks = NULL; } if (!(*errs)[0]) { tal_free(*errs); *errs = NULL; } return leaks; }
static void setup_words(void) { char *wordfile; /* read in the words */ wordfile = grab_file(NULL, "test/api-lazytrie-words.txt"); ok1(wordfile); wordarray = tal_strsplit(NULL, take(wordfile), "\n", STR_NO_EMPTY); ok1(wordarray); nwords = tal_count(wordarray) - 1; diag("lazytrie: %d words loaded", nwords); ok1(nwords == NWORDS); wordarrayb = tal_arr(NULL, char *, nwords); memcpy(wordarrayb, wordarray, tal_count(wordarrayb) * sizeof(char *)); qsort(wordarrayb, nwords, sizeof(char *), lensort); }
char *read_config_header(const char *ccan_dir, bool verbose) { char *fname = path_join(NULL, ccan_dir, "config.h"); char **lines; unsigned int i; char *config_header; config_header = grab_file(NULL, fname); tal_free(fname); if (!config_header) return NULL; lines = tal_strsplit(config_header, config_header, "\n", STR_EMPTY_OK); for (i = 0; i < tal_count(lines) - 1; i++) { char *sym; const char **line = (const char **)&lines[i]; if (!get_token(line, "#")) continue; if (!get_token(line, "define")) continue; sym = get_symbol_token(lines, line); if (streq(sym, "CCAN_COMPILER")) { compiler = demangle_string(lines[i]); if (!compiler) errx(1, "%s:%u:could not parse CCAN_COMPILER", fname, i+1); if (verbose) printf("%s: compiler set to '%s'\n", fname, compiler); } else if (streq(sym, "CCAN_CFLAGS")) { cflags = demangle_string(lines[i]); if (!cflags) errx(1, "%s:%u:could not parse CCAN_CFLAGS", fname, i+1); if (verbose) printf("%s: compiler flags set to '%s'\n", fname, cflags); } } return config_header; }
lines_from_cmd(const void *ctx, const char *format, ...) { va_list ap; char *cmd; FILE *p; struct rbuf in; va_start(ap, format); cmd = tal_vfmt(ctx, format, ap); va_end(ap); p = popen(cmd, "r"); if (!p) err(1, "Executing '%s'", cmd); /* FIXME: Use rbuf_read_str(&in, '\n') rather than strsplit! */ rbuf_init(&in, fileno(p), tal_arr(ctx, char, 0), 0); if (!rbuf_read_str(&in, 0, do_tal_realloc) && errno) err(1, "Reading from '%s'", cmd); pclose(p); return tal_strsplit(ctx, in.buf, "\n", STR_EMPTY_OK); }
int main(int argc, char *argv[]) { char **split, *str; void *ctx; plan_tests(69); split = tal_strsplit(NULL, "hello world", " ", STR_EMPTY_OK); ok1(!strcmp(split[0], "hello")); ok1(!strcmp(split[1], "")); ok1(!strcmp(split[2], "world")); ok1(split[3] == NULL); ok1(tal_count(split) == 4); tal_free(split); split = tal_strsplit(NULL, "hello world", " ", STR_NO_EMPTY); ok1(!strcmp(split[0], "hello")); ok1(!strcmp(split[1], "world")); ok1(split[2] == NULL); ok1(tal_count(split) == 3); tal_free(split); split = tal_strsplit(NULL, " hello world", " ", STR_NO_EMPTY); ok1(!strcmp(split[0], "hello")); ok1(!strcmp(split[1], "world")); ok1(split[2] == NULL); ok1(tal_count(split) == 3); tal_free(split); split = tal_strsplit(NULL, "hello world", "o ", STR_EMPTY_OK); ok1(!strcmp(split[0], "hell")); ok1(!strcmp(split[1], "")); ok1(!strcmp(split[2], "")); ok1(!strcmp(split[3], "w")); ok1(!strcmp(split[4], "rld")); ok1(split[5] == NULL); ok1(tal_count(split) == 6); ctx = split; split = tal_strsplit(ctx, "hello world", "o ", STR_EMPTY_OK); ok1(tal_parent(split) == ctx); tal_free(ctx); str = tal_strjoin(NULL, (char **)substrings, ", ", STR_TRAIL); ok1(!strcmp(str, "far, bar, baz, b, ba, z, ar, ")); ctx = str; str = tal_strjoin(ctx, (char **)substrings, "", STR_TRAIL); ok1(!strcmp(str, "farbarbazbbazar")); ok1(tal_parent(str) == ctx); str = tal_strjoin(ctx, (char **)substrings, ", ", STR_NO_TRAIL); ok1(tal_parent(str) == ctx); ok1(!strcmp(str, "far, bar, baz, b, ba, z, ar")); str = tal_strjoin(ctx, (char **)substrings, "", STR_NO_TRAIL); ok1(!strcmp(str, "farbarbazbbazar")); ok1(tal_parent(str) == ctx); tal_free(ctx); ctx = tal_strdup(NULL, "context"); /* Pass through NULLs from take. */ ok1(tal_strsplit(NULL, take(NULL), " ", STR_EMPTY_OK) == NULL); ok1(tal_strsplit(NULL, "foo", take(NULL), STR_EMPTY_OK) == NULL); /* tal_strsplit take string. It reallocs it to same size, but * that sometimes causes a move, so we can't directly check * that split[0] == str. */ str = tal_strdup(ctx, "hello world"); ok1(tal_check(ctx, NULL)); ok1(tal_check(str, NULL)); split = tal_strsplit(ctx, take(str), " ", STR_EMPTY_OK); ok1(tal_parent(split) == ctx); ok1(!strcmp(split[0], "hello")); ok1(!strcmp(split[1], "world")); ok1(split[2] == NULL); ok1(tal_check(split, NULL)); ok1(tal_check(ctx, NULL)); tal_free(split); /* Previous free should get rid of str */ ok1(!tal_first(ctx)); /* tal_strsplit take delims */ str = tal_strdup(ctx, " "); split = tal_strsplit(ctx, "hello world", take(str), STR_EMPTY_OK); ok1(tal_parent(split) == ctx); ok1(!strcmp(split[0], "hello")); ok1(!strcmp(split[1], "world")); ok1(split[2] == NULL); ok1(tal_check(split, NULL)); ok1(tal_check(ctx, NULL)); tal_free(split); /* str is gone... */ ok1(!tal_first(ctx)); /* tal_strsplit takes both. */ split = tal_strsplit(ctx, take(tal_strdup(NULL, "hello world")), take(tal_strdup(NULL, " ")), STR_EMPTY_OK); ok1(tal_parent(split) == ctx); ok1(!strcmp(split[0], "hello")); ok1(!strcmp(split[1], "world")); ok1(split[2] == NULL); ok1(tal_check(split, NULL)); ok1(tal_check(ctx, NULL)); tal_free(split); /* temp allocs are gone... */ ok1(!tal_first(ctx)); /* tal_strjoin passthrough taken NULLs OK. */ ok1(tal_strjoin(ctx, take(NULL), "", STR_TRAIL) == NULL); ok1(tal_strjoin(ctx, take(NULL), "", STR_NO_TRAIL) == NULL); ok1(tal_strjoin(ctx, split, take(NULL), STR_TRAIL) == NULL); ok1(tal_strjoin(ctx, split, take(NULL), STR_NO_TRAIL) == NULL); /* tal_strjoin take strings[] */ split = tal_strsplit(ctx, "hello world", " ", STR_EMPTY_OK); str = tal_strjoin(ctx, take(split), " there ", STR_NO_TRAIL); ok1(!strcmp(str, "hello there world")); ok1(tal_parent(str) == ctx); /* split is gone... */ ok1(tal_first(ctx) == str && !tal_next(ctx, str)); tal_free(str); ok1(!tal_first(ctx)); /* tal_strjoin take delim */ split = tal_strsplit(ctx, "hello world", " ", STR_EMPTY_OK); str = tal_strjoin(ctx, split, take(tal_strdup(ctx, " there ")), STR_NO_TRAIL); ok1(!strcmp(str, "hello there world")); ok1(tal_parent(str) == ctx); tal_free(split); /* tmp alloc is gone, str is only remainder. */ ok1(tal_first(ctx) == str && !tal_next(ctx, str)); tal_free(str); ok1(!tal_first(ctx)); /* tal_strjoin take both. */ str = tal_strjoin(ctx, take(tal_strsplit(ctx, "hello world", " ", STR_EMPTY_OK)), take(tal_strdup(ctx, " there ")), STR_NO_TRAIL); ok1(!strcmp(str, "hello there world")); ok1(tal_parent(str) == ctx); /* tmp allocs are gone, str is only remainder. */ ok1(tal_first(ctx) == str && !tal_next(ctx, str)); tal_free(str); ok1(!tal_first(ctx)); tal_free(ctx); return exit_status(); }
int main(int argc, char *argv[]) { size_t i, j, num; struct timeabs start, stop; char **w; ENTRY *words, *misswords; w = tal_strsplit(NULL, grab_file(NULL, argv[1] ? argv[1] : "/usr/share/dict/words"), "\n", STR_NO_EMPTY); num = tal_count(w) - 1; printf("%zu words\n", num); hcreate(num+num/3); words = tal_arr(w, ENTRY, num); for (i = 0; i < num; i++) { words[i].key = w[i]; words[i].data = words[i].key; } /* Append and prepend last char for miss testing. */ misswords = tal_arr(w, ENTRY, num); for (i = 0; i < num; i++) { char lastc; if (strlen(w[i])) lastc = w[i][strlen(w[i])-1]; else lastc = 'z'; misswords[i].key = tal_fmt(misswords, "%c%s%c%c", lastc, w[i], lastc, lastc); } printf("#01: Initial insert: "); fflush(stdout); start = time_now(); for (i = 0; i < num; i++) hsearch(words[i], ENTER); stop = time_now(); printf(" %zu ns\n", normalize(&start, &stop, num)); printf("#02: Initial lookup (match): "); fflush(stdout); start = time_now(); for (i = 0; i < num; i++) if (hsearch(words[i], FIND)->data != words[i].data) abort(); stop = time_now(); printf(" %zu ns\n", normalize(&start, &stop, num)); printf("#03: Initial lookup (miss): "); fflush(stdout); start = time_now(); for (i = 0; i < num; i++) { if (hsearch(misswords[i], FIND)) abort(); } stop = time_now(); printf(" %zu ns\n", normalize(&start, &stop, num)); /* Lookups in order are very cache-friendly for judy; try random */ printf("#04: Initial lookup (random): "); fflush(stdout); start = time_now(); for (i = 0, j = 0; i < num; i++, j = (j + 10007) % num) if (hsearch(words[i], FIND)->data != words[i].data) abort(); stop = time_now(); printf(" %zu ns\n", normalize(&start, &stop, num)); return 0; }