String AbstractFileManager::makeRelative(const String& absolutePath, const String& referencePath) { if (!::wxIsAbsolutePath(absolutePath)) return absolutePath; if (!::wxIsAbsolutePath(referencePath)) return ""; StringList absolutePathComponents = resolvePath(pathComponents(absolutePath)); StringList referencePathComponents = resolvePath(pathComponents(referencePath)); StringList relativePathComponents; if (!isDirectory(referencePath)) referencePathComponents.pop_back(); unsigned int i = 0; for (; i < (std::min)(absolutePathComponents.size(), referencePathComponents.size()); i++) { const String& absolutePathComponent = absolutePathComponents[i]; const String& referencePathComponent = referencePathComponents[i]; if (absolutePathComponent != referencePathComponent) break; } for (unsigned int j = i; j < referencePathComponents.size(); j++) relativePathComponents.push_back(".."); for (unsigned int j = i; j < absolutePathComponents.size(); j++) relativePathComponents.push_back(absolutePathComponents[j]); return joinComponents(relativePathComponents); }
StringList AbstractFileManager::resolvePath(const StringList& pathComponents) { StringList cleanComponents; for (unsigned int i = 0; i < pathComponents.size(); i++) { const String& component = pathComponents[i]; if (component != ".") { if (component == ".." && !cleanComponents.empty()) cleanComponents.pop_back(); else cleanComponents.push_back(component); } } return cleanComponents; }
String sanitizePath(const String &path) { // Standardize slashes to POSIX style String fixedPath = posixPath(path); // Check if path is absolute bool isAbsolute = isAbsolutePath(fixedPath); // Tokenize path StringList pathComponents; std::size_t start = 0; do { std::size_t separator = (std::min)(fixedPath.find('/', start), fixedPath.length()); String token = fixedPath.substr(start, separator - start); if (token.empty() || token == ".") { // a/./b -> a/b and a//b -> a/b } else if (token == "..") { if (pathComponents.empty()) { // ../a -> ../a // /../a -> /a if (!isAbsolute) pathComponents.push_back(token); } else { // ../../a -> ../../a // a/../c -> c if (pathComponents.back() == "..") pathComponents.push_back(token); else pathComponents.pop_back(); } } else { pathComponents.push_back(token); } start = separator + 1; } while (start < path.length()); // Figure out if we need to add a leading slash String prefix; if (strBeginsWith(fixedPath, "/")) prefix = "/"; // Return reassembled path return prefix + joinStrings(pathComponents, "/"); }
void SearchContext::searchProc() { int id = searchID_; HANDLE findHandle = INVALID_HANDLE_VALUE; StringList paths; paths = params_.paths; RegexList filespecRegexes; pcre *matchRegex = NULL; directoriesSearched_ = 0; directoriesSkipped_ = 0; filesSearched_ = 0; filesSkipped_ = 0; filesWithHits_ = 0; linesWithHits_ = 0; hits_ = 0; unsigned int startTick = GetTickCount(); bool filespecUsesRegexes = ((params_.flags & SF_FILESPEC_REGEXES) != 0); bool matchUsesRegexes = ((params_.flags & SF_MATCH_REGEXES) != 0); delete pokeData_; pokeData_ = new PokeData; if(matchUsesRegexes) { const char *error; int erroffset; int flags = 0; if(!(params_.flags & SF_MATCH_CASE_SENSITIVE)) flags |= PCRE_CASELESS; matchRegex = pcre_compile(params_.match.c_str(), flags, &error, &erroffset, NULL); if(!matchRegex) { MessageBox(window_, error, "Match Regex Error", MB_OK); goto cleanup; } } for(StringList::iterator it = params_.filespecs.begin(); it != params_.filespecs.end(); ++it) { std::string regexString = it->c_str(); if(!filespecUsesRegexes) convertWildcard(regexString); int flags = 0; if(!(params_.flags & SF_FILESPEC_CASE_SENSITIVE)) flags |= PCRE_CASELESS; const char *error; int erroffset; pcre *regex = pcre_compile(regexString.c_str(), flags, &error, &erroffset, NULL); if(regex) filespecRegexes.push_back(regex); else { MessageBox(window_, error, "Filespec Regex Error", MB_OK); goto cleanup; } } PostMessage(window_, WM_SEARCHCONTEXT_STATE, 1, 0); while(!paths.empty()) { directoriesSearched_++; stopCheck(); std::string currentSearchPath = paths.back(); std::string currentSearchWildcard = currentSearchPath + "\\*"; paths.pop_back(); WIN32_FIND_DATA wfd; findHandle = FindFirstFile(currentSearchWildcard.c_str(), &wfd); if(findHandle == INVALID_HANDLE_VALUE) continue; while(FindNextFile(findHandle, &wfd)) { stopCheck(); bool isDirectory = ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); if((wfd.cFileName[0] == '.') || (wfd.cFileName[0] == 0)) { if(isDirectory) directoriesSkipped_++; else filesSkipped_++; continue; } std::string filename = currentSearchPath; filename += "\\"; filename += wfd.cFileName; if(isDirectory) { if(params_.flags & SF_RECURSIVE) paths.push_back(filename); } else { if(searchFile(id, filename, filespecRegexes, matchRegex)) { filesSearched_++; } else { filesSkipped_++; } poke(id, "", HighlightList(), 0, false); } } if(findHandle != INVALID_HANDLE_VALUE) { FindClose(findHandle); } } cleanup: for(RegexList::iterator it = filespecRegexes.begin(); it != filespecRegexes.end(); ++it) { pcre_free(*it); } if(matchRegex) pcre_free(matchRegex); filespecRegexes.clear(); if(!stop_) { unsigned int endTick = GetTickCount(); char buffer[512]; float sec = (endTick - startTick) / 1000.0f; const char *verb = "searched"; if(params_.flags & SF_REPLACE) verb = "updated"; sprintf(buffer, "\n%d hits in %d lines across %d files.\n%d directories scanned, %d files %s, %d files skipped (%3.3f sec)", hits_, linesWithHits_, filesWithHits_, directoriesSearched_, filesSearched_, verb, filesSkipped_, sec); poke(id, buffer, HighlightList(), 0, true); } delete pokeData_; pokeData_ = NULL; PostMessage(window_, WM_SEARCHCONTEXT_STATE, 0, 0); }