converted buffer.c from linked list to array - iomenu - interactive terminal-based selection menu
HTML 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
HTML 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);