commit - 845963e5c302bb5f612a56968d0081f5f61feba4
commit + 1a4491e52655784bd60ea3de287121314a03ffcd
blob - 5d7e58e4aaf497fa9135558aa218a19b681f45a9
blob + 6caf9fbf02dcbd1835de562398550930b3515557
--- mymenu.c
+++ mymenu.c
#include <stdbool.h>
#include <limits.h>
#include <errno.h>
+#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h> // XLookupString
# define strcasestr strstr
#endif
-// The initial number of items to read
-#define INITIAL_ITEMS 64
+// The number of char to read
+#define STDIN_CHUNKS 64
+
+// the number of lines to allocate in advance
+#define LINES_CHUNK 32
// Abort if a is nil
#define check_allocation(a) { \
return s;
}
-// read an arbitrary amount of text until an EOF and store it in
-// lns. `items` is the capacity of lns. It may increase lns with
-// `realloc(3)` to store more line. Return the number of lines
-// read. The last item will always be a NULL pointer. It ignore the
-// "null" (empty) lines
-size_t readlines(char ***lns, size_t items) {
- size_t n = 0;
- char **lines = *lns;
- while (true) {
- size_t linelen = 0;
- ssize_t l = getline(lines + n, &linelen, stdin);
+size_t read_stdin(char **buf) {
+ size_t offset = 0;
+ size_t len = STDIN_CHUNKS;
+ *buf = malloc(len * sizeof(char));
+ if (*buf == nil)
+ goto err;
- if (l == -1) {
- break;
- }
+ while (true) {
+ ssize_t r = read(0, *buf + offset, STDIN_CHUNKS);
+ if (r < 1)
+ return len;
- if (linelen == 0 || lines[n][0] == '\n') {
- free(lines[n]);
- lines[n] = nil;
- continue; // forget about this line
- }
+ offset += r;
- strtok(lines[n], "\n"); // get rid of the \n
+ len += STDIN_CHUNKS;
+ *buf = realloc(*buf, len);
+ if (*buf == nil)
+ goto err;
- ++n;
+ for (size_t i = offset; i < len; ++i)
+ (*buf)[i] = '\0';
+ }
- if (n == items - 1) {
- items += items >>1;
- char **l = realloc(lines, sizeof(char*) * items);
- check_allocation(l);
- *lns = l;
- lines = l;
+ err:
+ fprintf(stderr, "Error in allocating memory for stdin.\n");
+ exit(EX_UNAVAILABLE);
+}
+
+//
+size_t readlines(char ***lns, char **buf) {
+ *buf = nil;
+ size_t len = read_stdin(buf);
+
+ size_t ll = LINES_CHUNK;
+ *lns = malloc(ll * sizeof(char*));
+ size_t lines = 0;
+ bool in_line = false;
+ for (size_t i = 0; i < len; i++) {
+ char c = (*buf)[i];
+
+ if (c == '\0')
+ break;
+
+ if (c == '\n')
+ (*buf)[i] = '\0';
+
+ if (in_line && c == '\n')
+ in_line = false;
+
+ if (!in_line && c != '\n') {
+ in_line = true;
+ (*lns)[lines] = (*buf) + i;
+ lines++;
+
+ if (lines == ll) { // resize
+ ll += LINES_CHUNK;
+ *lns = realloc(*lns, ll * sizeof(char*));
+ if (*lns == nil) {
+ fprintf(stderr, "Error in memory allocation.\n");
+ exit(EX_UNAVAILABLE);
+ }
+ }
}
}
- n++;
- lines[n] = nil;
- return items;
+ return lines;
}
// Compute the dimension of the string str once rendered, return the
}
// read the lines from stdin
- char **lines = calloc(INITIAL_ITEMS, sizeof(char*));
- check_allocation(lines);
- size_t nlines = readlines(&lines, INITIAL_ITEMS);
+ char **lines = nil;
+ char *buf = nil;
+ size_t nlines = readlines(&lines, &buf);
+
char **vlines = nil;
if (sep != nil) {
int l = strlen(sep);
free(fontname);
free(text);
- char *l = nil;
- char **lns = lines;
- while ((l = *lns) != nil) {
- free(l);
- ++lns;
- }
-
+ free(buf);
free(lines);
free(vlines);
compls_delete(cs);