诸暨麻将添加redis
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

236 lines
8.7 KiB

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