| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040 |
- //
- // Path.cpp
- //
- // $Id: //poco/1.4/Foundation/src/Path.cpp#5 $
- //
- // Library: Foundation
- // Package: Filesystem
- // Module: Path
- //
- // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
- // and Contributors.
- //
- // SPDX-License-Identifier: BSL-1.0
- //
- #include "Poco/Path.h"
- #include "Poco/File.h"
- #include "Poco/Exception.h"
- #include "Poco/StringTokenizer.h"
- #if defined(_WIN32) && defined(POCO_WIN32_UTF8)
- #include "Poco/UnicodeConverter.h"
- #include "Poco/Buffer.h"
- #endif
- #include <algorithm>
- #if defined(POCO_OS_FAMILY_VMS)
- #include "Path_VMS.cpp"
- #elif defined(POCO_OS_FAMILY_UNIX)
- #include "Path_UNIX.cpp"
- #elif defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8)
- #if defined(_WIN32_WCE)
- #include "Path_WINCE.cpp"
- #else
- #include "Path_WIN32U.cpp"
- #endif
- #elif defined(POCO_OS_FAMILY_WINDOWS)
- #include "Path_WIN32.cpp"
- #endif
- namespace Poco {
- Path::Path(): _absolute(false)
- {
- }
- Path::Path(bool absolute): _absolute(absolute)
- {
- }
- Path::Path(const std::string& path)
- {
- assign(path);
- }
- Path::Path(const std::string& path, Style style)
- {
- assign(path, style);
- }
- Path::Path(const char* path)
- {
- poco_check_ptr(path);
- assign(path);
- }
- Path::Path(const char* path, Style style)
- {
- poco_check_ptr(path);
- assign(path, style);
- }
- Path::Path(const Path& path):
- _node(path._node),
- _device(path._device),
- _name(path._name),
- _version(path._version),
- _dirs(path._dirs),
- _absolute(path._absolute)
- {
- }
- Path::Path(const Path& parent, const std::string& fileName):
- _node(parent._node),
- _device(parent._device),
- _name(parent._name),
- _version(parent._version),
- _dirs(parent._dirs),
- _absolute(parent._absolute)
- {
- makeDirectory();
- _name = fileName;
- }
- Path::Path(const Path& parent, const char* fileName):
- _node(parent._node),
- _device(parent._device),
- _name(parent._name),
- _version(parent._version),
- _dirs(parent._dirs),
- _absolute(parent._absolute)
- {
- makeDirectory();
- _name = fileName;
- }
- Path::Path(const Path& parent, const Path& relative):
- _node(parent._node),
- _device(parent._device),
- _name(parent._name),
- _version(parent._version),
- _dirs(parent._dirs),
- _absolute(parent._absolute)
- {
- resolve(relative);
- }
- Path::~Path()
- {
- }
-
- Path& Path::operator = (const Path& path)
- {
- return assign(path);
- }
-
- Path& Path::operator = (const std::string& path)
- {
- return assign(path);
- }
- Path& Path::operator = (const char* path)
- {
- poco_check_ptr(path);
- return assign(path);
- }
- void Path::swap(Path& path)
- {
- std::swap(_node, path._node);
- std::swap(_device, path._device);
- std::swap(_name, path._name);
- std::swap(_version, path._version);
- std::swap(_dirs, path._dirs);
- std::swap(_absolute, path._absolute);
- }
- Path& Path::assign(const Path& path)
- {
- if (&path != this)
- {
- _node = path._node;
- _device = path._device;
- _name = path._name;
- _version = path._version;
- _dirs = path._dirs;
- _absolute = path._absolute;
- }
- return *this;
- }
- Path& Path::assign(const std::string& path)
- {
- #if defined(POCO_OS_FAMILY_VMS)
- parseVMS(path);
- #elif defined(POCO_OS_FAMILY_WINDOWS)
- parseWindows(path);
- #else
- parseUnix(path);
- #endif
- return *this;
- }
-
- Path& Path::assign(const std::string& path, Style style)
- {
- switch (style)
- {
- case PATH_UNIX:
- parseUnix(path);
- break;
- case PATH_WINDOWS:
- parseWindows(path);
- break;
- case PATH_VMS:
- parseVMS(path);
- break;
- case PATH_NATIVE:
- assign(path);
- break;
- case PATH_GUESS:
- parseGuess(path);
- break;
- default:
- poco_bugcheck();
- }
- return *this;
- }
- Path& Path::assign(const char* path)
- {
- return assign(std::string(path));
- }
- std::string Path::toString() const
- {
- #if defined(POCO_OS_FAMILY_UNIX)
- return buildUnix();
- #elif defined(POCO_OS_FAMILY_WINDOWS)
- return buildWindows();
- #else
- return buildVMS();
- #endif
- }
-
- std::string Path::toString(Style style) const
- {
- switch (style)
- {
- case PATH_UNIX:
- return buildUnix();
- case PATH_WINDOWS:
- return buildWindows();
- case PATH_VMS:
- return buildVMS();
- case PATH_NATIVE:
- case PATH_GUESS:
- return toString();
- default:
- poco_bugcheck();
- }
- return std::string();
- }
- bool Path::tryParse(const std::string& path)
- {
- try
- {
- Path p;
- p.parse(path);
- assign(p);
- return true;
- }
- catch (...)
- {
- return false;
- }
- }
- bool Path::tryParse(const std::string& path, Style style)
- {
- try
- {
- Path p;
- p.parse(path, style);
- assign(p);
- return true;
- }
- catch (...)
- {
- return false;
- }
- }
- Path& Path::parseDirectory(const std::string& path)
- {
- assign(path);
- return makeDirectory();
- }
- Path& Path::parseDirectory(const std::string& path, Style style)
- {
- assign(path, style);
- return makeDirectory();
- }
- Path& Path::makeDirectory()
- {
- #if defined(POCO_OS_FAMILY_VMS)
- pushDirectory(getBaseName());
- #else
- pushDirectory(_name);
- #endif
- _name.clear();
- _version.clear();
- return *this;
- }
- Path& Path::makeFile()
- {
- if (!_dirs.empty() && _name.empty())
- {
- _name = _dirs.back();
- _dirs.pop_back();
- #if defined(POCO_OS_FAMILY_VMS)
- setExtension("DIR");
- #endif
- }
- return *this;
- }
- Path& Path::makeAbsolute()
- {
- return makeAbsolute(current());
- }
- Path& Path::makeAbsolute(const Path& base)
- {
- if (!_absolute)
- {
- Path tmp = base;
- tmp.makeDirectory();
- for (StringVec::const_iterator it = _dirs.begin(); it != _dirs.end(); ++it)
- {
- tmp.pushDirectory(*it);
- }
- _node = tmp._node;
- _device = tmp._device;
- _dirs = tmp._dirs;
- _absolute = base._absolute;
- }
- return *this;
- }
- Path Path::absolute() const
- {
- Path result(*this);
- if (!result._absolute)
- {
- result.makeAbsolute();
- }
- return result;
- }
- Path Path::absolute(const Path& base) const
- {
- Path result(*this);
- if (!result._absolute)
- {
- result.makeAbsolute(base);
- }
- return result;
- }
- Path Path::parent() const
- {
- Path p(*this);
- return p.makeParent();
- }
- Path& Path::makeParent()
- {
- if (_name.empty())
- {
- if (_dirs.empty())
- {
- if (!_absolute)
- _dirs.push_back("..");
- }
- else
- {
- if (_dirs.back() == "..")
- _dirs.push_back("..");
- else
- _dirs.pop_back();
- }
- }
- else
- {
- _name.clear();
- _version.clear();
- }
- return *this;
- }
- Path& Path::append(const Path& path)
- {
- makeDirectory();
- _dirs.insert(_dirs.end(), path._dirs.begin(), path._dirs.end());
- _name = path._name;
- _version = path._version;
- return *this;
- }
- Path& Path::resolve(const Path& path)
- {
- if (path.isAbsolute())
- {
- assign(path);
- }
- else
- {
- for (int i = 0; i < path.depth(); ++i)
- pushDirectory(path[i]);
- _name = path._name;
- }
- return *this;
- }
- Path& Path::setNode(const std::string& node)
- {
- _node = node;
- _absolute = _absolute || !node.empty();
- return *this;
- }
-
- Path& Path::setDevice(const std::string& device)
- {
- _device = device;
- _absolute = _absolute || !device.empty();
- return *this;
- }
-
- const std::string& Path::directory(int n) const
- {
- poco_assert (0 <= n && n <= _dirs.size());
-
- if (n < _dirs.size())
- return _dirs[n];
- else
- return _name;
- }
- const std::string& Path::operator [] (int n) const
- {
- poco_assert (0 <= n && n <= _dirs.size());
-
- if (n < _dirs.size())
- return _dirs[n];
- else
- return _name;
- }
-
- Path& Path::pushDirectory(const std::string& dir)
- {
- if (!dir.empty() && dir != ".")
- {
- #if defined(POCO_OS_FAMILY_VMS)
- if (dir == ".." || dir == "-")
- {
- if (!_dirs.empty() && _dirs.back() != ".." && _dirs.back() != "-")
- _dirs.pop_back();
- else if (!_absolute)
- _dirs.push_back(dir);
- }
- else _dirs.push_back(dir);
- #else
- if (dir == "..")
- {
- if (!_dirs.empty() && _dirs.back() != "..")
- _dirs.pop_back();
- else if (!_absolute)
- _dirs.push_back(dir);
- }
- else _dirs.push_back(dir);
- #endif
- }
- return *this;
- }
-
- Path& Path::popDirectory()
- {
- poco_assert (!_dirs.empty());
-
- _dirs.pop_back();
- return *this;
- }
- Path& Path::popFrontDirectory()
- {
- poco_assert (!_dirs.empty());
-
- StringVec::iterator it = _dirs.begin();
- _dirs.erase(it);
- return *this;
- }
-
- Path& Path::setFileName(const std::string& name)
- {
- _name = name;
- return *this;
- }
- Path& Path::setBaseName(const std::string& name)
- {
- std::string ext = getExtension();
- _name = name;
- if (!ext.empty())
- {
- _name.append(".");
- _name.append(ext);
- }
- return *this;
- }
- std::string Path::getBaseName() const
- {
- std::string::size_type pos = _name.rfind('.');
- if (pos != std::string::npos)
- return _name.substr(0, pos);
- else
- return _name;
- }
- Path& Path::setExtension(const std::string& extension)
- {
- _name = getBaseName();
- if (!extension.empty())
- {
- _name.append(".");
- _name.append(extension);
- }
- return *this;
- }
-
- std::string Path::getExtension() const
- {
- std::string::size_type pos = _name.rfind('.');
- if (pos != std::string::npos)
- return _name.substr(pos + 1);
- else
- return std::string();
- }
- Path& Path::clear()
- {
- _node.clear();
- _device.clear();
- _name.clear();
- _dirs.clear();
- _version.clear();
- _absolute = false;
- return *this;
- }
- std::string Path::current()
- {
- return PathImpl::currentImpl();
- }
-
- std::string Path::home()
- {
- return PathImpl::homeImpl();
- }
-
- std::string Path::temp()
- {
- return PathImpl::tempImpl();
- }
- std::string Path::null()
- {
- return PathImpl::nullImpl();
- }
-
- std::string Path::expand(const std::string& path)
- {
- return PathImpl::expandImpl(path);
- }
- void Path::listRoots(std::vector<std::string>& roots)
- {
- PathImpl::listRootsImpl(roots);
- }
- bool Path::find(StringVec::const_iterator it, StringVec::const_iterator end, const std::string& name, Path& path)
- {
- while (it != end)
- {
- #if defined(WIN32)
- std::string cleanPath(*it);
- if (cleanPath.size() > 1 && cleanPath[0] == '"' && cleanPath[cleanPath.size() - 1] == '"')
- {
- cleanPath = cleanPath.substr(1, cleanPath.size() - 2);
- }
- Path p(cleanPath);
- #else
- Path p(*it);
- #endif
- p.makeDirectory();
- p.resolve(Path(name));
- File f(p);
- if (f.exists())
- {
- path = p;
- return true;
- }
- ++it;
- }
- return false;
- }
- bool Path::find(const std::string& pathList, const std::string& name, Path& path)
- {
- StringTokenizer st(pathList, std::string(1, pathSeparator()), StringTokenizer::TOK_IGNORE_EMPTY + StringTokenizer::TOK_TRIM);
- return find(st.begin(), st.end(), name, path);
- }
- void Path::parseUnix(const std::string& path)
- {
- clear();
- std::string::const_iterator it = path.begin();
- std::string::const_iterator end = path.end();
- if (it != end)
- {
- if (*it == '/')
- {
- _absolute = true; ++it;
- }
- else if (*it == '~')
- {
- ++it;
- if (it == end || *it == '/')
- {
- Path cwd(home());
- _dirs = cwd._dirs;
- _absolute = true;
- }
- else --it;
- }
- while (it != end)
- {
- std::string name;
- while (it != end && *it != '/') name += *it++;
- if (it != end)
- {
- if (_dirs.empty())
- {
- if (!name.empty() && *(name.rbegin()) == ':')
- {
- _absolute = true;
- _device.assign(name, 0, name.length() - 1);
- }
- else
- {
- pushDirectory(name);
- }
- }
- else pushDirectory(name);
- }
- else _name = name;
- if (it != end) ++it;
- }
- }
- }
- void Path::parseWindows(const std::string& path)
- {
- clear();
- std::string::const_iterator it = path.begin();
- std::string::const_iterator end = path.end();
- if (it != end)
- {
- if (*it == '\\' || *it == '/') { _absolute = true; ++it; }
- if (_absolute && it != end && (*it == '\\' || *it == '/')) // UNC
- {
- ++it;
- while (it != end && *it != '\\' && *it != '/') _node += *it++;
- if (it != end) ++it;
- }
- else if (it != end)
- {
- char d = *it++;
- if (it != end && *it == ':') // drive letter
- {
- if (_absolute || !((d >= 'a' && d <= 'z') || (d >= 'A' && d <= 'Z'))) throw PathSyntaxException(path);
- _absolute = true;
- _device += d;
- ++it;
- if (it == end || (*it != '\\' && *it != '/')) throw PathSyntaxException(path);
- ++it;
- }
- else --it;
- }
- while (it != end)
- {
- std::string name;
- while (it != end && *it != '\\' && *it != '/') name += *it++;
- if (it != end)
- pushDirectory(name);
- else
- _name = name;
- if (it != end) ++it;
- }
- }
- if (!_node.empty() && _dirs.empty() && !_name.empty())
- makeDirectory();
- }
- void Path::parseVMS(const std::string& path)
- {
- clear();
- std::string::const_iterator it = path.begin();
- std::string::const_iterator end = path.end();
- if (it != end)
- {
- std::string name;
- while (it != end && *it != ':' && *it != '[' && *it != ';') name += *it++;
- if (it != end)
- {
- if (*it == ':')
- {
- ++it;
- if (it != end && *it == ':')
- {
- _node = name;
- ++it;
- }
- else _device = name;
- _absolute = true;
- name.clear();
- }
- if (it != end)
- {
- if (_device.empty() && *it != '[')
- {
- while (it != end && *it != ':' && *it != ';') name += *it++;
- if (it != end)
- {
- if (*it == ':')
- {
- _device = name;
- _absolute = true;
- name.clear();
- ++it;
- }
- }
- }
- }
- if (name.empty())
- {
- if (it != end && *it == '[')
- {
- ++it;
- if (it != end)
- {
- _absolute = true;
- if (*it == '.')
- { _absolute = false; ++it; }
- else if (*it == ']' || *it == '-')
- _absolute = false;
- while (it != end && *it != ']')
- {
- name.clear();
- if (*it == '-')
- name = "-";
- else
- while (it != end && *it != '.' && *it != ']') name += *it++;
- if (!name.empty())
- {
- if (name == "-")
- {
- if (_dirs.empty() || _dirs.back() == "..")
- _dirs.push_back("..");
- else
- _dirs.pop_back();
- }
- else _dirs.push_back(name);
- }
- if (it != end && *it != ']') ++it;
- }
- if (it == end) throw PathSyntaxException(path);
- ++it;
- if (it != end && *it == '[')
- {
- if (!_absolute) throw PathSyntaxException(path);
- ++it;
- if (it != end && *it == '.') throw PathSyntaxException(path);
- int d = int(_dirs.size());
- while (it != end && *it != ']')
- {
- name.clear();
- if (*it == '-')
- name = "-";
- else
- while (it != end && *it != '.' && *it != ']') name += *it++;
- if (!name.empty())
- {
- if (name == "-")
- {
- if (_dirs.size() > d)
- _dirs.pop_back();
- }
- else _dirs.push_back(name);
- }
- if (it != end && *it != ']') ++it;
- }
- if (it == end) throw PathSyntaxException(path);
- ++it;
- }
- }
- _name.clear();
- }
- while (it != end && *it != ';') _name += *it++;
- }
- else _name = name;
- if (it != end && *it == ';')
- {
- ++it;
- while (it != end) _version += *it++;
- }
- }
- else _name = name;
- }
- }
- void Path::parseGuess(const std::string& path)
- {
- bool hasBackslash = false;
- bool hasSlash = false;
- bool hasOpenBracket = false;
- bool hasClosBracket = false;
- bool isWindows = path.length() > 2 && path[1] == ':' && (path[2] == '/' || path[2] == '\\');
- std::string::const_iterator end = path.end();
- std::string::const_iterator semiIt = end;
- if (!isWindows)
- {
- for (std::string::const_iterator it = path.begin(); it != end; ++it)
- {
- switch (*it)
- {
- case '\\': hasBackslash = true; break;
- case '/': hasSlash = true; break;
- case '[': hasOpenBracket = true;
- case ']': hasClosBracket = hasOpenBracket;
- case ';': semiIt = it; break;
- }
- }
- }
- if (hasBackslash || isWindows)
- {
- parseWindows(path);
- }
- else if (hasSlash)
- {
- parseUnix(path);
- }
- else
- {
- bool isVMS = hasClosBracket;
- if (!isVMS && semiIt != end)
- {
- isVMS = true;
- ++semiIt;
- while (semiIt != end)
- {
- if (*semiIt < '0' || *semiIt > '9')
- {
- isVMS = false; break;
- }
- ++semiIt;
- }
- }
- if (isVMS)
- parseVMS(path);
- else
- parseUnix(path);
- }
- }
- std::string Path::buildUnix() const
- {
- std::string result;
- if (!_device.empty())
- {
- result.append("/");
- result.append(_device);
- result.append(":/");
- }
- else if (_absolute)
- {
- result.append("/");
- }
- for (StringVec::const_iterator it = _dirs.begin(); it != _dirs.end(); ++it)
- {
- result.append(*it);
- result.append("/");
- }
- result.append(_name);
- return result;
- }
- std::string Path::buildWindows() const
- {
- std::string result;
- if (!_node.empty())
- {
- result.append("\\\\");
- result.append(_node);
- result.append("\\");
- }
- else if (!_device.empty())
- {
- result.append(_device);
- result.append(":\\");
- }
- else if (_absolute)
- {
- result.append("\\");
- }
- for (StringVec::const_iterator it = _dirs.begin(); it != _dirs.end(); ++it)
- {
- result.append(*it);
- result.append("\\");
- }
- result.append(_name);
- return result;
- }
- std::string Path::buildVMS() const
- {
- std::string result;
- if (!_node.empty())
- {
- result.append(_node);
- result.append("::");
- }
- if (!_device.empty())
- {
- result.append(_device);
- result.append(":");
- }
- if (!_dirs.empty())
- {
- result.append("[");
- if (!_absolute && _dirs[0] != "..")
- result.append(".");
- for (StringVec::const_iterator it = _dirs.begin(); it != _dirs.end(); ++it)
- {
- if (it != _dirs.begin() && *it != "..")
- result.append(".");
- if (*it == "..")
- result.append("-");
- else
- result.append(*it);
- }
- result.append("]");
- }
- result.append(_name);
- if (!_version.empty())
- {
- result.append(";");
- result.append(_version);
- }
- return result;
- }
- std::string Path::transcode(const std::string& path)
- {
- #if defined(_WIN32) && defined(POCO_WIN32_UTF8)
- std::wstring uniPath;
- UnicodeConverter::toUTF16(path, uniPath);
- DWORD len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, uniPath.c_str(), static_cast<int>(uniPath.length()), NULL, 0, NULL, NULL);
- if (len > 0)
- {
- Buffer<char> buffer(len);
- DWORD rc = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, uniPath.c_str(), static_cast<int>(uniPath.length()), buffer.begin(), static_cast<int>(buffer.size()), NULL, NULL);
- if (rc)
- {
- return std::string(buffer.begin(), buffer.size());
- }
- }
- #endif
- return path;
- }
- } // namespace Poco
|