forsyth20121205-174063a80cc13 years agoHistory
154 lines · 2.9 KB · Brainfuck
RawDownload
implement Names; include "sys.m"; include "names.m"; # return name rewritten to compress /+, eliminate ., and interpret .. cleanname(name: string): string{	if(name == nil)		return "."; 	p := rooted := name[0]=='/';	if(name[0] == '#'){	# special		if(len name < 2)			return name;		p += 2;	# character after # whatever it is, is the name (including /)		for(; p < len name; p++)			if(name[p] == '/')				break;		rooted = p;	}	dotdot := rooted; 	#	# invariants:	#	p points at beginning of path element we're considering.	#	out records up to the last path element (no trailing slash unless root or #/).	#	dotdot points in out just past the point where .. cannot backtrack	#		any further (no slash).	#	out := name[0:rooted];	while(p < len name){		for(q := p; p < len name && name[p] != '/'; p++){			# skip		}		n := name[q:p];	# path element		p++;		case n {		"" or "." =>			;	# null effect		".." =>			if(len out > dotdot){	# can backtrack				for(q = len out; --q > dotdot && out[q] != '/';)					;				out = out[:q];			}else if(!rooted){	# /.. is / but ./../ is ..				if(out != nil)					out += "/..";				else					out += "..";				dotdot = len out;			}		* =>			if(rooted > 1 || len out > rooted)				out[len out] = '/';			out += n;		}	}	if(out == nil)		return ".";	return out;} dirname(name: string): string{	for(i := len name; --i >= 0;)		if(name[i] == '/')			break;	if(i < 0)		return nil;	d := name[0:i];	if(d != nil)		return d;	if(name[0] == '/')		return "/";	return nil;} basename(name: string, suffix: string): string{	for(i := len name; --i >= 0;)		if(name[i] == '/')			break;	if(i >= 0)		name = name[i+1:];	if(suffix != nil){		o := len name - len suffix;		if(o >= 0 && name[o:] == suffix)			return name[0:o];	}	return name;} relative(name: string, root: string): string{	if(root == nil || name == nil)		return name;	if(isprefix(root, name)){		name = name[len root:];		while(name != nil && name[0] == '/')			name = name[1:];	}	return name;} rooted(root: string, name: string): string{	if(name == nil)		return root;	if(root == nil || name[0] == '/' || name[0] == '#')		return name;	if(root[len root-1] != '/' && name[0] != '/')		return root+"/"+name;	return root+name;} isprefix(a: string, b: string): int{	la := len a;	if(la == 0)		return 0;	# "" isn't a pathname	while(la > 1 && a[la-1] == '/')		a = a[0:--la];	lb := len b;	if(la > lb)		return 0;	if(la == lb)		return a == b;	return a == b[0:la] && (a == "/" || b[la] == '/');} elements(name: string): list of string{	sys := load Sys Sys->PATH;	(nil, fld) := sys->tokenize(name, "/");	if(name != nil && name[0] == '/')		fld = "/" :: fld;	return fld;} pathname(els: list of string): string{	name: string;	sl := els != nil && hd els == "/";	for(; els != nil; els = tl els){		if(!sl)			name += "/";		name += hd els;		sl = 0;	}	return name;}