//	FilePath.cp#include "FilePath.h"#ifdef macintosh	#include <Files.h>	OSErr MacRename( const String s1, const String s2 )		{ return Rename( s1, 0, s2 ); }#else	// for Unix...	#include <sys/stat.h>		#include <stdio.h>#endifPathFormat FilePath::defaultFormat = kCommon;String CommonToNative(const String& pStr){	#ifdef macintosh		// under MacOS...		String out;		// convert each part of the pathname to Mac format		String part;		for (int i=(pStr[0]=='/'); (part=pStr.Element(i,'/'))!=""; i++) {			if (part == "..") out += ":";		// up-indicator			else out = out + ":" + part;		// directory or file name		}		// extra colon is needed if pathname is all ".."'s		if (pStr.Right(2)=="..") out += ":";		// if common name starts with a slash, strip leading colon		if (pStr[0]=='/') return out.Substr(1,999);		return out;	#else					// under Unix, common == native		if (pStr=="") return ".";	// (but convert "" to ".")		return pStr;	#endif}String NativeToCommon(const String& pStr){	#ifdef macintosh		// under MacOS...		String out;		int i;		// do up-indicators first...		for (i=1; pStr.Substr(i-1,i) == "::"; i++) {			out += "/..";		}		if (pStr[0] != ':') i=0;		String part;		// now convert each part of the pathname to common format		for (int j=0; (part=pStr.Substr(i,999).Element(j,':'))!=""; j++) {			out = out + "/" + part;		// directory or file name		}		// if Mac name starts with a colon, strip leading slash		if (pStr[0]==':' && out[0]=='/') return out.Substr(1,999);		return out;	#else					// under Unix, common == native		return pStr;	#endif}PathError FilePath::SetTo( const String& pathname, const PathFormat format ){	// first, get the given pathname in common format	String s;	if (format==kCommon || (format==kDefault && defaultFormat==kCommon))		s = pathname;	else		s = NativeToCommon(pathname);		// if pathname is absolute (starts with a slash), then simply set it	if (s[0] == '/') {		itsString = s;		return kOK;	}		// if it's relative:	// change the pathname, keeping it "linear" (no down-and-back-up patterns)	String part;	for (int i=0; (part=s.Element(i,'/'))!=""; i++) {		if (part == "..") SetToParent();			// up-indicator		else {										// directory or file name			if (itsString!="") itsString += (String)"/" + part;			else itsString = part;		}	}	return kOK;}PathError FilePath::SetToParent(){	int p;	for (p=itsString.Length()-2; p>=0 && itsString[p]!='/'; p--) ;	if (p>=0 && itsString(p,p+2) != "/..") {		// if we can strip off last file element of path, do it		if (p) itsString = itsString.Left(p);		else itsString = "";	} else {		// if not, then return to CWD or do a relative-up		if (itsString=="") itsString = "..";		else if (itsString==".." || itsString.Left(3)=="../")			itsString += (String)"/..";		else itsString = "";	}	return kOK;}PathError FilePath::SetToCWD(){		itsString = "";		return kOK;}PathType FilePath::FileType() const{	// return whether the path points to a file, a directory, or nothing extant    #ifdef macintosh  		CInfoPBRec	pb;				// combined info record	HFileInfo	*fpb = (HFileInfo *)&pb;	// same, treated as a file record	OSErr	err;	String	pathname = CommonToNative(itsString);		fpb->ioVRefNum = 0;				// default volume	fpb->ioNamePtr = pathname;		// search for this file name	fpb->ioDirID = 0;				// search from working directory	fpb->ioFDirIndex = 0;			// gimme info about all files & dirs	err = PBGetCatInfo( &pb, FALSE );	// *** get the catalog info ***	if (err) return kNonexistant;	// assume any error means NoSuchFile...	else if (fpb->ioFlAttrib & 16) return kDirectory;	else return kFile;  #else	// Unix...	struct stat sb;	if (stat( CommonToNative(itsString), &sb) == -1)		return kNonexistant;	// system error	if ((sb.st_mode & S_IFMT) == S_IFDIR) return kDirectory;	// special files -- not yet supported...	if ((sb.st_mode & S_IFMT) == S_IFREG) return kFile;	return kOtherType;  #endif}String FilePath::FilePrefix() const{	int p;	for (p=itsString.Length()-2; p>=0 && itsString[p]!='/'; p--) ;	if (p<1) return "";	return itsString.Left(p);}	String FilePath::FileName() const{	int p;	for (p=itsString.Length()-2; p>=0 && itsString[p]!='/'; p--) ;	if (p<1) return itsString;	return itsString.Substr(p+1,999);}int FilePath::Rename( const String& newname ){	PathType ftype = FileType();	if (ftype == kNonexistant) return 0;		String fprefix = CommonToNative(FilePrefix());	String foldpath = CommonToNative(itsString);		#ifdef macintosh	  OSErr err = MacRename( foldpath, fprefix + ":" + newname );	  return !err;		#else	  return (rename( foldpath, fprefix + "/" + newname ) != -1);	#endif}