| |
| |
|
|
| |
| |
| |
| |
| const char slash = '\\'; |
| const char auxslash = '/'; |
| const char wslash = L'\\'; |
| const char wauxslash = L'/'; |
| |
| const char slash = '/'; |
| const char auxslash = '\\'; |
| const char wslash = '/'; |
| const char wauxslash = '\\'; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| bool TFilePath::m_underscoreFormatAllowed = true; |
| |
| namespace { |
| |
| /*-- fromSeg位置 と |
| * toSeg位置は含まず、それらの間に挟まれている文字列が「数字4ケタ」ならtrueを返す |
| * --*/ |
| bool isNumbers(std::wstring str, int fromSeg, int toSeg) { |
| if (toSeg - fromSeg != 5) return false; |
| for (int pos = fromSeg + 1; pos < toSeg; pos++) { |
| if (str[pos] < '0' || str[pos] > '9') return false; |
| } |
| return true; |
| } |
| }; |
| |
| |
| std::string TFrameId::expand(FrameFormat format) const { |
| if (m_frame == EMPTY_FRAME) |
| return ""; |
| else if (m_frame == NO_FRAME) |
| return "-"; |
| std::ostringstream o_buff; |
| if (format == FOUR_ZEROS || format == UNDERSCORE_FOUR_ZEROS) { |
| o_buff.fill('0'); |
| o_buff.width(4); |
| o_buff << m_frame; |
| o_buff.width(0); |
| } else { |
| o_buff << m_frame; |
| } |
| if (m_letter != '\0') o_buff << m_letter; |
| return o_buff.str(); |
| } |
| |
| |
| |
| const TFrameId &TFrameId::operator++() { |
| ++m_frame; |
| m_letter = 0; |
| return *this; |
| } |
| |
| |
| |
| const TFrameId &TFrameId::operator--() { |
| if (m_letter > 0) |
| m_letter = 0; |
| else |
| --m_frame; |
| return *this; |
| } |
| |
| |
| |
| inline bool isSlash(char c) { return c == slash || c == auxslash; } |
| |
| |
| |
| inline bool isSlash(wchar_t c) { return c == wslash || c == wauxslash; } |
| |
| |
| |
| |
| |
| |
| inline int getLastSlash(const std::wstring &path) { |
| int i; |
| for (i = path.length() - 1; i >= 0 && !isSlash(path[i]); i--) { |
| } |
| return i; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| void TFilePath::setPath(std::wstring path) { |
| bool isUncName = false; |
| |
| |
| int length = path.length(); |
| int pos = 0; |
| |
| if (path.length() >= 2 && iswalpha(path[0]) && path[1] == L':') { |
| m_path.append(1, (wchar_t)path[0]); |
| m_path.append(1, L':'); |
| |
| pos = 2; |
| if (path.length() == 2 || !isSlash(path[pos])) m_path.append(1, wslash); |
| } |
| |
| else if (path.length() >= 3 && path[0] == L'\\' && path[1] == L'\\' && |
| iswalnum(path[2]) || |
| path.length() >= 3 && path[0] == L'/' && path[1] == L'/' && |
| iswalnum(path[2])) { |
| isUncName = true; |
| m_path.append(2, L'\\'); |
| m_path.append(1, path[2]); |
| pos = 3; |
| } |
| for (; pos < length; pos++) |
| if (path[pos] == L'.') { |
| pos++; |
| if (pos >= length) { |
| if (pos > 1) m_path.append(1, L'.'); |
| } else if (!isSlash(path[pos])) { |
| m_path.append(1, L'.'); |
| m_path.append(1, path[pos]); |
| } else { |
| while (pos + 1 < length && isSlash(path[pos + 1])) pos++; |
| } |
| } else if (isSlash(path[pos])) { |
| int firstSlashPos = pos; |
| do |
| pos++; |
| while (pos < length && isSlash(path[pos])); |
| if (firstSlashPos == 0 && pos == 4) |
| m_path.append(2, wslash); |
| else |
| m_path.append(1, wslash); |
| pos--; |
| } else { |
| m_path.append(1, path[pos]); |
| } |
| |
| |
| |
| |
| if (!(m_path.length() == 1 && m_path[0] == wslash || |
| m_path.length() == 3 && iswalpha(m_path[0]) && m_path[1] == L':' && |
| m_path[2] == wslash) && |
| m_path.length() > 1 && m_path[m_path.length() - 1] == wslash) |
| m_path.erase(m_path.length() - 1, 1); |
| |
| if (isUncName && |
| !(m_path.find_last_of(L'\\') > 1 || |
| m_path.find_last_of(L'/') > |
| 1)) |
| m_path.append(1, wslash); |
| } |
| |
| |
| |
| TFilePath::TFilePath(const char *path) { setPath(::to_wstring(path)); } |
| |
| |
| |
| TFilePath::TFilePath(const std::string &path) { setPath(::to_wstring(path)); } |
| |
| |
| |
| TFilePath::TFilePath(const std::wstring &path) { setPath(path); } |
| |
| |
| |
| TFilePath::TFilePath(const QString &path) { setPath(path.toStdWString()); } |
| |
| |
| |
| bool TFilePath::operator==(const TFilePath &fp) const { |
| |
| return _wcsicmp(m_path.c_str(), fp.m_path.c_str()) == 0; |
| |
| return m_path == fp.m_path; |
| |
| } |
| |
| |
| |
| bool TFilePath::operator<(const TFilePath &fp) const { |
| std::wstring iName = m_path; |
| std::wstring jName = fp.m_path; |
| int i1 = 0, j1 = 0; |
| int i2 = m_path.find(L"\\"); |
| int j2 = fp.m_path.find(L"\\"); |
| if (i2 == j2 && j2 == -1) |
| |
| return _wcsicmp(m_path.c_str(), fp.m_path.c_str()) < 0; |
| |
| return m_path < fp.m_path; |
| |
| if (!i2) { |
| ++i1; |
| i2 = m_path.find(L"\\", i1); |
| } |
| if (!j2) { |
| ++j1; |
| j2 = fp.m_path.find(L"\\", j1); |
| } |
| while (i2 != -1 || j2 != -1) { |
| iName = (i2 != -1) ? m_path.substr(i1, i2 - i1) : m_path; |
| jName = (j2 != -1) ? fp.m_path.substr(j1, j2 - j1) : fp.m_path; |
| |
| |
| |
| char differ; |
| differ = _wcsicmp(iName.c_str(), jName.c_str()); |
| if (differ != 0) return differ < 0 ? true : false; |
| |
| if (TFilePath(iName) != TFilePath(jName)) |
| return TFilePath(iName) < TFilePath(jName); |
| |
| i1 = (i2 != -1) ? i2 + 1 : m_path.size(); |
| j1 = (j2 != -1) ? j2 + 1 : fp.m_path.size(); |
| i2 = m_path.find(L"\\", i1); |
| j2 = fp.m_path.find(L"\\", j1); |
| } |
| |
| iName = m_path.substr(i1, m_path.size() - i1); |
| jName = fp.m_path.substr(j1, fp.m_path.size() - j1); |
| |
| return _wcsicmp(iName.c_str(), jName.c_str()) < 0; |
| |
| return TFilePath(iName) < TFilePath(jName); |
| |
| } |
| |
| |
| bool TFilePath::operator<(const TFilePath &fp) const { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| wstring a = toLower(m_path), b = toLower(fp.m_path); |
| return a < b; |
| } |
| |
| |
| |
| |
| TFilePath &TFilePath::operator+=(const TFilePath &fp) { |
| assert(!fp.isAbsolute()); |
| if (fp.isEmpty()) |
| return *this; |
| else if (isEmpty()) { |
| *this = fp; |
| return *this; |
| } else if (m_path.length() != 1 || m_path[0] != slash) { |
| assert(!m_path.empty()); |
| if (!isSlash(m_path[m_path.length() - 1])) m_path.append(1, wslash); |
| m_path += fp.m_path; |
| return *this; |
| } else { |
| *this = TFilePath(m_path + fp.m_path); |
| return *this; |
| } |
| } |
| |
| TFilePath TFilePath::operator+(const TFilePath &fp) const { |
| TFilePath ret(*this); |
| ret += fp; |
| return ret; |
| } |
| |
| |
| TFilePath &TFilePath::operator+=(const std::wstring &s) { |
| if (s.empty()) return *this; |
| |
| |
| if (m_path.length() > 0 && !isSlash(m_path[m_path.length() - 1])) |
| m_path.append(1, wslash); |
| m_path += s; |
| return *this; |
| } |
| |
| |
| |
| const std::wstring TFilePath::getWideString() const { |
| return m_path; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| QString TFilePath::getQString() const { |
| return QString::fromStdWString(getWideString()); |
| } |
| |
| |
| |
| std::ostream &operator<<(std::ostream &out, const TFilePath &path) { |
| std::wstring w = path.getWideString(); |
| return out << ::to_string(w) << " "; |
| |
| |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| bool TFilePath::isAbsolute() const { |
| return m_path.length() >= 1 && m_path[0] == slash || |
| m_path.length() >= 2 && iswalpha(m_path[0]) && m_path[1] == ':'; |
| } |
| |
| |
| |
| bool TFilePath::isRoot() const { |
| return m_path.length() == 1 && m_path[0] == slash || |
| m_path.length() == 3 && iswalpha(m_path[0]) && m_path[1] == ':' && |
| m_path[2] == slash || |
| m_path.length() > 2 && m_path[0] == slash && m_path[1] == slash && |
| (std::string::npos == m_path.find(slash, 2) || |
| m_path.find(slash, 2) == m_path.size() - 1); |
| } |
| |
| |
| |
| |
| |
| std::string TFilePath::getDots() const { |
| if (isFfmpegType()) return "."; |
| int i = getLastSlash(m_path); |
| std::wstring str = m_path.substr(i + 1); |
| |
| i = str.rfind(L"."); |
| if (i == (int)std::wstring::npos || str == L"..") return ""; |
| |
| if (str.substr(0, i).rfind(L".") != std::wstring::npos) |
| return ".."; |
| else if (m_underscoreFormatAllowed) { |
| int j = str.substr(0, i).rfind(L"_"); |
| |
| return (j != (int)std::wstring::npos && |
| (j == i - 1 || isNumbers(str, j, i))) |
| ? ".." |
| : "."; |
| } else |
| return "."; |
| } |
| |
| |
| |
| std::string TFilePath::getDottedType() |
| const |
| { |
| int i = getLastSlash(m_path); |
| std::wstring str = m_path.substr(i + 1); |
| i = str.rfind(L"."); |
| if (i == (int)std::wstring::npos) return ""; |
| |
| return toLower(::to_string(str.substr(i))); |
| } |
| |
| |
| |
| std::string TFilePath::getUndottedType() |
| const |
| { |
| size_t i = getLastSlash(m_path); |
| std::wstring str = m_path.substr(i + 1); |
| i = str.rfind(L"."); |
| if (i == std::wstring::npos || i == str.length() - 1) return ""; |
| return toLower(::to_string(str.substr(i + 1))); |
| } |
| |
| |
| |
| std::wstring TFilePath::getWideName() const |
| { |
| int i = getLastSlash(m_path); |
| std::wstring str = m_path.substr(i + 1); |
| i = str.rfind(L"."); |
| if (i == (int)std::wstring::npos) return str; |
| int j = str.substr(0, i).rfind(L"."); |
| if (j != (int)std::wstring::npos) |
| i = j; |
| else if (m_underscoreFormatAllowed) { |
| j = str.substr(0, i).rfind(L"_"); |
| if (j != (int)std::wstring::npos && isNumbers(str, j, i)) i = j; |
| } |
| return str.substr(0, i); |
| } |
| |
| |
| |
| std::string TFilePath::getName() const |
| { |
| return ::to_string(getWideName()); |
| } |
| |
| |
| |
| std::string TFilePath::getLevelName() const { |
| return ::to_string(getLevelNameW()); |
| } |
| |
| |
| |
| |
| std::wstring TFilePath::getLevelNameW() const { |
| int i = getLastSlash(m_path); |
| std::wstring str = m_path.substr(i + 1); |
| if (isFfmpegType()) return str; |
| int j = str.rfind(L"."); |
| if (j == (int)std::wstring::npos) return str; |
| i = str.substr(0, j).rfind(L'.'); |
| if (i == (int)std::wstring::npos && m_underscoreFormatAllowed) |
| i = str.substr(0, j).rfind(L'_'); |
| |
| if (j == i || j - i == 1) |
| return str; |
| |
| if (!isNumbers(str, i, j)) return str; |
| |
| return str.erase(i + 1, j - i - 1); |
| } |
| |
| |
| |
| TFilePath TFilePath::getParentDir() const |
| { |
| int i = getLastSlash(m_path); |
| if (i < 0) { |
| if (m_path.length() >= 2 && ('a' <= m_path[0] && m_path[0] <= 'z' || |
| 'A' <= m_path[0] && m_path[0] <= 'Z') && |
| m_path[1] == ':') |
| return TFilePath(m_path.substr(0, 2)); |
| else |
| return TFilePath(""); |
| } else if (i == 0) |
| return TFilePath("/"); |
| else |
| return TFilePath(m_path.substr(0, i)); |
| } |
| |
| |
| |
| bool TFilePath::isLevelName() const { |
| if (isFfmpegType()) return false; |
| try { |
| return getFrame() == TFrameId(TFrameId::EMPTY_FRAME); |
| } |
| |
| catch (...) { |
| return false; |
| } |
| } |
| |
| TFrameId TFilePath::getFrame() const { |
| int i = getLastSlash(m_path); |
| std::wstring str = m_path.substr(i + 1); |
| i = str.rfind(L'.'); |
| if (i == (int)std::wstring::npos || str == L"." || str == L"..") |
| return TFrameId(TFrameId::NO_FRAME); |
| int j; |
| |
| j = str.substr(0, i).rfind(L'.'); |
| if (j == (int)std::wstring::npos && m_underscoreFormatAllowed) |
| j = str.substr(0, i).rfind(L'_'); |
| |
| if (j == (int)std::wstring::npos) return TFrameId(TFrameId::NO_FRAME); |
| if (i == j + 1) return TFrameId(TFrameId::EMPTY_FRAME); |
| |
| |
| |
| if (!isNumbers(str, j, i)) return TFrameId(TFrameId::NO_FRAME); |
| |
| int k, number = 0; |
| for (k = j + 1; k < i && iswdigit(str[k]); k++) |
| number = number * 10 + str[k] - L'0'; |
| char letter = '\0'; |
| if (iswalpha(str[k])) letter = str[k++] + ('a' - L'a'); |
| |
| if (number == 0 || k < i) |
| throw TMalformedFrameException( |
| *this, |
| str + L": " + QObject::tr("Malformed frame name").toStdWString()); |
| |
| return TFrameId(number, letter); |
| } |
| |
| |
| |
| bool TFilePath::isFfmpegType() const { |
| QString type = QString::fromStdString(getType()).toLower(); |
| if (type == "gif" || type == "mp4" || type == "webm") |
| return true; |
| else |
| return false; |
| } |
| |
| |
| TFilePath TFilePath::withType(const std::string &type) const { |
| assert(type.length() < 2 || type.substr(0, 2) != ".."); |
| int i = getLastSlash(m_path); |
| std::wstring str = m_path.substr(i + 1); |
| int j = str.rfind(L'.'); |
| if (j == (int)std::wstring::npos || str == L"..") |
| |
| { |
| if (type == "") |
| return *this; |
| else if (type[0] == '.') |
| return TFilePath(m_path + ::to_wstring(type)); |
| else |
| return TFilePath(m_path + ::to_wstring("." + type)); |
| } else |
| |
| { |
| if (type == "") |
| return TFilePath(m_path.substr(0, i + j + 1)); |
| else if (type[0] == '.') |
| return TFilePath(m_path.substr(0, i + j + 1) + ::to_wstring(type)); |
| else |
| return TFilePath(m_path.substr(0, i + j + 2) + ::to_wstring(type)); |
| } |
| } |
| |
| |
| |
| TFilePath TFilePath::withName(const std::string &name) const { |
| return withName(::to_wstring(name)); |
| } |
| |
| |
| |
| TFilePath TFilePath::withName(const std::wstring &name) const { |
| int i = getLastSlash(m_path); |
| std::wstring str = m_path.substr(i + 1); |
| int j; |
| j = str.rfind(L'.'); |
| |
| if (j == (int)std::wstring::npos) { |
| if (m_underscoreFormatAllowed) { |
| j = str.rfind(L'_'); |
| if (j != (int)std::wstring::npos) |
| return TFilePath(m_path.substr(0, i + 1) + name + str.substr(j)); |
| } |
| return TFilePath(m_path.substr(0, i + 1) + name); |
| } |
| int k; |
| |
| k = str.substr(0, j).rfind(L"."); |
| if (k == (int)std::wstring::npos && m_underscoreFormatAllowed) |
| k = str.substr(0, j).rfind(L"_"); |
| |
| if (k == (int)(std::wstring::npos)) |
| k = j; |
| else if (k != j - 1 && !isNumbers(str, k, j)) |
| k = j; |
| |
| return TFilePath(m_path.substr(0, i + 1) + name + str.substr(k)); |
| } |
| |
| |
| |
| TFilePath TFilePath::withParentDir(const TFilePath &dir) const { |
| int i = getLastSlash(m_path); |
| return dir + TFilePath(m_path.substr(i + 1)); |
| } |
| |
| |
| |
| TFilePath TFilePath::withFrame(const TFrameId &frame, |
| TFrameId::FrameFormat format) const { |
| const std::wstring dot = L".", dotDot = L".."; |
| int i = getLastSlash(m_path); |
| std::wstring str = m_path.substr(i + 1); |
| assert(str != dot && str != dotDot); |
| int j = str.rfind(L'.'); |
| const char *ch = "."; |
| if (m_underscoreFormatAllowed && (format == TFrameId::UNDERSCORE_FOUR_ZEROS || |
| format == TFrameId::UNDERSCORE_NO_PAD)) |
| ch = "_"; |
| if (j == (int)std::wstring::npos) { |
| if (frame.isEmptyFrame() || frame.isNoFrame()) |
| return *this; |
| else |
| return TFilePath(m_path + ::to_wstring(ch + frame.expand(format))); |
| } |
| |
| std::string frameString; |
| if (frame.isNoFrame()) |
| frameString = ""; |
| else |
| frameString = ch + frame.expand(format); |
| |
| int k = str.substr(0, j).rfind(L'.'); |
| |
| if (k != (int)std::wstring::npos) |
| return TFilePath(m_path.substr(0, k + i + 1) + ::to_wstring(frameString) + |
| str.substr(j)); |
| else if (m_underscoreFormatAllowed) { |
| k = str.substr(0, j).rfind(L'_'); |
| if (k != (int)std::wstring::npos && |
| (k == j - 1 || |
| isNumbers(str, k, j))) |
| return TFilePath(m_path.substr(0, k + i + 1) + |
| ((frame.isNoFrame()) |
| ? L"" |
| : ::to_wstring("_" + frame.expand(format))) + |
| str.substr(j)); |
| } |
| return TFilePath(m_path.substr(0, j + i + 1) + ::to_wstring(frameString) + |
| str.substr(j)); |
| } |
| |
| |
| |
| bool TFilePath::isAncestorOf(const TFilePath &possibleDescendent) const { |
| size_t len = m_path.length(); |
| if (len == 0) { |
| |
| return !possibleDescendent.isAbsolute(); |
| } |
| |
| |
| if (m_path == possibleDescendent.m_path) return true; |
| |
| int possibleDescendentLen = possibleDescendent.m_path.length(); |
| |
| if ((int)len >= possibleDescendentLen) return false; |
| |
| if (toLower(m_path) != toLower(possibleDescendent.m_path.substr(0, len))) |
| return false; |
| |
| |
| if (m_path[len - 1] != wslash && possibleDescendent.m_path[len] != wslash) |
| return false; |
| |
| return true; |
| } |
| |
| |
| |
| TFilePath TFilePath::operator-(const TFilePath &fp) const { |
| if (toLower(m_path) == toLower(fp.m_path)) return TFilePath(""); |
| if (!fp.isAncestorOf(*this)) return *this; |
| int len = fp.m_path.length(); |
| if (len == 0 || fp.m_path[len - 1] != wslash) len++; |
| |
| return TFilePath(m_path.substr(len)); |
| } |
| |
| |
| |
| bool TFilePath::match(const TFilePath &fp) const { |
| return getParentDir() == fp.getParentDir() && getName() == fp.getName() && |
| getFrame() == fp.getFrame() && getType() == fp.getType(); |
| } |
| |
| |
| |
| void TFilePath::split(std::wstring &head, TFilePath &tail) const { |
| TFilePath ancestor = getParentDir(); |
| if (ancestor == TFilePath()) { |
| head = getWideString(); |
| tail = TFilePath(); |
| return; |
| } |
| for (;;) { |
| if (ancestor.isRoot()) break; |
| TFilePath p = ancestor.getParentDir(); |
| if (p == TFilePath()) break; |
| ancestor = p; |
| } |
| head = ancestor.getWideString(); |
| tail = *this - ancestor; |
| } |
| |