1 //===-- TildeExpressionResolver.cpp ---------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Utility/TildeExpressionResolver.h"
12 #include <system_error>
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/Path.h"
18 #include "llvm/Support/raw_ostream.h"
24 using namespace lldb_private
;
27 namespace fs
= llvm::sys::fs
;
28 namespace path
= llvm::sys::path
;
30 TildeExpressionResolver::~TildeExpressionResolver() = default;
32 bool StandardTildeExpressionResolver::ResolveExact(
33 StringRef Expr
, SmallVectorImpl
<char> &Output
) {
34 // We expect the tilde expression to be ONLY the expression itself, and
35 // contain no separators.
36 assert(!llvm::any_of(Expr
, [](char c
) { return path::is_separator(c
); }));
37 assert(Expr
.empty() || Expr
[0] == '~');
39 return !fs::real_path(Expr
, Output
, true);
42 bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr
,
43 StringSet
<> &Output
) {
44 // We expect the tilde expression to be ONLY the expression itself, and
45 // contain no separators.
46 assert(!llvm::any_of(Expr
, [](char c
) { return path::is_separator(c
); }));
47 assert(Expr
.empty() || Expr
[0] == '~');
50 #if defined(_WIN32) || defined(__ANDROID__)
56 SmallString
<32> Buffer("~");
58 struct passwd
*user_entry
;
59 Expr
= Expr
.drop_front();
61 while ((user_entry
= getpwent()) != nullptr) {
62 StringRef
ThisName(user_entry
->pw_name
);
63 if (!ThisName
.starts_with(Expr
))
67 Buffer
.append(ThisName
);
68 Buffer
.append(path::get_separator());
69 Output
.insert(Buffer
);
76 bool TildeExpressionResolver::ResolveFullPath(
77 StringRef Expr
, llvm::SmallVectorImpl
<char> &Output
) {
78 if (!Expr
.starts_with("~")) {
79 Output
.assign(Expr
.begin(), Expr
.end());
83 namespace path
= llvm::sys::path
;
85 Expr
.take_until([](char c
) { return path::is_separator(c
); });
87 if (!ResolveExact(Left
, Output
)) {
88 Output
.assign(Expr
.begin(), Expr
.end());
92 Output
.append(Expr
.begin() + Left
.size(), Expr
.end());