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_UTIL_REF_COUNTED_STRING_H 18 #define GRPC_SRC_CORE_UTIL_REF_COUNTED_STRING_H 19 20 #include <grpc/support/port_platform.h> 21 #include <stddef.h> 22 23 #include <string> 24 25 #include "absl/strings/string_view.h" 26 #include "src/core/util/ref_counted.h" 27 #include "src/core/util/ref_counted_ptr.h" 28 29 namespace grpc_core { 30 31 // An immutable reference counted string. 32 class RefCountedString { 33 public: 34 static RefCountedPtr<RefCountedString> Make(absl::string_view src); 35 36 // Not copyable. 37 RefCountedString(const RefCountedString&) = delete; 38 RefCountedString& operator=(const RefCountedString&) = delete; 39 40 // Provide the same interface as RefCounted<>. 41 // We reimplement this instead of inheritting to make pointer math 42 // easier in Make(). Ref()43 RefCountedPtr<RefCountedString> Ref() { 44 IncrementRefCount(); 45 return RefCountedPtr<RefCountedString>(this); 46 } Unref()47 void Unref() { 48 if (header_.rc.Unref()) Destroy(); 49 } 50 as_string_view()51 absl::string_view as_string_view() const { 52 return absl::string_view(payload_, header_.length); 53 } 54 c_str()55 char* c_str() { return payload_; } 56 57 private: 58 // Allow RefCountedPtr<> to access IncrementRefCount(). 59 template <typename T> 60 friend class RefCountedPtr; 61 62 explicit RefCountedString(absl::string_view src); IncrementRefCount()63 void IncrementRefCount() { header_.rc.Ref(); } 64 void Destroy(); 65 66 struct Header { 67 RefCount rc; 68 size_t length; 69 }; 70 Header header_; 71 char payload_[]; 72 }; 73 74 // Wrapper around RefCountedPtr<RefCountedString> to give value semantics, 75 // especially to overloaded operators. 76 class RefCountedStringValue { 77 public: RefCountedStringValue()78 RefCountedStringValue() : str_{} {} RefCountedStringValue(absl::string_view str)79 explicit RefCountedStringValue(absl::string_view str) 80 : str_(RefCountedString::Make(str)) {} 81 as_string_view()82 absl::string_view as_string_view() const { 83 return str_ == nullptr ? absl::string_view() : str_->as_string_view(); 84 } 85 c_str()86 const char* c_str() const { return str_ == nullptr ? "" : str_->c_str(); } 87 88 private: 89 RefCountedPtr<RefCountedString> str_; 90 }; 91 92 inline bool operator==(const RefCountedStringValue& lhs, 93 absl::string_view rhs) { 94 return lhs.as_string_view() == rhs; 95 } 96 inline bool operator==(absl::string_view lhs, 97 const RefCountedStringValue& rhs) { 98 return lhs == rhs.as_string_view(); 99 } 100 inline bool operator==(const RefCountedStringValue& lhs, 101 const RefCountedStringValue& rhs) { 102 return lhs.as_string_view() == rhs.as_string_view(); 103 } 104 105 inline bool operator!=(const RefCountedStringValue& lhs, 106 absl::string_view rhs) { 107 return lhs.as_string_view() != rhs; 108 } 109 inline bool operator!=(absl::string_view lhs, 110 const RefCountedStringValue& rhs) { 111 return lhs != rhs.as_string_view(); 112 } 113 inline bool operator!=(const RefCountedStringValue& lhs, 114 const RefCountedStringValue& rhs) { 115 return lhs.as_string_view() != rhs.as_string_view(); 116 } 117 118 inline bool operator<(const RefCountedStringValue& lhs, absl::string_view rhs) { 119 return lhs.as_string_view() < rhs; 120 } 121 inline bool operator<(absl::string_view lhs, const RefCountedStringValue& rhs) { 122 return lhs < rhs.as_string_view(); 123 } 124 inline bool operator<(const RefCountedStringValue& lhs, 125 const RefCountedStringValue& rhs) { 126 return lhs.as_string_view() < rhs.as_string_view(); 127 } 128 129 inline bool operator>(const RefCountedStringValue& lhs, absl::string_view rhs) { 130 return lhs.as_string_view() > rhs; 131 } 132 inline bool operator>(absl::string_view lhs, const RefCountedStringValue& rhs) { 133 return lhs > rhs.as_string_view(); 134 } 135 inline bool operator>(const RefCountedStringValue& lhs, 136 const RefCountedStringValue& rhs) { 137 return lhs.as_string_view() > rhs.as_string_view(); 138 } 139 140 // A sorting functor to support heterogeneous lookups in sorted containers. 141 struct RefCountedStringValueLessThan { 142 using is_transparent = void; operatorRefCountedStringValueLessThan143 bool operator()(const RefCountedStringValue& lhs, 144 const RefCountedStringValue& rhs) const { 145 return lhs < rhs; 146 } operatorRefCountedStringValueLessThan147 bool operator()(absl::string_view lhs, 148 const RefCountedStringValue& rhs) const { 149 return lhs < rhs; 150 } operatorRefCountedStringValueLessThan151 bool operator()(const RefCountedStringValue& lhs, 152 absl::string_view rhs) const { 153 return lhs < rhs; 154 } 155 }; 156 157 } // namespace grpc_core 158 159 #endif // GRPC_SRC_CORE_UTIL_REF_COUNTED_STRING_H 160