forsyth20121205-174063a80cc13 years agoHistory
123 lines · 2.5 KB · Brainfuck
RawDownload
implement Readdir; include "sys.m";	sys: Sys;	Dir: import sys;include "readdir.m"; init(path: string, sortkey: int): (array of ref Dir, int){	sys = load Sys Sys->PATH;	fd := sys->open(path, Sys->OREAD);	if(fd == nil)		return (nil, -1);	return readall(fd, sortkey);} readall(fd: ref Sys->FD, sortkey: int): (array of ref Dir, int){	sys = load Sys Sys->PATH;	dl: list of array of Dir;	n := 0;	for(;;){		(nr, b) := sys->dirread(fd);		if(nr <= 0){			# any error makes the whole directory unreadable			if(nr < 0)				return (nil, -1);			break;		}		dl = b :: dl;		n += nr;	}	rl := dl;	for(dl = nil; rl != nil; rl = tl rl)		dl = hd rl :: dl;	a := makerefs(dl, n, sortkey & COMPACT);	sortkey &= ~COMPACT;	if((sortkey & ~DESCENDING) == NONE)		return (a, len a);	return sortdir(a, sortkey);} makerefs(dl: list of array of Dir, n: int, compact: int): array of ref Dir{	a := array[n] of ref Dir;	ht: array of list of string;	if(compact)		ht = array[41] of list of string;	j := 0;	for(; dl != nil; dl = tl dl){		d := hd dl;		for(i := 0; i < len d; i++)			if(ht == nil || hashadd(ht, d[i].name))				a[j++] = ref d[i];	}	if(j != n)		a = a[0:j];	return a;} sortdir(a: array of ref Dir, key: int): (array of ref Dir, int){	mergesort(a, array[len a] of ref Dir, key);	return (a, len a);}	# mergesort because it's stable.mergesort(a, b: array of ref Dir, key: int){	r := len a;	if (r > 1) {		m := (r-1)/2 + 1;		mergesort(a[0:m], b[0:m], key);		mergesort(a[m:], b[m:], key);		b[0:] = a;		for ((i, j, k) := (0, m, 0); i < m && j < r; k++) {			if (greater(b[i], b[j], key))				a[k] = b[j++];			else				a[k] = b[i++];		}		if (i < m)			a[k:] = b[i:m];		else if (j < r)			a[k:] = b[j:r];	}} greater(x, y: ref Dir, sortkey: int): int{	case (sortkey) {	NAME => return(x.name > y.name);	ATIME => return(x.atime < y.atime);	MTIME => return(x.mtime < y.mtime);	SIZE => return(x.length > y.length);	NAME|DESCENDING => return(x.name < y.name);	ATIME|DESCENDING => return(x.atime > y.atime);	MTIME|DESCENDING => return(x.mtime > y.mtime);	SIZE|DESCENDING => return(x.length < y.length);	}	return 0;} # from tcl_strhash.bhashfn(key: string, n : int): int{	h := 0;	for(i := 0; i < len key; i++){		h = 10*h + key[i];		h = h%n;	}	return h%n;} hashadd(ht: array of list of string, nm: string): int{	idx := hashfn(nm, len ht);	for (ent := ht[idx]; ent != nil; ent = tl ent)		if (hd ent == nm)			return 0;	ht[idx] = nm :: ht[idx];	return 1;}