• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <google/protobuf/arena.h>
40 #include <google/protobuf/generated_message_util.h>
41 
42 
43 
44 // This is the implementation of arena string fields written for the open-source
45 // release. The ArenaStringPtr struct below is an internal implementation class
46 // and *should not be used* by user code. It is used to collect string
47 // operations together into one place and abstract away the underlying
48 // string-field pointer representation, so that (for example) an alternate
49 // implementation that knew more about ::std::string's internals could integrate more
50 // closely with the arena allocator.
51 
52 namespace google {
53 namespace protobuf {
54 namespace internal {
55 
56 struct LIBPROTOBUF_EXPORT ArenaStringPtr {
SetArenaStringPtr57   inline void Set(const ::std::string* default_value,
58                   const ::std::string& value, ::google::protobuf::Arena* arena) {
59     if (ptr_ == default_value) {
60       CreateInstance(arena, &value);
61     } else {
62       *ptr_ = value;
63     }
64   }
65 
66   // Basic accessors.
GetArenaStringPtr67   inline const ::std::string& Get(const ::std::string* /* default_value */) const {
68     return *ptr_;
69   }
70 
MutableArenaStringPtr71   inline ::std::string* Mutable(const ::std::string* default_value,
72                            ::google::protobuf::Arena* arena) {
73     if (ptr_ == default_value) {
74       CreateInstance(arena, default_value);
75     }
76     return ptr_;
77   }
78 
79   // Release returns a ::std::string* instance that is heap-allocated and is not
80   // Own()'d by any arena. If the field was not set, it returns NULL. The caller
81   // retains ownership. Clears this field back to NULL state. Used to implement
82   // release_<field>() methods on generated classes.
ReleaseArenaStringPtr83   inline ::std::string* Release(const ::std::string* default_value,
84                            ::google::protobuf::Arena* arena) {
85     if (ptr_ == default_value) {
86       return NULL;
87     }
88     ::std::string* released = NULL;
89     if (arena != NULL) {
90       // ptr_ is owned by the arena -- we need to return a copy.
91       released = new ::std::string(*ptr_);
92     } else {
93       released = ptr_;
94     }
95     ptr_ = const_cast< ::std::string* >(default_value);
96     return released;
97   }
98 
99   // UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned (i.e.
100   // have its destructor already registered) if arena != NULL. If the field was
101   // not set, this returns NULL. This method clears this field back to NULL
102   // state. Used to implement unsafe_arena_release_<field>() methods on
103   // generated classes.
UnsafeArenaReleaseArenaStringPtr104   inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
105                                       ::google::protobuf::Arena* /* arena */) {
106     if (ptr_ == default_value) {
107       return NULL;
108     }
109     ::std::string* released = ptr_;
110     ptr_ = const_cast< ::std::string* >(default_value);
111     return released;
112   }
113 
114   // Takes a string that is heap-allocated, and takes ownership. The string's
115   // destructor is registered with the arena. Used to implement
116   // set_allocated_<field> in generated classes.
SetAllocatedArenaStringPtr117   inline void SetAllocated(const ::std::string* default_value,
118                            ::std::string* value, ::google::protobuf::Arena* arena) {
119     if (arena == NULL && ptr_ != default_value) {
120       Destroy(default_value, arena);
121     }
122     if (value != NULL) {
123       ptr_ = value;
124       if (arena != NULL) {
125         arena->Own(value);
126       }
127     } else {
128       ptr_ = const_cast< ::std::string* >(default_value);
129     }
130   }
131 
132   // Takes a string that has lifetime equal to the arena's lifetime. The arena
133   // must be non-null. It is safe only to pass this method a value returned by
134   // UnsafeArenaRelease() on another field of a message in the same arena. Used
135   // to implement unsafe_arena_set_allocated_<field> in generated classes.
UnsafeArenaSetAllocatedArenaStringPtr136   inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
137                                       ::std::string* value,
138                                       ::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.
SwapArenaStringPtr149   GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
150     std::swap(ptr_, other->ptr_);
151   }
152 
153   // Frees storage (if not on an arena) and sets field to default value.
DestroyArenaStringPtr154   inline void Destroy(const ::std::string* default_value,
155                       ::google::protobuf::Arena* arena) {
156     if (arena == NULL && ptr_ != default_value) {
157       delete ptr_;
158     }
159     ptr_ = const_cast< ::std::string* >(default_value);
160   }
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.
ClearToEmptyArenaStringPtr166   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|.
ClearToDefaultArenaStringPtr178   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).
UnsafeSetDefaultArenaStringPtr195   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     ptr_ = const_cast< ::std::string* >(default_value);
199   }
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.
SetNoArenaArenaStringPtr208   inline void SetNoArena(const ::std::string* default_value,
209                          const ::std::string& value) {
210     if (ptr_ == default_value) {
211       CreateInstanceNoArena(&value);
212     } else {
213       *ptr_ = value;
214     }
215   }
216 
217   void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
218 
GetNoArenaArenaStringPtr219   inline const ::std::string& GetNoArena(const ::std::string* /* default_value */) const {
220     return *ptr_;
221   }
222 
MutableNoArenaArenaStringPtr223   inline ::std::string* MutableNoArena(const ::std::string* default_value) {
224     if (ptr_ == default_value) {
225       CreateInstanceNoArena(default_value);
226     }
227     return ptr_;
228   }
229 
ReleaseNoArenaArenaStringPtr230   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 
SetAllocatedNoArenaArenaStringPtr240   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 
DestroyNoArenaArenaStringPtr252   inline void DestroyNoArena(const ::std::string* default_value) {
253     if (ptr_ != default_value) {
254       delete ptr_;
255     }
256     ptr_ = NULL;
257   }
258 
ClearToEmptyNoArenaArenaStringPtr259   inline void ClearToEmptyNoArena(const ::std::string* default_value) {
260     if (ptr_ == default_value) {
261       // Nothing: already equal to default (which is the empty string).
262     } else {
263       ptr_->clear();
264     }
265   }
266 
ClearToDefaultNoArenaArenaStringPtr267   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.
UnsafeRawStringPointerArenaStringPtr280   inline ::std::string** UnsafeRawStringPointer() {
281     return &ptr_;
282   }
283 
284  private:
285   ::std::string* ptr_;
286 
CreateInstanceArenaStringPtr287   GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena,
288                                          const ::std::string* initial_value) {
289     // Assumes ptr_ is not NULL.
290     if (initial_value != NULL) {
291       ptr_ = new ::std::string(*initial_value);
292     } else {
293       ptr_ = new ::std::string();
294     }
295     if (arena != NULL) {
296       arena->Own(ptr_);
297     }
298   }
CreateInstanceNoArenaArenaStringPtr299   GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* initial_value) {
300     if (initial_value != NULL) {
301       ptr_ = new ::std::string(*initial_value);
302     } else {
303       ptr_ = new ::std::string();
304     }
305   }
306 };
307 
308 }  // namespace internal
309 }  // namespace protobuf
310 
311 
312 
313 }  // namespace google
314 #endif  // GOOGLE_PROTOBUF_ARENASTRING_H__
315