path.cpp #1

  • //
  • guest/
  • ququlala/
  • libsprawl/
  • mainline/
  • filesystem/
  • path.cpp
  • View
  • Commits
  • Open Download .zip Download (4 KB)
#include "path.hpp"
#include "filesystem.hpp"
#ifdef _WIN32
	#include <windows.h>
	#define PATH_MAX MAX_PATH
	#define access _access
	#include <io.h>
	#define F_OK 0
	#define R_OK 2
	#define W_OK 4
	#define X_OK 0 //X_OK equivalent to F_OK on Windows
#else
	#include <limits.h>
	#include <unistd.h>
#endif

sprawl::String sprawl::path::AbsolutePath(String const& path)
{
	String cwd = filesystem::GetCwd();
	String joined = Join(cwd, path);
	return NormPath(joined);
}

sprawl::String sprawl::path::Basename(String const& path)
{
	int i = int(path.length() - 1);
	char const sep = Separator();
	char const altSep = AltSeparator();
	for( ; i >= 0; --i)
	{
		if(path[i] == sep || path[i] == altSep)
		{
			break;
		}
	}
	if(i < 0)
	{
		return path;
	}
	return String(path.c_str() + i + 1, path.length() - i - 1);
}

sprawl::String sprawl::path::Dirname(String const& path)
{
	int i = int(path.length() - 1);
	char const sep = Separator();
	char const altSep = AltSeparator();
	for( ; i >= 0; --i)
	{
		if(path[i] == sep || path[i] == altSep)
		{
			break;
		}
	}
	if(i < 0)
	{
		return "";
	}
	return String(path.c_str(), i + 1);
}


bool sprawl::path::Exists(String const& path)
{
	return access(path.GetOwned().c_str(), F_OK) == 0;
}


sprawl::path::SplitResult sprawl::path::Split(String const& path)
{
	int i = int(path.length() - 1);
	char const sep = Separator();
	char const altSep = AltSeparator();
	for( ; i >= 0; --i)
	{
		if(path[i] == sep || path[i] == altSep)
		{
			break;
		}
	}
	if(i < 0)
	{
		return { "", path };
	}
	return { String(path.c_str(), i + 1), String(path.c_str() + i + 1, path.length() - i - 1) };
}

sprawl::path::DriveResult sprawl::path::SplitDrive(String const& path)
{
	int i = int(path.length() - 1);
	char const sep = DriveSeparator();
	if(sep == '\0')
	{
		return { String(), path };
	}
	for( ; i >= 0; --i)
	{
		if(path[i] == sep)
		{
			break;
		}
	}
	if(i < 0)
	{
		return { "", path };
	}
	return { String(path.c_str(), i + 1), String(path.c_str() + i + 1, path.length() - i - 1) };
}

sprawl::path::ExtResult  sprawl::path::SplitExt(String const& path)
{
	int i = int(path.length() - 1);
	char const sep = ExtSeparator();
	for( ; i >= 0; --i)
	{
		if(path[i] == sep)
		{
			break;
		}
	}
	if(i < 0)
	{
		return { path, "" };
	}
	return { String(path.c_str(), i), String(path.c_str() + i + 1, path.length() - i - 1) };
}

sprawl::String sprawl::path::NormPath(String const& path)
{
	char out[PATH_MAX];
	char const sep = Separator();
	char const altSep = AltSeparator();
	size_t length = 0;
	for(size_t i = 0; i < path.length(); ++i)
	{
		char c = path[i];
		if (c == altSep)
		{
			c = sep;
		}
		if(c == sep)
		{
			//Collapse redundant separators
			if(i != 0)
			{
				if(path[i-1] == sep || path[i-1] == altSep)
				{
					continue;
				}
				if(path[i-1] == '.')
				{
					if(i > 2 && path[i-2] == '.' && (path[i-3] == sep || path[i-3] == altSep))
					{
						if(length < 4)
						{
							length = 1;
							continue;
						}
						length -= 4;
						if(out[length] == '.')
						{
							length += 4;
							out[length++] = c;
							continue;
						}
						while(length > 1 && out[length-1] != sep)
						{
							--length;
						}
						continue;
					}
					if(i > 1 && (path[i-2] == sep || path[i-2] == altSep))
					{
						--length;
						continue;
					}
				}
			}
		}

		out[length++] = c;
	}
	if (length > 1 && out[length - 1] == sep)
	{
		--length;
	}
	out[length] = '\0';
	return String(out, length);
}

bool sprawl::path::IsAbsolute(String const& path)
{
	if(path.empty())
	{
		return false;
	}
	DriveResult result = SplitDrive(path);
	char c = result.tail[0];
	return c == Separator() || (c != '\0' && c == AltSeparator());
}

sprawl::String sprawl::path::CommonPrefix(String const& path1, String const& path2)
{
	size_t maxLengthToIterate = path1.length() < path2.length() ? path1.length() : path2.length();
	char const* const path1ptr = path1.c_str();
	char const* const path2ptr = path2.c_str();
	for(size_t i = 0; i < maxLengthToIterate; ++i)
	{
		if(path1ptr[i] != path2ptr[i])
		{
			return sprawl::String(path1ptr, i);
		}
	}
	return sprawl::String(path1ptr, maxLengthToIterate);
}
# Change User Description Committed
#1 23398 ququlala "Forking branch Mainline of shadauxcat-libsprawl to ququlala-libsprawl."
//guest/ShadauxCat/Sprawl/Mainline/filesystem/path.cpp
#4 14816 ShadauxCat Filled in some more filesystem functions, added appropriate unit tests.
Only a few remain.

#review-14817
#3 14785 ShadauxCat -Fixed search/replace mishap in const movement
-Fixed a couple of missing windows headers
-Adjusted PutEnv() so that Linux and Windows have matching functionality - empty string is equivalent to UnsetEnv.

#review-14786
#2 14781 ShadauxCat -Finished path library
-Added some more functionality to filesystem library
-Added a few more unit tests, still more needed for path

#review-14782
#1 14761 ShadauxCat First drop of code for sprawl::filesystem and sprawl::path.
Library will continue to grow.

Also fixed a warning on linux.

#review-14762