| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- #include "CmPath.h"
- #include "CmException.h"
- namespace BansheeEngine
- {
- const Path Path::BLANK = Path();
- Path::Path()
- :mIsAbsolute(false)
- { }
- Path::Path(const WString& pathStr, PathType type)
- {
- assign(pathStr, type);
- }
- Path::Path(const String& pathStr, PathType type)
- {
- assign(pathStr, type);
- }
- Path::Path(wchar_t* pathStr, PathType type)
- {
- assign(pathStr);
- }
- Path::Path(const char* pathStr, PathType type)
- {
- assign(pathStr);
- }
- Path::Path(const Path& other)
- {
- assign(other);
- }
- Path& Path::operator= (const Path& path)
- {
- assign(path);
- return *this;
- }
- Path& Path::operator= (const WString& pathStr)
- {
- assign(pathStr);
- return *this;
- }
- Path& Path::operator= (const String& pathStr)
- {
- assign(pathStr);
- return *this;
- }
- Path& Path::operator= (const wchar_t* pathStr)
- {
- assign(pathStr);
- return *this;
- }
- Path& Path::operator= (const char* pathStr)
- {
- assign(pathStr);
- return *this;
- }
- void Path::swap(Path& path)
- {
- std::swap(mDirectories, path.mDirectories);
- std::swap(mFilename, path.mFilename);
- std::swap(mDevice, path.mDevice);
- std::swap(mNode, path.mNode);
- std::swap(mIsAbsolute, path.mIsAbsolute);
- }
- void Path::assign(const Path& path)
- {
- mDirectories = path.mDirectories;
- mFilename = path.mFilename;
- mDevice = path.mDevice;
- mNode = path.mNode;
- mIsAbsolute = path.mIsAbsolute;
- }
- void Path::assign(const WString& pathStr, PathType type)
- {
- assign(pathStr.data(), (UINT32)pathStr.length(), type);
- }
- void Path::assign(const String& pathStr, PathType type)
- {
- assign(pathStr.data(), (UINT32)pathStr.length(), type);
- }
- void Path::assign(const wchar_t* pathStr, PathType type)
- {
- assign(pathStr, (UINT32)wcslen(pathStr), type);
- }
- void Path::assign(const char* pathStr, PathType type)
- {
- assign(pathStr, (UINT32)strlen(pathStr), type);
- }
- void Path::assign(const wchar_t* pathStr, UINT32 numChars, PathType type)
- {
- switch (type)
- {
- case PathType::Windows:
- parseWindows(pathStr, numChars);
- break;
- case PathType::Unix:
- parseUnix(pathStr, numChars);
- break;
- default:
- #if CM_PLATFORM == CM_PLATFORM_WIN32
- parseWindows(pathStr, numChars);
- #elif CM_PLATFORM == CM_PLATFORM_APPLE || CM_PLATFORM == CM_PLATFORM_LINUX
- parseUnix(pathStr, numChars);
- #else
- static_assert(false, "Unsupported platform for path.");
- #endif
- break;
- }
- }
- void Path::assign(const char* pathStr, UINT32 numChars, PathType type)
- {
- switch (type)
- {
- case PathType::Windows:
- parseWindows(pathStr, numChars);
- break;
- case PathType::Unix:
- parseUnix(pathStr, numChars);
- break;
- default:
- #if CM_PLATFORM == CM_PLATFORM_WIN32
- parseWindows(pathStr, numChars);
- #elif CM_PLATFORM == CM_PLATFORM_APPLE || CM_PLATFORM == CM_PLATFORM_LINUX
- parseUnix(pathStr, numChars);
- #else
- static_assert(false, "Unsupported platform for path.");
- #endif
- break;
- }
- }
- WString Path::toWString(PathType type) const
- {
- switch (type)
- {
- case PathType::Windows:
- return buildWindows();
- case PathType::Unix:
- return buildUnix();
- default:
- #if CM_PLATFORM == CM_PLATFORM_WIN32
- return buildWindows();
- #elif CM_PLATFORM == CM_PLATFORM_APPLE || CM_PLATFORM == CM_PLATFORM_LINUX
- return buildUnix();
- #else
- static_assert(false, "Unsupported platform for path.");
- #endif
- break;
- }
- }
- String Path::toString(PathType type) const
- {
- switch (type)
- {
- case PathType::Windows:
- return BansheeEngine::toString(buildWindows());
- case PathType::Unix:
- return BansheeEngine::toString(buildUnix());
- default:
- #if CM_PLATFORM == CM_PLATFORM_WIN32
- return BansheeEngine::toString(buildWindows());
- #elif CM_PLATFORM == CM_PLATFORM_APPLE || CM_PLATFORM == CM_PLATFORM_LINUX
- return BansheeEngine::toString(buildUnix());
- #else
- static_assert(false, "Unsupported platform for path.");
- #endif
- break;
- }
- }
- Path Path::getParent() const
- {
- Path copy = *this;
- copy.makeParent();
- return copy;
- }
- Path Path::getAbsolute(const Path& base) const
- {
- Path copy = *this;
- copy.makeAbsolute(base);
- return copy;
- }
- Path Path::getRelative(const Path& base) const
- {
- Path copy = *this;
- copy.makeRelative(base);
- return copy;
- }
- Path Path::getDirectory() const
- {
- Path copy = *this;
- copy.mFilename.clear();
- return copy;
- }
- Path& Path::makeParent()
- {
- if (mFilename.empty())
- {
- if (mDirectories.empty())
- {
- if (!mIsAbsolute)
- mDirectories.push_back(L"..");
- }
- else
- {
- if (mDirectories.back() == L"..")
- mDirectories.push_back(L"..");
- else
- mDirectories.pop_back();
- }
- }
- else
- {
- mFilename.clear();
- }
- return *this;
- }
- Path& Path::makeAbsolute(const Path& base)
- {
- if (mIsAbsolute)
- return *this;
- Path absDir = base.getDirectory();
- if (base.isFile())
- absDir.pushDirectory(base.mFilename);
- for (auto& dir : mDirectories)
- absDir.pushDirectory(dir);
- *this = absDir;
- return *this;
- }
- Path& Path::makeRelative(const Path& base)
- {
- if (!base.includes(*this))
- return *this;
- mDirectories.erase(mDirectories.begin(), mDirectories.begin() + base.mDirectories.size());
- mIsAbsolute = false;
- return *this;
- }
- bool Path::includes(const Path& child) const
- {
- if (mDevice != child.mDevice)
- return false;
- if (mNode != child.mNode)
- return false;
- auto iterParent = mDirectories.begin();
- auto iterChild = child.mDirectories.begin();
- for (; iterParent != mDirectories.end(); ++iterChild, ++iterParent)
- {
- if (iterChild == child.mDirectories.end())
- return false;
- if (!comparePathElem(*iterChild, *iterParent))
- return false;
- }
- if (mFilename != child.mFilename)
- return false;
- return true;
- }
- bool Path::equals(const Path& other) const
- {
- if (mIsAbsolute != other.mIsAbsolute)
- return false;
- if (mIsAbsolute)
- {
- if (!comparePathElem(mDevice, other.mDevice))
- return false;
- }
- if (mDirectories.size() != other.mDirectories.size())
- return false;
- if (!comparePathElem(mFilename, other.mFilename))
- return false;
- if (!comparePathElem(mNode, other.mNode))
- return false;
- auto iterMe = mDirectories.begin();
- auto iterOther = other.mDirectories.begin();
- for (; iterMe != mDirectories.end(); ++iterMe, ++iterOther)
- {
- if (!comparePathElem(*iterMe, *iterOther))
- return false;
- }
- return true;
- }
- Path& Path::append(const Path& path)
- {
- if (!mFilename.empty())
- pushDirectory(mFilename);
- for (auto& dir : path.mDirectories)
- pushDirectory(dir);
- mFilename = path.mFilename;
- return *this;
- }
- void Path::setBasename(const WString& basename)
- {
- mFilename = basename + getWExtension();
- }
- void Path::setBasename(const String& basename)
- {
- mFilename = BansheeEngine::toWString(basename) + getWExtension();
- }
- void Path::setExtension(const WString& extension)
- {
- WStringStream stream;
- stream << getWFilename(false);
- stream << extension;
- mFilename = stream.str();
- }
- void Path::setExtension(const String& extension)
- {
- setExtension(BansheeEngine::toWString(extension));
- }
- WString Path::getWFilename(bool extension) const
- {
- if (extension)
- return mFilename;
- else
- {
- WString::size_type pos = mFilename.rfind(L'.');
- if (pos != WString::npos)
- return mFilename.substr(0, pos);
- else
- return mFilename;
- }
- }
- String Path::getFilename(bool extension) const
- {
- return BansheeEngine::toString(getWFilename(extension));
- }
- WString Path::getWExtension() const
- {
- WString::size_type pos = mFilename.rfind(L'.');
- if (pos != WString::npos)
- return mFilename.substr(pos);
- else
- return WString();
- }
- String Path::getExtension() const
- {
- return BansheeEngine::toString(getWExtension());
- }
- const WString& Path::getWDirectory(UINT32 idx) const
- {
- if (idx >= (UINT32)mDirectories.size())
- {
- CM_EXCEPT(InvalidParametersException, "Index out of range: " + BansheeEngine::toString(idx) +
- ". Valid range: [0, " + BansheeEngine::toString((UINT32)mDirectories.size() - 1) + "]");
- }
- return mDirectories[idx];
- }
- String Path::getDirectory(UINT32 idx) const
- {
- return BansheeEngine::toString(getWDirectory(idx));
- }
- WString Path::getWTail(PathType type) const
- {
- if (isFile())
- return mFilename;
- else if (mDirectories.size() > 0)
- return mDirectories.back();
- else
- return toWString(type);
- }
- String Path::getTail(PathType type) const
- {
- return BansheeEngine::toString(getWTail(type));
- }
- void Path::clear()
- {
- mDirectories.clear();
- mDevice.clear();
- mFilename.clear();
- mNode.clear();
- mIsAbsolute = false;
- }
- void Path::throwInvalidPathException(const WString& path) const
- {
- CM_EXCEPT(InvalidParametersException, "Incorrectly formatted path provided: " + BansheeEngine::toString(path));
- }
- void Path::throwInvalidPathException(const String& path) const
- {
- CM_EXCEPT(InvalidParametersException, "Incorrectly formatted path provided: " + path);
- }
- WString Path::buildWindows() const
- {
- WStringStream result;
- if (!mNode.empty())
- {
- result << L"\\\\";
- result << mNode;
- result << L"\\";
- }
- else if (!mDevice.empty())
- {
- result << mDevice;
- result << L":\\";
- }
- else if (mIsAbsolute)
- {
- result << L"\\";
- }
- for (auto& dir : mDirectories)
- {
- result << dir;
- result << L"\\";
- }
- result << mFilename;
- return result.str();
- }
- WString Path::buildUnix() const
- {
- WStringStream result;
- auto dirIter = mDirectories.begin();
- if (!mDevice.empty())
- {
- result << L"/";
- result << mDevice;
- result << L":/";
- }
- else if (mIsAbsolute)
- {
- if (dirIter != mDirectories.end() && *dirIter == L"~")
- {
- result << L"~";
- dirIter++;
- }
- result << L"/";
- }
- for (; dirIter != mDirectories.end(); ++dirIter)
- {
- result << *dirIter;
- result << L"/";
- }
- result << mFilename;
- return result.str();
- }
- bool Path::comparePathElem(const WString& left, const WString& right)
- {
- if (left.size() != right.size())
- return false;
- // TODO: Case sensitive/insensitive file path actually depends on used file-system but I'm not gonna check that
- for (UINT32 i = 0; i < (UINT32)left.size(); i++)
- {
- if (tolower(left[i]) != tolower(right[i]))
- return false;
- }
- return true;
- }
- void Path::pushDirectory(const WString& dir)
- {
- if (!dir.empty() && dir != L".")
- {
- if (dir == L"..")
- {
- if (!mDirectories.empty() && mDirectories.back() != L"..")
- mDirectories.pop_back();
- else
- mDirectories.push_back(dir);
- }
- else
- mDirectories.push_back(dir);
- }
- }
- void Path::pushDirectory(const String& dir)
- {
- pushDirectory(BansheeEngine::toWString(dir));
- }
- }
|