OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 22 matching lines...) Expand all Loading... |
33 // representation to be made more space-efficient via various optimizations. | 33 // representation to be made more space-efficient via various optimizations. |
34 // | 34 // |
35 // Note that this is distinct from google::protobuf::Metadata, which encapsulate
s | 35 // Note that this is distinct from google::protobuf::Metadata, which encapsulate
s |
36 // Descriptor and Reflection pointers. | 36 // Descriptor and Reflection pointers. |
37 | 37 |
38 #ifndef GOOGLE_PROTOBUF_METADATA_H__ | 38 #ifndef GOOGLE_PROTOBUF_METADATA_H__ |
39 #define GOOGLE_PROTOBUF_METADATA_H__ | 39 #define GOOGLE_PROTOBUF_METADATA_H__ |
40 | 40 |
41 #include <google/protobuf/stubs/common.h> | 41 #include <google/protobuf/stubs/common.h> |
42 #include <google/protobuf/arena.h> | 42 #include <google/protobuf/arena.h> |
| 43 #include <google/protobuf/arenastring.h> |
| 44 #include <google/protobuf/generated_message_util.h> |
43 #include <google/protobuf/unknown_field_set.h> | 45 #include <google/protobuf/unknown_field_set.h> |
44 | 46 |
45 namespace google { | 47 namespace google { |
46 namespace protobuf { | 48 namespace protobuf { |
47 namespace internal { | 49 namespace internal { |
48 | 50 |
49 // This is the representation for messages that support arena allocation. It | 51 // This is the representation for messages that support arena allocation. It |
50 // uses a tagged pointer to either store the Arena pointer, if there are no | 52 // uses a tagged pointer to either store the Arena pointer, if there are no |
51 // unknown fields, or a pointer to a block of memory with both the Arena pointer | 53 // unknown fields, or a pointer to a block of memory with both the Arena pointer |
52 // and the UnknownFieldSet, if there are unknown fields. This optimization | 54 // and the UnknownFieldSet, if there are unknown fields. This optimization |
53 // allows for "zero-overhead" storage of the Arena pointer, relative to the | 55 // allows for "zero-overhead" storage of the Arena pointer, relative to the |
54 // above baseline implementation. | 56 // above baseline implementation. |
55 // | 57 // |
56 // The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to | 58 // The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to |
57 // indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container | 59 // indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container |
58 // pointer. | 60 // pointer. |
59 class LIBPROTOBUF_EXPORT InternalMetadataWithArena { | 61 template <class T, class Derived> |
| 62 class InternalMetadataWithArenaBase { |
60 public: | 63 public: |
61 InternalMetadataWithArena() : ptr_(NULL) {} | 64 InternalMetadataWithArenaBase() : ptr_(NULL) {} |
62 explicit InternalMetadataWithArena(Arena* arena) | 65 explicit InternalMetadataWithArenaBase(Arena* arena) : ptr_(arena) {} |
63 : ptr_ (arena) {} | |
64 | 66 |
65 ~InternalMetadataWithArena() { | 67 ~InternalMetadataWithArenaBase() { |
66 if (have_unknown_fields() && arena() == NULL) { | 68 if (have_unknown_fields() && arena() == NULL) { |
67 delete PtrValue<Container>(); | 69 delete PtrValue<Container>(); |
68 } | 70 } |
69 ptr_ = NULL; | 71 ptr_ = NULL; |
70 } | 72 } |
71 | 73 |
72 GOOGLE_ATTRIBUTE_ALWAYS_INLINE const UnknownFieldSet& unknown_fields() const { | 74 GOOGLE_ATTRIBUTE_ALWAYS_INLINE const T& unknown_fields() const { |
73 if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { | 75 if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { |
74 return PtrValue<Container>()->unknown_fields_; | 76 return PtrValue<Container>()->unknown_fields; |
75 } else { | 77 } else { |
76 return *UnknownFieldSet::default_instance(); | 78 return Derived::default_instance(); |
77 } | 79 } |
78 } | 80 } |
79 | 81 |
80 GOOGLE_ATTRIBUTE_ALWAYS_INLINE UnknownFieldSet* mutable_unknown_fields() { | 82 GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* mutable_unknown_fields() { |
81 if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) { | 83 if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) { |
82 return &PtrValue<Container>()->unknown_fields_; | 84 return &PtrValue<Container>()->unknown_fields; |
83 } else { | 85 } else { |
84 return mutable_unknown_fields_slow(); | 86 return mutable_unknown_fields_slow(); |
85 } | 87 } |
86 } | 88 } |
87 | 89 |
88 GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const { | 90 GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const { |
89 if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { | 91 if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { |
90 return PtrValue<Container>()->arena_; | 92 return PtrValue<Container>()->arena; |
91 } else { | 93 } else { |
92 return PtrValue<Arena>(); | 94 return PtrValue<Arena>(); |
93 } | 95 } |
94 } | 96 } |
95 | 97 |
96 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const { | 98 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const { |
97 return PtrTag() == kTagContainer; | 99 return PtrTag() == kTagContainer; |
98 } | 100 } |
99 | 101 |
100 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(InternalMetadataWithArena* other) { | 102 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(Derived* other) { |
101 // Semantics here are that we swap only the unknown fields, not the arena | 103 // Semantics here are that we swap only the unknown fields, not the arena |
102 // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to | 104 // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to |
103 // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in | 105 // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in |
104 // different states (direct arena pointer vs. container with UFS) so we | 106 // different states (direct arena pointer vs. container with UFS) so we |
105 // cannot simply swap ptr_ and then restore the arena pointers. We reuse | 107 // cannot simply swap ptr_ and then restore the arena pointers. We reuse |
106 // UFS's swap implementation instead. | 108 // UFS's swap implementation instead. |
107 if (have_unknown_fields() || other->have_unknown_fields()) { | 109 if (have_unknown_fields() || other->have_unknown_fields()) { |
108 mutable_unknown_fields()->Swap(other->mutable_unknown_fields()); | 110 static_cast<Derived*>(this)->DoSwap(other->mutable_unknown_fields()); |
109 } | 111 } |
110 } | 112 } |
111 | 113 |
| 114 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void MergeFrom(const Derived& other) { |
| 115 if (other.have_unknown_fields()) { |
| 116 static_cast<Derived*>(this)->DoMergeFrom(other.unknown_fields()); |
| 117 } |
| 118 } |
| 119 |
| 120 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Clear() { |
| 121 if (have_unknown_fields()) { |
| 122 static_cast<Derived*>(this)->DoClear(); |
| 123 } |
| 124 } |
| 125 |
112 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const { | 126 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const { |
113 return ptr_; | 127 return ptr_; |
114 } | 128 } |
115 | 129 |
116 private: | 130 private: |
117 void* ptr_; | 131 void* ptr_; |
118 | 132 |
119 // Tagged pointer implementation. | 133 // Tagged pointer implementation. |
120 enum { | 134 enum { |
121 // ptr_ is an Arena*. | 135 // ptr_ is an Arena*. |
122 kTagArena = 0, | 136 kTagArena = 0, |
123 // ptr_ is a Container*. | 137 // ptr_ is a Container*. |
124 kTagContainer = 1, | 138 kTagContainer = 1, |
125 }; | 139 }; |
126 static const intptr_t kPtrTagMask = 1; | 140 static const intptr_t kPtrTagMask = 1; |
127 static const intptr_t kPtrValueMask = ~kPtrTagMask; | 141 static const intptr_t kPtrValueMask = ~kPtrTagMask; |
128 | 142 |
129 // Accessors for pointer tag and pointer value. | 143 // Accessors for pointer tag and pointer value. |
130 GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const { | 144 GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const { |
131 return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask; | 145 return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask; |
132 } | 146 } |
133 | 147 |
134 template<typename T> T* PtrValue() const { | 148 template<typename U> U* PtrValue() const { |
135 return reinterpret_cast<T*>( | 149 return reinterpret_cast<U*>( |
136 reinterpret_cast<intptr_t>(ptr_) & kPtrValueMask); | 150 reinterpret_cast<intptr_t>(ptr_) & kPtrValueMask); |
137 } | 151 } |
138 | 152 |
139 // If ptr_'s tag is kTagContainer, it points to an instance of this struct. | 153 // If ptr_'s tag is kTagContainer, it points to an instance of this struct. |
140 struct Container { | 154 struct Container { |
141 UnknownFieldSet unknown_fields_; | 155 T unknown_fields; |
142 Arena* arena_; | 156 Arena* arena; |
143 }; | 157 }; |
144 | 158 |
145 GOOGLE_ATTRIBUTE_NOINLINE UnknownFieldSet* mutable_unknown_fields_slow() { | 159 GOOGLE_ATTRIBUTE_NOINLINE T* mutable_unknown_fields_slow() { |
146 Arena* my_arena = arena(); | 160 Arena* my_arena = arena(); |
147 Container* container = Arena::Create<Container>(my_arena); | 161 Container* container = Arena::Create<Container>(my_arena); |
148 ptr_ = reinterpret_cast<void*>( | 162 ptr_ = reinterpret_cast<void*>( |
149 reinterpret_cast<intptr_t>(container) | kTagContainer); | 163 reinterpret_cast<intptr_t>(container) | kTagContainer); |
150 container->arena_ = my_arena; | 164 container->arena = my_arena; |
151 return &(container->unknown_fields_); | 165 return &(container->unknown_fields); |
152 } | 166 } |
153 }; | 167 }; |
154 | 168 |
155 // Temporary compatibility typedef. Remove once this is released in components | 169 class InternalMetadataWithArena |
156 // and upb CL is submitted. | 170 : public InternalMetadataWithArenaBase<UnknownFieldSet, |
157 typedef InternalMetadataWithArena InternalMetadata; | 171 InternalMetadataWithArena> { |
| 172 public: |
| 173 InternalMetadataWithArena() {} |
| 174 explicit InternalMetadataWithArena(Arena* arena) |
| 175 : InternalMetadataWithArenaBase(arena) {} |
| 176 |
| 177 void DoSwap(UnknownFieldSet* other) { |
| 178 mutable_unknown_fields()->Swap(other); |
| 179 } |
| 180 |
| 181 void DoMergeFrom(const UnknownFieldSet& other) { |
| 182 mutable_unknown_fields()->MergeFrom(other); |
| 183 } |
| 184 |
| 185 void DoClear() { |
| 186 mutable_unknown_fields()->Clear(); |
| 187 } |
| 188 |
| 189 static const UnknownFieldSet& default_instance() { |
| 190 return *UnknownFieldSet::default_instance(); |
| 191 } |
| 192 }; |
| 193 |
| 194 // We store unknown fields as a string right now, because there is currently no |
| 195 // good interface for reading unknown fields into an ArenaString. We may want |
| 196 // to revisit this to allow unknown fields to be parsed onto the Arena. |
| 197 class InternalMetadataWithArenaLite |
| 198 : public InternalMetadataWithArenaBase<string, |
| 199 InternalMetadataWithArenaLite> { |
| 200 public: |
| 201 InternalMetadataWithArenaLite() {} |
| 202 |
| 203 explicit InternalMetadataWithArenaLite(Arena* arena) |
| 204 : InternalMetadataWithArenaBase(arena) {} |
| 205 |
| 206 void DoSwap(string* other) { |
| 207 mutable_unknown_fields()->swap(*other); |
| 208 } |
| 209 |
| 210 void DoMergeFrom(const string& other) { |
| 211 mutable_unknown_fields()->append(other); |
| 212 } |
| 213 |
| 214 void DoClear() { |
| 215 mutable_unknown_fields()->clear(); |
| 216 } |
| 217 |
| 218 static const string& default_instance() { |
| 219 return GetEmptyStringAlreadyInited(); |
| 220 } |
| 221 }; |
158 | 222 |
159 } // namespace internal | 223 } // namespace internal |
160 } // namespace protobuf | 224 } // namespace protobuf |
161 | 225 |
162 } // namespace google | 226 } // namespace google |
163 #endif // GOOGLE_PROTOBUF_METADATA_H__ | 227 #endif // GOOGLE_PROTOBUF_METADATA_H__ |
OLD | NEW |