1 // 2 // Copyright 2023 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef GRPC_SRC_CORE_LIB_GPRPP_REF_COUNTED_STRING_H 18 #define GRPC_SRC_CORE_LIB_GPRPP_REF_COUNTED_STRING_H 19 20 #include <grpc/support/port_platform.h> 21 22 #include <stddef.h> 23 24 #include <string> 25 26 #include "absl/strings/string_view.h" 27 28 #include "src/core/lib/gprpp/ref_counted.h" 29 #include "src/core/lib/gprpp/ref_counted_ptr.h" 30 31 namespace grpc_core { 32 33 // An immutable reference counted string. 34 class RefCountedString { 35 public: 36 static RefCountedPtr<RefCountedString> Make(absl::string_view src); 37 38 // Not copyable. 39 RefCountedString(const RefCountedString&) = delete; 40 RefCountedString& operator=(const RefCountedString&) = delete; 41 42 // Provide the same interface as RefCounted<>. 43 // We reimplement this instead of inheritting to make pointer math 44 // easier in Make(). Ref()45 RefCountedPtr<RefCountedString> Ref() { 46 IncrementRefCount(); 47 return RefCountedPtr<RefCountedString>(this); 48 } Unref()49 void Unref() { 50 if (header_.rc.Unref()) Destroy(); 51 } 52 as_string_view()53 absl::string_view as_string_view() const { 54 return absl::string_view(payload_, header_.length); 55 } 56 c_str()57 char* c_str() { return payload_; } 58 59 private: 60 // Allow RefCountedPtr<> to access IncrementRefCount(). 61 template <typename T> 62 friend class RefCountedPtr; 63 64 explicit RefCountedString(absl::string_view src); IncrementRefCount()65 void IncrementRefCount() { header_.rc.Ref(); } 66 void Destroy(); 67 68 struct Header { 69 RefCount rc; 70 size_t length; 71 }; 72 Header header_; 73 char payload_[]; 74 }; 75 76 // Wrapper around RefCountedPtr<RefCountedString> to give value semantics, 77 // especially to overloaded operators. 78 class RefCountedStringValue { 79 public: RefCountedStringValue()80 RefCountedStringValue() : str_{} {} RefCountedStringValue(absl::string_view str)81 explicit RefCountedStringValue(absl::string_view str) 82 : str_(RefCountedString::Make(str)) {} 83 as_string_view()84 absl::string_view as_string_view() const { 85 return str_ == nullptr ? absl::string_view() : str_->as_string_view(); 86 } 87 c_str()88 const char* c_str() const { return str_ == nullptr ? "" : str_->c_str(); } 89 90 private: 91 RefCountedPtr<RefCountedString> str_; 92 }; 93 94 inline bool operator==(const RefCountedStringValue& lhs, 95 absl::string_view rhs) { 96 return lhs.as_string_view() == rhs; 97 } 98 inline bool operator==(absl::string_view lhs, 99 const RefCountedStringValue& rhs) { 100 return lhs == rhs.as_string_view(); 101 } 102 inline bool operator==(const RefCountedStringValue& lhs, 103 const RefCountedStringValue& rhs) { 104 return lhs.as_string_view() == rhs.as_string_view(); 105 } 106 107 inline bool operator!=(const RefCountedStringValue& lhs, 108 absl::string_view rhs) { 109 return lhs.as_string_view() != rhs; 110 } 111 inline bool operator!=(absl::string_view lhs, 112 const RefCountedStringValue& rhs) { 113 return lhs != rhs.as_string_view(); 114 } 115 inline bool operator!=(const RefCountedStringValue& lhs, 116 const RefCountedStringValue& rhs) { 117 return lhs.as_string_view() != rhs.as_string_view(); 118 } 119 120 inline bool operator<(const RefCountedStringValue& lhs, absl::string_view rhs) { 121 return lhs.as_string_view() < rhs; 122 } 123 inline bool operator<(absl::string_view lhs, const RefCountedStringValue& rhs) { 124 return lhs < rhs.as_string_view(); 125 } 126 inline bool operator<(const RefCountedStringValue& lhs, 127 const RefCountedStringValue& rhs) { 128 return lhs.as_string_view() < rhs.as_string_view(); 129 } 130 131 inline bool operator>(const RefCountedStringValue& lhs, absl::string_view rhs) { 132 return lhs.as_string_view() > rhs; 133 } 134 inline bool operator>(absl::string_view lhs, const RefCountedStringValue& rhs) { 135 return lhs > rhs.as_string_view(); 136 } 137 inline bool operator>(const RefCountedStringValue& lhs, 138 const RefCountedStringValue& rhs) { 139 return lhs.as_string_view() > rhs.as_string_view(); 140 } 141 142 // A sorting functor to support heterogeneous lookups in sorted containers. 143 struct RefCountedStringValueLessThan { 144 using is_transparent = void; operatorRefCountedStringValueLessThan145 bool operator()(const RefCountedStringValue& lhs, 146 const RefCountedStringValue& rhs) const { 147 return lhs < rhs; 148 } operatorRefCountedStringValueLessThan149 bool operator()(absl::string_view lhs, 150 const RefCountedStringValue& rhs) const { 151 return lhs < rhs; 152 } operatorRefCountedStringValueLessThan153 bool operator()(const RefCountedStringValue& lhs, 154 absl::string_view rhs) const { 155 return lhs < rhs; 156 } 157 }; 158 159 } // namespace grpc_core 160 161 #endif // GRPC_SRC_CORE_LIB_GPRPP_REF_COUNTED_STRING_H 162