📄 ncbifile.cpp
字号:
"path_to is not absolute path"); } // Split and strip FROM string dir_from; SplitPath(AddTrailingPathSeparator(path_from), &dir_from); vector<string> dir_from_parts; s_StripDir(dir_from, &dir_from_parts); if ( dir_from_parts.empty() ) { NCBI_THROW(CFileException, eRelativePath, "path_from is empty path"); } // Split and strip TO string dir_to; string base_to; string ext_to; SplitPath(path_to, &dir_to, &base_to, &ext_to); vector<string> dir_to_parts; s_StripDir(dir_to, &dir_to_parts); if ( dir_to_parts.empty() ) { NCBI_THROW(CFileException, eRelativePath, "path_to is empty path"); }//Platform-dependent compare mode#ifdef NCBI_OS_MSWIN# define DIR_PARTS_CMP_MODE NStr::eNocase#endif#ifdef NCBI_OS_UNIX# define DIR_PARTS_CMP_MODE NStr::eCase#endif // Roots must be the same to create relative path from one to another if (NStr::Compare(dir_from_parts.front(), dir_to_parts.front(), DIR_PARTS_CMP_MODE) != 0) { NCBI_THROW(CFileException, eRelativePath, "roots of input pathes are different"); } size_t min_parts = min(dir_from_parts.size(), dir_to_parts.size()); size_t common_length = min_parts; for (size_t i = 0; i < min_parts; i++) { if (NStr::Compare(dir_from_parts[i], dir_to_parts[i], DIR_PARTS_CMP_MODE) != 0) { common_length = i; break; } } for (size_t i = common_length; i < dir_from_parts.size(); i++) { path += ".."; path += GetPathSeparator(); } for (size_t i = common_length; i < dir_to_parts.size(); i++) { path += dir_to_parts[i]; path += GetPathSeparator(); } return path + base_to + ext_to;#else NCBI_THROW(CFileException, eRelativePath, "not implemented"); return string();#endif}string CDirEntry::ConvertToOSPath(const string& path){ // Not process empty and absolute path if ( path.empty() || IsAbsolutePathEx(path) ) { return path; } // Now we have relative "path" string xpath = path; // Add trailing separator if path ends with DIR_PARENT or DIR_CURRENT#if defined(DIR_PARENT) if ( NStr::EndsWith(xpath, DIR_PARENT) ) { xpath += DIR_SEPARATOR; }#endif#if defined(DIR_CURRENT) if ( NStr::EndsWith(xpath, DIR_CURRENT) ) { xpath += DIR_SEPARATOR; }#endif // Replace each path separator with the current OS separator character for (size_t i = 0; i < xpath.length(); i++) { char c = xpath[i]; if ( c == '\\' || c == '/' || c == ':') { xpath[i] = DIR_SEPARATOR; } }#if defined(NCBI_OS_MAC) // Fix current and parent refs in the path for MAC string xsearch= "..:"; size_t pos = 0; while ((pos = xpath.find(xsearch)) != NPOS) { xpath.replace(pos, xsearch.length(), ":"); if ( xpath.substr(pos + 1, 2) == ".:" ) { xpath.erase(pos + 1, 2); } else { if ( xpath.substr(pos + 1, xsearch.length()) != xsearch ) { xpath.insert(pos,":"); } } } xpath = NStr::Replace(xpath, ".:", kEmptyStr); // Add leading ":" (criterion of relativity of the dir) if ( xpath[0] != ':' ) { xpath = ":" + xpath; }#else // Fix current and parent refs in the path after conversion from MAC path // Replace all "::" to "/../" string xsearch = string(2,DIR_SEPARATOR); string xreplace = string(1,DIR_SEPARATOR) + DIR_PARENT + DIR_SEPARATOR; size_t pos = 0; while ((pos = xpath.find(xsearch, pos)) != NPOS ) { xpath.replace(pos, xsearch.length(), xreplace); } // Remove leading ":" in the relative path on non-MAC platforms if ( xpath[0] == DIR_SEPARATOR ) { xpath.erase(0,1); } // Replace something like "../aaa/../bbb/ccc" with "../bbb/ccc" xpath = NormalizePath(xpath);#endif return xpath;}string CDirEntry::ConcatPath(const string& first, const string& second){ // Prepare first part of path string path = AddTrailingPathSeparator(NStr::TruncateSpaces(first)); // Remove leading separator in "second" part string part = NStr::TruncateSpaces(second); if ( part.length() > 0 && part[0] == DIR_SEPARATOR ) { part.erase(0,1); } // Add second part path += part; return path;}string CDirEntry::ConcatPathEx(const string& first, const string& second){ // Prepare first part of path string path = NStr::TruncateSpaces(first); // Add trailing path separator to first part (OS independence) size_t pos = path.length();#if defined(NCBI_OS_MAC) if ( !pos ) { path = string(1,GetPathSeparator()); }#endif if ( pos && string(ALL_OS_SEPARATORS).find(path.at(pos-1)) == NPOS ) { // Find used path separator char sep = GetPathSeparator(); size_t sep_pos = path.find_last_of(ALL_OS_SEPARATORS); if ( sep_pos != NPOS ) { sep = path.at(sep_pos); } path += sep; } // Remove leading separator in "second" part string part = NStr::TruncateSpaces(second); if ( part.length() > 0 && string(ALL_OS_SEPARATORS).find(part[0]) != NPOS ) { part.erase(0,1); } // Add second part path += part; return path;}string CDirEntry::NormalizePath(const string& path, EFollowLinks follow_links){#if defined(NCBI_OS_MSWIN) || defined(NCBI_OS_UNIX) static const char kSeps[] = { DIR_SEPARATOR,# ifdef DIR_SEPARATOR_ALT DIR_SEPARATOR_ALT,# endif '\0' }; list<string> head; // already resolved to our satisfaction string current = path; // to resolve next list<string> tail; // to resolve afterwards int link_depth = 0; while ( !current.empty() || !tail.empty() ) { list<string> pretail; if ( !current.empty() ) { NStr::Split(current, kSeps, pretail, NStr::eNoMergeDelims); current.erase(); if (pretail.front().empty()# ifdef DISK_SEPARATOR || pretail.front().find(DISK_SEPARATOR) != NPOS# endif ) { // absolute path head.clear();# ifdef NCBI_OS_MSWIN // Remove leading "\\?\". Replace leading "\\?\UNC\" with "\\" static const char* const kUNC[] = { "", "", "?", "UNC" }; list<string>::iterator it = pretail.begin(); unsigned int matched = 0; while (matched < 4 && it != pretail.end() && !NStr::CompareNocase(*it, kUNC[matched])) { ++it; ++matched; } pretail.erase(pretail.begin(), it); switch (matched) { case 2: case 4: // got a UNC path (\\... or \\?\UNC\...) head.push_back(kEmptyStr); // fall through case 1: case 3/*?*/: // normal volume-less absolute path head.push_back(kEmptyStr); break; }# endif } tail.splice(tail.begin(), pretail); } string next = tail.front(); tail.pop_front(); if ( !head.empty() ) { // empty heads should accept anything string& last = head.back(); if (last == DIR_CURRENT) { head.pop_back(); _ASSERT(head.empty()); } else if (next == DIR_CURRENT) { continue; // leave out, since we already have content# ifdef DISK_SEPARATOR } else if (last[last.size()-1] == DISK_SEPARATOR) { // allow almost anything right after a volume specification# endif } else if (next.empty()) { continue; // leave out empty components in most cases } else if (next == DIR_PARENT) {# ifdef DISK_SEPARATOR SIZE_TYPE pos;# endif // back up if possible, assuming existing path to be "physical" if (last.empty()) { // already at the root; .. is a no-op continue;# ifdef DISK_SEPARATOR } else if ((pos = last.find(DISK_SEPARATOR) != NPOS)) { last.erase(pos + 1);# endif } else if (last != DIR_PARENT) { head.pop_back(); continue; } } }# ifdef NCBI_OS_UNIX // Is there a Windows equivalent for readlink? if (follow_links) { string s(head.empty() ? next : NStr::Join(head, string(1, DIR_SEPARATOR)) + DIR_SEPARATOR + next); char buf[PATH_MAX]; int length = readlink(s.c_str(), buf, sizeof(buf)); if (length > 0) { current.assign(buf, length); if (++link_depth >= 1024) { ERR_POST(Warning << "CDirEntry::NormalizePath: " "Reached symlink depth limit " << link_depth << " when resolving " << path); follow_links = eIgnoreLinks; } continue; } }# endif // normal case: just append the next element to head head.push_back(next); } return NStr::Join(head, string(1, DIR_SEPARATOR));#else // Not Unix or Windows // NOT implemented! return path;#endif}// Match "name" against the filename "mask", returning TRUE if// it matches, FALSE if not. //bool CDirEntry::MatchesMask(const char* name, const char* mask) { return NStr::MatchesMask(name, mask);}bool CDirEntry::GetMode(TMode* user_mode, TMode* group_mode, TMode* other_mode) const{#if defined(NCBI_OS_MAC) FSSpec fss = FSS(); OSErr err = FSpCheckObjectLock(&fss); if (err != noErr && err != fLckdErr) { return false; } bool locked = (err == fLckdErr); TMode mode = fRead | (locked ? 0 : fWrite); // User if (user_mode) { *user_mode = mode; } // Group if (group_mode) { *group_mode = mode; } // Other if (other_mode) { *other_mode = mode; } return true;#else struct stat st; if (stat(GetPath().c_str(), &st) != 0) { return false; } // Other if (other_mode) { *other_mode = st.st_mode & 0007; } st.st_mode >>= 3; // Group if (group_mode) { *group_mode = st.st_mode & 0007; } st.st_mode >>= 3; // User if (user_mode) { *user_mode = st.st_mode & 0007; } return true;#endif}bool CDirEntry::SetMode(TMode user_mode, TMode group_mode, TMode other_mode) const{ if (user_mode == fDefault) { user_mode = m_DefaultMode[eUser]; }#if defined(NCBI_OS_MAC) bool wantLocked = (user_mode & fWrite) == 0; FSSpec fss = FSS(); OSErr err = FSpCheckObjectLock(&fss); if (err != noErr && err != fLckdErr) { return false; } bool locked = (err == fLckdErr); if (locked == wantLocked) { return true; } err = wantLocked ? ::FSpSetFLock(&fss) : ::FSpRstFLock(&fss); return err == noErr;#else if (group_mode == fDefault) { group_mode = m_DefaultMode[eGroup]; } if (other_mode == fDefault) { other_mode = m_DefaultMode[eOther]; } TMode mode = s_ConstructMode(user_mode, group_mode, other_mode); return chmod(GetPath().c_str(), mode) == 0;#endif}void CDirEntry::SetDefaultModeGlobal(EType entry_type, TMode user_mode, TMode group_mode, TMode other_mode){ if (entry_type >= eUnknown ) { return; } if (entry_type == eDir ) { if ( user_mode == fDefault ) { user_mode = fDefaultDirUser; } if ( group_mode == fDefault ) { group_mode = fDefaultDirGroup; } if ( other_mode == fDefault ) { other_mode = fDefaultDirOther; } } else { if ( user_mode == fDefault ) { user_mode = fDefaultUser; } if ( group_mode == fDefault ) { group_mode = fDefaultGroup; } if ( other_mode == fDefault ) { other_mode = fDefaultOther; } } m_DefaultModeGlobal[entry_type][eUser] = user_mode; m_DefaultModeGlobal[entry_type][eGroup] = group_mode; m_DefaultModeGlobal[entry_type][eOther] = other_mode;}void CDirEntry::SetDefaultMode(EType entry_type, TMode user_mode, TMode group_mode, TMode other_mode){ if ( user_mode == fDefault ) { user_mode = m_DefaultModeGlobal[entry_type][eUser]; } if ( group_mode == fDefault ) { group_mode = m_DefaultModeGlobal[entry_type][eGroup]; } if ( other_mode == fDefault ) { other_mode = m_DefaultModeGlobal[entry_type][eOther]; } m_DefaultMode[eUser] = user_mode; m_DefaultMode[eGroup] = group_mode; m_DefaultMode[eOther] = other_mode;}void CDirEntry::GetDefaultModeGlobal(EType entry_type, TMode* user_mode, TMode* group_mode, TMode* other_mode){ if ( user_mode ) { *user_mode = m_DefaultModeGlobal[entry_type][eUser]; } if ( group_mode ) { *group_mode = m_DefaultModeGlobal[entry_type][eGroup]; } if ( other_mode ) { *other_mode = m_DefaultModeGlobal[entry_type][eOther]; }}void CDirEntry::GetDefaultMode(TMode* user_mode, TMode* group_mode, TMode* other_mode) const{ if ( user_mode ) { *user_mode = m_DefaultMode[eUser]; } if ( group_mode ) { *group_mode = m_DefaultMode[eGroup];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -