# HG changeset patch # User John Tsiombikas # Date 1314852922 -10800 # Node ID 95f010f7eadc718c51bbe1553b1aa49ced8dd9c5 # Parent eec4999989608551b377a6fcf95b1899d42a2a19 *burp* diff -r eec499998960 -r 95f010f7eadc src/dsys.c --- a/src/dsys.c Wed Aug 31 23:23:38 2011 +0300 +++ b/src/dsys.c Thu Sep 01 07:55:22 2011 +0300 @@ -6,27 +6,45 @@ #include "dsys2.h" #include "dsys_impl.h" +static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname); + static float eval_step(struct dsys_event *ev, demotime_t t); static float eval_lerp(struct dsys_event *ev, demotime_t t); static float eval_sigmoid(struct dsys_event *ev, demotime_t t); static void free_event(struct dsys_event *ev); +static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev); +static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2); struct dsys_demo *dsys_open(const char *fname) { FILE *fp; - struct dsys_demo *res; + struct dsys_demo *demo; if(!(fp = fopen(fname, "r"))) { fprintf(stderr, "failed to open demoscript: %s: %s\n", fname, strerror(errno)); return 0; } - res = dsys_open_stream(fp); + if(!(demo = malloc(sizeof *demo))) { + perror("failed to allocate memory"); + fclose(fp); + return 0; + } + memset(demo, 0, sizeof *demo); + + demo->src_tm = demo->start_tm = -1; + + if(read_script(demo, fp, fname) == -1) { + free(demo); + fclose(fp); + return 0; + } + fclose(fp); - return res; + return demo; } struct dsys_demo *dsys_open_stream(FILE *fp) @@ -41,7 +59,7 @@ demo->src_tm = demo->start_tm = -1; - if(read_script(demo, fp) == -1) { + if(read_script(demo, fp, 0) == -1) { free(demo); return 0; } @@ -51,9 +69,9 @@ void dsys_close(struct dsys_demo *demo) { - while(demo->ev) { - struct dsys_event *ev = demo->ev; - demo->ev = demo->ev->next; + while(demo->evlist) { + struct dsys_event *ev = demo->evlist; + demo->evlist = demo->evlist->next; free_event(ev); } @@ -61,14 +79,19 @@ } +#define SEP " \t\n\r" -static int read_script(struct dsys_demo *demo, FILE *fp) +static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname) { int nline = 0; - char buf[512], *line, tok; - int timestamp; + char buf[512], *line, *tok, *endp; + unsigned int t0, t1; struct dsys_event *ev; + if(!fname) { + fname = ""; + } + while(fgets(buf, sizeof buf, fp)) { nline++; @@ -78,17 +101,26 @@ continue; } - if(!(tok = strtok(line, SEP)) || !isdigit(*tok)) { - fprintf(stderr, "error reading script at line: %d: expected timestamp\n", nline); + if(!(tok = strtok(line, SEP)) || (t0 = strtol(tok, &endp, 10), endp == tok)) { + fprintf(stderr, "%s line: %d, error: expected timestamp t0\n", fname, nline); return -1; } - timestamp = atoi(tok); if(!(tok = strtok(0, SEP))) { - fprintf(stderr, "error reading script at line: %d: expected event name\n", nline); + fprintf(stderr, "%s line: %d, error: expected second timestamp or event name\n", fname, nline); return -1; } + t1 = strtol(tok, &endp, 10); + if(endp == tok) { + t1 = t0; + } else { + if(!(tok = strtok(0, SEP))) { + fprintf(stderr, "%s line: %d, error: expected event name\n", fname, nline); + return -1; + } + } + if(!(ev = malloc(sizeof *ev))) { perror("read_script: failed to allocate memory for an event\n"); return -1; @@ -101,8 +133,21 @@ sprintf("read_script: failed to allocate memory for the event name: %s\n", tok); return -1; } + strcpy(ev->name, tok); + + ev->eval_func = t0 == t1 ? eval_step : eval_lerp; + + ev->next = demo->evlist; + ev->prev = 0; + if(demo->evlist) { + demo->evlist->prev = ev; + } + demo->evlist = ev; + demo->num_ev++; } + demo->evlist = sort_evlist(demo->evlist, demo->num_ev); + return 0; } @@ -240,3 +285,74 @@ free(cb); } } + +static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev) +{ + int i, num_left, num_right; + struct dsys_event *left, *right, *node = list; + + if(num_ev < 2) { + return list; + } + + num_left = num_ev / 2; + num_right = num_ev - num_left; + + for(i=0; inext; + } + + if(node->prev) { + node->prev->next = 0; + node->prev = 0; + } + + left = sort_evlist(list, num_left); + right = sort_evlist(node, num_right); + + return merge_evlists(left, right); +} + +static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2) +{ + struct dsys_event *head, *tail, *node; + + if(!list1) { + return list2; + } + if(!list2) { + return list1; + } + + head = tail = 0; + + while(list1 && list2) { + if(list1->t0 < list2->t0) { + node = list1; + list1 = list1->next; + } else { + node = list2; + list2 = list2->next; + } + + node->next = 0; + node->prev = tail; + + if(!head) { + head = node; + } else { + tail->next = node; + } + tail = node; + } + + if(list1) { + tail->next = list1; + list1->prev = tail; + } else if(list2) { + tail->next = list2; + list2->prev = tail; + } + + return head; +} diff -r eec499998960 -r 95f010f7eadc src/dsys_impl.h --- a/src/dsys_impl.h Wed Aug 31 23:23:38 2011 +0300 +++ b/src/dsys_impl.h Thu Sep 01 07:55:22 2011 +0300 @@ -7,7 +7,7 @@ demotime_t tm, src_tm, start_tm, stop_tm, duration; demotime_t stoppage_tm; - struct dsys_event *ev; + struct dsys_event *evlist; int num_ev; int running; @@ -24,10 +24,11 @@ struct dsys_event { enum dsys_evtype type; + char *name; demotime_t t0, t1; float val; - float (*eval_func)(struct dsys_event*); + float (*eval_func)(struct dsys_event*, demotime_t); struct callback *cblist;