mirror of
https://github.com/google/leveldb.git
synced 2025-03-14 09:50:07 +08:00
122 lines
3.1 KiB
C++
122 lines
3.1 KiB
C++
#include "leveldb/db_path.h"
|
|
|
|
namespace leveldb {
|
|
namespace path {
|
|
|
|
bool DbPath::IsDirectorySeparator(const char c) {
|
|
return (c == DbPath::kDirectorySeparator || c == DbPath::kAltDirecttorySeparator);
|
|
}
|
|
|
|
bool DbPath::StartsWith(const std::string& value, bool ignore_case) const {
|
|
if (value.size() > path_.size()) {
|
|
return false;
|
|
}
|
|
if (ignore_case) {
|
|
auto ignore_case_cmp_func = [](char a, char b) { return std::tolower(a) == std::tolower(b); };
|
|
return std::equal(value.begin(), value.end(), path_.begin(), ignore_case_cmp_func);
|
|
}
|
|
return std::equal(value.begin(), value.end(), path_.begin());
|
|
}
|
|
|
|
// Windows
|
|
|
|
bool WindowsDbPath::IsAbsolute() const {
|
|
return path_.size() >= 3 && IsValidDriveChar(path_[0]) &&
|
|
path_[1] == DbPath::kVolumeSeparatorChar;
|
|
};
|
|
|
|
bool WindowsDbPath::IsRelative() const {
|
|
if (path_.size() < 2) {
|
|
return true;
|
|
}
|
|
|
|
if (IsDirectorySeparator(path_[0])) {
|
|
if (path_[1] != '?') {
|
|
return !IsDirectorySeparator(path_[1]);
|
|
}
|
|
return false;
|
|
}
|
|
if (path_.size() >= 3 && path_[1] == DbPath::kVolumeSeparatorChar &&
|
|
IsDirectorySeparator(path_[2])) {
|
|
return IsValidDriveChar(path_[0]);
|
|
}
|
|
return true;
|
|
};
|
|
|
|
bool WindowsDbPath::IsValidDriveChar(const char c) {
|
|
const char drive_char = std::toupper(c);
|
|
return drive_char >= 'A' && drive_char <= 'Z';
|
|
}
|
|
|
|
size_t WindowsDbPath::RootLength() const {
|
|
size_t path_length = path_.size();
|
|
size_t root_length = 0;
|
|
size_t volume_separator_length = 2;
|
|
size_t unc_root_length = 2;
|
|
|
|
bool extended_syntax = StartsWith(kExtendedPathPrefix);
|
|
bool extended_unc_syntax = StartsWith(kUncExtendedPathPrefix);
|
|
|
|
if (extended_syntax) {
|
|
if (extended_unc_syntax) {
|
|
unc_root_length = std::strlen(kUncExtendedPathPrefix);
|
|
} else {
|
|
volume_separator_length += std::strlen(kExtendedPathPrefix);
|
|
}
|
|
}
|
|
|
|
if ((!extended_syntax || extended_unc_syntax) && path_length != 0 && IsDirectorySeparator(path_[0])) {
|
|
root_length = 1;
|
|
|
|
if (extended_unc_syntax || (path_length > 1 && IsDirectorySeparator(path_[1]))) {
|
|
root_length = unc_root_length;
|
|
int n = 2; // maximum separators to skip
|
|
while (root_length < path_length &&
|
|
(!IsDirectorySeparator(path_[root_length]) || --n > 0)) {
|
|
++root_length;
|
|
}
|
|
}
|
|
} else if (path_length >= volume_separator_length &&
|
|
path_[volume_separator_length - 1] == kVolumeSeparatorChar) {
|
|
root_length = volume_separator_length;
|
|
if (path_length >= volume_separator_length &&
|
|
IsDirectorySeparator(path_[volume_separator_length])) {
|
|
++root_length;
|
|
}
|
|
}
|
|
|
|
return root_length;
|
|
}
|
|
|
|
void WindowsDbPath::Normalize() {
|
|
auto out = path_.begin();
|
|
|
|
for (const char c : path_) {
|
|
if (!IsDirectorySeparator(c)) {
|
|
*(out++) = c;
|
|
} else if (out == path_.begin() || !IsDirectorySeparator(*std::prev(out))) {
|
|
*(out++) = kDirectorySeparator;
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
path_.erase(out, path_.end());
|
|
}
|
|
|
|
// Windows path
|
|
|
|
DbPath* PathFactory::Create(const std::string& path) {
|
|
#ifdef LEVELDB_PLATFORM_WINDOWS
|
|
return new WindowsDbPath(path);
|
|
#elif LEVELDB_PLATFORM_POSIX
|
|
return nullptr;
|
|
#endif
|
|
return nullptr;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|