converted buffer.c from linked list to array - iomenu - interactive terminal-based selection menu
 (HTM) git clone git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 9786d2c290cdd4b3a37979155ced24f86f8358f5
 (DIR) parent 6a1d1b6950adc20996a8bf22441762e08f1dabb8
 (HTM) Author: Josuah Demangeonā  ā µ <mail@josuah.net>
       Date:   Wed, 15 Mar 2017 23:02:10 +0100
       
       converted buffer.c from linked list to array
       
       Diffstat:
         M Makefile                            |       8 +++-----
         M buffer.c                            |     136 ++++++++++---------------------
         M iomenu.h                            |      80 +++++++++++++++----------------
       
       3 files changed, 82 insertions(+), 142 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       @@ -1,8 +1,6 @@
       -CFLAGS    = -std=c89 -pedantic -Wall -Wextra -g -static
       +CFLAGS    = -std=c99 -pedantic -Wall -Wextra -g -static
        OBJ       = ${SRC:.c=.o}
        
       -MANPREFIX = $(PREFIX)
       -
        all: clean iomenu
        
        iomenu: buffer.c draw.c input.c
       @@ -11,6 +9,6 @@ clean:
                rm -f iomenu ${OBJ}
        
        install: iomenu
       -        mkdir -p  $(PREFIX)/bin $(MANPREFIX)/man/man1
       -        cp *.1 $(MANPREFIX)/man/man1/
       +        mkdir -p  $(PREFIX)/bin $(PREFIX)/man/man1
       +        cp *.1 $(PREFIX)/man/man1/
                cp iomenu $(PREFIX)/bin/
 (DIR) diff --git a/buffer.c b/buffer.c
       @@ -9,129 +9,76 @@
        /*
         * Fill the buffer apropriately with the lines
         */
       -Buffer *
       +void
        fill_buffer(void)
        {
       -        /* fill buffer with string */
       -        char    s[LINE_SIZE];
       -        Line  **buffer = malloc(sizeof(Line));
       -        FILE   *fp     = stdin;
       -        int     l;
       +        extern Line **buffer;
       +
       +        char  s[LINE_SIZE];
       +        size_t size = 1;
        
       -        if (!fp)
       -                die("Can not open file for reading.");
       +        buffer = malloc(sizeof(Line) * 2 << 4);
        
                input[0] = '\0';
                total = matching = 1;
        
       -        /* empty line in case no line come from stdin */
       -        first = buffer[current] = malloc(sizeof(Line));
       -        first->next = first->prev = NULL;
       -        last = NULL;
       -
       -        /* read the file into a doubly linked list of lines */
       -        for (l = 1; fgets(s, LINE_SIZE, fp); total++, l++)
       -                last = add_line(l, s, last);
       -
       -        return buffer;
       -}
       -
       +        /* read the file into an array of lines */
       +        for (; fgets(s, LINE_SIZE, stdin); total++, matching++) {
       +                if (total > size) {
       +                        size *= 2;
       +                        if (!realloc(buffer, size * sizeof(Line)))
       +                                die("realloc");
       +                }
        
       -/*
       - * Add a line to the end of the buffer[current] buffer.
       - */
       -Line *
       -add_line( int number, Line *prev)
       -{
       -        /* allocate new line */
       -        last          = new_line(s);
       -        last->number  = number;
       -        last->matches = 1;  /* matches by default */
       -        matching++;
       -
       -        /* interlink with previous line if exists */
       -        if (prev) {
       -                prev->next = last;
       -                last->prev = prev;
       -        } else {
       -                first = last;
       +                buffer[total]->text[strlen(s) - 1] = '\0';
       +                buffer[total]->match = 1;  /* empty input match everything */
                }
       -
       -        return last;
        }
        
        
       -Line *
       -new_line(char *s)
       -{
       -        Line *line = malloc(sizeof(Line));
       -
       -        /* strip trailing newline */
       -        s[strlen(s) - 1] = '\0';
       -
       -        /* fill line->content */
       -        line->content = s;
       -
       -        return line;
       -}
       -
       -
       -/*
       - * Free the also recursing the doubly linked list.
       - */
        void
       -free_buffer(Buffer *buffer)
       +free_buffer(Line **buffer)
        {
                Line *next = NULL;
        
       -        while (first) {
       -                next = first->next;
       -
       -                free(first);
       -
       -                first = next;
       -        }
       +        for (; total > 0; total--)
       +                free(buffer[total - 1]->text);
        
                free(buffer);
        }
        
        
        /*
       - * Set the line->matching state according to the return value of match_line,
       - * and matching to number of matching candidates.
       - *
       - * The incremental parameter sets whether check already matching or
       - * non-matching lines only.  This is for performance concerns.
       + * If inc is 1, it will only check already matching lines.
       + * If inc is 0, it will only check non-matching lines.
         */
        void
       -filter_lines( int inc)
       +filter_lines(int inc)
        {
       -        Line    *line = first;
                char   **tokv = NULL;
       -        char    *s, buf[sizeof input];
       +        char    *s, buf[sizeof(input)];
                size_t   n = 0, tokc = 0;
        
                /* tokenize input from space characters, this comes from dmenu */
                strcpy(buf, input);
                for (s = strtok(buf, " "); s; s = strtok(NULL, " ")) {
                        if (++tokc > n && !(tokv = realloc(tokv, ++n * sizeof(*tokv))))
       -                        die("cannot realloc memory for tokv\n");
       +                        die("realloc");
        
                        tokv[tokc - 1] = s;
                }
        
                /* match lines */
                matching = 0;
       -        while (line) {
       -                if (input[0] && !strcmp(input, line->content)) {
       -                        line->matches = 1;
       -                        buffer[current] = line;
       -                } else if ((inc && line->matches) || (!inc && !line->matches)) {
       -                        line->matches     = match_line(line, tokv, tokc);
       -                        matching += line->matches;
       -                }
       +        for (int i = 0; i < total; i++) {
        
       -                line = line->next;
       +                if (input[0] && strcmp(input, buffer[i]->text) == 0) {
       +                        buffer[i]->match = 1;
       +
       +                } else if ((inc && buffer[i]->match) || (!inc && !buffer[i]->match)) {
       +                        buffer[i]->match = match_line(buffer[i], tokv, tokc);
       +                        matching += buffer[i]->match;
       +                }
                }
        }
        
       @@ -142,12 +89,11 @@ filter_lines( int inc)
        int
        match_line(Line *line, char **tokv, size_t tokc)
        {
       -        size_t i, match = 1, offset = 0;
       -
       -        for (i = 0; i < tokc && match; i++)
       -                match = !!strstr(line->content + offset, tokv[i]);
       +        for (int i = 0; i < tokc; i++)
       +                if (!!strstr(buffer[i]->text, tokv[i]))
       +                        return 0;
        
       -        return match;
       +        return 1;
        }
        
        
       @@ -155,10 +101,10 @@ match_line(Line *line, char **tokv, size_t tokc)
         * Seek the previous matching line, or NULL if none matches.
         */
        Line *
       -matching_prev(Line *line)
       +matching_prev(int pos)
        {
       -        while ((line = line->prev) && !line->matches);
       -        return line;
       +        for (; pos > 0 && !buffer[pos]->match; pos--);
       +        return buffer[pos];
        }
        
        
       @@ -166,8 +112,8 @@ matching_prev(Line *line)
         * Seek the next matching line, or NULL if none matches.
         */
        Line *
       -matching_next(Line *line)
       +matching_next(int pos)
        {
       -        while ((line = line->next) && !line->matches);
       -        return line;
       +        for (; pos < total && !buffer[pos]->match; pos++);
       +        return buffer[pos];
        }
 (DIR) diff --git a/iomenu.h b/iomenu.h
       @@ -1,65 +1,61 @@
       +/*--- constants --------------------------------------------------------------*/
       +
        #define LINE_SIZE  1024
        #define OFFSET     5
        #define CONTINUE   2  /* as opposed to EXIT_SUCCESS and EXIT_FAILURE */
        
       +
       +/*--- macros -----------------------------------------------------------------*/
       +
        #define CONTROL(char) (char ^ 0x40)
        #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
        #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
        
        
       -/*
       - * Line coming from stdin
       - */
       +/*--- structures -------------------------------------------------------------*/
       +
        typedef struct Line {
       -        char *content;               /* sent as output and matched by input */
       -        int   matches;                /* whether it matches buffer's input */
       +        char *text;  /* sent as output and matched by input */
       +        int   match;   /* whether it matches buffer's input */
        } Line;
        
        
       -/* buffer */
       -Line *buffer[];
       -int   current, matching, total;
       -Line *first, *last;
       -
       -/* flags */
       -int   opt_line_numbers;
       -int   opt_lines;
       -char *opt_prompt, *input;
       +/*--- variables --------------------------------------------------------------*/
        
       +Line **buffer;
       +int    current, matching, total;
       +int    opt_lines;
       +char  *opt_prompt, *input;
        
       -/* iomenu */
        
       -void             die(const char *);
       -struct  termios set_terminal(int);
       -void            usage(void);
       +/*--- functions --------------------------------------------------------------*/
        
       +/* iomenu */
       +void            die(const char *);
       +struct termios set_terminal(int);
       +void           usage(void);
        
        /* buffer */
       -
       -Line  ** fill_buffer(char *);
       -void     free_buffer();
       -Line   * add_line(int, char *, char *, Line *);
       -Line   * new_line(char *, char *);
       -Line   * matching_next(Line *);
       -Line   * matching_prev(Line *);
       -int      match_line(Line *, char **, size_t);
       -void     filter_lines(int);
       -
       +void   fill_buffer(void);
       +void   free_buffer();
       +Line * add_line(int, char *, char *, Line *);
       +Line * new_line(char *, char *);
       +Line * matching_next(int);
       +Line * matching_prev(int);
       +int    match_line(Line *, char **, size_t);
       +void   filter_lines(int);
        
        /* draw */
       -
       -void     draw_screen(int);
       -void     draw_clear(int);
       -void     draw_line(Line *, int);
       -void     draw_lines(int, int);
       -void     draw_prompt(int);
       -
       +void draw_screen(int);
       +void draw_clear(int);
       +void draw_line(Line *, int);
       +void draw_lines(int, int);
       +void draw_prompt(int);
        
        /* input */
       -
       -int      input_get(int);
       -int      input_key(FILE *);
       -void     action_jump(int);
       -void     action_print_selection(int);
       -void     action_remove_word_input();
       -void     action_add_character(char);
       +int  input_get(int);
       +int  input_key(FILE *);
       +void action_jump(int);
       +void action_print_selection(int);
       +void action_remove_word_input();
       +void action_add_character(char);