LCOV - code coverage report
Current view: top level - usr/include/google/protobuf - metadata_lite.h (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 1 36 2.8 %
Date: 2024-12-11 20:54:31 Functions: 1 5 20.0 %

          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_METADATA_LITE_H__
      32             : #define GOOGLE_PROTOBUF_METADATA_LITE_H__
      33             : 
      34             : #include <google/protobuf/stubs/common.h>
      35             : #include <google/protobuf/arena.h>
      36             : #include <google/protobuf/message_lite.h>
      37             : #include <google/protobuf/stubs/port.h>
      38             : 
      39             : namespace google {
      40             : namespace protobuf {
      41             : namespace internal {
      42             : 
      43             : // This is the representation for messages that support arena allocation. It
      44             : // uses a tagged pointer to either store the Arena pointer, if there are no
      45             : // unknown fields, or a pointer to a block of memory with both the Arena pointer
      46             : // and the UnknownFieldSet, if there are unknown fields. This optimization
      47             : // allows for "zero-overhead" storage of the Arena pointer, relative to the
      48             : // above baseline implementation.
      49             : //
      50             : // The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
      51             : // indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
      52             : // pointer.
      53             : template <class T, class Derived>
      54             : class InternalMetadataWithArenaBase {
      55             :  public:
      56             :   InternalMetadataWithArenaBase() : ptr_(NULL) {}
      57         462 :   explicit InternalMetadataWithArenaBase(Arena* arena) : ptr_(arena) {}
      58             : 
      59           0 :   ~InternalMetadataWithArenaBase() {
      60           0 :     if (have_unknown_fields() && arena() == NULL) {
      61           0 :       delete PtrValue<Container>();
      62             :     }
      63           0 :     ptr_ = NULL;
      64           0 :   }
      65             : 
      66             :   GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE const T& unknown_fields() const {
      67           0 :     if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
      68           0 :       return PtrValue<Container>()->unknown_fields;
      69             :     } else {
      70           0 :       return Derived::default_instance();
      71             :     }
      72             :   }
      73             : 
      74             :   GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* mutable_unknown_fields() {
      75           0 :     if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) {
      76           0 :       return &PtrValue<Container>()->unknown_fields;
      77             :     } else {
      78           0 :       return mutable_unknown_fields_slow();
      79             :     }
      80             :   }
      81             : 
      82             :   GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const {
      83           0 :     if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
      84           0 :       return PtrValue<Container>()->arena;
      85             :     } else {
      86           0 :       return PtrValue<Arena>();
      87             :     }
      88             :   }
      89             : 
      90             :   GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const {
      91           0 :     return PtrTag() == kTagContainer;
      92             :   }
      93             : 
      94             :   GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(Derived* other) {
      95             :     // Semantics here are that we swap only the unknown fields, not the arena
      96             :     // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
      97             :     // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
      98             :     // different states (direct arena pointer vs. container with UFS) so we
      99             :     // cannot simply swap ptr_ and then restore the arena pointers. We reuse
     100             :     // UFS's swap implementation instead.
     101           0 :     if (have_unknown_fields() || other->have_unknown_fields()) {
     102           0 :       static_cast<Derived*>(this)->DoSwap(other->mutable_unknown_fields());
     103             :     }
     104           0 :   }
     105             : 
     106             :   GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void MergeFrom(const Derived& other) {
     107           0 :     if (other.have_unknown_fields()) {
     108           0 :       static_cast<Derived*>(this)->DoMergeFrom(other.unknown_fields());
     109             :     }
     110           0 :   }
     111             : 
     112             :   GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Clear() {
     113           0 :     if (have_unknown_fields()) {
     114           0 :       static_cast<Derived*>(this)->DoClear();
     115             :     }
     116           0 :   }
     117             : 
     118             :   GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const {
     119             :     return ptr_;
     120             :   }
     121             : 
     122             :  private:
     123             :   void* ptr_;
     124             : 
     125             :   // Tagged pointer implementation.
     126             :   enum {
     127             :     // ptr_ is an Arena*.
     128             :     kTagArena = 0,
     129             :     // ptr_ is a Container*.
     130             :     kTagContainer = 1,
     131             :   };
     132             :   static const intptr_t kPtrTagMask = 1;
     133             :   static const intptr_t kPtrValueMask = ~kPtrTagMask;
     134             : 
     135             :   // Accessors for pointer tag and pointer value.
     136             :   GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const {
     137           0 :     return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask;
     138             :   }
     139             : 
     140           0 :   template<typename U> U* PtrValue() const {
     141             :     return reinterpret_cast<U*>(
     142           0 :         reinterpret_cast<intptr_t>(ptr_) & kPtrValueMask);
     143             :   }
     144             : 
     145             :   // If ptr_'s tag is kTagContainer, it points to an instance of this struct.
     146             :   struct Container {
     147             :     T unknown_fields;
     148             :     Arena* arena;
     149             :   };
     150             : 
     151           0 :   GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE T* mutable_unknown_fields_slow() {
     152           0 :     Arena* my_arena = arena();
     153           0 :     Container* container = Arena::Create<Container>(my_arena);
     154             :     // Two-step assignment works around a bug in clang's static analyzer:
     155             :     // https://bugs.llvm.org/show_bug.cgi?id=34198.
     156           0 :     ptr_ = container;
     157           0 :     ptr_ = reinterpret_cast<void*>(
     158           0 :         reinterpret_cast<intptr_t>(ptr_) | kTagContainer);
     159           0 :     container->arena = my_arena;
     160           0 :     return &(container->unknown_fields);
     161             :   }
     162             : };
     163             : 
     164             : // We store unknown fields as a string right now, because there is currently no
     165             : // good interface for reading unknown fields into an ArenaString.  We may want
     166             : // to revisit this to allow unknown fields to be parsed onto the Arena.
     167             : class InternalMetadataWithArenaLite
     168             :     : public InternalMetadataWithArenaBase<string,
     169             :                                            InternalMetadataWithArenaLite> {
     170             :  public:
     171             :   InternalMetadataWithArenaLite() {}
     172             : 
     173             :   explicit InternalMetadataWithArenaLite(Arena* arena)
     174             :       : InternalMetadataWithArenaBase<string,
     175             :                                       InternalMetadataWithArenaLite>(arena) {}
     176             : 
     177             :   void DoSwap(string* other) {
     178             :     mutable_unknown_fields()->swap(*other);
     179             :   }
     180             : 
     181             :   void DoMergeFrom(const string& other) {
     182             :     mutable_unknown_fields()->append(other);
     183             :   }
     184             : 
     185             :   void DoClear() {
     186             :     mutable_unknown_fields()->clear();
     187             :   }
     188             : 
     189             :   static const string& default_instance() {
     190             :     return GetEmptyStringAlreadyInited();
     191             :   }
     192             : };
     193             : 
     194             : // This helper RAII class is needed to efficiently parse unknown fields. We
     195             : // should only call mutable_unknown_fields if there are actual unknown fields.
     196             : // The obvious thing to just use a stack string and swap it at the end of the
     197             : // parse won't work, because the destructor of StringOutputStream needs to be
     198             : // called before we can modify the string (it check-fails). Using
     199             : // LiteUnknownFieldSetter setter(&_internal_metadata_);
     200             : // StringOutputStream stream(setter.buffer());
     201             : // guarantees that the string is only swapped after stream is destroyed.
     202             : class LIBPROTOBUF_EXPORT LiteUnknownFieldSetter {
     203             :  public:
     204             :   explicit LiteUnknownFieldSetter(InternalMetadataWithArenaLite* metadata)
     205             :       : metadata_(metadata) {
     206             :     if (metadata->have_unknown_fields()) {
     207             :       buffer_.swap(*metadata->mutable_unknown_fields());
     208             :     }
     209             :   }
     210             :   ~LiteUnknownFieldSetter() {
     211             :     if (!buffer_.empty()) metadata_->mutable_unknown_fields()->swap(buffer_);
     212             :   }
     213             :   string* buffer() { return &buffer_; }
     214             : 
     215             :  private:
     216             :   InternalMetadataWithArenaLite* metadata_;
     217             :   string buffer_;
     218             : };
     219             : 
     220             : }  // namespace internal
     221             : }  // namespace protobuf
     222             : 
     223             : }  // namespace google
     224             : #endif  // GOOGLE_PROTOBUF_METADATA_LITE_H__

Generated by: LCOV version 1.16