From ea6292168a6acd4c263913f0ccd7dd64daf4f5cf Mon Sep 17 00:00:00 2001 From: Sandro Jäckel Date: Fri, 23 Feb 2018 01:45:58 +0100 Subject: Revert "Applied clang-format on source" This reverts commit 5e5c9c07291f6b09623d31c92b1fb61c4ede576e. --- src/shared/appconfig.cpp | 4 +- src/shared/appconfig.h | 4 +- src/shared/directoryentry.cpp | 1332 ++++++++++++++++++++++------------------- src/shared/directoryentry.h | 405 +++++++------ src/shared/error_report.cpp | 98 +-- src/shared/leaktrace.cpp | 70 ++- src/shared/leaktrace.h | 7 +- src/shared/stackdata.cpp | 219 +++---- src/shared/stackdata.h | 43 +- src/shared/util.cpp | 209 ++++--- src/shared/util.h | 23 +- src/shared/windows_error.cpp | 43 +- src/shared/windows_error.h | 14 +- 13 files changed, 1347 insertions(+), 1124 deletions(-) (limited to 'src/shared') diff --git a/src/shared/appconfig.cpp b/src/shared/appconfig.cpp index ebb72aba..49edcbcc 100644 --- a/src/shared/appconfig.cpp +++ b/src/shared/appconfig.cpp @@ -22,12 +22,12 @@ along with Mod Organizer. If not, see . namespace AppConfig { #define PARWSTRING wstring -#define APPPARAM(partype, parid, value) \ - partype parid() { return value; } +#define APPPARAM(partype, parid, value) partype parid () { return value; } #include "appconfig.inc" namespace MOShared { #undef PARWSTRING #undef APPPARAM + } } // namespace MOShared diff --git a/src/shared/appconfig.h b/src/shared/appconfig.h index b2dda14a..b32043e5 100644 --- a/src/shared/appconfig.h +++ b/src/shared/appconfig.h @@ -24,13 +24,15 @@ along with Mod Organizer. If not, see . namespace AppConfig { + #define PARWSTRING wstring -#define APPPARAM(partype, parid, value) partype parid(); +#define APPPARAM(partype, parid, value) partype parid (); #include "appconfig.inc" namespace MOShared { #undef PARWSTRING #undef APPPARAM + } } // namespace MOShared diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 2e25a1a3..cebf270e 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -18,19 +18,20 @@ along with Mod Organizer. If not, see . */ #include "directoryentry.h" -#include "error_report.h" -#include "leaktrace.h" #include "windows_error.h" +#include "leaktrace.h" +#include "error_report.h" +#include #include #include -#include #define WIN32_LEAN_AND_MEAN #include -#include -#include +#include #include +#include #include -#include +#include + namespace MOShared { @@ -39,576 +40,671 @@ static const int MAXPATH_UNICODE = 32767; class OriginConnection { public: - typedef int Index; - static const int INVALID_INDEX = INT_MIN; + + typedef int Index; + static const int INVALID_INDEX = INT_MIN; public: - OriginConnection() : m_NextID(0) { LEAK_TRACE; } - - ~OriginConnection() { LEAK_UNTRACE; } - - FilesOrigin& createOrigin(const std::wstring& originName, const std::wstring& directory, int priority, - boost::shared_ptr fileRegister, - boost::shared_ptr originConnection) { - int newID = createID(); - m_Origins[newID] = FilesOrigin(newID, originName, directory, priority, fileRegister, originConnection); - m_OriginsNameMap[originName] = newID; - m_OriginsPriorityMap[priority] = newID; - return m_Origins[newID]; - } - bool exists(const std::wstring& name) { return m_OriginsNameMap.find(name) != m_OriginsNameMap.end(); } + OriginConnection() + : m_NextID(0) + { + LEAK_TRACE; + } - FilesOrigin& getByID(Index ID) { return m_Origins[ID]; } + ~OriginConnection() + { + LEAK_UNTRACE; + } - FilesOrigin& getByName(const std::wstring& name) { - std::map::iterator iter = m_OriginsNameMap.find(name); - if (iter != m_OriginsNameMap.end()) { - return m_Origins[iter->second]; - } else { - std::ostringstream stream; - stream << "invalid origin name: " << ToString(name, false); - throw std::runtime_error(stream.str()); - } + FilesOrigin& createOrigin(const std::wstring &originName, const std::wstring &directory, int priority, + boost::shared_ptr fileRegister, boost::shared_ptr originConnection) { + int newID = createID(); + m_Origins[newID] = FilesOrigin(newID, originName, directory, priority, fileRegister, originConnection); + m_OriginsNameMap[originName] = newID; + m_OriginsPriorityMap[priority] = newID; + return m_Origins[newID]; + } + + bool exists(const std::wstring &name) { + return m_OriginsNameMap.find(name) != m_OriginsNameMap.end(); + } + + FilesOrigin &getByID(Index ID) { + return m_Origins[ID]; + } + + FilesOrigin &getByName(const std::wstring &name) { + std::map::iterator iter = m_OriginsNameMap.find(name); + if (iter != m_OriginsNameMap.end()) { + return m_Origins[iter->second]; + } else { + std::ostringstream stream; + stream << "invalid origin name: " << ToString(name, false); + throw std::runtime_error(stream.str()); } + } - void changePriorityLookup(int oldPriority, int newPriority) { - auto iter = m_OriginsPriorityMap.find(oldPriority); - if (iter != m_OriginsPriorityMap.end()) { - Index idx = iter->second; - m_OriginsPriorityMap.erase(iter); - m_OriginsPriorityMap[newPriority] = idx; - } + void changePriorityLookup(int oldPriority, int newPriority) + { + auto iter = m_OriginsPriorityMap.find(oldPriority); + if (iter != m_OriginsPriorityMap.end()) { + Index idx = iter->second; + m_OriginsPriorityMap.erase(iter); + m_OriginsPriorityMap[newPriority] = idx; } + } - void changeNameLookup(const std::wstring& oldName, const std::wstring& newName) { - auto iter = m_OriginsNameMap.find(oldName); - if (iter != m_OriginsNameMap.end()) { - Index idx = iter->second; - m_OriginsNameMap.erase(iter); - m_OriginsNameMap[newName] = idx; - } else { - log("failed to change name lookup from %ls to %ls", oldName.c_str(), newName.c_str()); - } + void changeNameLookup(const std::wstring &oldName, const std::wstring &newName) + { + auto iter = m_OriginsNameMap.find(oldName); + if (iter != m_OriginsNameMap.end()) { + Index idx = iter->second; + m_OriginsNameMap.erase(iter); + m_OriginsNameMap[newName] = idx; + } else { + log("failed to change name lookup from %ls to %ls", oldName.c_str(), newName.c_str()); } + } private: - Index createID() { return m_NextID++; } + + Index createID() { + return m_NextID++; + } private: - Index m_NextID; - std::map m_Origins; - std::map m_OriginsNameMap; - std::map m_OriginsPriorityMap; + Index m_NextID; + + std::map m_Origins; + std::map m_OriginsNameMap; + std::map m_OriginsPriorityMap; + }; + // // FilesOrigin // -void FilesOrigin::enable(bool enabled, time_t notAfter) { - if (!enabled) { - std::set copy = m_Files; - m_FileRegister.lock()->removeOriginMulti(copy, m_ID, notAfter); - m_Files.clear(); - } - m_Disabled = !enabled; + +void FilesOrigin::enable(bool enabled, time_t notAfter) +{ + if (!enabled) { + std::set copy = m_Files; + m_FileRegister.lock()->removeOriginMulti(copy, m_ID, notAfter); + m_Files.clear(); + } + m_Disabled = !enabled; } -void FilesOrigin::removeFile(FileEntry::Index index) { - auto iter = m_Files.find(index); - if (iter != m_Files.end()) { - m_Files.erase(iter); - } + +void FilesOrigin::removeFile(FileEntry::Index index) +{ + auto iter = m_Files.find(index); + if (iter != m_Files.end()) { + m_Files.erase(iter); + } } -static std::wstring tail(const std::wstring& source, const size_t count) { - if (count >= source.length()) { - return source; - } - return source.substr(source.length() - count); + +static std::wstring tail(const std::wstring &source, const size_t count) +{ + if (count >= source.length()) { + return source; + } + + return source.substr(source.length() - count); } -FilesOrigin::FilesOrigin() : m_ID(0), m_Disabled(false), m_Name(), m_Path(), m_Priority(0) { LEAK_TRACE; } -FilesOrigin::FilesOrigin(const FilesOrigin& reference) - : m_ID(reference.m_ID), m_Disabled(reference.m_Disabled), m_Name(reference.m_Name), m_Path(reference.m_Path), - m_Priority(reference.m_Priority), m_FileRegister(reference.m_FileRegister), - m_OriginConnection(reference.m_OriginConnection) { - LEAK_TRACE; +FilesOrigin::FilesOrigin() + : m_ID(0), m_Disabled(false), m_Name(), m_Path(), m_Priority(0) +{ + LEAK_TRACE; } -FilesOrigin::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) { - LEAK_TRACE; +FilesOrigin::FilesOrigin(const FilesOrigin &reference) + : m_ID(reference.m_ID) + , m_Disabled(reference.m_Disabled) + , m_Name(reference.m_Name) + , m_Path(reference.m_Path) + , m_Priority(reference.m_Priority) + , m_FileRegister(reference.m_FileRegister) + , m_OriginConnection(reference.m_OriginConnection) +{ + LEAK_TRACE; +} + + +FilesOrigin::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) +{ + LEAK_TRACE; } -FilesOrigin::~FilesOrigin() { LEAK_UNTRACE; } +FilesOrigin::~FilesOrigin() +{ + LEAK_UNTRACE; +} -void FilesOrigin::setPriority(int priority) { - m_OriginConnection.lock()->changePriorityLookup(m_Priority, priority); - m_Priority = priority; +void FilesOrigin::setPriority(int priority) +{ + m_OriginConnection.lock()->changePriorityLookup(m_Priority, priority); + + m_Priority = priority; } -void FilesOrigin::setName(const std::wstring& name) { - m_OriginConnection.lock()->changeNameLookup(m_Name, name); - // change path too - if (tail(m_Path, m_Name.length()) == m_Name) { - m_Path = m_Path.substr(0, m_Path.length() - m_Name.length()).append(name); - } - m_Name = name; + +void FilesOrigin::setName(const std::wstring &name) +{ + m_OriginConnection.lock()->changeNameLookup(m_Name, name); + // change path too + if (tail(m_Path, m_Name.length()) == m_Name) { + m_Path = m_Path.substr(0, m_Path.length() - m_Name.length()).append(name); + } + m_Name = name; } -std::vector FilesOrigin::getFiles() const { - std::vector result; - for (FileEntry::Index fileIdx : m_Files) - if (FileEntry::Ptr p = m_FileRegister.lock()->getFile(fileIdx)) - result.push_back(p); +std::vector FilesOrigin::getFiles() const +{ + std::vector result; + for (FileEntry::Index fileIdx : m_Files) + if (FileEntry::Ptr p = m_FileRegister.lock()->getFile(fileIdx)) + result.push_back(p); - return result; + return result; } + // // FileEntry // -void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring& archive) { - m_LastAccessed = time(nullptr); - if (m_Parent != nullptr) { - m_Parent->propagateOrigin(origin); - } - if (m_Origin == -1) { - m_Origin = origin; - m_FileTime = fileTime; - m_Archive = archive; - } else if ((m_Parent != nullptr) && - (m_Parent->getOriginByID(origin).getPriority() > m_Parent->getOriginByID(m_Origin).getPriority()) && - (archive.size() == 0 || m_Archive.size() > 0)) { - if (std::find_if(m_Alternatives.begin(), m_Alternatives.end(), - [&](const std::pair& i) -> bool { return i.first == m_Origin; }) == - m_Alternatives.end()) { - m_Alternatives.push_back(std::pair(m_Origin, m_Archive)); - } - m_Origin = origin; - m_FileTime = fileTime; - m_Archive = archive; - } else { - bool found = false; - if (m_Origin == origin) { - // already an origin - return; - } - for (std::vector>::iterator iter = m_Alternatives.begin(); - iter != m_Alternatives.end(); ++iter) { - if (iter->first == origin) { - // already an origin - return; - } - if ((m_Parent != nullptr) && - (m_Parent->getOriginByID(iter->first).getPriority() < m_Parent->getOriginByID(origin).getPriority())) { - m_Alternatives.insert(iter, std::pair(origin, archive)); - found = true; - break; - } - } - if (!found) { - m_Alternatives.push_back(std::pair(origin, archive)); - } +void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &archive) +{ + m_LastAccessed = time(nullptr); + if (m_Parent != nullptr) { + m_Parent->propagateOrigin(origin); + } + if (m_Origin == -1) { + m_Origin = origin; + m_FileTime = fileTime; + m_Archive = archive; + } else if ((m_Parent != nullptr) + && (m_Parent->getOriginByID(origin).getPriority() > m_Parent->getOriginByID(m_Origin).getPriority()) + && (archive.size() == 0 || m_Archive.size() > 0 )) { + if (std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair &i) -> bool { return i.first == m_Origin; }) == m_Alternatives.end()) { + m_Alternatives.push_back(std::pair(m_Origin, m_Archive)); + } + m_Origin = origin; + m_FileTime = fileTime; + m_Archive = archive; + } else { + bool found = false; + if (m_Origin == origin) { + // already an origin + return; + } + for (std::vector>::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) { + if (iter->first == origin) { + // already an origin + return; + } + if ((m_Parent != nullptr) + && (m_Parent->getOriginByID(iter->first).getPriority() < m_Parent->getOriginByID(origin).getPriority())) { + m_Alternatives.insert(iter, std::pair(origin, archive)); + found = true; + break; + } + } + if (!found) { + m_Alternatives.push_back(std::pair(origin, archive)); } + } } -bool FileEntry::removeOrigin(int origin) { - if (m_Origin == origin) { - if (!m_Alternatives.empty()) { - // find alternative with the highest priority - std::vector>::iterator currentIter = m_Alternatives.begin(); - for (std::vector>::iterator iter = m_Alternatives.begin(); - iter != m_Alternatives.end(); ++iter) { - if ((m_Parent->getOriginByID(iter->first).getPriority() > - m_Parent->getOriginByID(currentIter->first).getPriority()) && - (iter->first != origin)) { - currentIter = iter; - } - } - int currentID = currentIter->first; - m_Alternatives.erase(currentIter); - - m_Origin = currentID; - - // now we need to update the file time... - std::wstring filePath = getFullPath(); - HANDLE file = ::CreateFile(filePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, nullptr); - if (!::GetFileTime(file, nullptr, nullptr, &m_FileTime)) { - // maybe this file is in a bsa, but there is no easy way to find out which. User should refresh - // the view to find out - m_Archive = L"bsa?"; - } else { - m_Archive = L""; - } - - ::CloseHandle(file); - - } else { - m_Origin = -1; - return true; +bool FileEntry::removeOrigin(int origin) +{ + if (m_Origin == origin) { + if (!m_Alternatives.empty()) { + // find alternative with the highest priority + std::vector>::iterator currentIter = m_Alternatives.begin(); + for (std::vector>::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) { + if ((m_Parent->getOriginByID(iter->first).getPriority() > m_Parent->getOriginByID(currentIter->first).getPriority()) && + (iter->first != origin)) { + currentIter = iter; } + } + int currentID = currentIter->first; + m_Alternatives.erase(currentIter); + + m_Origin = currentID; + + // now we need to update the file time... + std::wstring filePath = getFullPath(); + HANDLE file = ::CreateFile(filePath.c_str(), GENERIC_READ | GENERIC_WRITE, + 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (!::GetFileTime(file, nullptr, nullptr, &m_FileTime)) { + // maybe this file is in a bsa, but there is no easy way to find out which. User should refresh + // the view to find out + m_Archive = L"bsa?"; + } else { + m_Archive = L""; + } + + ::CloseHandle(file); + } else { - std::vector>::iterator newEnd = - std::find_if(m_Alternatives.begin(), m_Alternatives.end(), - [&](const std::pair& i) -> bool { return i.first == origin; }); - if (newEnd != m_Alternatives.end()) - m_Alternatives.erase(newEnd, m_Alternatives.end()); + m_Origin = -1; + return true; } - return false; + } else { + std::vector>::iterator newEnd = std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair &i) -> bool { return i.first == origin; }); + if (newEnd != m_Alternatives.end()) + m_Alternatives.erase(newEnd, m_Alternatives.end()); + } + return false; } -FileEntry::FileEntry() : m_Index(UINT_MAX), m_Name(), m_Origin(-1), m_Parent(nullptr), m_LastAccessed(time(nullptr)) { - LEAK_TRACE; +FileEntry::FileEntry() + : m_Index(UINT_MAX), m_Name(), m_Origin(-1), m_Parent(nullptr), m_LastAccessed(time(nullptr)) +{ + LEAK_TRACE; } -FileEntry::FileEntry(Index index, const std::wstring& name, DirectoryEntry* parent) - : m_Index(index), m_Name(name), m_Origin(-1), m_Archive(L""), m_Parent(parent), m_LastAccessed(time(nullptr)) { - LEAK_TRACE; +FileEntry::FileEntry(Index index, const std::wstring &name, DirectoryEntry *parent) + : m_Index(index), m_Name(name), m_Origin(-1), m_Archive(L""), m_Parent(parent), m_LastAccessed(time(nullptr)) +{ + LEAK_TRACE; } -FileEntry::~FileEntry() { LEAK_UNTRACE; } +FileEntry::~FileEntry() +{ + LEAK_UNTRACE; +} -void FileEntry::sortOrigins() { - m_Alternatives.push_back(std::pair(m_Origin, m_Archive)); - std::sort(m_Alternatives.begin(), m_Alternatives.end(), - [&](const std::pair& LHS, const std::pair& RHS) -> bool { - if ((!LHS.second.size() && !RHS.second.size()) || (LHS.second.size() && RHS.second.size())) { - int l = m_Parent->getOriginByID(LHS.first).getPriority(); - if (l < 0) - l = INT_MAX; - int r = m_Parent->getOriginByID(RHS.first).getPriority(); - if (r < 0) - r = INT_MAX; +void FileEntry::sortOrigins() +{ + m_Alternatives.push_back(std::pair(m_Origin, m_Archive)); + std::sort(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair &LHS, const std::pair &RHS) -> bool { + if ((!LHS.second.size() && !RHS.second.size()) || (LHS.second.size() && RHS.second.size())) { + int l = m_Parent->getOriginByID(LHS.first).getPriority(); if (l < 0) l = INT_MAX; + int r = m_Parent->getOriginByID(RHS.first).getPriority(); if (r < 0) r = INT_MAX; + + return l < r; + } + + if (RHS.second.size()) return false; + return true; + }); + if (!m_Alternatives.empty()) { + m_Origin = m_Alternatives.back().first; + m_Archive = m_Alternatives.back().second; + m_Alternatives.pop_back(); + } +} - return l < r; - } - if (RHS.second.size()) - return false; - return true; - }); - if (!m_Alternatives.empty()) { - m_Origin = m_Alternatives.back().first; - m_Archive = m_Alternatives.back().second; - m_Alternatives.pop_back(); +bool FileEntry::recurseParents(std::wstring &path, const DirectoryEntry *parent) const +{ + if (parent == nullptr) { + return false; + } else { + // don't append the topmost parent because it is the virtual data-root + if (recurseParents(path, parent->getParent())) { + path.append(L"\\").append(parent->getName()); } + return true; + } } -bool FileEntry::recurseParents(std::wstring& path, const DirectoryEntry* parent) const { - if (parent == nullptr) { - return false; - } else { - // don't append the topmost parent because it is the virtual data-root - if (recurseParents(path, parent->getParent())) { - path.append(L"\\").append(parent->getName()); - } - return true; - } +std::wstring FileEntry::getFullPath() const +{ + std::wstring result; + bool ignore = false; + result = m_Parent->getOriginByID(getOrigin(ignore)).getPath(); //base directory for origin + recurseParents(result, m_Parent); // all intermediate directories + return result + L"\\" + m_Name; } -std::wstring FileEntry::getFullPath() const { - std::wstring result; - bool ignore = false; - result = m_Parent->getOriginByID(getOrigin(ignore)).getPath(); // base directory for origin - recurseParents(result, m_Parent); // all intermediate directories - return result + L"\\" + m_Name; +std::wstring FileEntry::getRelativePath() const +{ + std::wstring result; + recurseParents(result, m_Parent); // all intermediate directories + return result + L"\\" + m_Name; } -std::wstring FileEntry::getRelativePath() const { - std::wstring result; - recurseParents(result, m_Parent); // all intermediate directories - return result + L"\\" + m_Name; -} // // DirectoryEntry // -DirectoryEntry::DirectoryEntry(const std::wstring& name, DirectoryEntry* parent, int originID) - : m_OriginConnection(new OriginConnection), m_Name(name), m_Parent(parent), m_Populated(false), m_TopLevel(true) { - m_FileRegister.reset(new FileRegister(m_OriginConnection)); - m_Origins.insert(originID); - LEAK_TRACE; +DirectoryEntry::DirectoryEntry(const std::wstring &name, DirectoryEntry *parent, int originID) + : m_OriginConnection(new OriginConnection), + m_Name(name), m_Parent(parent), m_Populated(false), m_TopLevel(true) +{ + m_FileRegister.reset(new FileRegister(m_OriginConnection)); + m_Origins.insert(originID); + LEAK_TRACE; } -DirectoryEntry::DirectoryEntry(const std::wstring& name, DirectoryEntry* parent, int originID, - boost::shared_ptr fileRegister, - boost::shared_ptr originConnection) - : m_FileRegister(fileRegister), m_OriginConnection(originConnection), m_Name(name), m_Parent(parent), - m_Populated(false), m_TopLevel(false) { - LEAK_TRACE; - m_Origins.insert(originID); +DirectoryEntry::DirectoryEntry(const std::wstring &name, DirectoryEntry *parent, int originID, + boost::shared_ptr fileRegister, boost::shared_ptr originConnection) + : m_FileRegister(fileRegister), m_OriginConnection(originConnection), + m_Name(name), m_Parent(parent), m_Populated(false), m_TopLevel(false) +{ + LEAK_TRACE; + m_Origins.insert(originID); } -DirectoryEntry::~DirectoryEntry() { - LEAK_UNTRACE; - clear(); + +DirectoryEntry::~DirectoryEntry() +{ + LEAK_UNTRACE; + clear(); } -const std::wstring& DirectoryEntry::getName() const { return m_Name; } -void DirectoryEntry::clear() { - m_Files.clear(); - for (DirectoryEntry* entry : m_SubDirectories) { - delete entry; - } - m_SubDirectories.clear(); +const std::wstring &DirectoryEntry::getName() const +{ + return m_Name; } -FilesOrigin& DirectoryEntry::createOrigin(const std::wstring& originName, const std::wstring& directory, int priority) { - if (m_OriginConnection->exists(originName)) { - FilesOrigin& origin = m_OriginConnection->getByName(originName); - origin.enable(true); - return origin; - } else { - return m_OriginConnection->createOrigin(originName, directory, priority, m_FileRegister, m_OriginConnection); - } + +void DirectoryEntry::clear() +{ + m_Files.clear(); + for (DirectoryEntry *entry : m_SubDirectories) { + delete entry; + } + m_SubDirectories.clear(); } -void DirectoryEntry::addFromOrigin(const std::wstring& originName, const std::wstring& directory, int priority) { - FilesOrigin& origin = createOrigin(originName, directory, priority); - if (directory.length() != 0) { - boost::scoped_array buffer(new wchar_t[MAXPATH_UNICODE + 1]); - memset(buffer.get(), L'\0', MAXPATH_UNICODE + 1); - int offset = _snwprintf(buffer.get(), MAXPATH_UNICODE, L"%ls", directory.c_str()); - buffer.get()[offset] = L'\0'; - addFiles(origin, buffer.get(), offset); - } - m_Populated = true; + +FilesOrigin &DirectoryEntry::createOrigin(const std::wstring &originName, const std::wstring &directory, int priority) +{ + if (m_OriginConnection->exists(originName)) { + FilesOrigin &origin = m_OriginConnection->getByName(originName); + origin.enable(true); + return origin; + } else { + return m_OriginConnection->createOrigin(originName, directory, priority, m_FileRegister, m_OriginConnection); + } } -void DirectoryEntry::addFromBSA(const std::wstring& originName, std::wstring& directory, const std::wstring& fileName, - int priority) { - FilesOrigin& origin = createOrigin(originName, directory, priority); - WIN32_FILE_ATTRIBUTE_DATA fileData; - if (::GetFileAttributesExW(fileName.c_str(), GetFileExInfoStandard, &fileData) == 0) { - throw windows_error("failed to determine file time"); - } +void DirectoryEntry::addFromOrigin(const std::wstring &originName, const std::wstring &directory, int priority) +{ + FilesOrigin &origin = createOrigin(originName, directory, priority); + if (directory.length() != 0) { + boost::scoped_array buffer(new wchar_t[MAXPATH_UNICODE + 1]); + memset(buffer.get(), L'\0', MAXPATH_UNICODE + 1); + int offset = _snwprintf(buffer.get(), MAXPATH_UNICODE, L"%ls", directory.c_str()); + buffer.get()[offset] = L'\0'; + addFiles(origin, buffer.get(), offset); + } + m_Populated = true; +} - BSA::Archive archive; - BSA::EErrorCode res = archive.read(ToString(fileName, false).c_str(), false); - if ((res != BSA::ERROR_NONE) && (res != BSA::ERROR_INVALIDHASHES)) { - std::ostringstream stream; - stream << "invalid bsa file: " << ToString(fileName, false) << " errorcode " << res << " - " - << ::GetLastError(); - throw std::runtime_error(stream.str()); - } - size_t namePos = fileName.find_last_of(L"\\/"); - if (namePos == std::wstring::npos) { - namePos = 0; - } else { - ++namePos; - } - addFiles(origin, archive.getRoot(), fileData.ftLastWriteTime, fileName.substr(namePos)); - m_Populated = true; +void DirectoryEntry::addFromBSA(const std::wstring &originName, std::wstring &directory, const std::wstring &fileName, int priority) +{ + FilesOrigin &origin = createOrigin(originName, directory, priority); + + WIN32_FILE_ATTRIBUTE_DATA fileData; + if (::GetFileAttributesExW(fileName.c_str(), GetFileExInfoStandard, &fileData) == 0) { + throw windows_error("failed to determine file time"); + } + + BSA::Archive archive; + BSA::EErrorCode res = archive.read(ToString(fileName, false).c_str(), false); + if ((res != BSA::ERROR_NONE) && (res != BSA::ERROR_INVALIDHASHES)) { + std::ostringstream stream; + stream << "invalid bsa file: " << ToString(fileName, false) << " errorcode " << res << " - " << ::GetLastError(); + throw std::runtime_error(stream.str()); + } + size_t namePos = fileName.find_last_of(L"\\/"); + if (namePos == std::wstring::npos) { + namePos = 0; + } else { + ++namePos; + } + + addFiles(origin, archive.getRoot(), fileData.ftLastWriteTime, fileName.substr(namePos)); + m_Populated = true; } -void DirectoryEntry::propagateOrigin(int origin) { - m_Origins.insert(origin); - if (m_Parent != nullptr) { - m_Parent->propagateOrigin(origin); - } +void DirectoryEntry::propagateOrigin(int origin) +{ + m_Origins.insert(origin); + if (m_Parent != nullptr) { + m_Parent->propagateOrigin(origin); + } } -static bool SupportOptimizedFind() { - // large fetch and basic info for FindFirstFileEx is supported on win server 2008 r2, win 7 and newer - OSVERSIONINFOEX versionInfo; - versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - versionInfo.dwMajorVersion = 6; - versionInfo.dwMinorVersion = 1; - ULONGLONG mask = ::VerSetConditionMask(::VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), - VER_MINORVERSION, VER_GREATER_EQUAL); +static bool SupportOptimizedFind() +{ + // large fetch and basic info for FindFirstFileEx is supported on win server 2008 r2, win 7 and newer + + OSVERSIONINFOEX versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + versionInfo.dwMajorVersion = 6; + versionInfo.dwMinorVersion = 1; + ULONGLONG mask = ::VerSetConditionMask( + ::VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), + VER_MINORVERSION, VER_GREATER_EQUAL); - bool res = ::VerifyVersionInfo(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, mask) == TRUE; - return res; + bool res = ::VerifyVersionInfo(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, mask) == TRUE; + return res; } -static bool DirCompareByName(const DirectoryEntry* lhs, const DirectoryEntry* rhs) { - return _wcsicmp(lhs->getName().c_str(), rhs->getName().c_str()) < 0; + +static bool DirCompareByName(const DirectoryEntry *lhs, const DirectoryEntry *rhs) +{ + return _wcsicmp(lhs->getName().c_str(), rhs->getName().c_str()) < 0; } -void DirectoryEntry::addFiles(FilesOrigin& origin, wchar_t* buffer, int bufferOffset) { - WIN32_FIND_DATAW findData; - _snwprintf_s(buffer + bufferOffset, MAXPATH_UNICODE - bufferOffset, _TRUNCATE, L"\\*"); +void DirectoryEntry::addFiles(FilesOrigin &origin, wchar_t *buffer, int bufferOffset) +{ + WIN32_FIND_DATAW findData; - HANDLE searchHandle = nullptr; + _snwprintf_s(buffer + bufferOffset, MAXPATH_UNICODE - bufferOffset, _TRUNCATE, L"\\*"); - if (SupportOptimizedFind()) { - searchHandle = ::FindFirstFileExW(buffer, FindExInfoBasic, &findData, FindExSearchNameMatch, nullptr, - FIND_FIRST_EX_LARGE_FETCH); - } else { - searchHandle = ::FindFirstFileExW(buffer, FindExInfoStandard, &findData, FindExSearchNameMatch, nullptr, 0); - } + HANDLE searchHandle = nullptr; - if (searchHandle != INVALID_HANDLE_VALUE) { - BOOL result = true; - while (result) { - if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if ((wcscmp(findData.cFileName, L".") != 0) && (wcscmp(findData.cFileName, L"..") != 0)) { - int offset = _snwprintf(buffer + bufferOffset, MAXPATH_UNICODE, L"\\%ls", findData.cFileName); - // recurse into subdirectories - getSubDirectory(findData.cFileName, true, origin.getID()) - ->addFiles(origin, buffer, bufferOffset + offset); - } - } else { - insert(findData.cFileName, origin, findData.ftLastWriteTime, L""); - } - result = ::FindNextFileW(searchHandle, &findData); + if (SupportOptimizedFind()) { + searchHandle = ::FindFirstFileExW(buffer, FindExInfoBasic, &findData, FindExSearchNameMatch, nullptr, + FIND_FIRST_EX_LARGE_FETCH); + } else { + searchHandle = ::FindFirstFileExW(buffer, FindExInfoStandard, &findData, FindExSearchNameMatch, nullptr, 0); + } + + if (searchHandle != INVALID_HANDLE_VALUE) { + BOOL result = true; + while (result) { + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if ((wcscmp(findData.cFileName, L".") != 0) && + (wcscmp(findData.cFileName, L"..") != 0)) { + int offset = _snwprintf(buffer + bufferOffset, MAXPATH_UNICODE, L"\\%ls", findData.cFileName); + // recurse into subdirectories + getSubDirectory(findData.cFileName, true, origin.getID())->addFiles(origin, buffer, bufferOffset + offset); } + } else { + insert(findData.cFileName, origin, findData.ftLastWriteTime, L""); + } + result = ::FindNextFileW(searchHandle, &findData); } - std::sort(m_SubDirectories.begin(), m_SubDirectories.end(), &DirCompareByName); - ::FindClose(searchHandle); + } + std::sort(m_SubDirectories.begin(), m_SubDirectories.end(), &DirCompareByName); + ::FindClose(searchHandle); } -void DirectoryEntry::addFiles(FilesOrigin& origin, BSA::Folder::Ptr archiveFolder, FILETIME& fileTime, - const std::wstring& archiveName) { - // add files - for (unsigned int fileIdx = 0; fileIdx < archiveFolder->getNumFiles(); ++fileIdx) { - BSA::File::Ptr file = archiveFolder->getFile(fileIdx); - insert(ToWString(file->getName(), true), origin, fileTime, archiveName); - } - // recurse into subdirectories - for (unsigned int folderIdx = 0; folderIdx < archiveFolder->getNumSubFolders(); ++folderIdx) { - BSA::Folder::Ptr folder = archiveFolder->getSubFolder(folderIdx); - DirectoryEntry* folderEntry = - getSubDirectoryRecursive(ToWString(folder->getName(), true), true, origin.getID()); +void DirectoryEntry::addFiles(FilesOrigin &origin, BSA::Folder::Ptr archiveFolder, FILETIME &fileTime, const std::wstring &archiveName) +{ + // add files + for (unsigned int fileIdx = 0; fileIdx < archiveFolder->getNumFiles(); ++fileIdx) { + BSA::File::Ptr file = archiveFolder->getFile(fileIdx); + insert(ToWString(file->getName(), true), origin, fileTime, archiveName); + } - folderEntry->addFiles(origin, folder, fileTime, archiveName); - } + // recurse into subdirectories + for (unsigned int folderIdx = 0; folderIdx < archiveFolder->getNumSubFolders(); ++folderIdx) { + BSA::Folder::Ptr folder = archiveFolder->getSubFolder(folderIdx); + DirectoryEntry *folderEntry = getSubDirectoryRecursive(ToWString(folder->getName(), true), true, origin.getID()); + + folderEntry->addFiles(origin, folder, fileTime, archiveName); + } } -bool DirectoryEntry::removeFile(const std::wstring& filePath, int* origin) { - size_t pos = filePath.find_first_of(L"\\/"); - if (pos == std::string::npos) { - return this->remove(filePath, origin); + +bool DirectoryEntry::removeFile(const std::wstring &filePath, int *origin) +{ + size_t pos = filePath.find_first_of(L"\\/"); + if (pos == std::string::npos) { + return this->remove(filePath, origin); + } else { + std::wstring dirName = filePath.substr(0, pos); + std::wstring rest = filePath.substr(pos + 1); + DirectoryEntry *entry = getSubDirectoryRecursive(dirName, false); + if (entry != nullptr) { + return entry->removeFile(rest, origin); } else { - std::wstring dirName = filePath.substr(0, pos); - std::wstring rest = filePath.substr(pos + 1); - DirectoryEntry* entry = getSubDirectoryRecursive(dirName, false); - if (entry != nullptr) { - return entry->removeFile(rest, origin); - } else { - return false; - } + return false; } + } } -void DirectoryEntry::removeDirRecursive() { - while (!m_Files.empty()) { - m_FileRegister->removeFile(m_Files.begin()->second); - } +void DirectoryEntry::removeDirRecursive() +{ + while (!m_Files.empty()) { + m_FileRegister->removeFile(m_Files.begin()->second); + } + + for (DirectoryEntry *entry : m_SubDirectories) { + entry->removeDirRecursive(); + delete entry; + } + m_SubDirectories.clear(); +} - for (DirectoryEntry* entry : m_SubDirectories) { +void DirectoryEntry::removeDir(const std::wstring &path) +{ + size_t pos = path.find_first_of(L"\\/"); + if (pos == std::string::npos) { + for (auto iter = m_SubDirectories.begin(); iter != m_SubDirectories.end(); ++iter) { + DirectoryEntry *entry = *iter; + if (CaseInsensitiveEqual(entry->getName(), path)) { entry->removeDirRecursive(); + m_SubDirectories.erase(iter); delete entry; + break; + } } - m_SubDirectories.clear(); -} - -void DirectoryEntry::removeDir(const std::wstring& path) { - size_t pos = path.find_first_of(L"\\/"); - if (pos == std::string::npos) { - for (auto iter = m_SubDirectories.begin(); iter != m_SubDirectories.end(); ++iter) { - DirectoryEntry* entry = *iter; - if (CaseInsensitiveEqual(entry->getName(), path)) { - entry->removeDirRecursive(); - m_SubDirectories.erase(iter); - delete entry; - break; - } - } - } else { - std::wstring dirName = path.substr(0, pos); - std::wstring rest = path.substr(pos + 1); - DirectoryEntry* entry = getSubDirectoryRecursive(dirName, false); - if (entry != nullptr) { - entry->removeDir(rest); - } + } else { + std::wstring dirName = path.substr(0, pos); + std::wstring rest = path.substr(pos + 1); + DirectoryEntry *entry = getSubDirectoryRecursive(dirName, false); + if (entry != nullptr) { + entry->removeDir(rest); } + } } -bool DirectoryEntry::hasContentsFromOrigin(int originID) const { return m_Origins.find(originID) != m_Origins.end(); } +bool DirectoryEntry::hasContentsFromOrigin(int originID) const +{ + return m_Origins.find(originID) != m_Origins.end(); +} -void DirectoryEntry::insertFile(const std::wstring& filePath, FilesOrigin& origin, FILETIME fileTime) { - size_t pos = filePath.find_first_of(L"\\/"); - if (pos == std::string::npos) { - this->insert(filePath, origin, fileTime, std::wstring()); - } else { - std::wstring dirName = filePath.substr(0, pos); - std::wstring rest = filePath.substr(pos + 1); - getSubDirectoryRecursive(dirName, true, origin.getID())->insertFile(rest, origin, fileTime); - } +void DirectoryEntry::insertFile(const std::wstring &filePath, FilesOrigin &origin, FILETIME fileTime) +{ + size_t pos = filePath.find_first_of(L"\\/"); + if (pos == std::string::npos) { + this->insert(filePath, origin, fileTime, std::wstring()); + } else { + std::wstring dirName = filePath.substr(0, pos); + std::wstring rest = filePath.substr(pos + 1); + getSubDirectoryRecursive(dirName, true, origin.getID())->insertFile(rest, origin, fileTime); + } } -void DirectoryEntry::removeFile(FileEntry::Index index) { - if (!m_Files.empty()) { - auto iter = std::find_if( - m_Files.begin(), m_Files.end(), - [&index](const std::pair& iter) -> bool { return iter.second == index; }); - if (iter != m_Files.end()) { - m_Files.erase(iter); - } else { - log("file \"%ls\" not in directory \"%ls\"", m_FileRegister->getFile(index)->getName().c_str(), - this->getName().c_str()); - } + +void DirectoryEntry::removeFile(FileEntry::Index index) +{ + if (!m_Files.empty()) { + auto iter = std::find_if(m_Files.begin(), m_Files.end(), + [&index](const std::pair &iter) -> bool { + return iter.second == index; } ); + if (iter != m_Files.end()) { + m_Files.erase(iter); } else { - log("file \"%ls\" not in directory \"%ls\", directory empty", m_FileRegister->getFile(index)->getName().c_str(), - this->getName().c_str()); + log("file \"%ls\" not in directory \"%ls\"", + m_FileRegister->getFile(index)->getName().c_str(), + this->getName().c_str()); } + } else { + log("file \"%ls\" not in directory \"%ls\", directory empty", + m_FileRegister->getFile(index)->getName().c_str(), + this->getName().c_str()); + } } -void DirectoryEntry::removeFiles(const std::set& indices) { - for (auto iter = m_Files.begin(); iter != m_Files.end();) { - if (indices.find(iter->second) != indices.end()) { - m_Files.erase(iter++); - } else { - ++iter; - } + +void DirectoryEntry::removeFiles(const std::set &indices) +{ + for (auto iter = m_Files.begin(); iter != m_Files.end();) { + if (indices.find(iter->second) != indices.end()) { + m_Files.erase(iter++); + } else { + ++iter; } + } } -int DirectoryEntry::anyOrigin() const { - bool ignore; - for (auto iter = m_Files.begin(); iter != m_Files.end(); ++iter) { - FileEntry::Ptr entry = m_FileRegister->getFile(iter->second); - if ((entry.get() != nullptr) && !entry->isFromArchive()) { - return entry->getOrigin(ignore); - } + +int DirectoryEntry::anyOrigin() const +{ + bool ignore; + for (auto iter = m_Files.begin(); iter != m_Files.end(); ++iter) { + FileEntry::Ptr entry = m_FileRegister->getFile(iter->second); + if ((entry.get() != nullptr) && !entry->isFromArchive()) { + return entry->getOrigin(ignore); } + } - // if we got here, no file directly within this directory is a valid indicator for a mod, thus - // we continue looking in subdirectories - for (DirectoryEntry* entry : m_SubDirectories) { - int res = entry->anyOrigin(); - if (res != -1) { - return res; - } + // if we got here, no file directly within this directory is a valid indicator for a mod, thus + // we continue looking in subdirectories + for (DirectoryEntry *entry : m_SubDirectories) { + int res = entry->anyOrigin(); + if (res != -1){ + return res; } - return *(m_Origins.begin()); + } + return *(m_Origins.begin()); +} + + +bool DirectoryEntry::originExists(const std::wstring &name) const +{ + return m_OriginConnection->exists(name); } -bool DirectoryEntry::originExists(const std::wstring& name) const { return m_OriginConnection->exists(name); } -FilesOrigin& DirectoryEntry::getOriginByID(int ID) const { return m_OriginConnection->getByID(ID); } +FilesOrigin &DirectoryEntry::getOriginByID(int ID) const +{ + return m_OriginConnection->getByID(ID); +} + -FilesOrigin& DirectoryEntry::getOriginByName(const std::wstring& name) const { - return m_OriginConnection->getByName(name); +FilesOrigin &DirectoryEntry::getOriginByName(const std::wstring &name) const +{ + return m_OriginConnection->getByName(name); } /* @@ -627,219 +723,251 @@ int DirectoryEntry::getOrigin(const std::wstring &path, bool &archive) } }*/ -std::vector DirectoryEntry::getFiles() const { - std::vector result; - for (auto iter = m_Files.begin(); iter != m_Files.end(); ++iter) { - result.push_back(m_FileRegister->getFile(iter->second)); - } - return result; +std::vector DirectoryEntry::getFiles() const +{ + std::vector result; + for (auto iter = m_Files.begin(); iter != m_Files.end(); ++iter) { + result.push_back(m_FileRegister->getFile(iter->second)); + } + return result; } -const FileEntry::Ptr DirectoryEntry::searchFile(const std::wstring& path, const DirectoryEntry** directory) const { + +const FileEntry::Ptr DirectoryEntry::searchFile(const std::wstring &path, const DirectoryEntry **directory) const +{ + if (directory != nullptr) { + *directory = nullptr; + } + + if ((path.length() == 0) || (path == L"*")) { + // no file name -> the path ended on a (back-)slash if (directory != nullptr) { - *directory = nullptr; + *directory = this; } + return FileEntry::Ptr(); + } - if ((path.length() == 0) || (path == L"*")) { - // no file name -> the path ended on a (back-)slash - if (directory != nullptr) { - *directory = this; - } - return FileEntry::Ptr(); - } + size_t len = path.find_first_of(L"\\/"); - size_t len = path.find_first_of(L"\\/"); - - if (len == std::string::npos) { - // no more path components - auto iter = m_Files.find(ToLower(path)); - if (iter != m_Files.end()) { - return m_FileRegister->getFile(iter->second); - } else if (directory != nullptr) { - DirectoryEntry* temp = findSubDirectory(path); - if (temp != nullptr) { - *directory = temp; - } - } - } else { - // file is in in a subdirectory, recurse into the matching subdirectory - std::wstring pathComponent = path.substr(0, len); - DirectoryEntry* temp = findSubDirectory(pathComponent); - if (temp != nullptr) { - if (len >= path.size()) { - log("unexpected end of path"); - return FileEntry::Ptr(); - } - return temp->searchFile(path.substr(len + 1), directory); - } + if (len == std::string::npos) { + // no more path components + auto iter = m_Files.find(ToLower(path)); + if (iter != m_Files.end()) { + return m_FileRegister->getFile(iter->second); + } else if (directory != nullptr) { + DirectoryEntry *temp = findSubDirectory(path); + if (temp != nullptr) { + *directory = temp; + } } - return FileEntry::Ptr(); + } else { + // file is in in a subdirectory, recurse into the matching subdirectory + std::wstring pathComponent = path.substr(0, len); + DirectoryEntry *temp = findSubDirectory(pathComponent); + if (temp != nullptr) { + if (len >= path.size()) { + log("unexpected end of path"); + return FileEntry::Ptr(); + } + return temp->searchFile(path.substr(len + 1), directory); + } + } + return FileEntry::Ptr(); } -DirectoryEntry* DirectoryEntry::findSubDirectory(const std::wstring& name) const { - for (DirectoryEntry* entry : m_SubDirectories) { - if (CaseInsensitiveEqual(entry->getName(), name)) { - return entry; - } + +DirectoryEntry *DirectoryEntry::findSubDirectory(const std::wstring &name) const +{ + for (DirectoryEntry *entry : m_SubDirectories) { + if (CaseInsensitiveEqual(entry->getName(), name)) { + return entry; } - return nullptr; + } + return nullptr; } -DirectoryEntry* DirectoryEntry::findSubDirectoryRecursive(const std::wstring& path) { - return getSubDirectoryRecursive(path, false, -1); + +DirectoryEntry *DirectoryEntry::findSubDirectoryRecursive(const std::wstring &path) +{ + return getSubDirectoryRecursive(path, false, -1); } -const FileEntry::Ptr DirectoryEntry::findFile(const std::wstring& name) const { - auto iter = m_Files.find(ToLower(name)); - if (iter != m_Files.end()) { - return m_FileRegister->getFile(iter->second); - } else { - return FileEntry::Ptr(); - } + +const FileEntry::Ptr DirectoryEntry::findFile(const std::wstring &name) const +{ + auto iter = m_Files.find(ToLower(name)); + if (iter != m_Files.end()) { + return m_FileRegister->getFile(iter->second); + } else { + return FileEntry::Ptr(); + } } -DirectoryEntry* DirectoryEntry::getSubDirectory(const std::wstring& name, bool create, int originID) { - for (DirectoryEntry* entry : m_SubDirectories) { - if (CaseInsensitiveEqual(entry->getName(), name)) { - return entry; - } - } - if (create) { - std::vector::iterator iter = m_SubDirectories.insert( - m_SubDirectories.end(), new DirectoryEntry(name, this, originID, m_FileRegister, m_OriginConnection)); - return *iter; - } else { - return nullptr; +DirectoryEntry *DirectoryEntry::getSubDirectory(const std::wstring &name, bool create, int originID) +{ + for (DirectoryEntry *entry : m_SubDirectories) { + if (CaseInsensitiveEqual(entry->getName(), name)) { + return entry; } + } + if (create) { + std::vector::iterator iter = m_SubDirectories.insert(m_SubDirectories.end(), + new DirectoryEntry(name, this, originID, m_FileRegister, m_OriginConnection)); + return *iter; + } else { + return nullptr; + } } -DirectoryEntry* DirectoryEntry::getSubDirectoryRecursive(const std::wstring& path, bool create, int originID) { - if (path.length() == 0) { - // path ended with a backslash? - return this; - } - size_t pos = path.find_first_of(L"\\/"); - if (pos == std::wstring::npos) { - return getSubDirectory(path, create); +DirectoryEntry *DirectoryEntry::getSubDirectoryRecursive(const std::wstring &path, bool create, int originID) +{ + if (path.length() == 0) { + // path ended with a backslash? + return this; + } + + size_t pos = path.find_first_of(L"\\/"); + if (pos == std::wstring::npos) { + return getSubDirectory(path, create); + } else { + DirectoryEntry *nextChild = getSubDirectory(path.substr(0, pos), create, originID); + if (nextChild == nullptr) { + return nullptr; } else { - DirectoryEntry* nextChild = getSubDirectory(path.substr(0, pos), create, originID); - if (nextChild == nullptr) { - return nullptr; - } else { - return nextChild->getSubDirectoryRecursive(path.substr(pos + 1), create, originID); - } + return nextChild->getSubDirectoryRecursive(path.substr(pos + 1), create, originID); } + } } + + FileRegister::FileRegister(boost::shared_ptr originConnection) - : m_OriginConnection(originConnection) { - LEAK_TRACE; + : m_OriginConnection(originConnection) +{ + LEAK_TRACE; } -FileRegister::~FileRegister() { - LEAK_UNTRACE; - m_Files.clear(); +FileRegister::~FileRegister() +{ + LEAK_UNTRACE; + m_Files.clear(); } -FileEntry::Index FileRegister::generateIndex() { - static std::atomic sIndex(0); - return sIndex++; + +FileEntry::Index FileRegister::generateIndex() +{ + static std::atomic sIndex(0); + return sIndex++; } -bool FileRegister::indexValid(FileEntry::Index index) const { return m_Files.find(index) != m_Files.end(); } +bool FileRegister::indexValid(FileEntry::Index index) const +{ + return m_Files.find(index) != m_Files.end(); +} -FileEntry::Ptr FileRegister::createFile(const std::wstring& name, DirectoryEntry* parent) { - FileEntry::Index index = generateIndex(); - m_Files[index] = FileEntry::Ptr(new FileEntry(index, name, parent)); - return m_Files[index]; +FileEntry::Ptr FileRegister::createFile(const std::wstring &name, DirectoryEntry *parent) +{ + FileEntry::Index index = generateIndex(); + m_Files[index] = FileEntry::Ptr(new FileEntry(index, name, parent)); + return m_Files[index]; } -FileEntry::Ptr FileRegister::getFile(FileEntry::Index index) const { - auto iter = m_Files.find(index); - if (iter != m_Files.end()) { - return iter->second; - } else { - return FileEntry::Ptr(); - } + +FileEntry::Ptr FileRegister::getFile(FileEntry::Index index) const +{ + auto iter = m_Files.find(index); + if (iter != m_Files.end()) { + return iter->second; + } else { + return FileEntry::Ptr(); + } } -void FileRegister::unregisterFile(FileEntry::Ptr file) { - bool ignore; - // unregister from origin - int originID = file->getOrigin(ignore); - m_OriginConnection->getByID(originID).removeFile(file->getIndex()); - const std::vector>& alternatives = file->getAlternatives(); - for (auto iter = alternatives.begin(); iter != alternatives.end(); ++iter) { - m_OriginConnection->getByID(iter->first).removeFile(file->getIndex()); - } +void FileRegister::unregisterFile(FileEntry::Ptr file) +{ + bool ignore; + // unregister from origin + int originID = file->getOrigin(ignore); + m_OriginConnection->getByID(originID).removeFile(file->getIndex()); + const std::vector> &alternatives = file->getAlternatives(); + for (auto iter = alternatives.begin(); iter != alternatives.end(); ++iter) { + m_OriginConnection->getByID(iter->first).removeFile(file->getIndex()); + } - // unregister from directory - if (file->getParent() != nullptr) { - file->getParent()->removeFile(file->getIndex()); - } + // unregister from directory + if (file->getParent() != nullptr) { + file->getParent()->removeFile(file->getIndex()); + } } -bool FileRegister::removeFile(FileEntry::Index index) { - auto iter = m_Files.find(index); - if (iter != m_Files.end()) { - unregisterFile(iter->second); - m_Files.erase(index); - return true; - } else { - log("invalid file index for remove: %lu", index); - return false; - } + +bool FileRegister::removeFile(FileEntry::Index index) +{ + auto iter = m_Files.find(index); + if (iter != m_Files.end()) { + unregisterFile(iter->second); + m_Files.erase(index); + return true; + } else { + log("invalid file index for remove: %lu", index); + return false; + } } -void FileRegister::removeOrigin(FileEntry::Index index, int originID) { - auto iter = m_Files.find(index); - if (iter != m_Files.end()) { - if (iter->second->removeOrigin(originID)) { - unregisterFile(iter->second); - m_Files.erase(iter); - } - } else { - log("invalid file index for remove (for origin): %lu", index); +void FileRegister::removeOrigin(FileEntry::Index index, int originID) +{ + auto iter = m_Files.find(index); + if (iter != m_Files.end()) { + if (iter->second->removeOrigin(originID)) { + unregisterFile(iter->second); + m_Files.erase(iter); } + } else { + log("invalid file index for remove (for origin): %lu", index); + } } -void FileRegister::removeOriginMulti(std::set indices, int originID, time_t notAfter) { - std::vector removedFiles; - for (auto iter = indices.begin(); iter != indices.end();) { - auto pos = m_Files.find(*iter); - if (pos != m_Files.end() && (pos->second->lastAccessed() < notAfter) && pos->second->removeOrigin(originID)) { - removedFiles.push_back(pos->second); - m_Files.erase(pos); - ++iter; - } else { - indices.erase(iter++); - } +void FileRegister::removeOriginMulti(std::set indices, int originID, time_t notAfter) +{ + std::vector removedFiles; + for (auto iter = indices.begin(); iter != indices.end();) { + auto pos = m_Files.find(*iter); + if (pos != m_Files.end() + && (pos->second->lastAccessed() < notAfter) + && pos->second->removeOrigin(originID)) { + removedFiles.push_back(pos->second); + m_Files.erase(pos); + ++iter; + } else { + indices.erase(iter++); } + } - // optimization: this is only called when disabling an origin and in this case we don't have - // to remove the file from the origin - - // need to remove files from their parent directories. multiple ways to go about this: - // a) for each file, search its parents file-list (preferably by name) and remove what is found - // b) gather the parent directories, go through the file list for each once and remove all files that have been - // removed the latter should be faster when there are many files in few directories. since this is called only when - // disabling an origin that is probably frequently the case - std::set parents; - for (const FileEntry::Ptr& file : removedFiles) { - if (file->getParent() != nullptr) { - parents.insert(file->getParent()); - } - } - for (DirectoryEntry* parent : parents) { - parent->removeFiles(indices); + // optimization: this is only called when disabling an origin and in this case we don't have + // to remove the file from the origin + + // need to remove files from their parent directories. multiple ways to go about this: + // a) for each file, search its parents file-list (preferably by name) and remove what is found + // b) gather the parent directories, go through the file list for each once and remove all files that have been removed + // the latter should be faster when there are many files in few directories. since this is called + // only when disabling an origin that is probably frequently the case + std::set parents; + for (const FileEntry::Ptr &file : removedFiles) { + if (file->getParent() != nullptr) { + parents.insert(file->getParent()); } + } + for (DirectoryEntry *parent : parents) { + parent->removeFiles(indices); + } } -void FileRegister::sortOrigins() { - for (auto iter = m_Files.begin(); iter != m_Files.end(); ++iter) { - iter->second->sortOrigins(); - } +void FileRegister::sortOrigins() +{ + for (auto iter = m_Files.begin(); iter != m_Files.end(); ++iter) { + iter->second->sortOrigins(); + } } } // namespace MOShared diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index c26fb433..8dbedaf4 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -20,11 +20,12 @@ along with Mod Organizer. If not, see . #ifndef DIRECTORYENTRY_H #define DIRECTORYENTRY_H -#include -#include -#include + #include +#include #include +#include +#include #define WIN32_MEAN_AND_LEAN #include #include @@ -34,291 +35,311 @@ along with Mod Organizer. If not, see . #endif #include "util.h" + namespace MOShared { + class DirectoryEntry; class OriginConnection; class FileRegister; + class FileEntry { public: - typedef unsigned int Index; - typedef boost::shared_ptr Ptr; + typedef unsigned int Index; + + typedef boost::shared_ptr Ptr; public: - FileEntry(); - FileEntry(Index index, const std::wstring& name, DirectoryEntry* parent); + FileEntry(); - ~FileEntry(); + FileEntry(Index index, const std::wstring &name, DirectoryEntry *parent); - Index getIndex() const { return m_Index; } + ~FileEntry(); - time_t lastAccessed() const { return m_LastAccessed; } + 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(); + time_t lastAccessed() const { return m_LastAccessed; } - // 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; } + 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(); - const std::wstring& getName() const { return m_Name; } - int getOrigin() const { return m_Origin; } - 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; } + // 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() const { return m_Origin; } + 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; } + 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(); + bool recurseParents(std::wstring &path, const DirectoryEntry *parent) const; + + void determineTime(); private: - Index m_Index; - std::wstring m_Name; - int m_Origin = -1; - std::wstring m_Archive; - std::vector> m_Alternatives; - DirectoryEntry* m_Parent; - mutable FILETIME m_FileTime; - - time_t m_LastAccessed; - - 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; - } + + Index m_Index; + std::wstring m_Name; + int m_Origin = -1; + std::wstring m_Archive; + std::vector> m_Alternatives; + DirectoryEntry *m_Parent; + mutable FILETIME m_FileTime; + + time_t m_LastAccessed; + + 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; - + friend class OriginConnection; public: - FilesOrigin(); - FilesOrigin(const FilesOrigin& reference); - ~FilesOrigin(); - // 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); + FilesOrigin(); + FilesOrigin(const FilesOrigin &reference); + ~FilesOrigin(); + + // 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; } + int getPriority() const { return m_Priority; } - void setName(const std::wstring& name); - const std::wstring& getName() const { return m_Name; } + 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; } + int getID() const { return m_ID; } + const std::wstring &getPath() const { return m_Path; } - std::vector getFiles() const; + std::vector getFiles() const; - void enable(bool enabled, time_t notAfter = LONG_MAX); - bool isDisabled() const { return m_Disabled; } + void enable(bool enabled, time_t notAfter = LONG_MAX); + bool isDisabled() const { return m_Disabled; } - void addFile(FileEntry::Index index) { m_Files.insert(index); } - void removeFile(FileEntry::Index index); + 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); + + FilesOrigin(int ID, const std::wstring &name, const std::wstring &path, int priority, + boost::shared_ptr fileRegister, boost::shared_ptr originConnection); + private: - int m_ID; - bool m_Disabled; + int m_ID; + + bool m_Disabled; + + std::set m_Files; + std::wstring m_Name; + std::wstring m_Path; + int m_Priority; + boost::weak_ptr m_FileRegister; + boost::weak_ptr m_OriginConnection; - std::set m_Files; - std::wstring m_Name; - std::wstring m_Path; - int m_Priority; - boost::weak_ptr m_FileRegister; - boost::weak_ptr m_OriginConnection; }; -class FileRegister { + +class FileRegister +{ public: - FileRegister(boost::shared_ptr originConnection); - ~FileRegister(); - bool indexValid(FileEntry::Index index) const; + FileRegister(boost::shared_ptr originConnection); + ~FileRegister(); - FileEntry::Ptr createFile(const std::wstring& name, DirectoryEntry* parent); - FileEntry::Ptr getFile(FileEntry::Index index) const; + bool indexValid(FileEntry::Index index) const; - size_t size() const { return m_Files.size(); } + FileEntry::Ptr createFile(const std::wstring &name, DirectoryEntry *parent); + FileEntry::Ptr getFile(FileEntry::Index index) const; - bool removeFile(FileEntry::Index index); - void removeOrigin(FileEntry::Index index, int originID); - void removeOriginMulti(std::set indices, int originID, time_t notAfter); + size_t size() const { return m_Files.size(); } - void sortOrigins(); + bool removeFile(FileEntry::Index index); + void removeOrigin(FileEntry::Index index, int originID); + void removeOriginMulti(std::set indices, int originID, time_t notAfter); + + void sortOrigins(); private: - FileEntry::Index generateIndex(); - void unregisterFile(FileEntry::Ptr file); + FileEntry::Index generateIndex(); + + void unregisterFile(FileEntry::Ptr file); private: - std::map m_Files; - boost::shared_ptr m_OriginConnection; + std::map m_Files; + + boost::shared_ptr m_OriginConnection; + }; -class DirectoryEntry { + +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(const std::wstring &name, DirectoryEntry *parent, int originID); - ~DirectoryEntry(); + DirectoryEntry(const std::wstring &name, DirectoryEntry *parent, int originID, + boost::shared_ptr fileRegister, + boost::shared_ptr originConnection); - void clear(); - bool isPopulated() const { return m_Populated; } + ~DirectoryEntry(); - bool isEmpty() const { return m_Files.empty() && m_SubDirectories.empty(); } + void clear(); + bool isPopulated() const { return m_Populated; } - const DirectoryEntry* getParent() const { return m_Parent; } + bool isEmpty() const { return m_Files.empty() && m_SubDirectories.empty(); } - // 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 DirectoryEntry *getParent() const { return m_Parent; } - void propagateOrigin(int origin); + // 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; + void propagateOrigin(int origin); - boost::shared_ptr getFileRegister() { return m_FileRegister; } + const std::wstring &getName() const; - bool originExists(const std::wstring& name) const; - FilesOrigin& getOriginByID(int ID) const; - FilesOrigin& getOriginByName(const std::wstring& name) const; + boost::shared_ptr getFileRegister() { return m_FileRegister; } - int anyOrigin() const; + 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); + int anyOrigin() const; - std::vector getFiles() const; + //int getOrigin(const std::wstring &path, bool &archive); - void getSubDirectories(std::vector::const_iterator& begin, - std::vector::const_iterator& end) const { - begin = m_SubDirectories.begin(); - end = m_SubDirectories.end(); - } + 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; + DirectoryEntry *findSubDirectoryRecursive(const std::wstring &path); - DirectoryEntry* findSubDirectory(const std::wstring& name) const; - DirectoryEntry* findSubDirectoryRecursive(const std::wstring& path); - - /** retrieve a file in this directory by name. - * @param name name of the file - * @return fileentry object for the file or nullptr if no file matches - */ - const FileEntry::Ptr findFile(const std::wstring& name) const; - - /** search through this directory and all subdirectories for a file by the specified name (relative path). - if directory is not nullptr, the referenced variable will be set to the path containing the file */ - const FileEntry::Ptr 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 - bool removeFile(const std::wstring& filePath, int* origin = nullptr); - - /** - * @brief remove the specified directory - * @param path directory to remove - */ - 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; + /** retrieve a file in this directory by name. + * @param name name of the file + * @return fileentry object for the file or nullptr if no file matches + */ + const FileEntry::Ptr findFile(const std::wstring &name) const; + + /** search through this directory and all subdirectories for a file by the specified name (relative path). + if directory is not nullptr, the referenced variable will be set to the path containing the file */ + const FileEntry::Ptr 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 + bool removeFile(const std::wstring &filePath, int *origin = nullptr); + + /** + * @brief remove the specified directory + * @param path directory to remove + */ + 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 hasContentsFromOrigin(int originID) const; + bool hasContentsFromOrigin(int originID) const; - FilesOrigin& createOrigin(const std::wstring& originName, const std::wstring& directory, int priority); + FilesOrigin &createOrigin(const std::wstring &originName, const std::wstring &directory, int priority); - void removeFiles(const std::set& indices); + void removeFiles(const std::set &indices); private: - DirectoryEntry(const DirectoryEntry& reference); - DirectoryEntry& operator=(const DirectoryEntry& reference); - - void insert(const std::wstring& fileName, FilesOrigin& origin, FILETIME fileTime, const std::wstring& archive) { - 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); - origin.addFile(file->getIndex()); + + DirectoryEntry(const DirectoryEntry &reference); + DirectoryEntry &operator=(const DirectoryEntry &reference); + + void insert(const std::wstring &fileName, FilesOrigin &origin, FILETIME fileTime, const std::wstring &archive) { + 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); + origin.addFile(file->getIndex()); + } - void addFiles(FilesOrigin& origin, wchar_t* buffer, int bufferOffset); - void addFiles(FilesOrigin& origin, BSA::Folder::Ptr archiveFolder, FILETIME& fileTime, - const std::wstring& archiveName); + 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 *getSubDirectory(const std::wstring &name, bool create, int originID = -1); - DirectoryEntry* getSubDirectoryRecursive(const std::wstring& path, bool create, int originID = -1); + DirectoryEntry *getSubDirectoryRecursive(const std::wstring &path, bool create, int originID = -1); - void removeDirRecursive(); + void removeDirRecursive(); private: - boost::shared_ptr m_FileRegister; - boost::shared_ptr m_OriginConnection; - std::wstring m_Name; - std::map m_Files; - std::vector m_SubDirectories; + 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; - std::set m_Origins; + DirectoryEntry *m_Parent; + std::set m_Origins; - bool m_Populated; + bool m_Populated; + + bool m_TopLevel; - bool m_TopLevel; }; + } // namespace MOShared #endif // DIRECTORYENTRY_H diff --git a/src/shared/error_report.cpp b/src/shared/error_report.cpp index fffd77b9..6d091630 100644 --- a/src/shared/error_report.cpp +++ b/src/shared/error_report.cpp @@ -23,71 +23,77 @@ along with Mod Organizer. If not, see . namespace MOShared { -void reportError(LPCSTR format, ...) { - char buffer[1025]; - memset(buffer, 0, sizeof(char) * 1025); - va_list argList; - va_start(argList, format); +void reportError(LPCSTR format, ...) +{ + char buffer[1025]; + memset(buffer, 0, sizeof(char) * 1025); - vsnprintf(buffer, 1024, format, argList); - va_end(argList); + va_list argList; + va_start(argList, format); - MessageBoxA(nullptr, buffer, "Error", MB_OK | MB_ICONERROR); + vsnprintf(buffer, 1024, format, argList); + va_end(argList); + + MessageBoxA(nullptr, buffer, "Error", MB_OK | MB_ICONERROR); } -void reportError(LPCWSTR format, ...) { - WCHAR buffer[1025]; - memset(buffer, 0, sizeof(WCHAR) * 1025); +void reportError(LPCWSTR format, ...) +{ + WCHAR buffer[1025]; + memset(buffer, 0, sizeof(WCHAR) * 1025); - va_list argList; - va_start(argList, format); + va_list argList; + va_start(argList, format); - _vsnwprintf_s(buffer, 1024, format, argList); - va_end(argList); + _vsnwprintf_s(buffer, 1024, format, argList); + va_end(argList); - MessageBoxW(nullptr, buffer, L"Error", MB_OK | MB_ICONERROR); + MessageBoxW(nullptr, buffer, L"Error", MB_OK | MB_ICONERROR); } -std::string getCurrentErrorStringA() { - LPSTR buffer = nullptr; - DWORD errorCode = ::GetLastError(); +std::string getCurrentErrorStringA() +{ + LPSTR buffer = nullptr; + + DWORD errorCode = ::GetLastError(); - if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buffer, 0, nullptr) == 0) { - ::SetLastError(errorCode); - return std::string(); - } else { - LPSTR lastChar = buffer + strlen(buffer) - 2; - *lastChar = '\0'; + if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buffer, 0, nullptr) == 0) { + ::SetLastError(errorCode); + return std::string(); + } else { + LPSTR lastChar = buffer + strlen(buffer) - 2; + *lastChar = '\0'; - std::string result(buffer); + std::string result(buffer); - LocalFree(buffer); - ::SetLastError(errorCode); - return result; - } + LocalFree(buffer); + ::SetLastError(errorCode); + return result; + } } -std::wstring getCurrentErrorStringW() { - LPWSTR buffer = nullptr; +std::wstring getCurrentErrorStringW() +{ + LPWSTR buffer = nullptr; - DWORD errorCode = ::GetLastError(); + DWORD errorCode = ::GetLastError(); - if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&buffer, 0, nullptr) == 0) { - ::SetLastError(errorCode); - return std::wstring(); - } else { - LPWSTR lastChar = buffer + wcslen(buffer) - 2; - *lastChar = '\0'; + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&buffer, 0, nullptr) == 0) { + ::SetLastError(errorCode); + return std::wstring(); + } else { + LPWSTR lastChar = buffer + wcslen(buffer) - 2; + *lastChar = '\0'; - std::wstring result(buffer); + std::wstring result(buffer); - LocalFree(buffer); - ::SetLastError(errorCode); - return result; - } + LocalFree(buffer); + ::SetLastError(errorCode); + return result; + } } } // namespace MOShared diff --git a/src/shared/leaktrace.cpp b/src/shared/leaktrace.cpp index dd85c4b4..1ff1fa9d 100644 --- a/src/shared/leaktrace.cpp +++ b/src/shared/leaktrace.cpp @@ -1,47 +1,57 @@ #include "leaktrace.h" #include "stackdata.h" -#include #include -#include -#include +#include #include -#include +#include #include +#include +#include + using namespace MOShared; + static struct __TraceData { - void regTrace(void* pointer, const char* functionName, int line) { - m_Traces[reinterpret_cast(pointer)] = StackData(functionName, line); - } - void deregTrace(void* pointer) { - auto iter = m_Traces.find(reinterpret_cast(pointer)); - if (iter != m_Traces.end()) { - m_Traces.erase(iter); - } + void regTrace(void *pointer, const char *functionName, int line) { + m_Traces[reinterpret_cast(pointer)] = StackData(functionName, line); + } + void deregTrace(void *pointer) { + auto iter = m_Traces.find(reinterpret_cast(pointer)); + if (iter != m_Traces.end()) { + m_Traces.erase(iter); } + } - ~__TraceData() { - std::map> result; - for (auto iter = m_Traces.begin(); iter != m_Traces.end(); ++iter) { - result[iter->second].push_back(iter->first); - } - for (auto iter = result.begin(); iter != result.end(); ++iter) { - printf("-----------------------------------\n" - "%d objects not freed, allocated at:\n%s", - iter->second.size(), iter->first.toString().c_str()); - printf("Addresses: "); - for (int i = 0; i < (std::min)(5, static_cast(iter->second.size())); ++i) { - printf("%p, ", reinterpret_cast(iter->second[i])); - } - printf("\n"); - } + ~__TraceData() { + std::map > result; + for (auto iter = m_Traces.begin(); iter != m_Traces.end(); ++iter) { + result[iter->second].push_back(iter->first); + } + for (auto iter = result.begin(); iter != result.end(); ++iter) { + printf("-----------------------------------\n" + "%d objects not freed, allocated at:\n%s", + iter->second.size(), iter->first.toString().c_str()); + printf("Addresses: "); + for (int i = 0; + i < (std::min)(5, static_cast(iter->second.size())); ++i) { + printf("%p, ", reinterpret_cast(iter->second[i])); + } + printf("\n"); } + } - std::map m_Traces; + std::map m_Traces; } __trace; -void LeakTrace::TraceAlloc(void* ptr, const char* functionName, int line) { __trace.regTrace(ptr, functionName, line); } -void LeakTrace::TraceDealloc(void* ptr) { __trace.deregTrace(ptr); } +void LeakTrace::TraceAlloc(void *ptr, const char *functionName, int line) +{ + __trace.regTrace(ptr, functionName, line); +} + +void LeakTrace::TraceDealloc(void *ptr) +{ + __trace.deregTrace(ptr); +} diff --git a/src/shared/leaktrace.h b/src/shared/leaktrace.h index b0d04129..4985925e 100644 --- a/src/shared/leaktrace.h +++ b/src/shared/leaktrace.h @@ -1,12 +1,13 @@ #ifndef LEAKTRACE_H #define LEAKTRACE_H + namespace LeakTrace { -void TraceAlloc(void* ptr, const char* functionName, int line); -void TraceDealloc(void* ptr); +void TraceAlloc(void *ptr, const char *functionName, int line); +void TraceDealloc(void *ptr); -}; // namespace LeakTrace +}; #ifdef TRACE_LEAKS diff --git a/src/shared/stackdata.cpp b/src/shared/stackdata.cpp index 5f77bbfa..b336593a 100644 --- a/src/shared/stackdata.cpp +++ b/src/shared/stackdata.cpp @@ -1,150 +1,169 @@ #include "stackdata.h" -#include "error_report.h" #include "util.h" #include +#include #include -#include #include -#include +#include "error_report.h" +#include + using namespace MOShared; #if defined _MSC_VER -static void initDbgIfNecess() { - HANDLE process = ::GetCurrentProcess(); - static std::set initialized; - if (initialized.find(::GetCurrentProcessId()) == initialized.end()) { - static bool firstCall = true; - if (firstCall) { - ::SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); - firstCall = false; - } - if (!::SymInitialize(process, NULL, TRUE)) { - printf("failed to initialize symbols: %lu", ::GetLastError()); - } - initialized.insert(::GetCurrentProcessId()); +static void initDbgIfNecess() +{ + HANDLE process = ::GetCurrentProcess(); + static std::set initialized; + if (initialized.find(::GetCurrentProcessId()) == initialized.end()) { + static bool firstCall = true; + if (firstCall) { + ::SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); + firstCall = false; } + if (!::SymInitialize(process, NULL, TRUE)) { + printf("failed to initialize symbols: %lu", ::GetLastError()); + } + initialized.insert(::GetCurrentProcessId()); + } +} + + + +StackData::StackData() + : m_Count(0) + , m_Function() + , m_Line(-1) +{ + initTrace(); } -StackData::StackData() : m_Count(0), m_Function(), m_Line(-1) { initTrace(); } +StackData::StackData(const char *function, int line) + : m_Count(0) + , m_Function(function) + , m_Line(line) +{ -StackData::StackData(const char* function, int line) : m_Count(0), m_Function(function), m_Line(line) {} +} std::string StackData::toString() const { - initDbgIfNecess(); + initDbgIfNecess(); - char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; - PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - symbol->MaxNameLen = MAX_SYM_NAME; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; - std::ostringstream stackStream; + std::ostringstream stackStream; - if (m_Function.length() > 0) { - stackStream << "[" << m_Function << ":" << m_Line << "]\n"; - } + if (m_Function.length() > 0) { + stackStream << "[" << m_Function << ":" << m_Line << "]\n"; + } - for (unsigned int i = 0; i < m_Count; ++i) { - DWORD64 displacement = 0; - if (!::SymFromAddr(::GetCurrentProcess(), (DWORD64)m_Stack[i], &displacement, symbol)) { - stackStream << m_Count - i - 1 << ": [" << m_Stack[i] << "]\n"; - } else { - stackStream << m_Count - i - 1 << ": " << symbol->Name << "\n"; - } + for(unsigned int i = 0; i < m_Count; ++i) { + DWORD64 displacement = 0; + if (!::SymFromAddr(::GetCurrentProcess(), (DWORD64)m_Stack[i], &displacement, symbol)) { + stackStream << m_Count - i - 1 << ": [" << m_Stack[i] << "]\n"; + } else { + stackStream << m_Count - i - 1 << ": " << symbol->Name << "\n"; } - return stackStream.str(); + } + return stackStream.str(); } void StackData::load_modules(HANDLE process, DWORD processID) { - HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID); - if (snap == INVALID_HANDLE_VALUE) - return; - - MODULEENTRY32 entry; - entry.dwSize = sizeof(entry); - - if (Module32First(snap, &entry)) { - do { - std::string fileName = ToString(entry.szExePath, false); - std::string moduleName = ToString(entry.szModule, false); - SymLoadModule64(process, NULL, fileName.c_str(), moduleName.c_str(), (DWORD64)entry.modBaseAddr, - entry.modBaseSize); - } while (Module32Next(snap, &entry)); - } - CloseHandle(snap); + HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID); + if (snap == INVALID_HANDLE_VALUE) + return; + + MODULEENTRY32 entry; + entry.dwSize = sizeof(entry); + + if (Module32First(snap, &entry)) { + do { + std::string fileName = ToString(entry.szExePath, false); + std::string moduleName = ToString(entry.szModule, false); + SymLoadModule64(process, NULL, fileName.c_str(), moduleName.c_str(), (DWORD64) entry.modBaseAddr, entry.modBaseSize); + } while (Module32Next(snap, &entry)); + } + CloseHandle(snap); } -#pragma warning(disable : 4748) +#pragma warning( disable : 4748 ) void StackData::initTrace() { #ifdef _X86_ - load_modules(::GetCurrentProcess(), ::GetCurrentProcessId()); - CONTEXT context; - std::memset(&context, 0, sizeof(CONTEXT)); - context.ContextFlags = CONTEXT_CONTROL; - // Why only for 64 bit? + load_modules(::GetCurrentProcess(), ::GetCurrentProcessId()); + CONTEXT context; + std::memset(&context, 0, sizeof(CONTEXT)); + context.ContextFlags = CONTEXT_CONTROL; + //Why only for 64 bit? #if BOOST_ARCH_X86_64 || defined(__clang__) - ::RtlCaptureContext(&context); + ::RtlCaptureContext(&context); #else - __asm { + __asm + { Label: mov [context.Ebp], ebp; mov [context.Esp], esp; mov eax, [Label]; mov [context.Eip], eax; - } + } #endif - STACKFRAME64 stackFrame; - ::ZeroMemory(&stackFrame, sizeof(STACKFRAME64)); - stackFrame.AddrPC.Offset = context.Eip; - stackFrame.AddrPC.Mode = AddrModeFlat; - stackFrame.AddrFrame.Offset = context.Ebp; - stackFrame.AddrFrame.Mode = AddrModeFlat; - stackFrame.AddrStack.Offset = context.Esp; - stackFrame.AddrStack.Mode = AddrModeFlat; - m_Count = 0; - while (m_Count < FRAMES_TO_CAPTURE) { - if (!StackWalk64(IMAGE_FILE_MACHINE_I386, ::GetCurrentProcess(), ::GetCurrentThread(), &stackFrame, &context, - NULL, &SymFunctionTableAccess64, &SymGetModuleBase64, NULL)) { - break; - } - - if (stackFrame.AddrPC.Offset == 0) { - continue; - break; - } - - m_Stack[m_Count++] = reinterpret_cast(stackFrame.AddrPC.Offset); + STACKFRAME64 stackFrame; + ::ZeroMemory(&stackFrame, sizeof(STACKFRAME64)); + stackFrame.AddrPC.Offset = context.Eip; + stackFrame.AddrPC.Mode = AddrModeFlat; + stackFrame.AddrFrame.Offset = context.Ebp; + stackFrame.AddrFrame.Mode = AddrModeFlat; + stackFrame.AddrStack.Offset = context.Esp; + stackFrame.AddrStack.Mode = AddrModeFlat; + m_Count = 0; + while (m_Count < FRAMES_TO_CAPTURE) { + if (!StackWalk64(IMAGE_FILE_MACHINE_I386, ::GetCurrentProcess(), + ::GetCurrentThread(), &stackFrame, &context, NULL, + &SymFunctionTableAccess64, &SymGetModuleBase64, NULL)) { + break; } + + if (stackFrame.AddrPC.Offset == 0) { + continue; + break; + } + + m_Stack[m_Count++] = reinterpret_cast(stackFrame.AddrPC.Offset); + } #endif } -bool MOShared::operator==(const StackData& LHS, const StackData& RHS) { - if (LHS.m_Count != RHS.m_Count) { + +bool MOShared::operator==(const StackData &LHS, const StackData &RHS) { + if (LHS.m_Count != RHS.m_Count) { + return false; + } else { + for (int i = 0; i < LHS.m_Count; ++i) { + if (LHS.m_Stack[i] != RHS.m_Stack[i]) { return false; - } else { - for (int i = 0; i < LHS.m_Count; ++i) { - if (LHS.m_Stack[i] != RHS.m_Stack[i]) { - return false; - } - } + } } - return true; + } + return true; } -bool MOShared::operator<(const StackData& LHS, const StackData& RHS) { - if (LHS.m_Count != RHS.m_Count) { - return LHS.m_Count < RHS.m_Count; - } else { - for (int i = 0; i < LHS.m_Count; ++i) { - if (LHS.m_Stack[i] != RHS.m_Stack[i]) { - return LHS.m_Stack[i] < RHS.m_Stack[i]; - } - } + +bool MOShared::operator<(const StackData &LHS, const StackData &RHS) { + if (LHS.m_Count != RHS.m_Count) { + return LHS.m_Count < RHS.m_Count; + } else { + for (int i = 0; i < LHS.m_Count; ++i) { + if (LHS.m_Stack[i] != RHS.m_Stack[i]) { + return LHS.m_Stack[i] < RHS.m_Stack[i]; + } } - return false; + } + return false; } #endif diff --git a/src/shared/stackdata.h b/src/shared/stackdata.h index 252b5ba4..7151699c 100644 --- a/src/shared/stackdata.h +++ b/src/shared/stackdata.h @@ -1,41 +1,50 @@ #ifndef STACKDATA_H #define STACKDATA_H -#include + #include +#include + namespace MOShared { -class StackData { - friend bool operator==(const StackData& LHS, const StackData& RHS); - friend bool operator<(const StackData& LHS, const StackData& RHS); +class StackData { + friend bool operator==(const StackData &LHS, const StackData &RHS); + friend bool operator<(const StackData &LHS, const StackData &RHS); public: - StackData(); - StackData(const char* function, int line); - std::string toString() const; + StackData(); + StackData(const char *function, int line); + + std::string toString() const; private: - void load_modules(HANDLE process, DWORD processID); - void initTrace(); + void load_modules(HANDLE process, DWORD processID); + + void initTrace(); private: - static const int FRAMES_TO_SKIP = 1; - static const int FRAMES_TO_CAPTURE = 20; + + static const int FRAMES_TO_SKIP = 1; + static const int FRAMES_TO_CAPTURE = 20; private: - LPVOID m_Stack[FRAMES_TO_CAPTURE]; - USHORT m_Count; - std::string m_Function; - int m_Line; + + LPVOID m_Stack[FRAMES_TO_CAPTURE]; + USHORT m_Count; + std::string m_Function; + int m_Line; + }; -bool operator==(const StackData& LHS, const StackData& RHS); -bool operator<(const StackData& LHS, const StackData& RHS); +bool operator==(const StackData &LHS, const StackData &RHS); + +bool operator<(const StackData &LHS, const StackData &RHS); } // namespace MOShared + #endif // STACKDATA_H diff --git a/src/shared/util.cpp b/src/shared/util.cpp index 0243bb88..5491a9e6 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -18,136 +18,161 @@ along with Mod Organizer. If not, see . */ #include "util.h" -#include "error_report.h" #include "windows_error.h" +#include "error_report.h" -#include -#include -#include +#include #include +#include +#include #include -#include +#include namespace MOShared { -bool FileExists(const std::string& filename) { - DWORD dwAttrib = ::GetFileAttributesA(filename.c_str()); - return (dwAttrib != INVALID_FILE_ATTRIBUTES); +bool FileExists(const std::string &filename) +{ + DWORD dwAttrib = ::GetFileAttributesA(filename.c_str()); + + return (dwAttrib != INVALID_FILE_ATTRIBUTES); } -bool FileExists(const std::wstring& filename) { - DWORD dwAttrib = ::GetFileAttributesW(filename.c_str()); +bool FileExists(const std::wstring &filename) +{ + DWORD dwAttrib = ::GetFileAttributesW(filename.c_str()); - return (dwAttrib != INVALID_FILE_ATTRIBUTES); + return (dwAttrib != INVALID_FILE_ATTRIBUTES); } -bool FileExists(const std::wstring& searchPath, const std::wstring& filename) { - std::wstringstream stream; - stream << searchPath << "\\" << filename; - return FileExists(stream.str()); +bool FileExists(const std::wstring &searchPath, const std::wstring &filename) +{ + std::wstringstream stream; + stream << searchPath << "\\" << filename; + return FileExists(stream.str()); } -std::string ToString(const std::wstring& source, bool utf8) { - std::string result; - if (source.length() > 0) { - UINT codepage = CP_UTF8; - if (!utf8) { - codepage = AreFileApisANSI() ? GetACP() : GetOEMCP(); - } - int sizeRequired = ::WideCharToMultiByte(codepage, 0, &source[0], -1, nullptr, 0, nullptr, nullptr); - if (sizeRequired == 0) { - throw windows_error("failed to convert string to multibyte"); - } - // the size returned by WideCharToMultiByte contains zero termination IF -1 is specified for the length. - // we don't want that \0 in the string because then the length field would be wrong. Because madness - result.resize(sizeRequired - 1, '\0'); - ::WideCharToMultiByte(codepage, 0, &source[0], (int)source.size(), &result[0], sizeRequired, nullptr, nullptr); +std::string ToString(const std::wstring &source, bool utf8) +{ + std::string result; + if (source.length() > 0) { + UINT codepage = CP_UTF8; + if (!utf8) { + codepage = AreFileApisANSI() ? GetACP() : GetOEMCP(); + } + int sizeRequired = ::WideCharToMultiByte(codepage, 0, &source[0], -1, nullptr, 0, nullptr, nullptr); + if (sizeRequired == 0) { + throw windows_error("failed to convert string to multibyte"); } + // the size returned by WideCharToMultiByte contains zero termination IF -1 is specified for the length. + // we don't want that \0 in the string because then the length field would be wrong. Because madness + result.resize(sizeRequired - 1, '\0'); + ::WideCharToMultiByte(codepage, 0, &source[0], (int)source.size(), &result[0], sizeRequired, nullptr, nullptr); + } - return result; + return result; } -std::wstring ToWString(const std::string& source, bool utf8) { - std::wstring result; - if (source.length() > 0) { - UINT codepage = CP_UTF8; - if (!utf8) { - codepage = AreFileApisANSI() ? GetACP() : GetOEMCP(); - } - int sizeRequired = - ::MultiByteToWideChar(codepage, 0, source.c_str(), static_cast(source.length()), nullptr, 0); - if (sizeRequired == 0) { - throw windows_error("failed to convert string to wide character"); - } - result.resize(sizeRequired, L'\0'); - ::MultiByteToWideChar(codepage, 0, source.c_str(), static_cast(source.length()), &result[0], sizeRequired); +std::wstring ToWString(const std::string &source, bool utf8) +{ + std::wstring result; + if (source.length() > 0) { + UINT codepage = CP_UTF8; + if (!utf8) { + codepage = AreFileApisANSI() ? GetACP() : GetOEMCP(); + } + int sizeRequired + = ::MultiByteToWideChar(codepage, 0, source.c_str(), + static_cast(source.length()), nullptr, 0); + if (sizeRequired == 0) { + throw windows_error("failed to convert string to wide character"); } + result.resize(sizeRequired, L'\0'); + ::MultiByteToWideChar(codepage, 0, source.c_str(), + static_cast(source.length()), &result[0], + sizeRequired); + } - return result; + return result; } static std::locale loc(""); -static auto locToLowerW = [](wchar_t in) -> wchar_t { return std::tolower(in, loc); }; - -static auto locToLower = [](char in) -> char { return std::tolower(in, loc); }; - -std::string& ToLower(std::string& text) { - std::transform(text.begin(), text.end(), text.begin(), locToLower); - return text; +static auto locToLowerW = [] (wchar_t in) -> wchar_t { + return std::tolower(in, loc); +}; + +static auto locToLower = [] (char in) -> char { + return std::tolower(in, loc); +}; + +std::string &ToLower(std::string &text) +{ + std::transform(text.begin(), text.end(), text.begin(), locToLower); + return text; } -std::string ToLower(const std::string& text) { - std::string result(text); - std::transform(result.begin(), result.end(), result.begin(), locToLower); - return result; +std::string ToLower(const std::string &text) +{ + std::string result(text); + std::transform(result.begin(), result.end(), result.begin(), locToLower); + return result; } -std::wstring& ToLower(std::wstring& text) { - std::transform(text.begin(), text.end(), text.begin(), locToLowerW); - return text; +std::wstring &ToLower(std::wstring &text) +{ + std::transform(text.begin(), text.end(), text.begin(), locToLowerW); + return text; } -std::wstring ToLower(const std::wstring& text) { - std::wstring result(text); - std::transform(result.begin(), result.end(), result.begin(), locToLowerW); - return result; +std::wstring ToLower(const std::wstring &text) +{ + std::wstring result(text); + std::transform(result.begin(), result.end(), result.begin(), locToLowerW); + return result; } -bool CaseInsenstiveComparePred(wchar_t lhs, wchar_t rhs) { return std::tolower(lhs, loc) == std::tolower(rhs, loc); } +bool CaseInsenstiveComparePred(wchar_t lhs, wchar_t rhs) +{ + return std::tolower(lhs, loc) == std::tolower(rhs, loc); +} -bool CaseInsensitiveEqual(const std::wstring& lhs, const std::wstring& rhs) { - return (lhs.length() == rhs.length()) && - std::equal(lhs.begin(), lhs.end(), rhs.begin(), [](wchar_t lhs, wchar_t rhs) -> bool { - return std::tolower(lhs, loc) == std::tolower(rhs, loc); - }); +bool CaseInsensitiveEqual(const std::wstring &lhs, const std::wstring &rhs) +{ + return (lhs.length() == rhs.length()) + && std::equal(lhs.begin(), lhs.end(), + rhs.begin(), + [] (wchar_t lhs, wchar_t rhs) -> bool { + return std::tolower(lhs, loc) == std::tolower(rhs, loc); + }); } -VS_FIXEDFILEINFO GetFileVersion(const std::wstring& fileName) { - DWORD handle = 0UL; - DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); - if (size == 0) { - throw windows_error("failed to determine file version info size"); +VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) +{ + DWORD handle = 0UL; + DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); + if (size == 0) { + throw windows_error("failed to determine file version info size"); + } + + boost::scoped_array buffer(new char[size]); + try { + handle = 0UL; + if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer.get())) { + throw windows_error("failed to determine file version info"); } - boost::scoped_array buffer(new char[size]); - try { - handle = 0UL; - if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer.get())) { - throw windows_error("failed to determine file version info"); - } - - void* versionInfoPtr = nullptr; - UINT versionInfoLength = 0; - if (!::VerQueryValue(buffer.get(), L"\\", &versionInfoPtr, &versionInfoLength)) { - throw windows_error("failed to determine file version"); - } - - VS_FIXEDFILEINFO result = *(VS_FIXEDFILEINFO*)versionInfoPtr; - return result; - } catch (...) { - throw; + void *versionInfoPtr = nullptr; + UINT versionInfoLength = 0; + if (!::VerQueryValue(buffer.get(), L"\\", &versionInfoPtr, &versionInfoLength)) { + throw windows_error("failed to determine file version"); } + + VS_FIXEDFILEINFO result = *(VS_FIXEDFILEINFO*)versionInfoPtr; + return result; + } catch (...) { + throw; + } } + } // namespace MOShared diff --git a/src/shared/util.h b/src/shared/util.h index 4b390cf3..1e498059 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -20,6 +20,7 @@ along with Mod Organizer. If not, see . #ifndef UTIL_H #define UTIL_H + #include #define WIN32_LEAN_AND_MEAN #include @@ -27,23 +28,23 @@ along with Mod Organizer. If not, see . namespace MOShared { /// Test if a file (or directory) by the specified name exists -bool FileExists(const std::string& filename); -bool FileExists(const std::wstring& filename); +bool FileExists(const std::string &filename); +bool FileExists(const std::wstring &filename); -bool FileExists(const std::wstring& searchPath, const std::wstring& filename); +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 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 &ToLower(std::string &text); +std::string ToLower(const std::string &text); -std::wstring& ToLower(std::wstring& text); -std::wstring ToLower(const std::wstring& text); +std::wstring &ToLower(std::wstring &text); +std::wstring ToLower(const std::wstring &text); -bool CaseInsensitiveEqual(const std::wstring& lhs, const std::wstring& rhs); +bool CaseInsensitiveEqual(const std::wstring &lhs, const std::wstring &rhs); -VS_FIXEDFILEINFO GetFileVersion(const std::wstring& fileName); +VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName); } // namespace MOShared diff --git a/src/shared/windows_error.cpp b/src/shared/windows_error.cpp index ab5c7b8e..97a58a20 100644 --- a/src/shared/windows_error.cpp +++ b/src/shared/windows_error.cpp @@ -22,27 +22,28 @@ along with Mod Organizer. If not, see . namespace MOShared { -std::string windows_error::constructMessage(const std::string& input, int inErrorCode) { - std::ostringstream finalMessage; - finalMessage << input; - - LPSTR buffer = nullptr; - - DWORD errorCode = inErrorCode != -1 ? inErrorCode : ::GetLastError(); - - // TODO: the message is not english? - if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buffer, 0, nullptr) == 0) { - finalMessage << " (errorcode " << errorCode << ")"; - } else { - LPSTR lastChar = buffer + strlen(buffer) - 2; - *lastChar = '\0'; - finalMessage << " (" << buffer << " [" << errorCode << "])"; - LocalFree(buffer); // allocated by FormatMessage - } - - ::SetLastError(errorCode); // restore error code because FormatMessage might have modified it - return finalMessage.str(); +std::string windows_error::constructMessage(const std::string& input, int inErrorCode) +{ + std::ostringstream finalMessage; + finalMessage << input; + + LPSTR buffer = nullptr; + + DWORD errorCode = inErrorCode != -1 ? inErrorCode : ::GetLastError(); + + // TODO: the message is not english? + if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buffer, 0, nullptr) == 0) { + finalMessage << " (errorcode " << errorCode << ")"; + } else { + LPSTR lastChar = buffer + strlen(buffer) - 2; + *lastChar = '\0'; + finalMessage << " (" << buffer << " [" << errorCode << "])"; + LocalFree(buffer); // allocated by FormatMessage + } + + ::SetLastError(errorCode); // restore error code because FormatMessage might have modified it + return finalMessage.str(); } } // namespace MOShared diff --git a/src/shared/windows_error.h b/src/shared/windows_error.h index 66c512f6..03ce0abd 100644 --- a/src/shared/windows_error.h +++ b/src/shared/windows_error.h @@ -20,6 +20,7 @@ along with Mod Organizer. If not, see . #ifndef WINDOWS_ERROR_H #define WINDOWS_ERROR_H + #include #define WIN32_LEAN_AND_MEAN #include @@ -28,15 +29,14 @@ namespace MOShared { class windows_error : public std::runtime_error { public: - windows_error(const std::string& message, int errorcode = ::GetLastError()) - : runtime_error(constructMessage(message, errorcode)), m_ErrorCode(errorcode) {} - int getErrorCode() const { return m_ErrorCode; } - + windows_error(const std::string& message, int errorcode = ::GetLastError()) + : runtime_error(constructMessage(message, errorcode)), m_ErrorCode(errorcode) + {} + int getErrorCode() const { return m_ErrorCode; } private: - std::string constructMessage(const std::string& input, int errorcode); - + std::string constructMessage(const std::string& input, int errorcode); private: - int m_ErrorCode; + int m_ErrorCode; }; } // namespace MOShared -- cgit v1.3.1