From 981f8b3acf7e76f27c02f4ced80d55b424cc7497 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 3 Feb 2013 12:49:25 +0100 Subject: initial commit to mercurial repository. Corresponds to MO version 0.12.6 --- src/shared/directoryentry.h | 313 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 src/shared/directoryentry.h (limited to 'src/shared/directoryentry.h') diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h new file mode 100644 index 00000000..72e96357 --- /dev/null +++ b/src/shared/directoryentry.h @@ -0,0 +1,313 @@ +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + +#ifndef DIRECTORYENTRY_H +#define DIRECTORYENTRY_H + +#include +#include +#include +#include +#include +#define WIN32_MEAN_AND_LEAN +#include +#include +#include +#include "util.h" + + +class DirectoryEntry; +class OriginConnection; +class FileRegister; + + +class FileEntry { + +public: + + typedef unsigned int Index; + +public: + + FileEntry() : m_Index(UINT_MAX), m_Name(), m_Parent(NULL) {} + + FileEntry(Index index, const std::wstring &name, DirectoryEntry *parent); + + Index getIndex() const { return m_Index; } + + void addOrigin(int origin, FILETIME fileTime, const std::wstring &archive); + // remove the specified origin from the list of origins that contain this file. if no origin is left, + // the file is effectively deleted and true is returned. otherwise, false is returned + bool removeOrigin(int origin); + void sortOrigins(); + + // gets the list of alternative origins (origins with lower priority than the primary one). + // if sortOrigins has been called, it is sorted by priority (ascending) + const std::vector &getAlternatives() const { return m_Alternatives; } + + const std::wstring &getName() const { return m_Name; } + int getOrigin(bool &archive) const { archive = (m_Archive.length() != 0); return m_Origin; } + const std::wstring &getArchive() const { return m_Archive; } + bool isFromArchive() const { return m_Archive.length() != 0; } + std::wstring getFullPath() const; + std::wstring getRelativePath() const; + DirectoryEntry *getParent() { return m_Parent; } + + void setFileTime(FILETIME fileTime) const { m_FileTime = fileTime; } + FILETIME getFileTime() const { return m_FileTime; } + +private: + + bool recurseParents(std::wstring &path, const DirectoryEntry *parent) const; + + void determineTime(); + +private: + + Index m_Index; + std::wstring m_Name; + int m_Origin; + std::wstring m_Archive; + std::vector m_Alternatives; + DirectoryEntry *m_Parent; + mutable FILETIME m_FileTime; + + friend bool operator<(const FileEntry &lhs, const FileEntry &rhs) { + return _wcsicmp(lhs.m_Name.c_str(), rhs.m_Name.c_str()) < 0; + } + friend bool operator==(const FileEntry &lhs, const FileEntry &rhs) { + return _wcsicmp(lhs.m_Name.c_str(), rhs.m_Name.c_str()) == 0; + } +}; + + +// represents a mod or the data directory, providing files to the tree +class FilesOrigin { + friend class OriginConnection; +public: + + FilesOrigin() + : m_ID(0), m_Disabled(false), m_Name(), m_Path(), m_Priority(0) { } + + // sets priority for this origin, but it will overwrite the exisiting mapping for this priority, + // the previous origin will no longer be referenced + void setPriority(int priority); + + int getPriority() const { return m_Priority; } + + void setName(const std::wstring &name); + const std::wstring &getName() const { return m_Name; } + + int getID() const { return m_ID; } + const std::wstring &getPath() const { return m_Path; } + + std::vector getFiles() const; + + void enable(bool enabled); + bool isDisabled() const { return m_Disabled; } + + void addFile(FileEntry::Index index) { m_Files.insert(index); } + void removeFile(FileEntry::Index index); + +private: + + FilesOrigin(int ID, const std::wstring &name, const std::wstring &path, int priority, + boost::shared_ptr fileRegister, boost::shared_ptr originConnection) + : m_ID(ID), m_Disabled(false), m_Name(name), m_Path(path), m_Priority(priority), + m_FileRegister(fileRegister), m_OriginConnection(originConnection) {} + +private: + + int m_ID; + + bool m_Disabled; + + std::set m_Files; + std::wstring m_Name; + std::wstring m_Path; + int m_Priority; + boost::shared_ptr m_FileRegister; + boost::shared_ptr m_OriginConnection; + +}; + + +class FileRegister +{ + +public: + + FileRegister(boost::shared_ptr originConnection); + + bool indexValid(FileEntry::Index index) const; + + FileEntry &createFile(const std::wstring &name, DirectoryEntry *parent); + FileEntry *getFile(FileEntry::Index index); + + void removeFile(FileEntry::Index index); + void removeOrigin(FileEntry::Index index, int originID); + + void sortOrigins(); + +private: + + FileEntry::Index generateIndex(); + + void unregisterFile(FileEntry &file); + +private: + + std::map m_Files; + + boost::shared_ptr m_OriginConnection; + +}; + + +class DirectoryEntry +{ +public: + + DirectoryEntry(const std::wstring &name, DirectoryEntry *parent, int originID); + + DirectoryEntry(const std::wstring &name, DirectoryEntry *parent, int originID, + boost::shared_ptr fileRegister, boost::shared_ptr originConnection); + + ~DirectoryEntry(); + + void clear(); + bool isPopulated() const { return m_Populated; } + + boost::shared_ptr getRegister() { return m_FileRegister; } + const DirectoryEntry *getParent() const { return m_Parent; } + + // add files to this directory (and subdirectories) from the specified origin. That origin may exist or not + void addFromOrigin(const std::wstring &originName, const std::wstring &directory, int priority); + void addFromBSA(const std::wstring &originName, std::wstring &directory, const std::wstring &fileName, int priority); + + const std::wstring &getName() const; + + boost::shared_ptr getFileRegister() { return m_FileRegister; } + + bool originExists(const std::wstring &name) const; + FilesOrigin &getOriginByID(int ID) const; + FilesOrigin &getOriginByName(const std::wstring &name) const; + + int getOrigin(const std::wstring &path, bool &archive); + + std::vector getFiles() const; + + void getSubDirectories(std::vector::const_iterator &begin, std::vector::const_iterator &end) const { + begin = m_SubDirectories.begin(); end = m_SubDirectories.end(); + } + + DirectoryEntry *findSubDirectory(const std::wstring &name) const; + + /** retrieve a file in this directory by name. + * @param name name of the file + * @return fileentry object for the file or NULL if no file matches + */ + const FileEntry *findFile(const std::wstring &name); + + /** search through this directory and all subdirectories for a file by the specified name. + if directory is not NULL, the referenced variable will be set to true if the path refers to a directory. + the returned pointer is NULL in that case */ + const FileEntry *searchFile(const std::wstring &path, const DirectoryEntry **directory) const; + + void insertFile(const std::wstring &filePath, FilesOrigin &origin, FILETIME fileTime); + + void removeFile(FileEntry::Index index); + + // remove the specified file from the tree. This can be a path leading to a file in a subdirectory + void removeFile(const std::wstring &filePath, int *origin = NULL); + + /** + * @brief remove the specified directory + * @param path directory to remove + */ + void removeDir(const std::wstring &path); + + void remove(const std::wstring &fileName, int *origin) { + auto iter = m_Files.find(fileName); + if (iter != m_Files.end()) { + if (origin != NULL) { + FileEntry *entry = m_FileRegister->getFile(iter->second); + if (entry != NULL) { + bool ignore; + *origin = entry->getOrigin(ignore); + } + } + m_FileRegister->removeFile(iter->second); + } + } + +private: + + void insert(const std::wstring &fileName, FilesOrigin &origin, FILETIME fileTime, const std::wstring &archive) { + auto iter = m_Files.find(fileName); + FileEntry *file = NULL; + if (iter != m_Files.end()) { + file = m_FileRegister->getFile(iter->second); + } else { + file = &m_FileRegister->createFile(fileName, this); + m_Files[fileName] = file->getIndex(); + } + file->addOrigin(origin.getID(), fileTime, archive); + origin.addFile(file->getIndex()); + } + + FilesOrigin &createOrigin(const std::wstring &originName, const std::wstring &directory, int priority); + void addFiles(FilesOrigin &origin, wchar_t *buffer, int bufferOffset); + void addFiles(FilesOrigin &origin, BSA::Folder::Ptr archiveFolder, FILETIME &fileTime, const std::wstring &archiveName); + + DirectoryEntry *getSubDirectory(const std::wstring &name, bool create, int originID = -1); + + DirectoryEntry *getSubDirectoryRecursive(const std::wstring &path, bool create, int originID = -1); + + int anyOrigin() const; + + void removeDirRecursive(); + +private: + + struct WStrLess { + bool operator()(const std::wstring &LHS, const std::wstring &RHS) const { + return _wcsicmp(LHS.c_str(), RHS.c_str()) < 0; + } + }; + + +private: + + boost::shared_ptr m_FileRegister; + boost::shared_ptr m_OriginConnection; + + std::wstring m_Name; + std::map m_Files; + std::vector m_SubDirectories; + + DirectoryEntry *m_Parent; + int m_Origin; + + bool m_Populated; + +}; + + +#endif // DIRECTORYENTRY_H -- cgit v1.3.1