// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // // This file contains miscellaneous helper code used by generated code -- // including lite types -- but which should not be used directly by users. #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ #include #include #include #include #include #include #include #include #include #include #include // Add direct dep on port for pb.cc #include #include #include #include #include #include #ifdef SWIG #error "You cannot SWIG proto headers" #endif namespace google { namespace protobuf { class Arena; class Message; namespace io { class CodedInputStream; } namespace internal { template inline To DownCast(From* f) { return PROTOBUF_NAMESPACE_ID::internal::down_cast(f); } template inline To DownCast(From& f) { return PROTOBUF_NAMESPACE_ID::internal::down_cast(f); } // This fastpath inlines a single branch instead of having to make the // InitProtobufDefaults function call. // It also generates less inlined code than a function-scope static initializer. PROTOBUF_EXPORT extern std::atomic init_protobuf_defaults_state; PROTOBUF_EXPORT void InitProtobufDefaultsSlow(); PROTOBUF_EXPORT inline void InitProtobufDefaults() { if (PROTOBUF_PREDICT_FALSE( !init_protobuf_defaults_state.load(std::memory_order_acquire))) { InitProtobufDefaultsSlow(); } } // This used by proto1 PROTOBUF_EXPORT inline const std::string& GetEmptyString() { InitProtobufDefaults(); return GetEmptyStringAlreadyInited(); } // True if IsInitialized() is true for all elements of t. Type is expected // to be a RepeatedPtrField. It's useful to have this // helper here to keep the protobuf compiler from ever having to emit loops in // IsInitialized() methods. We want the C++ compiler to inline this or not // as it sees fit. template bool AllAreInitialized(const RepeatedPtrField& t) { for (int i = t.size(); --i >= 0;) { if (!t.Get(i).IsInitialized()) return false; } return true; } // "Weak" variant of AllAreInitialized, used to implement implicit weak fields. // This version operates on MessageLite to avoid introducing a dependency on the // concrete message type. template bool AllAreInitializedWeak(const RepeatedPtrField& t) { for (int i = t.size(); --i >= 0;) { if (!reinterpret_cast(t) .Get >(i) .IsInitialized()) { return false; } } return true; } inline bool IsPresent(const void* base, uint32 hasbit) { const uint32* has_bits_array = static_cast(base); return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0; } inline bool IsOneofPresent(const void* base, uint32 offset, uint32 tag) { const uint32* oneof = reinterpret_cast(static_cast(base) + offset); return *oneof == tag >> 3; } typedef void (*SpecialSerializer)(const uint8* base, uint32 offset, uint32 tag, uint32 has_offset, io::CodedOutputStream* output); PROTOBUF_EXPORT void ExtensionSerializer(const uint8* base, uint32 offset, uint32 tag, uint32 has_offset, io::CodedOutputStream* output); PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8* base, uint32 offset, uint32 tag, uint32 has_offset, io::CodedOutputStream* output); PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message); PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena, MessageLite* submessage, Arena* submessage_arena); PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2); // We specialize GenericSwap for non-lite messages to benefit from reflection. PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2); template T* DuplicateIfNonNull(T* message) { // The casts must be reinterpret_cast<> because T might be a forward-declared // type that the compiler doesn't know is related to MessageLite. return reinterpret_cast( DuplicateIfNonNullInternal(reinterpret_cast(message))); } template T* GetOwnedMessage(Arena* message_arena, T* submessage, Arena* submessage_arena) { // The casts must be reinterpret_cast<> because T might be a forward-declared // type that the compiler doesn't know is related to MessageLite. return reinterpret_cast(GetOwnedMessageInternal( message_arena, reinterpret_cast(submessage), submessage_arena)); } // Hide atomic from the public header and allow easy change to regular int // on platforms where the atomic might have a perf impact. class PROTOBUF_EXPORT CachedSize { public: int Get() const { return size_.load(std::memory_order_relaxed); } void Set(int size) { size_.store(size, std::memory_order_relaxed); } private: std::atomic size_{0}; }; // SCCInfo represents information of a strongly connected component of // mutual dependent messages. struct PROTOBUF_EXPORT SCCInfoBase { // We use 0 for the Initialized state, because test eax,eax, jnz is smaller // and is subject to macro fusion. enum { kInitialized = 0, // final state kRunning = 1, kUninitialized = -1, // initial state }; #if defined(_MSC_VER) && !defined(__clang__) // MSVC doesn't make std::atomic constant initialized. This union trick // makes it so. union { int visit_status_to_make_linker_init; std::atomic visit_status; }; #else std::atomic visit_status; #endif int num_deps; int num_implicit_weak_deps; void (*init_func)(); // This is followed by an array of num_deps // const SCCInfoBase* deps[]; }; // Zero-length arrays are a language extension available in GCC and Clang but // not MSVC. #ifdef __GNUC__ #define PROTOBUF_ARRAY_SIZE(n) (n) #else #define PROTOBUF_ARRAY_SIZE(n) ((n) ? (n) : 1) #endif template struct SCCInfo { SCCInfoBase base; // Semantically this is const SCCInfo* which is is a templated type. // The obvious inheriting from SCCInfoBase mucks with struct initialization. // Attempts showed the compiler was generating dynamic initialization code. // This deps array consists of base.num_deps pointers to SCCInfoBase followed // by base.num_implicit_weak_deps pointers to SCCInfoBase*. We need the extra // pointer indirection for implicit weak fields. We cannot use a union type // here, since that would prevent the array from being linker-initialized. void* deps[PROTOBUF_ARRAY_SIZE(N)]; }; #undef PROTOBUF_ARRAY_SIZE PROTOBUF_EXPORT void InitSCCImpl(SCCInfoBase* scc); inline void InitSCC(SCCInfoBase* scc) { auto status = scc->visit_status.load(std::memory_order_acquire); if (PROTOBUF_PREDICT_FALSE(status != SCCInfoBase::kInitialized)) InitSCCImpl(scc); } PROTOBUF_EXPORT void DestroyMessage(const void* message); PROTOBUF_EXPORT void DestroyString(const void* s); // Destroy (not delete) the message inline void OnShutdownDestroyMessage(const void* ptr) { OnShutdownRun(DestroyMessage, ptr); } // Destroy the string (call std::string destructor) inline void OnShutdownDestroyString(const std::string* ptr) { OnShutdownRun(DestroyString, ptr); } } // namespace internal } // namespace protobuf } // namespace google #include #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__