OLD | NEW |
(Empty) | |
| 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 { |
| 57 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. |
| 67 inline const ::std::string& Get(const ::std::string* default_value) const { |
| 68 return *ptr_; |
| 69 } |
| 70 |
| 71 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. |
| 83 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. |
| 104 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. |
| 117 inline void SetAllocated(const ::std::string* default_value, |
| 118 ::std::string* value, ::google::protobuf::Arena* aren
a) { |
| 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. |
| 136 inline void UnsafeArenaSetAllocated(const ::std::string* default_value, |
| 137 ::std::string* value, ::google::protobuf::
Arena* arena) { |
| 138 if (value != NULL) { |
| 139 ptr_ = value; |
| 140 } else { |
| 141 ptr_ = const_cast< ::std::string* >(default_value); |
| 142 } |
| 143 } |
| 144 |
| 145 // Swaps internal pointers. Arena-safety semantics: this is guarded by the |
| 146 // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is |
| 147 // 'unsafe' if called directly. |
| 148 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) { |
| 149 std::swap(ptr_, other->ptr_); |
| 150 } |
| 151 |
| 152 // Frees storage (if not on an arena) and sets field to default value. |
| 153 inline void Destroy(const ::std::string* default_value, |
| 154 ::google::protobuf::Arena* arena) { |
| 155 if (arena == NULL && ptr_ != default_value) { |
| 156 delete ptr_; |
| 157 } |
| 158 ptr_ = const_cast< ::std::string* >(default_value); |
| 159 } |
| 160 |
| 161 // Clears content, but keeps allocated string if arena != NULL, to avoid the |
| 162 // overhead of heap operations. After this returns, the content (as seen by |
| 163 // the user) will always be the empty string. Assumes that |default_value| |
| 164 // is an empty string. |
| 165 inline void ClearToEmpty(const ::std::string* default_value, |
| 166 ::google::protobuf::Arena* arena) { |
| 167 if (ptr_ == default_value) { |
| 168 // Already set to default (which is empty) -- do nothing. |
| 169 } else { |
| 170 ptr_->clear(); |
| 171 } |
| 172 } |
| 173 |
| 174 // Clears content, but keeps allocated string if arena != NULL, to avoid the |
| 175 // overhead of heap operations. After this returns, the content (as seen by |
| 176 // the user) will always be equal to |default_value|. |
| 177 inline void ClearToDefault(const ::std::string* default_value, |
| 178 ::google::protobuf::Arena* arena) { |
| 179 if (ptr_ == default_value) { |
| 180 // Already set to default -- do nothing. |
| 181 } else { |
| 182 // Have another allocated string -- rather than throwing this away and |
| 183 // resetting ptr_ to the canonical default string instance, we just reuse |
| 184 // this instance. |
| 185 *ptr_ = *default_value; |
| 186 } |
| 187 } |
| 188 |
| 189 // Called from generated code / reflection runtime only. Resets value to point |
| 190 // to a default string pointer, with the semantics that this ArenaStringPtr |
| 191 // does not own the pointed-to memory. Disregards initial value of ptr_ (so |
| 192 // this is the *ONLY* safe method to call after construction or when |
| 193 // reinitializing after becoming the active field in a oneof union). |
| 194 inline void UnsafeSetDefault(const ::std::string* default_value) { |
| 195 // Casting away 'const' is safe here: accessors ensure that ptr_ is only |
| 196 // returned as a const if it is equal to default_value. |
| 197 ptr_ = const_cast< ::std::string* >(default_value); |
| 198 } |
| 199 |
| 200 // The 'NoArena' variants of methods below assume arena == NULL and are |
| 201 // optimized to provide very little overhead relative to a raw string pointer |
| 202 // (while still being in-memory compatible with other code that assumes |
| 203 // ArenaStringPtr). Note the invariant that a class instance that has only |
| 204 // ever been mutated by NoArena methods must *only* be in the String state |
| 205 // (i.e., tag bits are not used), *NEVER* ArenaString. This allows all |
| 206 // tagged-pointer manipulations to be avoided. |
| 207 inline void SetNoArena(const ::std::string* default_value, |
| 208 const ::std::string& value) { |
| 209 if (ptr_ == default_value) { |
| 210 CreateInstanceNoArena(&value); |
| 211 } else { |
| 212 *ptr_ = value; |
| 213 } |
| 214 } |
| 215 |
| 216 void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr valu
e); |
| 217 |
| 218 inline const ::std::string& GetNoArena(const ::std::string* default_value) con
st { |
| 219 return *ptr_; |
| 220 } |
| 221 |
| 222 ::std::string* MutableNoArena(const ::std::string* default_value); |
| 223 |
| 224 inline ::std::string* ReleaseNoArena(const ::std::string* default_value) { |
| 225 if (ptr_ == default_value) { |
| 226 return NULL; |
| 227 } else { |
| 228 ::std::string* released = ptr_; |
| 229 ptr_ = const_cast< ::std::string* >(default_value); |
| 230 return released; |
| 231 } |
| 232 } |
| 233 |
| 234 inline void SetAllocatedNoArena(const ::std::string* default_value, |
| 235 ::std::string* value) { |
| 236 if (ptr_ != default_value) { |
| 237 delete ptr_; |
| 238 } |
| 239 if (value != NULL) { |
| 240 ptr_ = value; |
| 241 } else { |
| 242 ptr_ = const_cast< ::std::string* >(default_value); |
| 243 } |
| 244 } |
| 245 |
| 246 void DestroyNoArena(const ::std::string* default_value); |
| 247 |
| 248 inline void ClearToEmptyNoArena(const ::std::string* default_value) { |
| 249 if (ptr_ == default_value) { |
| 250 // Nothing: already equal to default (which is the empty string). |
| 251 } else { |
| 252 ptr_->clear(); |
| 253 } |
| 254 } |
| 255 |
| 256 inline void ClearToDefaultNoArena(const ::std::string* default_value) { |
| 257 if (ptr_ == default_value) { |
| 258 // Nothing: already set to default. |
| 259 } else { |
| 260 // Reuse existing allocated instance. |
| 261 *ptr_ = *default_value; |
| 262 } |
| 263 } |
| 264 |
| 265 // Internal accessor used only at parse time to provide direct access to the |
| 266 // raw pointer from the shared parse routine (in the non-arenas case). The |
| 267 // parse routine does the string allocation in order to save code size in the |
| 268 // generated parsing code. |
| 269 inline ::std::string** UnsafeRawStringPointer() { |
| 270 return &ptr_; |
| 271 } |
| 272 |
| 273 private: |
| 274 ::std::string* ptr_; |
| 275 |
| 276 GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena
, |
| 277 const ::std::string* initial_value) { |
| 278 // Assumes ptr_ is not NULL. |
| 279 if (initial_value != NULL) { |
| 280 ptr_ = new ::std::string(*initial_value); |
| 281 } else { |
| 282 ptr_ = new ::std::string(); |
| 283 } |
| 284 if (arena != NULL) { |
| 285 arena->Own(ptr_); |
| 286 } |
| 287 } |
| 288 GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* init
ial_value) { |
| 289 if (initial_value != NULL) { |
| 290 ptr_ = new ::std::string(*initial_value); |
| 291 } else { |
| 292 ptr_ = new ::std::string(); |
| 293 } |
| 294 } |
| 295 }; |
| 296 |
| 297 } // namespace internal |
| 298 } // namespace protobuf |
| 299 |
| 300 |
| 301 |
| 302 } // namespace google |
| 303 #endif // GOOGLE_PROTOBUF_ARENASTRING_H__ |
OLD | NEW |