aboutsummaryrefslogtreecommitdiffstats
path: root/util/folder/pathsplit.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/folder/pathsplit.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/folder/pathsplit.cpp')
-rw-r--r--util/folder/pathsplit.cpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/util/folder/pathsplit.cpp b/util/folder/pathsplit.cpp
new file mode 100644
index 0000000000..81d439a727
--- /dev/null
+++ b/util/folder/pathsplit.cpp
@@ -0,0 +1,151 @@
+#include "pathsplit.h"
+
+#include "dirut.h"
+
+#include <util/stream/output.h>
+#include <util/generic/yexception.h>
+
+template <class T>
+static inline size_t ToReserve(const T& t) {
+ size_t ret = t.size() + 5;
+
+ for (auto it = t.begin(); it != t.end(); ++it) {
+ ret += it->size();
+ }
+
+ return ret;
+}
+
+void TPathSplitTraitsUnix::DoParseFirstPart(const TStringBuf part) {
+ if (part == TStringBuf(".")) {
+ push_back(TStringBuf("."));
+
+ return;
+ }
+
+ if (IsAbsolutePath(part)) {
+ IsAbsolute = true;
+ }
+
+ DoParsePart(part);
+}
+
+void TPathSplitTraitsUnix::DoParsePart(const TStringBuf part0) {
+ DoAppendHint(part0.size() / 8);
+
+ TStringBuf next(part0);
+ TStringBuf part;
+
+ while (TStringBuf(next).TrySplit('/', part, next)) {
+ AppendComponent(part);
+ }
+
+ AppendComponent(next);
+}
+
+void TPathSplitTraitsWindows::DoParseFirstPart(const TStringBuf part0) {
+ TStringBuf part(part0);
+
+ if (part == TStringBuf(".")) {
+ push_back(TStringBuf("."));
+
+ return;
+ }
+
+ if (IsAbsolutePath(part)) {
+ IsAbsolute = true;
+
+ if (part.size() > 1 && part[1] == ':') {
+ Drive = part.SubStr(0, 2);
+ part = part.SubStr(2);
+ }
+ }
+
+ DoParsePart(part);
+}
+
+void TPathSplitTraitsWindows::DoParsePart(const TStringBuf part0) {
+ DoAppendHint(part0.size() / 8);
+
+ size_t pos = 0;
+ TStringBuf part(part0);
+
+ while (pos < part.size()) {
+ while (pos < part.size() && this->IsPathSep(part[pos])) {
+ ++pos;
+ }
+
+ const char* begin = part.data() + pos;
+
+ while (pos < part.size() && !this->IsPathSep(part[pos])) {
+ ++pos;
+ }
+
+ AppendComponent(TStringBuf(begin, part.data() + pos));
+ }
+}
+
+TString TPathSplitStore::DoReconstruct(const TStringBuf slash) const {
+ TString r;
+
+ r.reserve(ToReserve(*this));
+
+ if (IsAbsolute) {
+ r.AppendNoAlias(Drive);
+ r.AppendNoAlias(slash);
+ }
+
+ for (auto i = begin(); i != end(); ++i) {
+ if (i != begin()) {
+ r.AppendNoAlias(slash);
+ }
+
+ r.AppendNoAlias(*i);
+ }
+
+ return r;
+}
+
+void TPathSplitStore::AppendComponent(const TStringBuf comp) {
+ if (!comp || comp == TStringBuf(".")) {
+ ; // ignore
+ } else if (comp == TStringBuf("..") && !empty() && back() != TStringBuf("..")) {
+ pop_back();
+ } else {
+ // push back first .. also
+ push_back(comp);
+ }
+}
+
+TStringBuf TPathSplitStore::Extension() const {
+ return size() > 0 ? CutExtension(back()) : TStringBuf();
+}
+
+template <>
+void Out<TPathSplit>(IOutputStream& o, const TPathSplit& ps) {
+ o << ps.Reconstruct();
+}
+
+TString JoinPaths(const TPathSplit& p1, const TPathSplit& p2) {
+ if (p2.IsAbsolute) {
+ ythrow yexception() << "can not join " << p1 << " and " << p2;
+ }
+
+ return TPathSplit(p1).AppendMany(p2.begin(), p2.end()).Reconstruct();
+}
+
+TStringBuf CutExtension(const TStringBuf fileName) {
+ if (fileName.empty()) {
+ return fileName;
+ }
+
+ TStringBuf name;
+ TStringBuf extension;
+ fileName.RSplit('.', name, extension);
+ if (name.empty()) {
+ // dot at a start or not found
+ return name;
+ } else {
+ return extension;
+ }
+}