Line data Source code
1 : // Protocol Buffers - Google's data interchange format
2 : // Copyright 2008 Google Inc. All rights reserved.
3 : // https://developers.google.com/protocol-buffers/
4 : //
5 : // Redistribution and use in source and binary forms, with or without
6 : // modification, are permitted provided that the following conditions are
7 : // met:
8 : //
9 : // * Redistributions of source code must retain the above copyright
10 : // notice, this list of conditions and the following disclaimer.
11 : // * Redistributions in binary form must reproduce the above
12 : // copyright notice, this list of conditions and the following disclaimer
13 : // in the documentation and/or other materials provided with the
14 : // distribution.
15 : // * Neither the name of Google Inc. nor the names of its
16 : // contributors may be used to endorse or promote products derived from
17 : // this software without specific prior written permission.
18 : //
19 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 :
31 : #ifndef GOOGLE_PROTOBUF_ARENASTRING_H__
32 : #define GOOGLE_PROTOBUF_ARENASTRING_H__
33 :
34 : #include <string>
35 :
36 : #include <google/protobuf/stubs/logging.h>
37 : #include <google/protobuf/stubs/common.h>
38 : #include <google/protobuf/stubs/fastmem.h>
39 :
40 : #include <google/protobuf/arena.h>
41 : #include <google/protobuf/generated_message_util.h>
42 :
43 :
44 :
45 : // This is the implementation of arena string fields written for the open-source
46 : // release. The ArenaStringPtr struct below is an internal implementation class
47 : // and *should not be used* by user code. It is used to collect string
48 : // operations together into one place and abstract away the underlying
49 : // string-field pointer representation, so that (for example) an alternate
50 : // implementation that knew more about ::std::string's internals could integrate more
51 : // closely with the arena allocator.
52 :
53 : namespace google {
54 : namespace protobuf {
55 : namespace internal {
56 :
57 : struct LIBPROTOBUF_EXPORT ArenaStringPtr {
58 10 : inline void Set(const ::std::string* default_value,
59 : const ::std::string& value, ::google::protobuf::Arena* arena) {
60 10 : if (ptr_ == default_value) {
61 10 : CreateInstance(arena, &value);
62 : } else {
63 0 : *ptr_ = value;
64 : }
65 10 : }
66 :
67 : // Basic accessors.
68 : inline const ::std::string& Get(const ::std::string* default_value) const {
69 67 : return *ptr_;
70 : }
71 :
72 : inline ::std::string* Mutable(const ::std::string* default_value,
73 : ::google::protobuf::Arena* arena) {
74 : if (ptr_ == default_value) {
75 : CreateInstance(arena, default_value);
76 : }
77 : return ptr_;
78 : }
79 :
80 : // Release returns a ::std::string* instance that is heap-allocated and is not
81 : // Own()'d by any arena. If the field was not set, it returns NULL. The caller
82 : // retains ownership. Clears this field back to NULL state. Used to implement
83 : // release_<field>() methods on generated classes.
84 : inline ::std::string* Release(const ::std::string* default_value,
85 : ::google::protobuf::Arena* arena) {
86 : if (ptr_ == default_value) {
87 : return NULL;
88 : }
89 : ::std::string* released = NULL;
90 : if (arena != NULL) {
91 : // ptr_ is owned by the arena -- we need to return a copy.
92 : released = new ::std::string(*ptr_);
93 : } else {
94 : released = ptr_;
95 : }
96 : ptr_ = const_cast< ::std::string* >(default_value);
97 : return released;
98 : }
99 :
100 : // UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned (i.e.
101 : // have its destructor already registered) if arena != NULL. If the field was
102 : // not set, this returns NULL. This method clears this field back to NULL
103 : // state. Used to implement unsafe_arena_release_<field>() methods on
104 : // generated classes.
105 : inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
106 : ::google::protobuf::Arena* arena) {
107 : if (ptr_ == default_value) {
108 : return NULL;
109 : }
110 : ::std::string* released = ptr_;
111 : ptr_ = const_cast< ::std::string* >(default_value);
112 : return released;
113 : }
114 :
115 : // Takes a string that is heap-allocated, and takes ownership. The string's
116 : // destructor is registered with the arena. Used to implement
117 : // set_allocated_<field> in generated classes.
118 : inline void SetAllocated(const ::std::string* default_value,
119 : ::std::string* value, ::google::protobuf::Arena* arena) {
120 : if (arena == NULL && ptr_ != default_value) {
121 : Destroy(default_value, arena);
122 : }
123 : if (value != NULL) {
124 : ptr_ = value;
125 : if (arena != NULL) {
126 : arena->Own(value);
127 : }
128 : } else {
129 : ptr_ = const_cast< ::std::string* >(default_value);
130 : }
131 : }
132 :
133 : // Takes a string that has lifetime equal to the arena's lifetime. The arena
134 : // must be non-null. It is safe only to pass this method a value returned by
135 : // UnsafeArenaRelease() on another field of a message in the same arena. Used
136 : // to implement unsafe_arena_set_allocated_<field> in generated classes.
137 : inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
138 : ::std::string* value, ::google::protobuf::Arena* arena) {
139 : if (value != NULL) {
140 : ptr_ = value;
141 : } else {
142 : ptr_ = const_cast< ::std::string* >(default_value);
143 : }
144 : }
145 :
146 : // Swaps internal pointers. Arena-safety semantics: this is guarded by the
147 : // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
148 : // 'unsafe' if called directly.
149 : GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
150 0 : std::swap(ptr_, other->ptr_);
151 : }
152 :
153 : // Frees storage (if not on an arena) and sets field to default value.
154 22 : inline void Destroy(const ::std::string* default_value,
155 : ::google::protobuf::Arena* arena) {
156 22 : if (arena == NULL && ptr_ != default_value) {
157 20 : delete ptr_;
158 : }
159 22 : ptr_ = const_cast< ::std::string* >(default_value);
160 22 : }
161 :
162 : // Clears content, but keeps allocated string if arena != NULL, to avoid the
163 : // overhead of heap operations. After this returns, the content (as seen by
164 : // the user) will always be the empty string. Assumes that |default_value|
165 : // is an empty string.
166 : inline void ClearToEmpty(const ::std::string* default_value,
167 : ::google::protobuf::Arena* arena) {
168 : if (ptr_ == default_value) {
169 : // Already set to default (which is empty) -- do nothing.
170 : } else {
171 : ptr_->clear();
172 : }
173 : }
174 :
175 : // Clears content, but keeps allocated string if arena != NULL, to avoid the
176 : // overhead of heap operations. After this returns, the content (as seen by
177 : // the user) will always be equal to |default_value|.
178 : inline void ClearToDefault(const ::std::string* default_value,
179 : ::google::protobuf::Arena* arena) {
180 : if (ptr_ == default_value) {
181 : // Already set to default -- do nothing.
182 : } else {
183 : // Have another allocated string -- rather than throwing this away and
184 : // resetting ptr_ to the canonical default string instance, we just reuse
185 : // this instance.
186 : *ptr_ = *default_value;
187 : }
188 : }
189 :
190 : // Called from generated code / reflection runtime only. Resets value to point
191 : // to a default string pointer, with the semantics that this ArenaStringPtr
192 : // does not own the pointed-to memory. Disregards initial value of ptr_ (so
193 : // this is the *ONLY* safe method to call after construction or when
194 : // reinitializing after becoming the active field in a oneof union).
195 2766346 : inline void UnsafeSetDefault(const ::std::string* default_value) {
196 : // Casting away 'const' is safe here: accessors ensure that ptr_ is only
197 : // returned as a const if it is equal to default_value.
198 2930480 : ptr_ = const_cast< ::std::string* >(default_value);
199 2766346 : }
200 :
201 : // The 'NoArena' variants of methods below assume arena == NULL and are
202 : // optimized to provide very little overhead relative to a raw string pointer
203 : // (while still being in-memory compatible with other code that assumes
204 : // ArenaStringPtr). Note the invariant that a class instance that has only
205 : // ever been mutated by NoArena methods must *only* be in the String state
206 : // (i.e., tag bits are not used), *NEVER* ArenaString. This allows all
207 : // tagged-pointer manipulations to be avoided.
208 1397467 : inline void SetNoArena(const ::std::string* default_value,
209 : const ::std::string& value) {
210 1397467 : if (ptr_ == default_value) {
211 1397420 : CreateInstanceNoArena(&value);
212 : } else {
213 47 : *ptr_ = value;
214 : }
215 1397524 : }
216 :
217 : void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
218 :
219 7323372 : inline const ::std::string& GetNoArena(const ::std::string* default_value) const {
220 7414312 : return *ptr_;
221 : }
222 :
223 1517701 : inline ::std::string* MutableNoArena(const ::std::string* default_value) {
224 1540388 : if (ptr_ == default_value) {
225 1400798 : CreateInstanceNoArena(default_value);
226 : }
227 1540441 : return ptr_;
228 : }
229 :
230 : inline ::std::string* ReleaseNoArena(const ::std::string* default_value) {
231 : if (ptr_ == default_value) {
232 : return NULL;
233 : } else {
234 : ::std::string* released = ptr_;
235 : ptr_ = const_cast< ::std::string* >(default_value);
236 : return released;
237 : }
238 : }
239 :
240 : inline void SetAllocatedNoArena(const ::std::string* default_value,
241 : ::std::string* value) {
242 : if (ptr_ != default_value) {
243 : delete ptr_;
244 : }
245 : if (value != NULL) {
246 : ptr_ = value;
247 : } else {
248 : ptr_ = const_cast< ::std::string* >(default_value);
249 : }
250 : }
251 :
252 2928307 : inline void DestroyNoArena(const ::std::string* default_value) {
253 2928307 : if (ptr_ != default_value) {
254 2826122 : delete ptr_;
255 : }
256 2929991 : ptr_ = NULL;
257 2929991 : }
258 :
259 240454 : inline void ClearToEmptyNoArena(const ::std::string* default_value) {
260 240454 : if (ptr_ == default_value) {
261 : // Nothing: already equal to default (which is the empty string).
262 : } else {
263 139266 : ptr_->clear();
264 : }
265 240453 : }
266 :
267 : inline void ClearToDefaultNoArena(const ::std::string* default_value) {
268 : if (ptr_ == default_value) {
269 : // Nothing: already set to default.
270 : } else {
271 : // Reuse existing allocated instance.
272 : *ptr_ = *default_value;
273 : }
274 : }
275 :
276 : // Internal accessor used only at parse time to provide direct access to the
277 : // raw pointer from the shared parse routine (in the non-arenas case). The
278 : // parse routine does the string allocation in order to save code size in the
279 : // generated parsing code.
280 : inline ::std::string** UnsafeRawStringPointer() {
281 : return &ptr_;
282 : }
283 :
284 : private:
285 : ::std::string* ptr_;
286 :
287 10 : GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena,
288 : const ::std::string* initial_value) {
289 : // Assumes ptr_ is not NULL.
290 10 : if (initial_value != NULL) {
291 10 : ptr_ = new ::std::string(*initial_value);
292 : } else {
293 0 : ptr_ = new ::std::string();
294 : }
295 10 : if (arena != NULL) {
296 0 : arena->Own(ptr_);
297 : }
298 10 : }
299 2793391 : GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* initial_value) {
300 2793391 : if (initial_value != NULL) {
301 2793391 : ptr_ = new ::std::string(*initial_value);
302 : } else {
303 0 : ptr_ = new ::std::string();
304 : }
305 2797722 : }
306 : };
307 :
308 : } // namespace internal
309 : } // namespace protobuf
310 :
311 :
312 :
313 : } // namespace google
314 : #endif // GOOGLE_PROTOBUF_ARENASTRING_H__
|