Skip to content

Instantly share code, notes, and snippets.

@Maxdamantus
Last active August 18, 2017 07:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Maxdamantus/2e344f688d9715490cb0ea6dd6ffb8bd to your computer and use it in GitHub Desktop.
Save Maxdamantus/2e344f688d9715490cb0ea6dd6ffb8bd to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFSZ 8192
static const char *const less = "/usr/bin/less";
static int unicodedatafd = -1;
static long datasize, dataseek, imaginaryseek;
static struct {
size_t s;
unsigned char v[BUFSZ];
long dataoffset;
} buf;
static int ensureready(char *fn){
unicodedatafd = open(fn, O_RDONLY);
if(unicodedatafd < 0)
exit(1);
return (dataseek = datasize = lseek(unicodedatafd, 0, SEEK_END)) > 0;
}
static int fillbuf(void){
int rs;
if(dataseek != imaginaryseek)
if((dataseek = lseek(unicodedatafd, imaginaryseek, SEEK_SET)) < 0)
return 0;
buf.s = 0;
rs = read(unicodedatafd, buf.v, BUFSZ);
if(rs < 1)
return 0;
buf.s = rs;
buf.dataoffset = dataseek;
return 1;
}
static int getcurchar(void){
if(!buf.s || imaginaryseek < buf.dataoffset || imaginaryseek >= buf.dataoffset + buf.s)
if(!fillbuf())
return -1;
return buf.v[imaginaryseek - buf.dataoffset];
}
static int readchar(void){
int c = getcurchar();
if(c < 0)
return -1;
imaginaryseek++;
return c;
}
static int skiptonextline(void){
int c;
if(imaginaryseek == -1){
imaginaryseek = 0;
return 1;
}
while((c = readchar()) > 0)
if(c == '\n')
return 1;
return 0;
}
int compare(char *key){
for(;;){
if(!*key)
return 0;
int c = readchar();
if(c < 0)
return -1;
if(c != *(unsigned char *)key)
return *(unsigned char *)key - c;
else
key++;
}
}
int lookup(char *key, long *out){
long min = 0, max;
max = datasize;
int ret = 0;
while(max >= min){
long mid = (max + min)/2;
imaginaryseek = mid - 1;
skiptonextline();
long linestart = imaginaryseek;
int cmp = compare(key);
//fprintf(stderr, "%li > %li; mid = %li; cmp = %i\n", max, min, mid, cmp);
ret = cmp == 0;
if(cmp > 0)
min = mid + 1;
else if(cmp < 0)
max = mid - 1;
else if(max != mid)
max = mid;
else{
min = linestart;
break;
}
}
*out = min;
return ret;
}
int main(int argc, char **argv){
if(argc < 1)
return -1;
int exact = 0;
int prefix = 0;
int printnotfound = 0;
int exit = 0;
int readstdin = 0;
int plainargs = 0;
int execless = 0;
int first = 1;
char *fn = 0;
for(int x = 1; x < argc + readstdin; x++){
if(plainargs || x >= argc);
else if(!strcmp(argv[x], "-e")){
exact = !exact;
continue;
}else if(!strcmp(argv[x], "-w")){
printnotfound = !printnotfound;
continue;
}else if(!strcmp(argv[x], "-p")){
prefix = !prefix;
continue;
}else if(!strcmp(argv[x], "-i")){
readstdin = 1;
continue;
}else if(!strcmp(argv[x], "-l")){
execless = 1;
continue;
}else if(!strcmp(argv[x], "--")){
plainargs = 1;
continue;
}
if(first){
if(x > argc){
fprintf(stderr, "too few arguments\n");
return -1;
}
if(!ensureready(fn = argv[x]))
return -1;
first = 0;
continue;
}
char *needle;
char buf[1024];
if(x < argc)
needle = argv[x];
else{
if(!fgets(buf, sizeof buf, stdin))
continue;
size_t len = strlen(buf);
if(buf[len - 1] != '\n'){
fprintf(stderr, "line too long\n");
int c;
do
c = getchar();
while(c != EOF && c != '\n');
if(c == '\n')
x--;
continue;
}
x--;
buf[len - 1] = '\0';
needle = buf;
}
long pos;
int found = lookup(needle, &pos);
exit = exit || !found;
if(prefix){
imaginaryseek = pos;
for(;;){
int shouldbreak = 0;
long line = imaginaryseek;
int cmp = compare(needle);
if(cmp != 0)
break;
imaginaryseek = line;
for(;;){
int c = readchar();
shouldbreak = c <= 0;
if(shouldbreak || c == '\n')
break;
putchar(c);
}
if(shouldbreak)
break;
putchar('\n');
}
}else if(found || !exact){
if(execless){
close(unicodedatafd);
char lesscmd[1024];
snprintf(lesscmd, sizeof lesscmd, "++%liP", pos);
lesscmd[sizeof lesscmd - 1] = 0;
execv(less, (char *[]){ "less", "-n", lesscmd, fn, 0 });
perror("execv");
return 1;
}
imaginaryseek = pos;
for(;;){
int c = readchar();
if(c <= 0 || c == '\n')
break;
putchar(c);
}
putchar('\n');
}
if(printnotfound && !found)
fprintf(stderr, "not found: %s\n", needle);
}
close(unicodedatafd);
return exit;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment