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/arena.h>
37 : #include <google/protobuf/stubs/common.h>
38 : #include <google/protobuf/stubs/fastmem.h>
39 : #include <google/protobuf/stubs/logging.h>
40 : #include <google/protobuf/stubs/port.h>
41 :
42 : // This is the implementation of arena string fields written for the open-source
43 : // release. The ArenaStringPtr struct below is an internal implementation class
44 : // and *should not be used* by user code. It is used to collect string
45 : // operations together into one place and abstract away the underlying
46 : // string-field pointer representation, so that (for example) an alternate
47 : // implementation that knew more about ::std::string's internals could integrate more
48 : // closely with the arena allocator.
49 :
50 : namespace google {
51 : namespace protobuf {
52 : namespace internal {
53 :
54 : template <typename T>
55 : class TaggedPtr {
56 : public:
57 : void Set(T* p) { ptr_ = reinterpret_cast<uintptr_t>(p); }
58 : T* Get() const { return reinterpret_cast<T*>(ptr_); }
59 :
60 : bool IsNull() { return ptr_ == 0; }
61 :
62 : private:
63 : uintptr_t ptr_;
64 : };
65 :
66 : struct LIBPROTOBUF_EXPORT ArenaStringPtr {
67 : inline void Set(const ::std::string* default_value,
68 : const ::std::string& value, ::google::protobuf::Arena* arena) {
69 : if (ptr_ == default_value) {
70 : CreateInstance(arena, &value);
71 : } else {
72 : *ptr_ = value;
73 : }
74 : }
75 :
76 : inline void SetLite(const ::std::string* default_value,
77 : const ::std::string& value,
78 : ::google::protobuf::Arena* arena) {
79 : Set(default_value, value, arena);
80 : }
81 :
82 : // Basic accessors.
83 : inline const ::std::string& Get() const { return *ptr_; }
84 :
85 0 : inline ::std::string* Mutable(const ::std::string* default_value,
86 : ::google::protobuf::Arena* arena) {
87 0 : if (ptr_ == default_value) {
88 0 : CreateInstance(arena, default_value);
89 : }
90 0 : return ptr_;
91 : }
92 :
93 : // Release returns a ::std::string* instance that is heap-allocated and is not
94 : // Own()'d by any arena. If the field was not set, it returns NULL. The caller
95 : // retains ownership. Clears this field back to NULL state. Used to implement
96 : // release_<field>() methods on generated classes.
97 : inline ::std::string* Release(const ::std::string* default_value,
98 : ::google::protobuf::Arena* arena) {
99 : if (ptr_ == default_value) {
100 : return NULL;
101 : }
102 : return ReleaseNonDefault(default_value, arena);
103 : }
104 :
105 : // Similar to Release, but ptr_ cannot be the default_value.
106 : inline ::std::string* ReleaseNonDefault(
107 : const ::std::string* default_value, ::google::protobuf::Arena* arena) {
108 : GOOGLE_DCHECK(!IsDefault(default_value));
109 : ::std::string* released = NULL;
110 : if (arena != NULL) {
111 : // ptr_ is owned by the arena.
112 : released = new ::std::string;
113 : released->swap(*ptr_);
114 : } else {
115 : released = ptr_;
116 : }
117 : ptr_ = const_cast< ::std::string* >(default_value);
118 : return released;
119 : }
120 :
121 : // UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned (i.e.
122 : // have its destructor already registered) if arena != NULL. If the field was
123 : // not set, this returns NULL. This method clears this field back to NULL
124 : // state. Used to implement unsafe_arena_release_<field>() methods on
125 : // generated classes.
126 : inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
127 : ::google::protobuf::Arena* /* arena */) {
128 : if (ptr_ == default_value) {
129 : return NULL;
130 : }
131 : ::std::string* released = ptr_;
132 : ptr_ = const_cast< ::std::string* >(default_value);
133 : return released;
134 : }
135 :
136 : // Takes a string that is heap-allocated, and takes ownership. The string's
137 : // destructor is registered with the arena. Used to implement
138 : // set_allocated_<field> in generated classes.
139 : inline void SetAllocated(const ::std::string* default_value,
140 : ::std::string* value, ::google::protobuf::Arena* arena) {
141 : if (arena == NULL && ptr_ != default_value) {
142 : Destroy(default_value, arena);
143 : }
144 : if (value != NULL) {
145 : ptr_ = value;
146 : if (arena != NULL) {
147 : arena->Own(value);
148 : }
149 : } else {
150 : ptr_ = const_cast< ::std::string* >(default_value);
151 : }
152 : }
153 :
154 : // Takes a string that has lifetime equal to the arena's lifetime. The arena
155 : // must be non-null. It is safe only to pass this method a value returned by
156 : // UnsafeArenaRelease() on another field of a message in the same arena. Used
157 : // to implement unsafe_arena_set_allocated_<field> in generated classes.
158 : inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
159 : ::std::string* value,
160 : ::google::protobuf::Arena* /* arena */) {
161 : if (value != NULL) {
162 : ptr_ = value;
163 : } else {
164 : ptr_ = const_cast< ::std::string* >(default_value);
165 : }
166 : }
167 :
168 : // Swaps internal pointers. Arena-safety semantics: this is guarded by the
169 : // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
170 : // 'unsafe' if called directly.
171 : GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
172 : std::swap(ptr_, other->ptr_);
173 : }
174 : GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(
175 : ArenaStringPtr* other, const ::std::string* default_value, Arena* arena) {
176 : #ifndef NDEBUG
177 : // For debug builds, we swap the contents of the string, rather than the
178 : // string instances themselves. This invalidates previously taken const
179 : // references that are (per our documentation) invalidated by calling Swap()
180 : // on the message.
181 : //
182 : // If both strings are the default_value, swapping is uninteresting.
183 : // Otherwise, we use ArenaStringPtr::Mutable() to access the string, to
184 : // ensure that we do not try to mutate default_value itself.
185 0 : if (IsDefault(default_value) && other->IsDefault(default_value)) {
186 0 : return;
187 : }
188 :
189 0 : ::std::string* this_ptr = Mutable(default_value, arena);
190 0 : ::std::string* other_ptr = other->Mutable(default_value, arena);
191 :
192 0 : this_ptr->swap(*other_ptr);
193 : #else
194 : std::swap(ptr_, other->ptr_);
195 : #endif
196 : }
197 :
198 : // Frees storage (if not on an arena).
199 : inline void Destroy(const ::std::string* default_value,
200 : ::google::protobuf::Arena* arena) {
201 : if (arena == NULL && ptr_ != default_value) {
202 : delete ptr_;
203 : }
204 : }
205 :
206 : // Clears content, but keeps allocated string if arena != NULL, to avoid the
207 : // overhead of heap operations. After this returns, the content (as seen by
208 : // the user) will always be the empty string. Assumes that |default_value|
209 : // is an empty string.
210 : inline void ClearToEmpty(const ::std::string* default_value,
211 : ::google::protobuf::Arena* /* arena */) {
212 : if (ptr_ == default_value) {
213 : // Already set to default (which is empty) -- do nothing.
214 : } else {
215 : ptr_->clear();
216 : }
217 : }
218 :
219 : // Clears content, assuming that the current value is not the empty string
220 : // default.
221 : inline void ClearNonDefaultToEmpty() {
222 : ptr_->clear();
223 : }
224 : inline void ClearNonDefaultToEmptyNoArena() {
225 : ptr_->clear();
226 : }
227 :
228 : // Clears content, but keeps allocated string if arena != NULL, to avoid the
229 : // overhead of heap operations. After this returns, the content (as seen by
230 : // the user) will always be equal to |default_value|.
231 : inline void ClearToDefault(const ::std::string* default_value,
232 : ::google::protobuf::Arena* /* arena */) {
233 : if (ptr_ == default_value) {
234 : // Already set to default -- do nothing.
235 : } else {
236 : // Have another allocated string -- rather than throwing this away and
237 : // resetting ptr_ to the canonical default string instance, we just reuse
238 : // this instance.
239 : *ptr_ = *default_value;
240 : }
241 : }
242 :
243 : // Called from generated code / reflection runtime only. Resets value to point
244 : // to a default string pointer, with the semantics that this ArenaStringPtr
245 : // does not own the pointed-to memory. Disregards initial value of ptr_ (so
246 : // this is the *ONLY* safe method to call after construction or when
247 : // reinitializing after becoming the active field in a oneof union).
248 392 : inline void UnsafeSetDefault(const ::std::string* default_value) {
249 : // Casting away 'const' is safe here: accessors ensure that ptr_ is only
250 : // returned as a const if it is equal to default_value.
251 392 : ptr_ = const_cast< ::std::string* >(default_value);
252 392 : }
253 :
254 : // The 'NoArena' variants of methods below assume arena == NULL and are
255 : // optimized to provide very little overhead relative to a raw string pointer
256 : // (while still being in-memory compatible with other code that assumes
257 : // ArenaStringPtr). Note the invariant that a class instance that has only
258 : // ever been mutated by NoArena methods must *only* be in the String state
259 : // (i.e., tag bits are not used), *NEVER* ArenaString. This allows all
260 : // tagged-pointer manipulations to be avoided.
261 0 : inline void SetNoArena(const ::std::string* default_value,
262 : const ::std::string& value) {
263 0 : if (ptr_ == default_value) {
264 0 : CreateInstanceNoArena(&value);
265 : } else {
266 0 : *ptr_ = value;
267 : }
268 0 : }
269 :
270 : #if LANG_CXX11
271 0 : void SetNoArena(const ::std::string* default_value, ::std::string&& value) {
272 0 : if (IsDefault(default_value)) {
273 0 : ptr_ = new ::std::string(std::move(value));
274 : } else {
275 0 : *ptr_ = std::move(value);
276 : }
277 0 : }
278 : #endif
279 :
280 : void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
281 :
282 0 : inline const ::std::string& GetNoArena() const { return *ptr_; }
283 :
284 0 : inline ::std::string* MutableNoArena(const ::std::string* default_value) {
285 0 : if (ptr_ == default_value) {
286 0 : CreateInstanceNoArena(default_value);
287 : }
288 0 : return ptr_;
289 : }
290 :
291 : inline ::std::string* ReleaseNoArena(const ::std::string* default_value) {
292 : if (ptr_ == default_value) {
293 : return NULL;
294 : } else {
295 : return ReleaseNonDefaultNoArena(default_value);
296 : }
297 : }
298 :
299 : inline ::std::string* ReleaseNonDefaultNoArena(
300 : const ::std::string* default_value) {
301 : GOOGLE_DCHECK(!IsDefault(default_value));
302 : ::std::string* released = ptr_;
303 : ptr_ = const_cast< ::std::string* >(default_value);
304 : return released;
305 : }
306 :
307 :
308 : inline void SetAllocatedNoArena(const ::std::string* default_value,
309 : ::std::string* value) {
310 : if (ptr_ != default_value) {
311 : delete ptr_;
312 : }
313 : if (value != NULL) {
314 : ptr_ = value;
315 : } else {
316 : ptr_ = const_cast< ::std::string* >(default_value);
317 : }
318 : }
319 :
320 0 : inline void DestroyNoArena(const ::std::string* default_value) {
321 0 : if (ptr_ != default_value) {
322 0 : delete ptr_;
323 : }
324 0 : }
325 :
326 0 : inline void ClearToEmptyNoArena(const ::std::string* default_value) {
327 0 : if (ptr_ == default_value) {
328 : // Nothing: already equal to default (which is the empty string).
329 : } else {
330 0 : ptr_->clear();
331 : }
332 0 : }
333 :
334 : inline void ClearToDefaultNoArena(const ::std::string* default_value) {
335 : if (ptr_ == default_value) {
336 : // Nothing: already set to default.
337 : } else {
338 : // Reuse existing allocated instance.
339 : *ptr_ = *default_value;
340 : }
341 : }
342 :
343 : // Internal accessor used only at parse time to provide direct access to the
344 : // raw pointer from the shared parse routine (in the non-arenas case). The
345 : // parse routine does the string allocation in order to save code size in the
346 : // generated parsing code.
347 0 : inline ::std::string** UnsafeRawStringPointer() {
348 0 : return &ptr_;
349 : }
350 :
351 0 : inline bool IsDefault(const ::std::string* default_value) const {
352 0 : return ptr_ == default_value;
353 : }
354 :
355 : // Internal accessors!!!!
356 : void UnsafeSetTaggedPointer(TaggedPtr< ::std::string> value) {
357 : ptr_ = value.Get();
358 : }
359 : // Generated code only! An optimization, in certain cases the generated
360 : // code is certain we can obtain a string with no default checks and
361 : // tag tests.
362 : ::std::string* UnsafeMutablePointer() { return ptr_; }
363 :
364 : private:
365 : ::std::string* ptr_;
366 :
367 : GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
368 7088 : void CreateInstance(::google::protobuf::Arena* arena,
369 : const ::std::string* initial_value) {
370 7088 : GOOGLE_DCHECK(initial_value != NULL);
371 : // uses "new ::std::string" when arena is nullptr
372 7088 : ptr_ = Arena::Create< ::std::string >(arena, *initial_value);
373 7088 : }
374 : GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
375 0 : void CreateInstanceNoArena(const ::std::string* initial_value) {
376 0 : GOOGLE_DCHECK(initial_value != NULL);
377 0 : ptr_ = new ::std::string(*initial_value);
378 0 : }
379 : };
380 :
381 : } // namespace internal
382 : } // namespace protobuf
383 :
384 :
385 :
386 : namespace protobuf {
387 : namespace internal {
388 :
389 0 : inline void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value,
390 : ArenaStringPtr value) {
391 0 : const ::std::string* me = *UnsafeRawStringPointer();
392 0 : const ::std::string* other = *value.UnsafeRawStringPointer();
393 : // If the pointers are the same then do nothing.
394 0 : if (me != other) {
395 0 : SetNoArena(default_value, value.GetNoArena());
396 : }
397 0 : }
398 :
399 : } // namespace internal
400 : } // namespace protobuf
401 :
402 : } // namespace google
403 : #endif // GOOGLE_PROTOBUF_ARENASTRING_H__
|