view src/core/filesystem.cpp @ 60:d417e9381ca5

filesystem: WIP class-ification of paths
author Paper <mrpapersonic@gmail.com>
date Fri, 29 Sep 2023 13:52:50 -0400
parents 327e9a5c72f1
children 327568ad9be9
line wrap: on
line source

#ifdef WIN32
#	include <shlobj.h>
#elif defined(MACOSX)
#	include "sys/osx/filesystem.h"
#elif defined(__linux__)
#	include <pwd.h>
#	include <sys/types.h>
#endif

#ifdef WIN32
#	define DELIM "\\"
#else
#	define DELIM "/"
#	include <errno.h>
#	include <unistd.h>
#	include <sys/stat.h>
#endif

#include "core/filesystem.h"
#include "core/config.h"
#include <limits.h>

namespace Filesystem {

/* FIXME: This is a very C-like way of doing this.
   Make a path class. */
class Path {
	public:
		Path();
		Path(std::string path);
		Path(const Path& path);
		bool CreateDirectories() const;
		bool Exists() const;
		std::string Basename();
		std::string Stem();
		std::string Extension();
		Path GetParent();
		void SetPath();

	private:
		std::string _path;
}

bool Path::CreateDirectories() const {
	std::string temp = "";
	size_t start;
	size_t end = 0;
	temp.append(_path.substr(0, _path.find_first_not_of(DELIM, end)));

	while ((start = _path.find_first_not_of(DELIM, end)) != std::string::npos) {
		end = _path.find(DELIM, start);
		temp.append(_path.substr(start, end - start));
#ifdef WIN32
		if (!CreateDirectoryA(temp.c_str(), NULL) && GetLastError() == ERROR_PATH_NOT_FOUND)
			/* ERROR_PATH_NOT_FOUND should NOT happen here */
			return false;
#else
		struct stat st;
		if (stat(temp.c_str(), &st) == -1)
			mkdir(temp.c_str(), 0755);
#endif
		temp.append(DELIM);
	}
	return true;
}

bool Path::Exists() const {
#if WIN32
	return GetFileAttributes(_path.c_str()) != INVALID_FILE_ATTRIBUTES;
#else
	struct stat st;
	return stat(_path.c_str(), &st) == 0;
#endif
}

std::string Path::Basename() const {
	return _path.substr(0, path.find_last_of(DELIM));
}

std::string Path::Stem() const {
	std::string basename = Basename();
	return basename.substr(0, basename.find_last_of("."));
}

std::string Path::Extension() const {
	std::string basename = Basename(_path);
	return basename.substr(basename.find_last_of("."), basename.end());
}

std::string Path::GetParent() const {
	return _path.substr(0, _path.find_last_of(DELIM));
}

std::string GetDotPath(void) {
	std::string ret = "";
#ifdef WIN32
	char buf[PATH_MAX + 1];
	if (SHGetFolderPathAndSubDir(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, CONFIG_DIR, buf) == S_OK) {
		ret += buf;
	}
#elif defined(MACOSX)
	ret += osx::GetApplicationSupportDirectory();
	ret += DELIM CONFIG_DIR;
#else // just assume POSIX
	if (getenv("HOME") != NULL)
		ret += getenv("HOME");
#	ifdef __linux__
	else
		ret += getpwuid(getuid())->pw_dir;
#	endif // __linux__
	if (!ret.empty())
		ret += DELIM ".config" DELIM CONFIG_DIR;
#endif     // !WIN32 && !MACOSX
	return ret;
}

std::string GetConfigPath(void) {
	std::string ret = "";
	ret += GetDotPath();
	if (!ret.empty())
		ret += DELIM CONFIG_NAME;
	return ret;
}

std::string GetAnimeDBPath(void) {
	std::string ret = "";
	ret += GetDotPath();
	if (!ret.empty())
		ret += DELIM "anime" DELIM "db.json";
	return ret;
}

} // namespace Filesystem