#include "../../Platform/stdafx.h" #include "FileFilter.h" #include "../../Level/Storage/McRegionLevelStorageSource.h" #include "File.h" #include "PathHelper.h" #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) #include #include #endif #ifdef __PS3__ #include #endif #ifdef __PSVITA__ #include #endif const wchar_t File::pathSeparator = L'/'; #ifdef _XBOX const std::wstring File::pathRoot = L"GAME:"; // Path root after pathSeparator has been removed #else const std::wstring File::pathRoot = L""; // Path root after pathSeparator has been removed #endif #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) namespace { namespace fs = std::filesystem; fs::path ToFilesystemPath(const std::wstring& path) { const std::string nativePath = wstringtofilename(path); return fs::path(nativePath); } std::wstring ToFilename(const fs::path& path) { const std::string filename = path.filename().string(); return filenametowstring(filename.c_str()); } int64_t ToEpochMilliseconds(const fs::file_time_type& fileTime) { using namespace std::chrono; const auto systemTime = time_point_cast( fileTime - fs::file_time_type::clock::now() + system_clock::now()); return static_cast(systemTime.time_since_epoch().count()); } } // namespace #endif // Creates a new File instance from a parent abstract pathname and a child // pathname string. File::File(const File& parent, const std::wstring& child) { m_abstractPathName = parent.getPath() + pathSeparator + child; } // Creates a new File instance by converting the given pathname string into an // abstract pathname. File::File(const std::wstring& pathname) { if (pathname.empty()) { m_abstractPathName = L""; return; } std::wstring fixedPath = pathname; for (size_t i = 0; i < fixedPath.length(); ++i) { if (fixedPath[i] == L'\\') fixedPath[i] = L'/'; } size_t dpos; while ((dpos = fixedPath.find(L"//")) != std::wstring::npos) fixedPath.erase(dpos, 1); if (fixedPath.find(L"GAME:/") == 0) fixedPath = fixedPath.substr(6); m_abstractPathName = fixedPath; #if defined(__linux__) std::string request = wstringtofilename(m_abstractPathName); while (!request.empty() && request[0] == '/') request.erase(0, 1); if (request.find("res/") == 0) request.erase(0, 4); std::string exeDir = PathHelper::GetExecutableDirA(); std::string fileName = request; size_t lastSlash = fileName.find_last_of('/'); if (lastSlash != std::string::npos) fileName = fileName.substr(lastSlash + 1); const char* bases[] = {"/", "/Common/res/TitleUpdate/res/", "/Common/Media/", "/Common/res/", "/Common/", "/Minecraft.Assets/"}; for (const char* base : bases) { std::string tryFull = exeDir + base + request; std::string tryFile = exeDir + base + fileName; if (access(tryFull.c_str(), F_OK) != -1) { m_abstractPathName = convStringToWstring(tryFull); return; } if (access(tryFile.c_str(), F_OK) != -1) { m_abstractPathName = convStringToWstring(tryFile); return; } } #endif #ifdef _WINDOWS64 std::string path = wstringtofilename(m_abstractPathName); std::string finalPath = StorageManager.GetMountedPath(path.c_str()); if (finalPath.size() == 0) finalPath = path; m_abstractPathName = convStringToWstring(finalPath); #elif defined(_DURANGO) std::wstring finalPath = StorageManager.GetMountedPath(m_abstractPathName.c_str()); if (finalPath.size() == 0) finalPath = m_abstractPathName; m_abstractPathName = finalPath; #endif /* std::vector path = stringSplit( pathname, pathSeparator ); if( path.back().compare( pathRoot ) != 0 ) m_abstractPathName = path.back(); else m_abstractPathName = L""; path.pop_back(); if( path.size() > 0 ) { // If the last member of the vector is the root then just stop if( path.back().compare( pathRoot ) != 0 ) this->parent = new File( &path ); else this->parent = NULL; } */ } File::File(const std::wstring& parent, const std::wstring& child) //: m_abstractPathName( child ) { m_abstractPathName = pathRoot + pathSeparator + parent + pathSeparator + child; // this->parent = new File( parent ); } // Creates a new File instance by converting the given path vector into an // abstract pathname. /* File::File( std::vector *path ) : parent( NULL ) { m_abstractPathName = path->back(); path->pop_back(); if( path->size() > 0 ) { // If the last member of the vector is the root then just stop if( path->back().compare( pathRoot ) != 0 ) this->parent = new File( path ); else this->parent = NULL; } } */ // Deletes the file or directory denoted by this abstract pathname. If this // pathname denotes a directory, then the directory must be empty in order to be // deleted. Returns: true if and only if the file or directory is successfully // deleted; false otherwise bool File::_delete() { #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; const bool result = fs::remove(ToFilesystemPath(getPath()), error); #if defined _UNICODE if (!result || error) { #ifndef _CONTENT_PACKAGE printf("File::_delete - Error code %d (%#0.8X)\n", error.value(), error.value()); #endif return false; } return true; #elif defined(__linux__) if (!result || error) { printf("Unable to delete file :("); return false; } return true; #else if (!result || error) { #ifndef _CONTENT_PACKAGE printf("File::_delete - Error code %d (%#0.8X)\n", error.value(), error.value()); #endif return false; } return true; #endif #elif defined _UNICODE const bool result = DeleteFile(getPath().c_str()) != 0; #elif defined(__linux__) // FIXME const bool result = false; #else const bool result = DeleteFile(wstringtofilename(getPath())) != 0; #endif if (!result) { #if !defined(__linux__) const unsigned int error = GetLastError(); #ifndef _CONTENT_PACKAGE printf("File::_delete - Error code %d (%#0.8X)\n", error, error); #endif #else printf("Unable to delete file :("); #endif return false; } else return true; } // Creates the directory named by this abstract pathname. // Returns: // true if and only if the directory was created; false otherwise bool File::mkdir() const { #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; return fs::create_directory(ToFilesystemPath(getPath()), error); #elif defined(_UNICODE) return CreateDirectory(getPath().c_str(), NULL) != 0; #elif defined(__linux__) return ::mkdir(wstringtofilename(getPath()), 0777) == 0; #else return CreateDirectory(wstringtofilename(getPath()), NULL) != 0; #endif } // Creates the directory named by this abstract pathname, including any // necessary but nonexistent parent directories. Note that if this // operation fails it may have succeeded in creating some of the necessary // parent directories. // //@return true if and only if the directory was created, // along with all necessary parent directories; false // otherwise // //@throws SecurityException // If a security manager exists and its {@link // java.lang.SecurityManager#checkRead(java.lang.String)} // method does not permit verification of the existence of the // named directory and all necessary parent directories; or if // the {@link // java.lang.SecurityManager#checkWrite(java.lang.String)} // method does not permit the named directory and all necessary // parent directories to be created // bool File::mkdirs() const { #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; const fs::path path = ToFilesystemPath(getPath()); if (fs::exists(path, error)) { return fs::is_directory(path, error); } if (error) { return false; } return fs::create_directories(path, error); #else std::vector path = stringSplit(m_abstractPathName, pathSeparator); std::wstring pathToHere = L""; AUTO_VAR(itEnd, path.end()); for (AUTO_VAR(it, path.begin()); it != itEnd; it++) { // If this member of the vector is the root then just skip to the next if (pathRoot.compare(*it) == 0) { pathToHere = *it; continue; } pathToHere = pathToHere + pathSeparator + *it; // if not exists #ifdef _UNICODE if (GetFileAttributes(pathToHere.c_str()) == -1) { const bool result = CreateDirectory(pathToHere.c_str(), NULL) != 0; if (!result) { // Failed to create return false; } } #elif defined(__linux__) const char* mkpath = wstringtofilename(getPath()); struct stat info; if (stat(mkpath, &info) != 0 || !(info.st_mode & S_IFDIR)) { if (::mkdir(mkpath, 0777) != 0) { return false; } } #else if (GetFileAttributes(wstringtofilename(pathToHere)) == -1) { const bool result = CreateDirectory(wstringtofilename(pathToHere), NULL) != 0; if (!result) { // Failed to create return false; } } #endif } // We should now exist assert(exists()); return true; #endif } /* File *File::getParent() const { return (File *) parent; } */ // Tests whether the file or directory denoted by this abstract pathname exists. // Returns: // true if and only if the file or directory denoted by this abstract pathname // exists; false otherwise bool File::exists() const { // TODO 4J Stu - Possible we could get an error result from something other // than the file not existing? #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; return fs::exists(ToFilesystemPath(getPath()), error); #elif defined(_UNICODE) return GetFileAttributes(getPath().c_str()) != -1; #elif defined(__linux__) // BAD DOBBY BAD DOBBY return access(wstringtofilename(getPath()), F_OK) != -1; #else return GetFileAttributes(wstringtofilename(getPath())) != -1; #endif } // Tests whether the file denoted by this abstract pathname is a normal file. A // file is normal if it is not a directory and, in addition, satisfies other // system-dependent criteria. Any non-directory file created by a Java // application is guaranteed to be a normal file. Returns: true if and only if // the file denoted by this abstract pathname exists and is a normal file; false // otherwise bool File::isFile() const { return exists() && !isDirectory(); } // Renames the file denoted by this abstract pathname. // Whether or not this method can move a file from one filesystem to another is // platform-dependent. The return value should always be checked to make sure // that the rename operation was successful. // // Parameters: // dest - The new abstract pathname for the named file // Returns: // true if and only if the renaming succeeded; false otherwise bool File::renameTo(File dest) { #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; fs::rename(ToFilesystemPath(getPath()), ToFilesystemPath(dest.getPath()), error); if (error) { perror("File::renameTo - Error renaming file"); return false; } return true; #else std::string sourcePath = wstringtofilename(getPath()); std::string destPath = wstringtofilename(dest.getPath()); int result = rename(sourcePath.c_str(), destPath.c_str()); if (result != 0) { perror("File::renameTo - Error renaming file"); return false; } else { return true; } #endif } // Returns an array of abstract pathnames denoting the files in the directory // denoted by this abstract pathname. If this abstract pathname does not denote // a directory, then this method returns null. Otherwise an array of File // objects is returned, one for each file or directory in the directory. // Pathnames denoting the directory itself and the directory's parent directory // are not included in the result. Each resulting abstract pathname is // constructed from this abstract pathname using the File(File, String) // constructor. Therefore if this pathname is absolute then each resulting // pathname is absolute; if this pathname is relative then each resulting // pathname will be relative to the same directory. // // There is no guarantee that the name strings in the resulting array will // appear in any specific order; they are not, in particular, guaranteed to // appear in alphabetical order. // // Returns: // An array of abstract pathnames denoting the files and directories in the // directory denoted by this abstract pathname. The array will be empty if the // directory is empty. Returns null if this abstract pathname does not denote a // directory, or if an I/O error occurs. std::vector* File::listFiles() const { std::vector* vOutput = new std::vector(); // TODO 4J Stu - Also need to check for I/O errors? if (!isDirectory()) return vOutput; #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; for (fs::directory_iterator it(ToFilesystemPath(getPath()), error); !error && it != fs::directory_iterator(); it.increment(error)) { vOutput->push_back(new File(*this, ToFilename(it->path()))); } #else #ifdef __PS3__ const char* lpFileName = wstringtofilename(getPath()); char filePath[256]; std::string mountedPath = StorageManager.GetMountedPath(lpFileName); if (mountedPath.length() > 0) { strcpy(filePath, mountedPath.c_str()); } else if (lpFileName[0] == '/') // already fully qualified path strcpy(filePath, lpFileName); else sprintf(filePath, "%s/%s", getUsrDirPath(), lpFileName); int fd; CellFsErrno err = cellFsOpendir(filePath, &fd); CellFsDirectoryEntry de; std::uint32_t count = 0; err = cellFsGetDirectoryEntries(fd, &de, sizeof(CellFsDirectoryEntry), &count); if (count != 0) { do { if (de.attribute.st_mode & CELL_FS_S_IFREG) vOutput->push_back( new File(*this, filenametowstring(de.entry_name.d_name))); err = cellFsGetDirectoryEntries( fd, &de, sizeof(CellFsDirectoryEntry), &count); } while (count); } err = cellFsClose(fd); #elif defined __ORBIS__ || defined __PSVITA__ const char* lpFileName = wstringtofilename(getPath()); char filePath[256]; std::string mountedPath = StorageManager.GetMountedPath(lpFileName); if (mountedPath.length() > 0) { strcpy(filePath, mountedPath.c_str()); } else if (lpFileName[0] == '/') // already fully qualified path strcpy(filePath, lpFileName); else sprintf(filePath, "%s/%s", getUsrDirPath(), lpFileName); bool exists = sceFiosDirectoryExistsSync(NULL, filePath); if (!exists) { app.DebugPrintf( "\nsceFiosDirectoryExistsSync - Directory doesn't exist\n"); } // CD - Vita note: sceFiosDHOpenSync returns SCE_FIOS_ERROR_UNIMPLEMENTED // CD - The Handle also returns as 0 [dh], sceFiosDHOpen could also be // failing CD - Hence, this fails stating 0 files in directory SceFiosDH dh = SCE_FIOS_DH_INVALID; SceFiosBuffer buf; buf.length = 0; SceFiosOp op = sceFiosDHOpen(NULL, &dh, filePath, buf); int err = sceFiosOpWait(op); if (err != SCE_FIOS_OK) { app.DebugPrintf("\nsceFiosOpWait = 0x%x\n", err); } SceFiosSize size = sceFiosOpGetActualCount(op); char* pBuf = new char[size]; buf.set(pBuf, (size_t)size); sceFiosOpDelete(op); sceFiosDHClose(NULL, dh); err = sceFiosDHOpenSync(NULL, &dh, filePath, buf); if (err != SCE_FIOS_OK) { app.DebugPrintf("\nsceFiosDHOpenSync = 0x%x\n", err); } SceFiosDirEntry entry; ZeroMemory(&entry, sizeof(SceFiosDirEntry)); err = sceFiosDHReadSync(NULL, dh, &entry); while (err == SCE_FIOS_OK) { vOutput->push_back(new File( *this, filenametowstring(entry.fullPath + entry.offsetToName))); ZeroMemory(&entry, sizeof(SceFiosDirEntry)); err = sceFiosDHReadSync(NULL, dh, &entry); }; sceFiosDHClose(NULL, dh); delete pBuf; #else #if defined(__linux__) struct stat wfd; #else // _WIN32 WIN32_FIND_DATA wfd; #endif // __linux__ #ifdef _UNICODE WCHAR path[MAX_PATH]; swprintf(path, L"%ls\\*", getPath().c_str()); HANDLE hFind = FindFirstFile(path, &wfd); if (hFind != INVALID_HANDLE_VALUE) { int count = 0; do { vOutput->push_back(new File(*this, wfd.cFileName)); } while (FindNextFile(hFind, &wfd)); FindClose(hFind); } #elif defined(__linux__) char path[MAX_PATH]; ::listFiles(path); #else char path[MAX_PATH]; sprintf(path, "%s\\*", wstringtofilename(getPath())); HANDLE hFind = FindFirstFile(path, &wfd); if (hFind != INVALID_HANDLE_VALUE) { // int count = 0; do { vOutput->push_back( new File(*this, filenametowstring(wfd.cFileName))); } while (FindNextFile(hFind, &wfd)); FindClose(hFind); } #endif #endif #endif return vOutput; } // Returns an array of abstract pathnames denoting the files and directories in // the directory denoted by this abstract pathname that satisfy the specified // filter. The behavior of this method is the same as that of the listFiles() // method, except that the pathnames in the returned array must satisfy the // filter. If the given filter is null then all pathnames are accepted. // Otherwise, a pathname satisfies the filter if and only if the value true // results when the FileFilter.accept(java.io.File) method of the filter is // invoked on the pathname. Parameters: filter - A file filter Returns: An array // of abstract pathnames denoting the files and directories in the directory // denoted by this abstract pathname. The array will be empty if the directory // is empty. Returns null if this abstract pathname does not denote a directory, // or if an I/O error occurs. std::vector* File::listFiles(FileFilter* filter) const { // TODO 4J Stu - Also need to check for I/O errors? if (!isDirectory()) return NULL; std::vector* vOutput = new std::vector(); #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; for (fs::directory_iterator it(ToFilesystemPath(getPath()), error); !error && it != fs::directory_iterator(); it.increment(error)) { File thisFile = File(*this, ToFilename(it->path())); if (filter->accept(&thisFile)) { vOutput->push_back(new File(thisFile)); } } #else #ifdef __PS3__ const char* lpFileName = wstringtofilename(getPath()); char filePath[256]; std::string mountedPath = StorageManager.GetMountedPath(lpFileName); if (mountedPath.length() > 0) { strcpy(filePath, mountedPath.c_str()); } else if (lpFileName[0] == '/') // already fully qualified path strcpy(filePath, lpFileName); else sprintf(filePath, "%s/%s", getUsrDirPath(), lpFileName); int fd; CellFsErrno err = cellFsOpendir(filePath, &fd); CellFsDirectoryEntry de; std::uint32_t count = 0; err = cellFsGetDirectoryEntries(fd, &de, sizeof(CellFsDirectoryEntry), &count); if (count != 0) { do { File thisFile = File(*this, filenametowstring(de.entry_name.d_name)); if (filter->accept(&thisFile)) { File storageFile = thisFile; if (de.attribute.st_mode & CELL_FS_S_IFREG) vOutput->push_back(&storageFile); } err = cellFsGetDirectoryEntries( fd, &de, sizeof(CellFsDirectoryEntry), &count); } while (count); } err = cellFsClose(fd); #else #ifdef _UNICODE WCHAR path[MAX_PATH]; WIN32_FIND_DATA wfd; swprintf(path, L"%ls\\*", getPath().c_str()); HANDLE hFind = FindFirstFile(path, &wfd); if (hFind != INVALID_HANDLE_VALUE) { int count = 0; do { File thisFile = File(*this, wfd.cFileName); if (filter->accept(&thisFile)) { File storageFile = thisFile; vOutput->push_back(&storageFile); } } while (FindNextFile(hFind, &wfd)); FindClose(hFind); } #elif defined(__linux__) char path[MAX_PATH]; ::listFiles(path); #else char path[MAX_PATH]; WIN32_FIND_DATA wfd; sprintf(path, "%s\\*", wstringtofilename(getPath())); HANDLE hFind = FindFirstFile(path, &wfd); if (hFind != INVALID_HANDLE_VALUE) { // int count = 0; do { File thisFile = File(*this, filenametowstring(wfd.cFileName)); if (filter->accept(&thisFile)) { File storageFile = thisFile; vOutput->push_back(&storageFile); } } while (FindNextFile(hFind, &wfd)); FindClose(hFind); } #endif #endif #endif return vOutput; } // Tests whether the file denoted by this abstract pathname is a directory. // Returns: // true if and only if the file denoted by this abstract pathname exists and is // a directory; false otherwise bool File::isDirectory() const { #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; return fs::is_directory(ToFilesystemPath(getPath()), error); #elif defined(_UNICODE) return exists() && (GetFileAttributes(getPath().c_str()) & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY; #elif defined(__linux__) const char* dirpath = wstringtofilename(getPath()); struct stat st; return stat(dirpath, &st) == 0 && S_ISDIR(st.st_mode); #else return exists() && (GetFileAttributes(wstringtofilename(getPath())) & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY; #endif } // Returns the length of the file denoted by this abstract pathname. The return // value is unspecified if this pathname denotes a directory. Returns: The // length, in bytes, of the file denoted by this abstract pathname, or 0L if the // file does not exist int64_t File::length() { #ifdef __PS3__ // extern const char* getPS3HomePath(); CellFsErrno err = 0; const char* lpFileName = wstringtofilename(getPath()); char filePath[256]; std::string mountedPath = StorageManager.GetMountedPath(lpFileName); if (mountedPath.length() > 0) { strcpy(filePath, mountedPath.c_str()); } else if (lpFileName[0] == '/') // already fully qualified path strcpy(filePath, lpFileName); else sprintf(filePath, "%s/%s", getUsrDirPath(), lpFileName); #ifndef _CONTENT_PACKAGE // printf("+++File::length - %s\n",filePath); #endif // check if the file exists first CellFsStat statData; err = cellFsStat(filePath, &statData); if (err != CELL_FS_SUCCEEDED) { // printf("+++File::length FAILED with %d\n",err); return 0; } if (statData.st_mode == CELL_FS_S_IFDIR) { // printf("+++File::length FAILED with %d\n",err); return 0; } // printf("+++File::length - %ll\n",statData.st_size); return statData.st_size; #elif defined __ORBIS__ || defined __PSVITA__ char filePath[256]; const char* lpFileName = wstringtofilename(getPath()); std::string mountedPath = StorageManager.GetMountedPath(lpFileName); if (mountedPath.length() > 0) { strcpy(filePath, mountedPath.c_str()); } else if (lpFileName[0] == '/') // already fully qualified path strcpy(filePath, lpFileName); else sprintf(filePath, "%s/%s", getUsrDirPath(), lpFileName); // check if the file exists first SceFiosStat statData; if (sceFiosStatSync(NULL, filePath, &statData) != SCE_FIOS_OK) { return 0; } if (statData.statFlags & SCE_FIOS_STATUS_DIRECTORY) { return 0; } return statData.fileSize; #elif !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; const fs::path path = ToFilesystemPath(getPath()); if (fs::is_regular_file(path, error)) { const auto size = fs::file_size(path, error); if (!error) { return static_cast(size); } } return 0; #else WIN32_FILE_ATTRIBUTE_DATA fileInfoBuffer; #ifdef _UNICODE const bool result = GetFileAttributesEx(getPath().c_str(), // file or directory name GetFileExInfoStandard, // attribute &fileInfoBuffer // attribute information ) != 0; #else const bool result = GetFileAttributesEx( wstringtofilename(getPath()), // file or directory name GetFileExInfoStandard, // attribute &fileInfoBuffer // attribute information ) != 0; #endif if (result && !((fileInfoBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) { // Success LARGE_INTEGER liFileSize; liFileSize.HighPart = fileInfoBuffer.nFileSizeHigh; liFileSize.LowPart = fileInfoBuffer.nFileSizeLow; return liFileSize.QuadPart; } else { // Fail or a Directory return 0l; } #endif } // Returns the time that the file denoted by this abstract pathname was last // modified. Returns: A long value representing the time the file was last // modified, measured in milliseconds since the epoch (00:00:00 GMT, January 1, // 1970), or 0L if the file does not exist or if an I/O error occurs int64_t File::lastModified() { #if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) std::error_code error; const fs::path path = ToFilesystemPath(getPath()); if (fs::is_regular_file(path, error)) { const fs::file_time_type lastWriteTime = fs::last_write_time(path, error); if (!error) { return ToEpochMilliseconds(lastWriteTime); } } return 0l; #elif !defined(__linux__) WIN32_FILE_ATTRIBUTE_DATA fileInfoBuffer; #ifdef _UNICODE const bool result = GetFileAttributesEx(getPath().c_str(), // file or directory name GetFileExInfoStandard, // attribute &fileInfoBuffer // attribute information ) != 0; #else const bool result = GetFileAttributesEx( wstringtofilename(getPath()), // file or directory name GetFileExInfoStandard, // attribute &fileInfoBuffer // attribute information ) != 0; #endif if (result && !((fileInfoBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) { // Success LARGE_INTEGER liLastModified; liLastModified.HighPart = fileInfoBuffer.ftLastWriteTime.dwHighDateTime; liLastModified.LowPart = fileInfoBuffer.ftLastWriteTime.dwLowDateTime; return liLastModified.QuadPart; } else { // Fail or a Directory return 0l; } #else struct stat fileStat; if (stat(wstringtofilename(getPath()), &fileStat) == 0 && !S_ISDIR(fileStat.st_mode)) { return static_cast(fileStat.st_mtime); } else { return 0l; } #endif } const std::wstring File::getPath() const { /* std::wstring path; if ( parent != NULL) path = parent->getPath(); else path = std::wstring(pathRoot); path.push_back( pathSeparator ); path.append(m_abstractPathName); */ return m_abstractPathName; } std::wstring File::getName() const { unsigned int sep = (unsigned int)(m_abstractPathName.find_last_of(this->pathSeparator)); return m_abstractPathName.substr(sep + 1, m_abstractPathName.length()); } bool File::eq_test(const File& x, const File& y) { return x.getPath().compare(y.getPath()) == 0; } // 4J TODO JEV, a better hash function may be nessesary. int File::hash_fnct(const File& k) { int hashCode = 0; // if (k->parent != NULL) // hashCode = hash_fnct(k->getParent()); wchar_t* ref = (wchar_t*)k.m_abstractPathName.c_str(); for (unsigned int i = 0; i < k.m_abstractPathName.length(); i++) { hashCode += ((hashCode * 33) + ref[i]) % 149; } return (int)hashCode; }