From 250152580c31628eb5a57be1d0c7eba8feb7150d Mon Sep 17 00:00:00 2001 From: EyeGuy <vanya619@list.ru> Date: Sat, 1 Feb 2025 23:49:22 +0300 Subject: [PATCH] Update fs --- source/core/FileSystem.cpp | 592 ++++++++++++++++++------------------- source/core/FileSystem.h | 4 +- 2 files changed, 284 insertions(+), 312 deletions(-) diff --git a/source/core/FileSystem.cpp b/source/core/FileSystem.cpp index a55a92411..d66a395f2 100644 --- a/source/core/FileSystem.cpp +++ b/source/core/FileSystem.cpp @@ -12,7 +12,7 @@ IFileIterator *CFileSystem::getListIterator(const char *szPath, const char **szE Array<String> paths; String basePath(szPath); - if (!isAbsolutePath(szPath)) + if(!isAbsolutePath(szPath)) { getAllvariantsCanonizePath(szPath, paths); } @@ -26,47 +26,46 @@ IFileIterator *CFileSystem::getListIterator(const char *szPath, const char **szE void CFileSystem::addPathInPriorityArray(int id, int iPriority) { - Pair newElement{ iPriority, id }; + Pair newElement{iPriority, id}; //Если приоритет по умолчанию и нет элементов - задаем значение 0 (потому что первый) //Если элементов больше чем 0 то тогда ставим самый большой приоритет из возможных - if (iPriority == -1) + if(iPriority == -1) { UINT size = m_priorityArray.size(); newElement.priority = size > 0 ? m_priorityArray[0].priority + 1 : 0; } - m_priorityArray.insert(newElement, [](const Pair &obj, const Pair &obj2) -> bool {return obj.priority <= obj2.priority; }); + m_priorityArray.insert(newElement, [](const Pair &obj, const Pair &obj2) -> bool { return obj.priority <= obj2.priority; }); } bool CFileSystem::isFileOrDirectory(const char *szPath, bool isFile) { - char path[SIZE_PATH]; - getAbsoluteCanonizePath(szPath, path, SIZE_PATH); + char path[SIZE_PATH]; + getAbsoluteCanonizePath(szPath, path, SIZE_PATH); - if (CHECK_CORRECT_PATH(path)) - { - return false; - } + if(CHECK_CORRECT_PATH(path)) + { + return false; + } - DWORD flag = GetFileAttributesW(CMB2WC(path)); + DWORD flag = GetFileAttributesW(CMB2WC(path)); - //Проверка на то куда имено ведет путь - к файлу или папке - return (flag != INVALID_FILE_ATTRIBUTES) && (isFile ? !(flag & FILE_ATTRIBUTE_DIRECTORY) : (flag & FILE_ATTRIBUTE_DIRECTORY)); + //Проверка на то куда имено ведет путь - к файлу или папке + return (flag != INVALID_FILE_ATTRIBUTES) && (isFile ? !(flag & FILE_ATTRIBUTE_DIRECTORY) : (flag & FILE_ATTRIBUTE_DIRECTORY)); } void CFileSystem::getAllvariantsCanonizePath(const char *szPath, Array<String> &container) { - for (int i = 0, I = m_filePaths.size(); i < I; ++i) + char szBuff[SIZE_PATH]; + + for(int i = 0, I = m_filePaths.size(); i < I; ++i) { - String buff = m_filePaths[i]; - buff += '/'; - buff += szPath; - buff += '/'; // <- оптимизация buffObj + sprintf(szBuff, "%s/%s/", m_filePaths[i].c_str(), szPath); - if (isDirectory(buff.c_str())) + if(isDirectory(szBuff)) { - container.push_back(buff); + container.push_back(szBuff); } } } @@ -75,86 +74,85 @@ void CFileSystem::getNormalPath(const char *szPath, char *outBuff, int iOutMax) { if(szPath != outBuff) { - size_t len = strlen(szPath) + 1; - - if(iOutMax < len) - { - MEMCCPY_ERROR(outBuff); - return; - } + if(iOutMax < strlen(szPath) + 1) + { + MEMCCPY_ERROR(outBuff); + return; + } - memcpy(outBuff, szPath, len); + strcpy(outBuff, szPath); } - do - { - *outBuff = *outBuff == '/' ? '\\' : *outBuff; - } while (*outBuff++ != '\0'); + do + { + *outBuff = *outBuff == '/' ? '\\' : *outBuff; + } + while(*outBuff++ != '\0'); } bool CFileSystem::isAbsolutePathInRoot(const char *szPath) { - if (!isAbsolutePath(szPath)) - { - return false; - } + if(!isAbsolutePath(szPath)) + { + return false; + } - char rootPath[SIZE_PATH]; - getFullPathToBuild(rootPath, SIZE_PATH); - const char *pos = strstr(szPath, rootPath); + char rootPath[SIZE_PATH]; + getFullPathToBuild(rootPath, SIZE_PATH); + const char *pos = strstr(szPath, rootPath); - return pos != nullptr; + return pos != nullptr; } void CFileSystem::getAbsoluteCanonizePath(const char *szPath, char *outPath, int iOutMax) { - bool absolute = isAbsolutePath(szPath); - bool correctPath = true; - - size_t len = absolute ? strlen(szPath) + 1 : SIZE_PATH; - - if (absolute) - { - memcpy(outPath, szPath, len); - } - else - { - correctPath = resolvePath(szPath, outPath, len); - } - - //Во время поиска пути могут произойти ошибки - путь может быть не найден, или слишком маленький буфер для записи - if (correctPath) - { - //Если все корректно прошло, то путь можно канонизировать - canonize_path(outPath); - } - else - { - //Если что то пошло не так записываем '\0' в память, потом это значение можно проверить - MEMCCPY_ERROR(outPath); - } + bool absolute = isAbsolutePath(szPath); + bool correctPath = true; + + size_t len = absolute ? strlen(szPath) + 1 : SIZE_PATH; + + if(absolute) + { + memcpy(outPath, szPath, len); + } + else + { + correctPath = resolvePath(szPath, outPath, len); + } + + //Во время поиска пути могут произойти ошибки - путь может быть не найден, или слишком маленький буфер для записи + if(correctPath) + { + //Если все корректно прошло, то путь можно канонизировать + canonize_path(outPath); + } + else + { + //Если что то пошло не так записываем '\0' в память, потом это значение можно проверить + MEMCCPY_ERROR(outPath); + } } void CFileSystem::getFullPathToBuild(char *buff, int iSize) { - GetModuleFileName(nullptr, buff, iSize); - dirname(buff); - dirname(buff); - canonize_path(buff); + GetModuleFileName(nullptr, buff, iSize); + dirname(buff); + dirname(buff); + canonize_path(buff); } void CFileSystem::getFileName(const char *name, char *outName, int iOutBuff) { - WIN32_FIND_DATAW wfd; + WIN32_FIND_DATAW wfd; HANDLE hFind = FindFirstFileW(CMB2WC(name), &wfd); - if (hFind != INVALID_HANDLE_VALUE) - { - FIND_CLOSE(hFind); + if(hFind != INVALID_HANDLE_VALUE) + { + FIND_CLOSE(hFind); - //Если размера буфера хватает - то записываем имя файла, если нет то записываем в [0] '\0' + //Если размера буфера хватает - то записываем имя файла, если нет то записываем в [0] '\0' iOutBuff > MAX_PATH ? memcpy(outName, CWC2MB(wfd.cFileName), MAX_PATH) : MEMCCPY_ERROR(outName); - } + } } time_t CFileSystem::filetimeToTime_t(const FILETIME& ft) @@ -163,7 +161,7 @@ time_t CFileSystem::filetimeToTime_t(const FILETIME& ft) ull.LowPart = ft.dwLowDateTime; ull.HighPart = ft.dwHighDateTime; - return ull.QuadPart / 10000000ULL - 11644473600ULL; + return ull.QuadPart / 10000000ULL - 11644473600ULL; } HANDLE CFileSystem::getFileHandle(const char *szPath) @@ -179,135 +177,134 @@ HANDLE CFileSystem::getFileHandle(const char *szPath) bool CFileSystem::isAbsolutePath(const char *szPath) { - while (*szPath != '\0') - { - //Для корректности нужна проверка на разные слеши, ведь на вход может прийти путь не с / - if (*szPath == ':' && (*(szPath + 1) == '/' || *(szPath + 1) == '\\')) - { - return true; - } - ++szPath; - } - return false; + while(*szPath != '\0') + { + //Для корректности нужна проверка на разные слеши, ведь на вход может прийти путь не с / + if(*szPath == ':' && (*(szPath + 1) == '/' || *(szPath + 1) == '\\')) + { + return true; + } + ++szPath; + } + return false; } -String *CFileSystem::copyFile(const char* szPath) +void CFileSystem::copyFile(const char* szPath, char *szOut) { - createDirectory(m_filePaths[m_writableRoot].c_str()); + createDirectory(m_filePaths[m_writableRoot].c_str()); - char fn[MAX_PATH]; - getFileName(szPath, fn, MAX_PATH); - String *newFilePath = new String(m_filePaths[m_writableRoot] + '/' + fn); - CopyFileW(CMB2WC(szPath), CMB2WC(newFilePath->c_str()), false); - - return newFilePath; + char fn[SIZE_PATH]; + getFileName(szPath, fn, SIZE_PATH); + sprintf(szOut, "%s/%s", m_filePaths[m_writableRoot].c_str(), fn); + CopyFileW(CMB2WC(szPath), CMB2WC(szOut), false); } CFileSystem::CFileSystem() { - getFullPathToBuild(m_pathToBuild, SIZE_PATH); + getFullPathToBuild(m_pathToBuild, SIZE_PATH); } UINT CFileSystem::addRoot(const char *szPath, int iPriority) { - String str; - - //Если путь не абсолютный - то прибавляем к нему часть пути к папке build - if (!isAbsolutePath(szPath)) - { - str += m_pathToBuild; - } + char szBuff[SIZE_PATH]; - str += szPath; // <--- Оптимизация для того что бы не создавать временных объектов + //Если путь не абсолютный - то прибавляем к нему часть пути к папке build + if(!isAbsolutePath(szPath)) + { + sprintf(szBuff, "%s%s", m_pathToBuild, szPath); + } + else + { + sprintf(szBuff, "%s", szPath); + } - m_filePaths.push_back(str); - addPathInPriorityArray(m_filePaths.size() - 1, iPriority); + m_filePaths.push_back(szBuff); + addPathInPriorityArray(m_filePaths.size() - 1, iPriority); - //Если у нас некорректный путь для записи и путь не является архивным - if (m_writableRoot == -1 && *szPath != '@') - { - m_writableRoot = m_filePaths.size() - 1; - } + //Если у нас некорректный путь для записи и путь не является архивным + if(m_writableRoot == -1 && *szPath != '@') + { + m_writableRoot = m_filePaths.size() - 1; + } - return m_filePaths.size() - 1; + return m_filePaths.size() - 1; } -UINT CFileSystem::getRootCount() const +UINT CFileSystem::getRootCount() const { - return m_filePaths.size(); + return m_filePaths.size(); } const char *CFileSystem::getRoot(UINT id) const { - FILEID_CHECKED(m_filePaths.size()); + FILEID_CHECKED(m_filePaths.size()); - return m_filePaths[id].c_str(); + return m_filePaths[id].c_str(); } void CFileSystem::setWritableRoot(UINT id) { - FILEID_CHECKED(m_filePaths.size()); + FILEID_CHECKED(m_filePaths.size()); - m_writableRoot = id; + m_writableRoot = id; } bool CFileSystem::resolvePath(const char *szPath, char *szOut, size_t iOutMax) { - size_t len = 0; + size_t len = 0; - if (isAbsolutePath(szPath)) - { - len = strlen(szPath) + 1; + if(isAbsolutePath(szPath)) + { + len = strlen(szPath) + 1; + + CHECK_SIZE(len, iOutMax); - CHECK_SIZE(len, iOutMax); + memcpy(szOut, szPath, len); + return true; + } - memcpy(szOut, szPath, len); - return true; - } - - String buff; + char szBuff[SIZE_PATH]; - for (UINT i = 0, l = m_priorityArray.size(); i < l; ++i) - { - int id = m_priorityArray[i].pathId; - buff = (m_filePaths[id] + '/' + szPath); + for(UINT i = 0, l = m_priorityArray.size(); i < l; ++i) + { + int id = m_priorityArray[i].pathId; + len = sprintf(szBuff, "%s/%s", m_filePaths[id].c_str(), szPath) + 1; - if (fileExists(buff.c_str())/* && isFile(buff.c_str())*/) - { - CHECK_SIZE(len, iOutMax); + if(fileExists(szBuff)/* && isFile(buff.c_str())*/) + { + CHECK_SIZE(len, iOutMax); - len = buff.length() + 1; - memcpy(szOut, buff.c_str(), len); - return true; - } - } + strcpy(szOut, szBuff); + return true; + } + } - return false; + return false; } bool CFileSystem::fileExists(const char *szPath) { - char path[SIZE_PATH]; - getAbsoluteCanonizePath(szPath, path, SIZE_PATH); + char path[SIZE_PATH]; + getAbsoluteCanonizePath(szPath, path, SIZE_PATH); - if (CHECK_CORRECT_PATH(path)) - { - //Если не удалось найти полный путь - на выход - return false; - } + if(CHECK_CORRECT_PATH(path)) + { + //Если не удалось найти полный путь - на выход + return false; + } - return fileGetSize(path) != FILE_NOT_FOUND; + return fileGetSize(path) != FILE_NOT_FOUND; } size_t CFileSystem::fileGetSize(const char *szPath) { - char path[SIZE_PATH]; - getAbsoluteCanonizePath(szPath, path, SIZE_PATH); + char path[SIZE_PATH]; + getAbsoluteCanonizePath(szPath, path, SIZE_PATH); - if (CHECK_CORRECT_PATH(path)) - { - return FILE_NOT_FOUND; - } + if(CHECK_CORRECT_PATH(path)) + { + return FILE_NOT_FOUND; + } WIN32_FILE_ATTRIBUTE_DATA lpFileInformation; @@ -315,7 +312,7 @@ size_t CFileSystem::fileGetSize(const char *szPath) //Преобразование размера из старших и младших бит ULONGLONG FileSize = (static_cast<ULONGLONG>(lpFileInformation.nFileSizeHigh) << - sizeof(lpFileInformation.nFileSizeLow) * NUM_BITS_IN_BYTE) | + sizeof(lpFileInformation.nFileSizeLow) * NUM_BITS_IN_BYTE) | lpFileInformation.nFileSizeLow; //Если result != 0 то все хорошо, если 0 то файл не найден @@ -324,25 +321,25 @@ size_t CFileSystem::fileGetSize(const char *szPath) bool CFileSystem::isFile(const char *szPath) { - return isFileOrDirectory(szPath, true); + return isFileOrDirectory(szPath, true); } bool CFileSystem::isDirectory(const char *szPath) { - return isFileOrDirectory(szPath, false); + return isFileOrDirectory(szPath, false); } time_t CFileSystem::getFileModifyTime(const char *szPath) { - char path[SIZE_PATH]; - getAbsoluteCanonizePath(szPath, path, SIZE_PATH); + char path[SIZE_PATH]; + getAbsoluteCanonizePath(szPath, path, SIZE_PATH); - if (CHECK_CORRECT_PATH(path)) - { - return 0; - } + if(CHECK_CORRECT_PATH(path)) + { + return 0; + } - WIN32_FILE_ATTRIBUTE_DATA lpFileInformation; + WIN32_FILE_ATTRIBUTE_DATA lpFileInformation; GetFileAttributesExW(CMB2WC(path), GetFileExInfoStandard, &lpFileInformation); @@ -354,10 +351,10 @@ IFileIterator *CFileSystem::getFolderList(const char *szPath) Array<String> paths; String basePath(szPath); - if (!isAbsolutePath(szPath)) + if(!isAbsolutePath(szPath)) { getAllvariantsCanonizePath(szPath, paths); - } + } else { paths.push_back(szPath); @@ -368,7 +365,7 @@ IFileIterator *CFileSystem::getFolderList(const char *szPath) IFileIterator *CFileSystem::getFileList(const char *szPath, const char *szExt) { - const char *exts[] = { szExt }; + const char *exts[] = {szExt}; return getFileList(szPath, exts, 1); } @@ -379,7 +376,7 @@ IFileIterator *CFileSystem::getFileList(const char *szPath, const char **szExts, IFileIterator *CFileSystem::getFileListRecursive(const char *szPath, const char *szExt) { - const char *exts[] = { szExt }; + const char *exts[] = {szExt}; return getFileListRecursive(szPath, exts, 1); } @@ -390,159 +387,134 @@ IFileIterator *CFileSystem::getFileListRecursive(const char *szPath, const char bool CFileSystem::createDirectory(const char *szPath) { - char path[SIZE_PATH]; - getNormalPath(szPath, path, SIZE_PATH); - if(!isAbsolutePath(path)) - { - char szBuf[MAX_PATH]; - szBuf[0] = 0; - strcat(szBuf, m_filePaths[m_writableRoot].c_str()); - strcat(szBuf, "/"); - strcat(szBuf, szPath); - char *tmp = szBuf; - while(*tmp) - { - if(*tmp == '/') - { - *tmp = '\\'; - } - ++tmp; - } - return(SHCreateDirectoryExW(nullptr, CMB2WC(szBuf), nullptr) == NO_ERROR); - } + char path[SIZE_PATH]; + getNormalPath(szPath, path, SIZE_PATH); + if(!isAbsolutePath(path)) + { + char szBuf[SIZE_PATH]; + sprintf(szBuf, "%s/%s", m_filePaths[m_writableRoot].c_str(), szPath); + char *tmp = szBuf; + while(*tmp) + { + if(*tmp == '/') + { + *tmp = '\\'; + } + ++tmp; + } + return(SHCreateDirectoryExW(nullptr, CMB2WC(szBuf), nullptr) == NO_ERROR); + } return(SHCreateDirectoryExW(nullptr, CMB2WC(path), nullptr) == NO_ERROR); } bool CFileSystem::deleteDirectory(const char *szPath) { - char path[SIZE_PATH]; + char path[SIZE_PATH]; getAbsoluteCanonizePath(szPath, path, SIZE_PATH); getNormalPath(path, path, SIZE_PATH); - CMB2WC wszPath(path); - size_t len = wcslen(wszPath); - wchar_t *pBuf = (wchar_t*)alloca(sizeof(wchar_t) * (len + 2)); - memcpy(pBuf, wszPath, sizeof(wchar_t) * (len + 1)); - pBuf[len + 1] = 0; - - SHFILEOPSTRUCTW file_op = { - NULL, - FO_DELETE, - pBuf, - L"", - FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT, - false, - 0, - L"" - }; - - // Если вернуло не 0, то все плохо - return(SHFileOperationW(&file_op) == NO_ERROR); + CMB2WC wszPath(path); + size_t len = wcslen(wszPath); + wchar_t *pBuf = (wchar_t*)alloca(sizeof(wchar_t) * (len + 2)); + memcpy(pBuf, wszPath, sizeof(wchar_t) * (len + 1)); + pBuf[len + 1] = 0; + + SHFILEOPSTRUCTW file_op = { + NULL, + FO_DELETE, + pBuf, + L"", + FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT, + false, + 0, + L"" + }; + + // Если вернуло не 0, то все плохо + return(SHFileOperationW(&file_op) == NO_ERROR); } IFile *CFileSystem::openFile(const char *szPath, FILE_OPEN_MODE mode = FILE_MODE_READ) { - //Выходим если режим открытия - не для чтения и нет пути для записи - if (m_writableRoot == -1 && mode != FILE_MODE_READ) - { - return nullptr; - } - - //Зарезервированная строка, если вдруг не хватит SIZE_PATH - char reserveStr[SIZE_PATH * 2]; - bool useReserveStr = false; - - char fullPath[SIZE_PATH]; - getAbsoluteCanonizePath(szPath, fullPath, SIZE_PATH); - - //Если по каким либо причинам нельзя вернуть полный путь - на выход - if (CHECK_CORRECT_PATH(fullPath) && mode == FILE_MODE_READ) - { - return nullptr; - } - - IFile *file = new CFile; - - if (mode == FILE_MODE_READ) - { - //Если открываем только на чтение - то копирование не нужно (следовательно и выделение памяти тоже лишняя операция) - if (file->open(fullPath, CORE_FILE_BIN) != 0) - { - mem_delete(file); - } - return file; - } - - String *newFileName; - - if (CHECK_CORRECT_PATH(fullPath)) - { - newFileName = new String(m_filePaths[m_writableRoot].c_str()); - *newFileName += '/'; - *newFileName += szPath; - - getAbsoluteCanonizePath(newFileName->c_str(), fullPath, SIZE_PATH); - - mem_delete(newFileName); - } - - bool inRoot = isAbsolutePathInRoot(fullPath); - - //Если путь в корне, и файла не существует - создаем его - if (inRoot && !fileExists(fullPath)) - { - size_t len = strlen(fullPath) + 1; - char dirName[SIZE_PATH]; - - memcpy(dirName, fullPath, len); - dirname(dirName); - len = strlen(dirName); - dirName[len - 1] = '\0'; - createDirectory(dirName); - } - //Если путь не в корне и его не существует - на выход - else if (!fileExists(fullPath)) - { - mem_delete(file); - return nullptr; - } - //Если путь вне корня - тогда копируем в корень - else if (!inRoot) - { - newFileName = copyFile(fullPath); - size_t lenPath = strlen(fullPath) + 1; - - if (lenPath < newFileName->length()) - { - memcpy(reserveStr, newFileName->c_str(), newFileName->length() + 1); - useReserveStr = true; - } - - memcpy(fullPath, newFileName->c_str(), newFileName->length() + 1); - mem_delete(newFileName); - } - - int res = 0; - - //Определяем использован ли дополнительный путь для записи в файловой системе - char* correctPath = useReserveStr ? reserveStr : fullPath; - - switch (mode) - { - case FILE_MODE_WRITE: - res = file->create(correctPath, CORE_FILE_BIN); - break; - - case FILE_MODE_APPEND: - res = file->add(correctPath, CORE_FILE_BIN); - break; - } - - if (res != 0) - { - mem_delete(file); - } - - return file; + //Выходим если режим открытия - не для чтения и нет пути для записи + if(m_writableRoot == -1 && mode != FILE_MODE_READ) + { + return nullptr; + } + + char fullPath[SIZE_PATH]; + getAbsoluteCanonizePath(szPath, fullPath, SIZE_PATH); + + //Если по каким либо причинам нельзя вернуть полный путь - на выход + if(CHECK_CORRECT_PATH(fullPath) && mode == FILE_MODE_READ) + { + return nullptr; + } + + IFile *file = new CFile; + + if(mode == FILE_MODE_READ) + { + //Если открываем только на чтение - то копирование не нужно (следовательно и выделение памяти тоже лишняя операция) + if(file->open(fullPath, CORE_FILE_BIN) != 0) + { + mem_delete(file); + } + return file; + } + + char szNewFileName[SIZE_PATH]; + + if(CHECK_CORRECT_PATH(fullPath)) + { + sprintf(szNewFileName, "%s/%s", m_filePaths[m_writableRoot].c_str(), szPath); + + getAbsoluteCanonizePath(szNewFileName, fullPath, SIZE_PATH); + } + + bool inRoot = isAbsolutePathInRoot(fullPath); + + //Если путь в корне, и файла не существует - создаем его + if(inRoot && !fileExists(fullPath)) + { + char dirName[SIZE_PATH]; + + strcpy(dirName, fullPath); + dirname(dirName); + createDirectory(dirName); + } + //Если путь не в корне и его не существует - на выход + else if(!fileExists(fullPath)) + { + mem_delete(file); + return nullptr; + } + //Если путь вне корня - тогда копируем в корень + else if(!inRoot) + { + copyFile(fullPath, szNewFileName); + + strcpy(fullPath, szNewFileName); + } + + int res = 0; + + switch(mode) + { + case FILE_MODE_WRITE: + res = file->create(fullPath, CORE_FILE_BIN); + break; + + case FILE_MODE_APPEND: + res = file->add(fullPath, CORE_FILE_BIN); + break; + } + + if(res != 0) + { + mem_delete(file); + } + + return file; } \ No newline at end of file diff --git a/source/core/FileSystem.h b/source/core/FileSystem.h index 5bcfcb453..72cece8e5 100644 --- a/source/core/FileSystem.h +++ b/source/core/FileSystem.h @@ -43,7 +43,7 @@ See the license in LICENSE #define MEMCCPY_ERROR(buff) memcpy(buff, "\0", 1); -#define SIZE_PATH 4096 +#define SIZE_PATH 2048 #define INVALID_OR_NULL(handle) ((handle) == NULL || (handle) == INVALID_HANDLE_VALUE) @@ -128,7 +128,7 @@ private: bool isAbsolutePath(const char* szPath); - String *copyFile(const char* szPath); + void copyFile(const char* szPath, char *szOut); //!корневые пути и приоритет Array<String> m_filePaths; -- GitLab