| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- #include "Finder.h"
- #include "FileService.h"
- Finder::Finder(const char * fullPath, const char * findMask, dword flags, const char * _cppFileName, long _cppFileLine) : files(_FL_)
- {
- path = fullPath;
- if(path.Len() > 0 && path[path.Len() - 1] != '\\')
- {
- path += '\\';
- }
- mask = findMask;
- if(mask == "*")
- {
- mask = "*.*";
- }
- isRecursive = ((flags & find_no_recursive) == 0);
- isDots = ((flags & find_dots) != 0);
- isAddFolders = ((flags & find_folders) != 0);
- isFindInLoadedPacks = ((flags & find_no_files_from_packs) == 0);
- isFindInMirrors = ((flags & find_no_mirror_files) == 0);
- isInverseOrder = ((flags & find_inverse_order) != 0);
- #ifndef STOP_DEBUG
- cppFileName = _cppFileName;
- cppFileLine = _cppFileLine;
- #endif
- Reset();
- }
- Finder::~Finder()
- {
- }
- //Удалить сообщив об ошибке
- void Finder::ErrorRelease()
- {
- #ifndef STOP_DEBUG
- FileService::object->Error("FileService error: IFinder not release (file: %s, line %i)", cppFileName, cppFileLine);
- #endif
- delete this;
- }
- //Удалить объект
- void Finder::Release()
- {
- {
- SingleExClassThread(FileService::object)
- FileService::object->DeleteFinder(this);
- }
- delete this;
- }
- //Начать поиск заново, возвращает количество найденых файлов
- dword Finder::Reset()
- {
- SingleExClassThread(FileService::object)
- //Перебираем все файлы по реальному пути
- FindOnDisk(path, null);
- //Ищем в паках
- if(isFindInLoadedPacks)
- {
- FindInPacks();
- }
- //Просматриваем зеркальные пути
- if(isFindInMirrors)
- {
- dword count = FileService::object->filesTree.FindPaths(path);
- for(dword i = 0; i < count; i++)
- {
- //Зеркальный путь
- const char * mirrorPath = FileService::object->filesTree.GetPath(i);
- //Смотрим на диске
- FindOnDisk(mirrorPath, mirrorPath);
- }
- }
- for(dword i = 0; i < files.Size(); i++)
- {
- FindFile & fl = files[i];
- fl.fileNameIndex = string::GetFileName(fl.path.c_str()) - fl.path.c_str();
- fl.fileNameHash = string::HashNoCase(&fl.path[fl.fileNameIndex]);
- }
- //Замещяем одинаковые файлы файлами с большим приоритетом
- for(dword i = 0; i < files.Size(); i++)
- {
- if(!(files[i].flags & (f_mirror | f_pack))) continue;
- for(dword j = 0; j < files.Size(); j++)
- {
- //Пропускаем значения с разным хэшем
- FindFile & cur = files[i];
- FindFile & ff = files[j];
- if(ff.fileNameHash != cur.fileNameHash || (ff.flags & f_folder) != 0 || i == j) continue;
- if(!string::IsEqual(&ff.path[ff.fileNameIndex], &cur.path[cur.fileNameIndex])) continue;
- //Имена совпадают, решаем что делать
- if(cur.flags > ff.flags)
- {
- files.DelIndex(j);
- Assert(j != i);
- if(j < i) i--;
- j--;
- }
- }
- }
- /*
- api->Trace("-------------------------------------------------");
- api->Trace("Finder path: %s", path.c_str());
- api->Trace("Finder mask: %s", mask.c_str());
- for(long i = 0; i < files; i++)
- {
- api->Trace("%s", files[i].path.c_str());
- }
- api->Trace("-------------------------------------------------");
- */
- return files.Size();
- }
- //Получить количество найденых файлов
- dword Finder::Count() const
- {
- return files.Size();
- }
- //Получить полный путь с именем файла "С:\path\name.ext"
- const char * Finder::FilePath(dword index) const
- {
- if(index < files.Size())
- {
- return files[index].path.c_str();
- }
- return null;
- }
- //Получить полный путь до файла "С:\path\"
- const char * Finder::Path(dword index) const
- {
- if(index < files.Size())
- {
- if((files[index].flags & f_folder) == 0)
- {
- return buffer.GetFilePath(files[index].path);
- }else{
- return files[index].path.c_str();
- }
- }
- return null;
- }
- //Получить имя файла "name.ext"
- const char * Finder::Name(dword index) const
- {
- if(index < files.Size())
- {
- return buffer.GetFileName(files[index].path);
- }
- return null;
- }
- //Получить имя файла без расширения name
- const char * Finder::Title(dword index) const
- {
- if(index < files.Size())
- {
- return buffer.GetFileTitle(files[index].path);
- }
- return null;
- }
- //Получить расширение файла "ext"
- const char * Finder::Extension(dword index) const
- {
- if(index < files.Size())
- {
- return buffer.GetFileExt(files[index].path);
- }
- return null;
- }
- //true если найдены "." или ".."
- bool Finder::IsDot(dword index) const
- {
- if(index < files.Size())
- {
- buffer.GetFileName(files[index].path);
- return IsDots(buffer.c_str());
- }
- return false;
- }
- //true если найдена папка
- bool Finder::IsFolder(dword index) const
- {
- if(index < files.Size())
- {
- return (files[index].flags & f_folder) != 0;
- }
- return false;
- }
- //true если этот файл найден в зеркальной директории
- bool Finder::IsMirror(dword index) const
- {
- if(index < files.Size())
- {
- return (files[index].flags & f_mirror) != 0;
- }
- return false;
- }
- //Поиск файлов на диске
- void Finder::FindOnDisk(const char * findPath, const char * mirrorPath)
- {
- //Перебираем папки для рекурсивного поиска
- if(isInverseOrder && isRecursive)
- {
- FindOnDiskRecursive(findPath, mirrorPath);
- }
- WIN32_FIND_DATA wfd;
- //Ищем в текущей папке файлы
- buffer = findPath;
- if(buffer.Len() > 0)
- {
- Assert(buffer[buffer.Len() - 1] == '\\');
- }
- buffer += mask;
- HANDLE handle = ::FindFirstFile(buffer, &wfd);
- if(handle != INVALID_HANDLE_VALUE)
- {
- do
- {
- bool isFolder = ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
- if(isFolder)
- {
- if(!isAddFolders)
- {
- continue;
- }
- if(!isDots)
- {
- if(IsDots(wfd.cFileName))
- {
- continue;
- }
- }
- }
- FindFile & file = files[files.Add()];
- if(mirrorPath)
- {
- file.path = mirrorPath;
- buffer = findPath;
- buffer.GetRelativePath(file.path);
- file.path = path;
- file.path += buffer;
- }else{
- file.path = findPath;
- }
- file.path += wfd.cFileName;
- file.fileNameIndex = string::GetFileName(file.path.c_str()) - file.path.c_str();
- file.fileNameHash = string::HashNoCase(&file.path[file.fileNameIndex]);
- file.flags = (isFolder ? f_folder : 0) | ((mirrorPath != null) ? f_mirror : 0);
- }while(::FindNextFile(handle, &wfd));
- ::FindClose(handle);
- }
- //Перебираем папки для рекурсивного поиска
- if(!isInverseOrder && isRecursive)
- {
- FindOnDiskRecursive(findPath, mirrorPath);
- }
- }
- //Рекурсивный поиск на диске
- void Finder::FindOnDiskRecursive(const char * findPath, const char * mirrorPath)
- {
- WIN32_FIND_DATA wfd;
- buffer = findPath;
- if(buffer.Len() > 0)
- {
- Assert(buffer[buffer.Len() - 1] == '\\');
- }
- buffer += "*.*";
- string path;
- HANDLE handle = ::FindFirstFile(buffer, &wfd);
- if(handle != INVALID_HANDLE_VALUE)
- {
- do
- {
- bool isFolder = ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
- if(isFolder)
- {
- if(!IsDots(wfd.cFileName))
- {
- path = findPath;
- path += wfd.cFileName;
- path += '\\';
- FindOnDisk(path.c_str(), mirrorPath);
- }
- }
- }while(::FindNextFile(handle, &wfd));
- ::FindClose(handle);
- }
- }
- //Поиск файлов в загруженых пак-файлах
- void Finder::FindInPacks()
- {
- array<const char *> packsFiles(_FL_, 256);
- FileService::object->CollectFilesFromPacks(packsFiles);
- dword count = packsFiles.Size();
- for(dword i = 0; i < count; i++)
- {
- //Сравнивайм имя файла с маской
- buffer = packsFiles[i];
- if(buffer.IsFileMask(mask))
- {
- FindFile & file = files[files.Add()];
- file.path = packsFiles[i];
- file.fileNameIndex = string::GetFileName(file.path.c_str()) - file.path.c_str();
- file.fileNameHash = string::HashNoCase(&file.path[file.fileNameIndex]);
- file.flags = f_pack;
- }
- }
- buffer.Empty();
- }
- //Проверить точки ли это
- bool Finder::IsDots(const char * str)
- {
- if(!str) return false;
- for(const char * name = str; *str; str++)
- {
- if(*str == '\\' || *str == '/') name = str + 1;
- }
- if(name[0] == '.')
- {
- if(name[1] == 0)
- {
- return true;
- }
- if(name[1] == '.')
- {
- if(name[2] == 0)
- {
- return true;
- }
- }
- }
- return false;
- }
|