1 | #pragma once |
2 | |
3 | #include <c10/macros/Macros.h> |
4 | #include <c10/util/Exception.h> |
5 | #include <c10/util/Optional.h> |
6 | #include <c10/util/string_view.h> |
7 | #include <string> |
8 | #include <utility> |
9 | #include <ostream> |
10 | |
11 | namespace c10 { |
12 | |
13 | // TODO: consider storing namespace separately too |
14 | struct OperatorName final { |
15 | std::string name; |
16 | std::string overload_name; |
17 | OperatorName(std::string name, std::string overload_name) |
18 | : name(std::move(name)), overload_name(std::move(overload_name)) {} |
19 | |
20 | // TODO: These two functions below are slow! Fix internal data structures so |
21 | // I don't have to manually reconstruct the namespaces! |
22 | |
23 | // Return the namespace of this OperatorName, if it exists. The |
24 | // returned string_view is only live as long as the OperatorName |
25 | // exists and name is not mutated |
26 | c10::optional<c10::string_view> getNamespace() const { |
27 | auto pos = name.find("::" ); |
28 | if (pos == std::string::npos) { |
29 | return c10::nullopt; |
30 | } else { |
31 | return c10::make_optional(c10::string_view(name.data(), pos)); |
32 | } |
33 | } |
34 | |
35 | // Returns true if we successfully set the namespace |
36 | bool setNamespaceIfNotSet(const char* ns) { |
37 | if (!getNamespace().has_value()) { |
38 | const auto ns_len = strlen(ns); |
39 | const auto old_name_size = name.size(); |
40 | name.resize(ns_len + 2 + old_name_size); |
41 | // Shift current value of name to the end of the new space. |
42 | name.replace(name.size() - old_name_size, old_name_size, name, 0, old_name_size); |
43 | name.replace(0, ns_len, ns, ns_len); |
44 | name[ns_len] = ':'; |
45 | name[ns_len + 1] = ':'; |
46 | return true; |
47 | } else { |
48 | return false; |
49 | } |
50 | } |
51 | }; |
52 | |
53 | // Non-owning view of an OperatorName. Unlike OperatorName, most of |
54 | // its functions are constexpr, so it can be used for compile time |
55 | // computations |
56 | struct OperatorNameView final { |
57 | c10::string_view name; |
58 | c10::string_view overload_name; |
59 | constexpr OperatorNameView(c10::string_view name, c10::string_view overload_name) |
60 | : name(name), overload_name(overload_name) {} |
61 | // Parses strings like "foo.overload" and also "foo" |
62 | constexpr static OperatorNameView parse(c10::string_view full_name) { |
63 | auto i = full_name.find('.'); |
64 | if (i == c10::string_view::npos) { |
65 | return OperatorNameView(full_name, c10::string_view()); |
66 | } else { |
67 | return OperatorNameView(full_name.substr(0, i), full_name.substr(i + 1)); |
68 | } |
69 | } |
70 | }; |
71 | |
72 | inline bool operator==(const OperatorName& lhs, const OperatorName& rhs) { |
73 | return lhs.name == rhs.name && lhs.overload_name == rhs.overload_name; |
74 | } |
75 | |
76 | inline bool operator!=(const OperatorName& lhs, const OperatorName& rhs) { |
77 | return !operator==(lhs, rhs); |
78 | } |
79 | |
80 | TORCH_API std::string toString(const OperatorName& opName); |
81 | TORCH_API std::ostream& operator<<(std::ostream&, const OperatorName&); |
82 | |
83 | } // namespace c10 |
84 | |
85 | namespace std { |
86 | template <> |
87 | struct hash<::c10::OperatorName> { |
88 | size_t operator()(const ::c10::OperatorName& x) const { |
89 | return std::hash<std::string>()(x.name) ^ (~ std::hash<std::string>()(x.overload_name)); |
90 | } |
91 | }; |
92 | } |
93 | |