diff options
Diffstat (limited to 'src/shared')
| -rw-r--r-- | src/shared/directoryentry.cpp | 125 | ||||
| -rw-r--r-- | src/shared/directoryentry.h | 88 | ||||
| -rw-r--r-- | src/shared/util.cpp | 12 | ||||
| -rw-r--r-- | src/shared/util.h | 8 |
4 files changed, 176 insertions, 57 deletions
diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 97da1061..639d6cac 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -482,6 +482,8 @@ const std::wstring &DirectoryEntry::getName() const void DirectoryEntry::clear()
{
m_Files.clear();
+ m_FilesLookup.clear();
+
for (DirectoryEntry *entry : m_SubDirectories) {
delete entry;
}
@@ -663,6 +665,8 @@ void DirectoryEntry::removeDirRecursive() m_FileRegister->removeFile(m_Files.begin()->second);
}
+ m_FilesLookup.clear();
+
for (DirectoryEntry *entry : m_SubDirectories) {
entry->removeDirRecursive();
delete entry;
@@ -709,6 +713,56 @@ void DirectoryEntry::removeDir(const std::wstring &path) }
}
+bool DirectoryEntry::remove(const std::wstring &fileName, int *origin)
+{
+ const auto lcFileName = ToLowerCopy(fileName);
+
+ auto iter = m_Files.find(lcFileName);
+ bool b = false;
+
+ if (iter != m_Files.end()) {
+ if (origin != nullptr) {
+ FileEntry::Ptr entry = m_FileRegister->getFile(iter->second);
+ if (entry.get() != nullptr) {
+ bool ignore;
+ *origin = entry->getOrigin(ignore);
+ }
+ }
+
+ b = m_FileRegister->removeFile(iter->second);
+ }
+
+ if (m_Files.size() != m_FilesLookup.size()) {
+ DebugBreak();
+ }
+
+ return b;
+}
+
+void DirectoryEntry::insert(
+ const std::wstring &fileName, FilesOrigin &origin, FILETIME fileTime,
+ const std::wstring &archive, int order)
+{
+ std::wstring fileNameLower = ToLowerCopy(fileName);
+ auto iter = m_Files.find(fileNameLower);
+ FileEntry::Ptr file;
+
+ if (iter != m_Files.end()) {
+ file = m_FileRegister->getFile(iter->second);
+ } else {
+ file = m_FileRegister->createFile(fileName, this);
+ m_Files.emplace(fileNameLower, file->getIndex());
+ m_FilesLookup.emplace(fileNameLower, file->getIndex());
+ }
+
+ if (m_Files.size() != m_FilesLookup.size()) {
+ DebugBreak();
+ }
+
+ file->addOrigin(origin.getID(), fileTime, archive, order);
+ origin.addFile(file->getIndex());
+}
+
bool DirectoryEntry::hasContentsFromOrigin(int originID) const
{
return m_Origins.find(originID) != m_Origins.end();
@@ -726,13 +780,34 @@ void DirectoryEntry::insertFile(const std::wstring &filePath, FilesOrigin &origi }
}
-
void DirectoryEntry::removeFile(FileEntry::Index index)
{
+ if (!m_FilesLookup.empty()) {
+ auto iter = std::find_if(
+ m_FilesLookup.begin(), m_FilesLookup.end(),
+ [&index](auto&& pair) { return (pair.second == index); }
+ );
+
+ if (iter != m_FilesLookup.end()) {
+ m_FilesLookup.erase(iter);
+ } else {
+ log::error(
+ "file \"{}\" not in directory for lookup \"{}\"",
+ m_FileRegister->getFile(index)->getName(), this->getName());
+ }
+ } else {
+ log::error(
+ "file \"{}\" not in directory \"{}\" for lookup, directory empty",
+ m_FileRegister->getFile(index)->getName(), this->getName());
+ }
+
if (!m_Files.empty()) {
- auto iter = std::find_if(m_Files.begin(), m_Files.end(),
- [&index](const std::pair<std::wstring, FileEntry::Index> &iter) -> bool {
- return iter.second == index; } );
+ auto iter = std::find_if(
+ m_Files.begin(), m_Files.end(),
+ [&index](const std::pair<std::wstring, FileEntry::Index> &iter) -> bool {
+ return iter.second == index; }
+ );
+
if (iter != m_Files.end()) {
m_Files.erase(iter);
} else {
@@ -745,14 +820,25 @@ void DirectoryEntry::removeFile(FileEntry::Index index) QObject::tr("file \"{}\" not in directory \"{}\", directory empty").toStdString(),
m_FileRegister->getFile(index)->getName(), this->getName());
}
-}
+ if (m_Files.size() != m_FilesLookup.size()) {
+ DebugBreak();
+ }
+}
void DirectoryEntry::removeFiles(const std::set<FileEntry::Index> &indices)
{
for (auto iter = m_Files.begin(); iter != m_Files.end();) {
if (indices.find(iter->second) != indices.end()) {
- m_Files.erase(iter++);
+ iter = m_Files.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+
+ for (auto iter = m_FilesLookup.begin(); iter != m_FilesLookup.end();) {
+ if (indices.find(iter->second) != indices.end()) {
+ iter = m_FilesLookup.erase(iter);
} else {
++iter;
}
@@ -851,7 +937,7 @@ const FileEntry::Ptr DirectoryEntry::searchFile(const std::wstring &path, const if (len == std::string::npos) {
// no more path components
- auto iter = m_Files.find(ToLower(path));
+ auto iter = m_Files.find(ToLowerCopy(path));
if (iter != m_Files.end()) {
return m_FileRegister->getFile(iter->second);
} else if (directory != nullptr) {
@@ -884,7 +970,7 @@ DirectoryEntry *DirectoryEntry::findSubDirectory( if (alreadyLowerCase) {
itor = m_SubDirectoriesMap.find(name);
} else {
- itor = m_SubDirectoriesMap.find(ToLower(name));
+ itor = m_SubDirectoriesMap.find(ToLowerCopy(name));
}
if (itor == m_SubDirectoriesMap.end()) {
@@ -904,15 +990,26 @@ DirectoryEntry *DirectoryEntry::findSubDirectoryRecursive(const std::wstring &pa const FileEntry::Ptr DirectoryEntry::findFile(
const std::wstring &name, bool alreadyLowerCase) const
{
- std::map<std::wstring, FileEntry::Index>::const_iterator iter;
+ FilesLookup::const_iterator iter;
if (alreadyLowerCase) {
- iter = m_Files.find(name);
+ iter = m_FilesLookup.find(FileKey(name));
} else {
- iter = m_Files.find(ToLower(name));
+ iter = m_FilesLookup.find(FileKey(ToLowerCopy(name)));
}
- if (iter != m_Files.end()) {
+ if (iter != m_FilesLookup.end()) {
+ return m_FileRegister->getFile(iter->second);
+ } else {
+ return FileEntry::Ptr();
+ }
+}
+
+const FileEntry::Ptr DirectoryEntry::findFile(const FileKey& key) const
+{
+ auto iter = m_FilesLookup.find(key);
+
+ if (iter != m_FilesLookup.end()) {
return m_FileRegister->getFile(iter->second);
} else {
return FileEntry::Ptr();
@@ -921,7 +1018,7 @@ const FileEntry::Ptr DirectoryEntry::findFile( bool DirectoryEntry::hasFile(const std::wstring& name) const
{
- return m_Files.contains(ToLower(name));
+ return m_Files.contains(ToLowerCopy(name));
}
DirectoryEntry *DirectoryEntry::getSubDirectory(const std::wstring &name, bool create, int originID)
@@ -936,7 +1033,7 @@ DirectoryEntry *DirectoryEntry::getSubDirectory(const std::wstring &name, bool c name, this, originID, m_FileRegister, m_OriginConnection);
m_SubDirectories.push_back(entry);
- m_SubDirectoriesMap.emplace(ToLower(name), entry);
+ m_SubDirectoriesMap.emplace(ToLowerCopy(name), entry);
return entry;
} else {
diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index 79bc5cf2..fc68cae7 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -35,6 +35,20 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #endif
#include "util.h"
+namespace MOShared { struct DirectoryEntryFileKey; }
+
+namespace std
+{
+ template <>
+ struct hash<MOShared::DirectoryEntryFileKey>
+ {
+ using argument_type = MOShared::DirectoryEntryFileKey;
+ using result_type = std::size_t;
+
+ inline result_type operator()(const argument_type& key) const;
+ };
+}
+
namespace MOShared {
@@ -203,9 +217,32 @@ private: };
+struct DirectoryEntryFileKey
+{
+ DirectoryEntryFileKey(std::wstring v)
+ : value(std::move(v)), hash(getHash(value))
+ {
+ }
+
+ bool operator==(const DirectoryEntryFileKey& o) const
+ {
+ return (value == o.value);
+ }
+
+ static std::size_t getHash(const std::wstring& value)
+ {
+ return std::hash<std::wstring>()(value);
+ }
+
+ const std::wstring value;
+ const std::size_t hash;
+};
+
+
class DirectoryEntry
{
public:
+ using FileKey = DirectoryEntryFileKey;
DirectoryEntry(const std::wstring &name, DirectoryEntry *parent, int originID);
@@ -294,6 +331,7 @@ public: * @return fileentry object for the file or nullptr if no file matches
*/
const FileEntry::Ptr findFile(const std::wstring &name, bool alreadyLowerCase=false) const;
+ const FileEntry::Ptr findFile(const FileKey& key) const;
bool hasFile(const std::wstring& name) const;
bool containsArchive(std::wstring archiveName);
@@ -315,21 +353,7 @@ public: */
void removeDir(const std::wstring &path);
- bool remove(const std::wstring &fileName, int *origin) {
- auto iter = m_Files.find(ToLower(fileName));
- if (iter != m_Files.end()) {
- if (origin != nullptr) {
- FileEntry::Ptr entry = m_FileRegister->getFile(iter->second);
- if (entry.get() != nullptr) {
- bool ignore;
- *origin = entry->getOrigin(ignore);
- }
- }
- return m_FileRegister->removeFile(iter->second);
- } else {
- return false;
- }
- }
+ bool remove(const std::wstring &fileName, int *origin);
bool hasContentsFromOrigin(int originID) const;
@@ -342,20 +366,9 @@ private: DirectoryEntry(const DirectoryEntry &reference);
DirectoryEntry &operator=(const DirectoryEntry &reference);
- void insert(const std::wstring &fileName, FilesOrigin &origin, FILETIME fileTime, const std::wstring &archive, int order) {
- std::wstring fileNameLower = ToLower(fileName);
- auto iter = m_Files.find(fileNameLower);
- FileEntry::Ptr file;
- if (iter != m_Files.end()) {
- file = m_FileRegister->getFile(iter->second);
- } else {
- file = m_FileRegister->createFile(fileName, this);
- // TODO this has been observed to cause a crash, no clue why
- m_Files[fileNameLower] = file->getIndex();
- }
- file->addOrigin(origin.getID(), fileTime, archive, order);
- origin.addFile(file->getIndex());
- }
+ void insert(
+ const std::wstring &fileName, FilesOrigin &origin, FILETIME fileTime,
+ const std::wstring &archive, int order);
void addFiles(FilesOrigin &origin, wchar_t *buffer, int bufferOffset);
void addFiles(FilesOrigin &origin, BSA::Folder::Ptr archiveFolder, FILETIME &fileTime, const std::wstring &archiveName, int order);
@@ -367,13 +380,16 @@ private: void removeDirRecursive();
private:
+ using FilesMap = std::map<std::wstring, FileEntry::Index>;
+ using FilesLookup = std::unordered_map<FileKey, FileEntry::Index>;
using SubDirectoriesMap = std::unordered_map<std::wstring, DirectoryEntry*>;
boost::shared_ptr<FileRegister> m_FileRegister;
boost::shared_ptr<OriginConnection> m_OriginConnection;
std::wstring m_Name;
- std::map<std::wstring, FileEntry::Index> m_Files;
+ FilesMap m_Files;
+ FilesLookup m_FilesLookup;
std::vector<DirectoryEntry*> m_SubDirectories;
SubDirectoriesMap m_SubDirectoriesMap;
@@ -386,7 +402,17 @@ private: };
-
} // namespace MOShared
+
+namespace std
+{
+ hash<MOShared::DirectoryEntryFileKey>::result_type
+ hash<MOShared::DirectoryEntryFileKey>::operator()(
+ const argument_type& key) const
+ {
+ return key.hash;
+ }
+}
+
#endif // DIRECTORYENTRY_H
diff --git a/src/shared/util.cpp b/src/shared/util.cpp index 4ac95465..009aad70 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -102,32 +102,28 @@ static auto locToLower = [] (char in) -> char { return std::tolower(in, loc);
};
-std::string &ToLower(std::string &text)
+std::string& ToLowerInPlace(std::string& text)
{
- //std::transform(text.begin(), text.end(), text.begin(), locToLower);
CharLowerBuffA(const_cast<CHAR *>(text.c_str()), static_cast<DWORD>(text.size()));
return text;
}
-std::string ToLower(const std::string &text)
+std::string ToLowerCopy(const std::string& text)
{
std::string result(text);
- //std::transform(result.begin(), result.end(), result.begin(), locToLower);
CharLowerBuffA(const_cast<CHAR *>(result.c_str()), static_cast<DWORD>(result.size()));
return result;
}
-std::wstring &ToLower(std::wstring &text)
+std::wstring& ToLowerInPlace(std::wstring& text)
{
- //std::transform(text.begin(), text.end(), text.begin(), locToLowerW);
CharLowerBuffW(const_cast<WCHAR *>(text.c_str()), static_cast<DWORD>(text.size()));
return text;
}
-std::wstring ToLower(const std::wstring &text)
+std::wstring ToLowerCopy(const std::wstring& text)
{
std::wstring result(text);
- //std::transform(result.begin(), result.end(), result.begin(), locToLowerW);
CharLowerBuffW(const_cast<WCHAR *>(result.c_str()), static_cast<DWORD>(result.size()));
return result;
}
diff --git a/src/shared/util.h b/src/shared/util.h index 788d2444..79cadf71 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -36,11 +36,11 @@ bool FileExists(const std::wstring &searchPath, const std::wstring &filename); std::string ToString(const std::wstring &source, bool utf8);
std::wstring ToWString(const std::string &source, bool utf8);
-std::string &ToLower(std::string &text);
-std::string ToLower(const std::string &text);
+std::string& ToLowerInPlace(std::string& text);
+std::string ToLowerCopy(const std::string& text);
-std::wstring &ToLower(std::wstring &text);
-std::wstring ToLower(const std::wstring &text);
+std::wstring& ToLowerInPlace(std::wstring& text);
+std::wstring ToLowerCopy(const std::wstring& text);
bool CaseInsensitiveEqual(const std::wstring &lhs, const std::wstring &rhs);
|
