existsDirectory,createDirectories recursively,"Saved Ga

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Maragnus
Posts: 1
Joined: Wed Oct 20, 2010 2:53 pm
Location: USA
Contact:

existsDirectory,createDirectories recursively,"Saved Ga

Post by Maragnus »

-- EDIT --

I figure I should include a patch for my code as well to save anyone needing this some effort. I've also tested this in Windows (ANSI & UNICODE) and Linux.

http://maragnus.com/upload/irr-io-ifile ... ions.patch

-- /EDIT --

In the spirit of sharing, here are a couple extensions to Irrlicht that I've put into my projects. Also included is the hard to find method of getting the path to the Saved Games folder in Windows Vista and 7 with backwards compatibility with XP.

CFileSystem::existDirectory

This function tests if the provided path is an existing directory. The path must exist and it must be a directory to return true. Should work on all OSes.

You must include this for Windows.

Code: Select all

#if defined(_MSC_VER)
#include <sys/stat.h>
#endif

//! Returns true if filename points to an existing directory
bool CFileSystem::existDirectory(const io::path& filename)
{
#if defined(_MSC_VER)
#if defined(_IRR_WCHAR_FILESYSTEM)
	struct _stat stat;
	if (_wstat(filename.c_str(), &stat) != 0)
		return false;
	return (stat.st_mode & _S_IFDIR) != 0;
#else
	struct _stat stat;
	if (_stat(filename.c_str(), &stat) != 0)
		return false;
	return (stat.st_mode & _S_IFDIR) != 0;
#endif
#else
	struct stat stat;
	if (stat(filename.c_str(), &stat) != 0)
		return false;
	return (stat.st_mode & S_IFDIR) != 0;
#endif
}	
CFileSystem::createDirectories

This function creates the directories for the provided filename. If the entire filename is the path, suffix it with a slash.

IE #1: createDirectories("saves/world1/scene.xml") will make sure that the path leading up to scene.xml exists.
IE #2: createDirectories("saves/world1/") will do the same thing without the filename.

Code: Select all

//! Creates the directory structure for a file recursively.
bool CFileSystem::createDirectories(const io::path& filename)
{
	io::path path = getAbsolutePath(filename);
	path += "/";

#if defined(_IRR_WINDOWS_API_) && defined(_IRR_WCHAR_FILESYSTEM)
	for (int pos = path.findNext(L'/', 1); pos > 0; pos = path.findNext(L'/', pos+1))
#else
	for (int pos = path.findNext('/', 1); pos > 0; pos = path.findNext('/', pos+1))
#endif
	{
#if defined(_IRR_WINDOWS_API_) && !defined(_IRR_WINDOWS_CE_PLATFORM_)
		if (pos > 1 && path[pos-1] == L':')
			continue;
#endif
		io::path cur = path.subString(0, pos);
		if (existDirectory(cur))
			continue;
#if defined(_IRR_WINDOWS_API_) 
#if defined(_IRR_WCHAR_FILESYSTEM)
		if (_wmkdir(cur.c_str()) != 0)
			return false;
#else
		if (_mkdir(cur.c_str()) != 0)
			return false;
#endif
#else
		if (mkdir(cur.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
			return false;
#endif
	}
	return true;
}
getSavePath

Lastly, for Windows Vista and 7, I wanted to utilize the Saved Games folder. Windows XP doesn't even have the function that requests the folder, so I needed to get fancy and load the function dynamically. Windows XP defaults to My Documents\My Games

Obviously, this is Windows-only code and requires at least Windows 2000 or Windows XP. Haven't tested on anything earlier. You'll want to do a recursive mkdir on the returned value. I coded this with UNICODE defined, without it, you'll have to MultiByteToWideChar() the result from SHGetKnownFolderPath as there is no ASCII version.

Code: Select all

#include <shlobj.h>

#define PRODUCT_TITLE TEXT("Your Game Name")

typedef HRESULT (WINAPI *PSHGetKnownFolderPath)(const GUID &rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath); // free *ppszPath with CoTaskMemFree

irr::io::path getSavePath()
{
	// Get Save Path
	irr::io::path savepath;
	DWORD winver = GetVersion();
	if ((DWORD)(LOBYTE(LOWORD(winver))) >= 6)
	{
		CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
		PWSTR svgmpath = NULL;
		HMODULE shell = GetModuleHandle(TEXT("shell32.dll"));
		PSHGetKnownFolderPath GetKnownFolderPath = (PSHGetKnownFolderPath)GetProcAddress(shell, "SHGetKnownFolderPath");
		const GUID FOLDERID_SavedGames = {0x4C5C32FF, 0xBB9D, 0x43b0, {0xB5, 0xB4, 0x2D, 0x72, 0xE5, 0x4E, 0xAA, 0xA4}};
		GetKnownFolderPath(FOLDERID_SavedGames, KF_FLAG_CREATE | KF_FLAG_NO_ALIAS, NULL, &svgmpath);
		savepath = svgmpath;
		CoTaskMemFree(svgmpath);
		CoUninitialize();
	}
	else if ((DWORD)(LOBYTE(LOWORD(winver))) == 5)
	{
		WCHAR svgmpath[MAX_PATH];
		SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, svgmpath);
		wcscat_s(svgmpath, MAX_PATH, TEXT("\\My Games"));
		savepath = svgmpath;
	}
	else
	{
		MessageBox(NULL, TEXT("Windows XP or later is required."), PRODUCT_TITLE, MB_ICONERROR);
		ExitProcess(1);
		return 0;
	}
	savepath += TEXT("\\") PRODUCT_TITLE TEXT("\\");
	return savepath;
}
Post Reply