xref: /aosp_15_r20/external/grpc-grpc/src/core/lib/gprpp/ref_counted_string.h (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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