1 | //===-- UriParser.cpp -----------------------------------------------------===// |
---|---|
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/Utility/UriParser.h" |
10 | #include "llvm/Support/raw_ostream.h" |
11 | |
12 | #include <string> |
13 | |
14 | #include <cstdint> |
15 | #include <optional> |
16 | #include <tuple> |
17 | |
18 | using namespace lldb_private; |
19 | |
20 | llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &OS, |
21 | const URI &U) { |
22 | OS << U.scheme << "://["<< U.hostname << ']'; |
23 | if (U.port) |
24 | OS << ':' << *U.port; |
25 | return OS << U.path; |
26 | } |
27 | |
28 | std::optional<URI> URI::Parse(llvm::StringRef uri) { |
29 | URI ret; |
30 | |
31 | const llvm::StringRef kSchemeSep("://"); |
32 | auto pos = uri.find(Str: kSchemeSep); |
33 | if (pos == std::string::npos) |
34 | return std::nullopt; |
35 | |
36 | // Extract path. |
37 | ret.scheme = uri.substr(Start: 0, N: pos); |
38 | auto host_pos = pos + kSchemeSep.size(); |
39 | auto path_pos = uri.find(C: '/', From: host_pos); |
40 | if (path_pos != std::string::npos) |
41 | ret.path = uri.substr(Start: path_pos); |
42 | else |
43 | ret.path = "/"; |
44 | |
45 | auto host_port = uri.substr( |
46 | Start: host_pos, |
47 | N: ((path_pos != std::string::npos) ? path_pos : uri.size()) - host_pos); |
48 | |
49 | // Extract hostname |
50 | if (!host_port.empty() && host_port[0] == '[') { |
51 | // hostname is enclosed with square brackets. |
52 | pos = host_port.rfind(C: ']'); |
53 | if (pos == std::string::npos) |
54 | return std::nullopt; |
55 | |
56 | ret.hostname = host_port.substr(Start: 1, N: pos - 1); |
57 | host_port = host_port.drop_front(N: pos + 1); |
58 | if (!host_port.empty() && !host_port.consume_front(Prefix: ":")) |
59 | return std::nullopt; |
60 | } else { |
61 | std::tie(args&: ret.hostname, args&: host_port) = host_port.split(Separator: ':'); |
62 | } |
63 | |
64 | // Extract port |
65 | if (!host_port.empty()) { |
66 | uint16_t port_value = 0; |
67 | if (host_port.getAsInteger(Radix: 0, Result&: port_value)) |
68 | return std::nullopt; |
69 | ret.port = port_value; |
70 | } else |
71 | ret.port = std::nullopt; |
72 | |
73 | return ret; |
74 | } |
75 |