예제 #1
0
/** returns true if the specified path exists and is a directory */
bool Path_IsDirectory(const std::string & sPath)
{
	std::string sFixedPath = Path_FixSlashes(sPath);
	if (sFixedPath.empty())
		return false;
	char cLast = sFixedPath[sFixedPath.length() - 1];
	if (cLast == '/' || cLast == '\\')
		sFixedPath.erase(sFixedPath.end() - 1, sFixedPath.end());

	// see if the specified path actually exists.

#if defined(POSIX)
	struct	stat	buf;
	if (stat(sFixedPath.c_str(), &buf) == -1)
	{
		return false;
	}

#if defined( LINUX ) || defined( OSX )
	return S_ISDIR(buf.st_mode);
#else
	return (buf.st_mode & _S_IFDIR) != 0;
#endif

#else
	struct	_stat	buf;
	std::wstring wsFixedPath = UTF8to16(sFixedPath.c_str());
	if (_wstat(wsFixedPath.c_str(), &buf) == -1)
	{
		return false;
	}

	return (buf.st_mode & _S_IFDIR) != 0;
#endif
}
예제 #2
0
/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the
* specified path has a broken number of directories for its number of ..s */
std::string Path_Compact(const std::string & sRawPath, char slash)
{
	if (slash == 0)
		slash = Path_GetSlash();

	std::string sPath = Path_FixSlashes(sRawPath, slash);
	std::string sSlashString(1, slash);

	// strip out all /./
	for (std::string::size_type i = 0; (i + 3) < sPath.length(); )
	{
		if (sPath[i] == slash && sPath[i + 1] == '.' && sPath[i + 2] == slash)
		{
			sPath.replace(i, 3, sSlashString);
		}
		else
		{
			++i;
		}
	}


	// get rid of trailing /. but leave the path separator
	if (sPath.length() > 2)
	{
		std::string::size_type len = sPath.length();
		if (sPath[len - 1] == '.' && sPath[len - 2] == slash)
		{
			// sPath.pop_back();
			sPath[len - 1] = 0;  // for now, at least
		}
	}

	// get rid of leading ./ 
	if (sPath.length() > 2)
	{
		if (sPath[0] == '.' && sPath[1] == slash)
		{
			sPath.replace(0, 2, "");
		}
	}

	// each time we encounter .. back up until we've found the previous directory name
	// then get rid of both
	std::string::size_type i = 0;
	while (i < sPath.length())
	{
		if (i > 0 && sPath.length() - i >= 2
			&& sPath[i] == '.'
			&& sPath[i + 1] == '.'
			&& (i + 2 == sPath.length() || sPath[i + 2] == slash)
			&& sPath[i - 1] == slash)
		{
			// check if we've hit the start of the string and have a bogus path
			if (i == 1)
				return "";

			// find the separator before i-1
			std::string::size_type iDirStart = i - 2;
			while (iDirStart > 0 && sPath[iDirStart - 1] != slash)
				--iDirStart;

			// remove everything from iDirStart to i+2
			sPath.replace(iDirStart, (i - iDirStart) + 3, "");

			// start over
			i = 0;
		}
		else
		{
			++i;
		}
	}

	return sPath;
}
예제 #3
0
TEST( PathTools, FixSlashes )
{
	EXPECT_STREQ( "foo/bar/baz", Path_FixSlashes( "foo\\bar/baz", '/' ).c_str() );
	EXPECT_STREQ( "/foo/bar/baz", Path_FixSlashes( "/foo\\bar/baz", '/' ).c_str() );
	EXPECT_STREQ( "/foo/bar/baz", Path_FixSlashes( "\\foo\\bar/baz", '/' ).c_str() );
}