/* * Retrieve sorted list of system locales (or user locales, if PATH_LOCALE * environment variable is set) */ void init_locales_list(void) { DIR *dirp; struct dirent *dp; size_t i; int bogus; /* why call this function twice ? */ if (locales != NULL) return; /* initialize StringList */ locales = sl_init(); if (locales == NULL) err(1, "could not allocate memory"); /* get actual locales directory name */ if (__detect_path_locale() != 0) err(1, "unable to find locales storage"); /* open locales directory */ dirp = opendir(_PathLocale); if (dirp == NULL) err(1, "could not open directory '%s'", _PathLocale); /* scan directory and store its contents except "." and ".." */ while ((dp = readdir(dirp)) != NULL) { if (*(dp->d_name) == '.') continue; /* exclude "." and ".." */ for (bogus = i = 0; i < NBOGUS; i++) if (strncmp(dp->d_name, boguslocales[i], strlen(boguslocales[i])) == 0) bogus = 1; if (!bogus) sl_add(locales, strdup(dp->d_name)); } closedir(dirp); /* make sure that 'POSIX' and 'C' locales are present in the list. * POSIX 1003.1-2001 requires presence of 'POSIX' name only here, but * we also list 'C' for constistency */ if (sl_find(locales, "POSIX") == NULL) sl_add(locales, "POSIX"); if (sl_find(locales, "C") == NULL) sl_add(locales, "C"); /* make output nicer, sort the list */ qsort(locales->sl_str, locales->sl_cur, sizeof(char *), scmp); }
static char *sl_test_find(void) { int *v; for(int i = 0; i < ARRAY_LEN(keys); i++) { v = sl_find(slist, keys[i]); mu_assert("inserted item not found", v != NULL); mu_assert("value of found item incorrect", *v == vals[i]); } v = sl_find(slist, 99); mu_assert("find key not in list didn't return NULL", v == NULL); return 0; }
void sl_add_index(Skiplist *sl, SkiplistComparator comp, SkiplistComparator compk) { struct skiplistnode *m; Skiplist *ni; int icount=0; Alarm(SKIPLIST, "Adding index to %p\n", sl); sl_find(sl->index, (void *)comp, &m); if(m) return; /* Index already there! */ ni = (Skiplist *)malloc(sizeof(Skiplist)); sli_init(ni); sl_set_compare(ni, comp, compk); /* Build the new index... This can be expensive! */ m = sl_insert(sl->index, ni); while(m->prev) m=m->prev, icount++; for(m=sl_getlist(sl); m; sl_next(sl, &m)) { int j=icount-1; struct skiplistnode *nsln; nsln = sl_insert(ni, m->data); /* skip from main index down list */ while(j>0) m=m->nextindex, j--; /* insert this node in the indexlist after m */ nsln->nextindex = m->nextindex; if(m->nextindex) m->nextindex->previndex = nsln; nsln->previndex = m; m->nextindex = nsln; } }
vio_err_t vio_partition_val(vio_ctx *ctx, vio_val *v, vio_val *q, vio_val **out_rets, vio_val **out_parts) { vio_err_t err = 0; struct partition *p = NULL; struct partition_item *it = NULL; vio_val *ret; sl_skiplist parts; sl_init(&parts, cmp_vals, ctx, NULL, NULL); for (uint32_t i = 0; i < v->vlen; ++i) { VIO__ERRIF(ctx->sp >= VIO_STACK_SIZE, VE_STACK_OVERFLOW); ctx->stack[ctx->sp++] = v->vv[i]; vio_exec(ctx, q->bc); ret = ctx->stack[--ctx->sp]; if (!sl_find(&parts, ret, &p)) { VIO__ERRIF((p = (struct partition *)malloc(sizeof(struct partition))) == NULL, VE_ALLOC_FAIL); p->last = NULL; p->size = 0; sl_insert(&parts, ret, p, NULL); } VIO__ERRIF((it = (struct partition_item *)malloc(sizeof(struct partition_item))) == NULL, VE_ALLOC_FAIL); it->next = p->last; it->v = v->vv[i]; p->last = it; ++p->size; } VIO__CHECK(vio_vec(ctx, out_rets, sl_size(&parts), NULL)); VIO__CHECK(vio_vec(ctx, out_parts, sl_size(&parts), NULL)); struct part_data pd = { .i = 0, .rets = *out_rets, .parts = *out_parts, .ctx = ctx }; sl_iter(&parts, fill_partitions_and_free, &pd); sl_free(&parts); return 0; error: sl_iter(&parts, gotta_free_em_all, NULL); sl_free(&parts); return err; } vio_err_t vio_partition(vio_ctx *ctx) { vio_err_t err = 0; vio_val *q, *vec, *rets, *parts; VIO__RAISEIF(ctx->sp < 2, VE_STACK_EMPTY, "Partition context requires a quotation and vector, but the " "stack doesnt't have enough values."); VIO__CHECK(vio_coerce(ctx, ctx->stack[--ctx->sp], &q, vv_quot)); VIO__CHECK(vio_coerce(ctx, ctx->stack[--ctx->sp], &vec, vv_vec)); VIO__CHECK(vio_partition_val(ctx, vec, q, &rets, &parts)); ctx->stack[ctx->sp++] = rets; ctx->stack[ctx->sp++] = parts; return 0; error: return err; }
static char *sl_test_update(void) { int v1 = 5; int v2 = 6; int *v; sl *slist = sl_create(); sl_insert(slist, 9, &v1); sl_insert(slist, 9, &v2); v = sl_find(slist, 9); mu_assert("updating list with one element fails", *v == v2); sl_destroy(slist); return 0; }
/* * Output information about all available charmaps * * XXX this function is doing a task in hackish way, i.e. by scaning * list of locales, spliting their codeset part and building list of * them. */ void list_charmaps(void) { size_t i; char *s, *cs; StringList *charmaps; /* initialize StringList */ charmaps = sl_init(); if (charmaps == NULL) err(1, "could not allocate memory"); /* fetch locales list */ init_locales_list(); /* split codesets and build their list */ for (i = 0; i < locales->sl_cur; i++) { s = locales->sl_str[i]; if ((cs = strchr(s, '.')) != NULL) { cs++; if (sl_find(charmaps, cs) == NULL) sl_add(charmaps, cs); } } /* add US-ASCII, if not yet added */ if (sl_find(charmaps, "US-ASCII") == NULL) sl_add(charmaps, "US-ASCII"); /* sort the list */ qsort(charmaps->sl_str, charmaps->sl_cur, sizeof(char *), scmp); /* print results */ for (i = 0; i < charmaps->sl_cur; i++) { printf("%s\n", charmaps->sl_str[i]); } }
void *sl_find_compare(Skiplist *sli, void *data, struct skiplistnode **iter, SkiplistComparator comp) { struct skiplistnode *m = NULL; Skiplist *sl; if(comp==sli->compare || !sli->index) { sl = sli; } else { sl_find(sli->index, (void *)comp, &m); assert(m); sl=m->data; } sli_find_compare(sl, data, iter, sl->comparek); return (*iter)?((*iter)->data):(*iter); }
int sl_remove_compare(Skiplist *sli, void *data, FreeFunc myfree, SkiplistComparator comp) { struct skiplistnode *m; Skiplist *sl; if(comp==sli->comparek || !sli->index) { sl = sli; } else { sl_find(sli->index, (void *)comp, &m); assert(m); sl=m->data; } sli_find_compare(sl, data, &m, comp); if (!m) return( 0 ); while(m->previndex) m=m->previndex; return sli_remove(sl, m, myfree); }
static char *sl_test_removal(void) { int *v; int r; int len; len = sl_len(slist); r = sl_remove(slist, keys[0]); v = sl_find(slist, keys[0]); mu_assert("find key removed from list didn't return NULL", v == NULL); mu_assert("wrong length after key removed", len-1 == sl_len(slist)); r = sl_remove(slist, -1); mu_assert("can't remove first key", r == 1); r = sl_remove(slist, 7455); mu_assert("can't remove last key", r == 1); mu_assert("wrong length after keys removed", len-3 == sl_len(slist)); return 0; }
static char *test_speed_compare(void) { struct _timeb start; struct _timeb finish; unsigned long sl_time_taken; unsigned long kl_time_taken; int keys[10000]; int vals[10000]; int test_keys[100]; sl *slist = sl_create(); kl *klist = kl_create(); int *v; _ftime(&start); /* generate long list (same for both) */ for(int i = 0; i < 10000; i++) { keys[i] = rand(); vals[i] = rand(); } for(int i = 0; i < 100; i++) { test_keys[i] = rand() % 10000; } /* fill lists with it (time this) */ _ftime(&start); for(int i = 0; i < 10000; i++) { kl_insert(klist, keys[i], &vals[i]); } _ftime(&finish); printf("kl: inserted 10,000 keys in %lums\n", ftime_diff(&start, &finish)); _ftime(&start); for(int i = 0; i < 10000; i++) { sl_insert(slist, keys[i], &vals[i]); } _ftime(&finish); printf("sl: inserted 10,000 keys in %lums\n", ftime_diff(&start, &finish)); /* find random values in it (same for both) n times, average time taken */ _ftime(&start); for(int i = 0; i < 1000; i++) { for(int j = 0; j < 100; j++) { v = sl_find(slist, keys[test_keys[j]]); } } _ftime(&finish); sl_time_taken = ftime_diff(&start, &finish); _ftime(&start); for(int i = 0; i < 1000; i++) { for(int j = 0; j < 100; j++) { v = kl_find(klist, keys[test_keys[j]]); } } _ftime(&finish); kl_time_taken = ftime_diff(&start, &finish); printf("sl: found 100,000 keys in %fs, %.2fkeys/s\n", sl_time_taken/1000.0, 100.0*100000/sl_time_taken); printf("kl: found 100,000 keys in %fs, %.2fkeys/s\n\n", kl_time_taken/1000.0, 100.0*100000/kl_time_taken); mu_assert("average sl find speed is slower than kl", sl_time_taken < kl_time_taken); sl_destroy(slist); kl_destroy(klist); return 0; }
static int token(char *line, FILE *out, bool *skip) { char *walk, c, a; if (strncmp(line, "endif", 5) == 0) { *skip = false; return (T_OK); } if (*skip) return (T_OK); if (strncmp(line, "include", 7) == 0) { walk = line + 7; trimlr(&walk); if (*walk == '\0') { warnx("Expecting arguments after #include"); return (T_ERR); } if (*walk != '<' && *walk != '\"') { warnx("Excecting '<' or '\"' after #include"); return (T_ERR); } a = *walk; walk++; c = walk[strlen(walk) - 1]; switch(c) { case '>': if (a != '<') { warnx("Unterminated include expecting '\"'"); return (T_ERR); } break; case '\"': if (a != '\"') { warnx("Unterminated include expecting '>'"); return (T_ERR); } break; default: warnx("Unterminated include expecting '%c'", a == '<' ? '>' : '\"' ); return (T_ERR); } walk[strlen(walk) - 1] = '\0'; if (cal_parse(cal_fopen(walk), out)) return (T_ERR); return (T_OK); } if (strncmp(line, "define", 6) == 0) { if (definitions == NULL) definitions = sl_init(); walk = line + 6; trimlr(&walk); if (*walk == '\0') { warnx("Expecting arguments after #define"); return (T_ERR); } sl_add(definitions, strdup(walk)); return (T_OK); } if (strncmp(line, "ifndef", 6) == 0) { walk = line + 6; trimlr(&walk); if (*walk == '\0') { warnx("Expecting arguments after #ifndef"); return (T_ERR); } if (definitions != NULL && sl_find(definitions, walk) != NULL) *skip = true; return (T_OK); } return (T_PROCESS); }