Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: third_party/protobuf/src/google/protobuf/map_entry_lite.h

Issue 2495533002: third_party/protobuf: Update to HEAD (83d681ee2c) (Closed)
Patch Set: Make chrome settings proto generated file a component Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 13 matching lines...) Expand all
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 30
31 #ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ 31 #ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
32 #define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ 32 #define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
33 33
34 #include <assert.h>
34 #include <google/protobuf/map_type_handler.h> 35 #include <google/protobuf/map_type_handler.h>
35 #include <google/protobuf/wire_format_lite_inl.h> 36 #include <google/protobuf/wire_format_lite_inl.h>
36 37
37 namespace google { 38 namespace google {
38 namespace protobuf { 39 namespace protobuf {
39 class Arena; 40 class Arena;
40 namespace internal { 41 namespace internal {
41 template <typename Key, typename Value, 42 template <typename Key, typename Value,
42 WireFormatLite::FieldType kKeyFieldType, 43 WireFormatLite::FieldType kKeyFieldType,
43 WireFormatLite::FieldType kValueFieldType, 44 WireFormatLite::FieldType kValueFieldType,
44 int default_enum_value> 45 int default_enum_value>
45 class MapEntry; 46 class MapEntry;
46 template <typename Key, typename Value, 47 template <typename Key, typename Value,
47 WireFormatLite::FieldType kKeyFieldType, 48 WireFormatLite::FieldType kKeyFieldType,
48 WireFormatLite::FieldType kValueFieldType, 49 WireFormatLite::FieldType kValueFieldType,
49 int default_enum_value> 50 int default_enum_value>
50 class MapFieldLite; 51 class MapFieldLite;
51 } // namespace internal 52 } // namespace internal
52 } // namespace protobuf 53 } // namespace protobuf
53 54
54 namespace protobuf { 55 namespace protobuf {
55 namespace internal { 56 namespace internal {
56 57
58 // MoveHelper::Move is used to set *dest. It copies *src, or moves it (in
59 // the C++11 sense), or swaps it. *src is left in a sane state for
60 // subsequent destruction, but shouldn't be used for anything.
61 template <bool is_enum, bool is_message, bool is_stringlike, typename T>
62 struct MoveHelper { // primitives
63 static void Move(T* src, T* dest) { *dest = *src; }
64 };
65
66 template <bool is_message, bool is_stringlike, typename T>
67 struct MoveHelper<true, is_message, is_stringlike, T> { // enums
68 static void Move(T* src, T* dest) { *dest = *src; }
69 // T is an enum here, so allow conversions to and from int.
70 static void Move(T* src, int* dest) { *dest = static_cast<int>(*src); }
71 static void Move(int* src, T* dest) { *dest = static_cast<T>(*src); }
72 };
73
74 template <bool is_stringlike, typename T>
75 struct MoveHelper<false, true, is_stringlike, T> { // messages
76 static void Move(T* src, T* dest) { dest->Swap(src); }
77 };
78
79 template <typename T>
80 struct MoveHelper<false, false, true, T> { // strings and similar
81 static void Move(T* src, T* dest) {
82 #if __cplusplus >= 201103L
83 *dest = std::move(*src);
84 #else
85 dest->swap(*src);
86 #endif
87 }
88 };
89
57 // MapEntryLite is used to implement parsing and serialization of map for lite 90 // MapEntryLite is used to implement parsing and serialization of map for lite
58 // runtime. 91 // runtime.
59 template <typename Key, typename Value, 92 template <typename Key, typename Value,
60 WireFormatLite::FieldType kKeyFieldType, 93 WireFormatLite::FieldType kKeyFieldType,
61 WireFormatLite::FieldType kValueFieldType, 94 WireFormatLite::FieldType kValueFieldType,
62 int default_enum_value> 95 int default_enum_value>
63 class MapEntryLite : public MessageLite { 96 class MapEntryLite : public MessageLite {
64 // Provide utilities to parse/serialize key/value. Provide utilities to 97 // Provide utilities to parse/serialize key/value. Provide utilities to
65 // manipulate internal stored type. 98 // manipulate internal stored type.
66 typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler; 99 typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
(...skipping 12 matching lines...) Expand all
79 112
80 // Constants for field number. 113 // Constants for field number.
81 static const int kKeyFieldNumber = 1; 114 static const int kKeyFieldNumber = 1;
82 static const int kValueFieldNumber = 2; 115 static const int kValueFieldNumber = 2;
83 116
84 // Constants for field tag. 117 // Constants for field tag.
85 static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( 118 static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
86 kKeyFieldNumber, KeyTypeHandler::kWireType); 119 kKeyFieldNumber, KeyTypeHandler::kWireType);
87 static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( 120 static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
88 kValueFieldNumber, ValueTypeHandler::kWireType); 121 kValueFieldNumber, ValueTypeHandler::kWireType);
89 static const int kTagSize = 1; 122 static const size_t kTagSize = 1;
90 123
91 public: 124 public:
92 ~MapEntryLite() { 125 ~MapEntryLite() {
93 if (this != default_instance_) { 126 if (this != default_instance_) {
94 if (GetArenaNoVirtual() != NULL) return; 127 if (GetArenaNoVirtual() != NULL) return;
95 KeyTypeHandler::DeleteNoArena(key_); 128 KeyTypeHandler::DeleteNoArena(key_);
96 ValueTypeHandler::DeleteNoArena(value_); 129 ValueTypeHandler::DeleteNoArena(value_);
97 } 130 }
98 } 131 }
99 132
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 164
132 for (;;) { 165 for (;;) {
133 // 1) corrupted data: return false; 166 // 1) corrupted data: return false;
134 // 2) unknown field: skip without putting into unknown field set; 167 // 2) unknown field: skip without putting into unknown field set;
135 // 3) unknown enum value: keep it in parsing. In proto2, caller should 168 // 3) unknown enum value: keep it in parsing. In proto2, caller should
136 // check the value and put this entry into containing message's unknown 169 // check the value and put this entry into containing message's unknown
137 // field set if the value is an unknown enum. In proto3, caller doesn't 170 // field set if the value is an unknown enum. In proto3, caller doesn't
138 // need to care whether the value is unknown enum; 171 // need to care whether the value is unknown enum;
139 // 4) missing key/value: missed key/value will have default value. caller 172 // 4) missing key/value: missed key/value will have default value. caller
140 // should take this entry as if key/value is set to default value. 173 // should take this entry as if key/value is set to default value.
141 tag = input->ReadTag(); 174 tag = input->ReadTagNoLastTag();
142 switch (tag) { 175 switch (tag) {
143 case kKeyTag: 176 case kKeyTag:
144 if (!KeyTypeHandler::Read(input, mutable_key())) { 177 if (!KeyTypeHandler::Read(input, mutable_key())) {
145 return false; 178 return false;
146 } 179 }
147 set_has_key(); 180 set_has_key();
148 if (!input->ExpectTag(kValueTag)) break; 181 if (!input->ExpectTag(kValueTag)) break;
149 GOOGLE_FALLTHROUGH_INTENDED; 182 GOOGLE_FALLTHROUGH_INTENDED;
150 183
151 case kValueTag: 184 case kValueTag:
152 if (!ValueTypeHandler::Read(input, mutable_value())) { 185 if (!ValueTypeHandler::Read(input, mutable_value())) {
153 return false; 186 return false;
154 } 187 }
155 set_has_value(); 188 set_has_value();
156 if (input->ExpectAtEnd()) return true; 189 if (input->ExpectAtEnd()) return true;
157 break; 190 break;
158 191
159 default: 192 default:
160 if (tag == 0 || 193 if (tag == 0 ||
161 WireFormatLite::GetTagWireType(tag) == 194 WireFormatLite::GetTagWireType(tag) ==
162 WireFormatLite::WIRETYPE_END_GROUP) { 195 WireFormatLite::WIRETYPE_END_GROUP) {
163 return true; 196 return true;
164 } 197 }
165 if (!WireFormatLite::SkipField(input, tag)) return false; 198 if (!WireFormatLite::SkipField(input, tag)) return false;
166 break; 199 break;
167 } 200 }
168 } 201 }
169 } 202 }
170 203
171 int ByteSize() const { 204 size_t ByteSizeLong() const {
172 int size = 0; 205 size_t size = 0;
173 size += has_key() ? kTagSize + KeyTypeHandler::ByteSize(key()) : 0; 206 size += has_key() ? kTagSize + KeyTypeHandler::ByteSize(key()) : 0;
174 size += has_value() ? kTagSize + ValueTypeHandler::ByteSize(value()) : 0; 207 size += has_value() ? kTagSize + ValueTypeHandler::ByteSize(value()) : 0;
175 return size; 208 return size;
176 } 209 }
177 210
178 void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* outpu t) const { 211 void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* outpu t) const {
179 KeyTypeHandler::Write(kKeyFieldNumber, key(), output); 212 KeyTypeHandler::Write(kKeyFieldNumber, key(), output);
180 ValueTypeHandler::Write(kValueFieldNumber, value(), output); 213 ValueTypeHandler::Write(kValueFieldNumber, value(), output);
181 } 214 }
182 215
216 ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(bool determ inistic,
217 ::google::protobuf::uint8* ou tput) const {
218 output = KeyTypeHandler::InternalWriteToArray(kKeyFieldNumber, key(),
219 deterministic, output);
220 output = ValueTypeHandler::InternalWriteToArray(kValueFieldNumber, value(),
221 deterministic, output);
222 return output;
223 }
183 ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf: :uint8* output) const { 224 ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf: :uint8* output) const {
184 output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key(), output); 225 return InternalSerializeWithCachedSizesToArray(false, output);
185 output = ValueTypeHandler::WriteToArray(kValueFieldNumber, value(), output);
186 return output;
187 } 226 }
188 227
189 int GetCachedSize() const { 228 int GetCachedSize() const {
190 int size = 0; 229 int size = 0;
191 size += has_key() 230 size += has_key()
192 ? kTagSize + KeyTypeHandler::GetCachedSize(key()) 231 ? kTagSize + KeyTypeHandler::GetCachedSize(key())
193 : 0; 232 : 0;
194 size += has_value() 233 size += has_value()
195 ? kTagSize + ValueTypeHandler::GetCachedSize( 234 ? kTagSize + ValueTypeHandler::GetCachedSize(
196 value()) 235 value())
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 303
265 // Like above, but for all the other types. This avoids value copy to create 304 // Like above, but for all the other types. This avoids value copy to create
266 // MapEntryLite from google::protobuf::Map in serialization. 305 // MapEntryLite from google::protobuf::Map in serialization.
267 static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) { 306 static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) {
268 return Arena::CreateMessage<MapEntryWrapper<Key, Value, kKeyFieldType, 307 return Arena::CreateMessage<MapEntryWrapper<Key, Value, kKeyFieldType,
269 kValueFieldType, 308 kValueFieldType,
270 default_enum_value> >( 309 default_enum_value> >(
271 arena, key, value); 310 arena, key, value);
272 } 311 }
273 312
313 // Parsing using MergePartialFromCodedStream, above, is not as
314 // efficient as it could be. This helper class provides a speedier way.
315 template <typename MapField, typename Map>
316 class Parser {
317 public:
318 explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {}
319
320 // This does what the typical MergePartialFromCodedStream() is expected to
321 // do, with the additional side-effect that if successful (i.e., if true is
322 // going to be its return value) it inserts the key-value pair into map_.
323 bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* i nput) {
324 // Look for the expected thing: a key and then a value. If it fails,
325 // invoke the enclosing class's MergePartialFromCodedStream, or return
326 // false if that would be pointless.
327 if (input->ExpectTag(kKeyTag)) {
328 if (!KeyTypeHandler::Read(input, &key_)) {
329 return false;
330 }
331 // Peek at the next byte to see if it is kValueTag. If not, bail out.
332 const void* data;
333 int size;
334 input->GetDirectBufferPointerInline(&data, &size);
335 // We could use memcmp here, but we don't bother. The tag is one byte.
336 GOOGLE_COMPILE_ASSERT(kTagSize == 1, tag_size_error);
337 if (size > 0 && *reinterpret_cast<const char*>(data) == kValueTag) {
338 typename Map::size_type size = map_->size();
339 value_ptr_ = &(*map_)[key_];
340 if (GOOGLE_PREDICT_TRUE(size != map_->size())) {
341 // We created a new key-value pair. Fill in the value.
342 typedef
343 typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type T;
344 input->Skip(kTagSize); // Skip kValueTag.
345 if (!ValueTypeHandler::Read(input,
346 reinterpret_cast<T>(value_ptr_))) {
347 map_->erase(key_); // Failure! Undo insertion.
348 return false;
349 }
350 if (input->ExpectAtEnd()) return true;
351 return ReadBeyondKeyValuePair(input);
352 }
353 }
354 } else {
355 key_ = Key();
356 }
357
358 entry_.reset(mf_->NewEntry());
359 *entry_->mutable_key() = key_;
360 const bool result = entry_->MergePartialFromCodedStream(input);
361 if (result) UseKeyAndValueFromEntry();
362 if (entry_->GetArena() != NULL) entry_.release();
363 return result;
364 }
365
366 const Key& key() const { return key_; }
367 const Value& value() const { return *value_ptr_; }
368
369 private:
370 void UseKeyAndValueFromEntry() GOOGLE_ATTRIBUTE_COLD {
371 // Update key_ in case we need it later (because key() is called).
372 // This is potentially inefficient, especially if the key is
373 // expensive to copy (e.g., a long string), but this is a cold
374 // path, so it's not a big deal.
375 key_ = entry_->key();
376 value_ptr_ = &(*map_)[key_];
377 MoveHelper<ValueTypeHandler::kIsEnum,
378 ValueTypeHandler::kIsMessage,
379 ValueTypeHandler::kWireType ==
380 WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
381 Value>::Move(entry_->mutable_value(), value_ptr_);
382 }
383
384 // After reading a key and value successfully, and inserting that data
385 // into map_, we are not at the end of the input. This is unusual, but
386 // allowed by the spec.
387 bool ReadBeyondKeyValuePair(::google::protobuf::io::CodedInputStream* input)
388 GOOGLE_ATTRIBUTE_COLD {
389 typedef MoveHelper<KeyTypeHandler::kIsEnum,
390 KeyTypeHandler::kIsMessage,
391 KeyTypeHandler::kWireType ==
392 WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
393 Key> KeyMover;
394 typedef MoveHelper<ValueTypeHandler::kIsEnum,
395 ValueTypeHandler::kIsMessage,
396 ValueTypeHandler::kWireType ==
397 WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
398 Value> ValueMover;
399 entry_.reset(mf_->NewEntry());
400 ValueMover::Move(value_ptr_, entry_->mutable_value());
401 map_->erase(key_);
402 KeyMover::Move(&key_, entry_->mutable_key());
403 const bool result = entry_->MergePartialFromCodedStream(input);
404 if (result) UseKeyAndValueFromEntry();
405 if (entry_->GetArena() != NULL) entry_.release();
406 return result;
407 }
408
409 MapField* const mf_;
410 Map* const map_;
411 Key key_;
412 Value* value_ptr_;
413 // On the fast path entry_ is not used. And, when entry_ is used, it's set
414 // to mf_->NewEntry(), so in the arena case we must call entry_.release.
415 google::protobuf::scoped_ptr<MapEntryLite> entry_;
416 };
417
274 protected: 418 protected:
275 void set_has_key() { _has_bits_[0] |= 0x00000001u; } 419 void set_has_key() { _has_bits_[0] |= 0x00000001u; }
276 bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; } 420 bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
277 void clear_has_key() { _has_bits_[0] &= ~0x00000001u; } 421 void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
278 void set_has_value() { _has_bits_[0] |= 0x00000002u; } 422 void set_has_value() { _has_bits_[0] |= 0x00000002u; }
279 bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; } 423 bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
280 void clear_has_value() { _has_bits_[0] &= ~0x00000002u; } 424 void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
281 425
282 private: 426 private:
283 // Serializing a generated message containing map field involves serializing 427 // Serializing a generated message containing map field involves serializing
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 template <typename K, typename V, WireFormatLite::FieldType, 531 template <typename K, typename V, WireFormatLite::FieldType,
388 WireFormatLite::FieldType, int> 532 WireFormatLite::FieldType, int>
389 friend class internal::MapEntry; 533 friend class internal::MapEntry;
390 template <typename K, typename V, WireFormatLite::FieldType, 534 template <typename K, typename V, WireFormatLite::FieldType,
391 WireFormatLite::FieldType, int> 535 WireFormatLite::FieldType, int>
392 friend class internal::MapFieldLite; 536 friend class internal::MapFieldLite;
393 537
394 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite); 538 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
395 }; 539 };
396 540
541 // Helpers for deterministic serialization =============================
542
543 // This struct can be used with any generic sorting algorithm. If the Key
544 // type is relatively small and easy to copy then copying Keys into an
545 // array of SortItems can be beneficial. Then all the data the sorting
546 // algorithm needs to touch is in that one array.
547 template <typename Key, typename PtrToKeyValuePair> struct SortItem {
548 SortItem() {}
549 explicit SortItem(PtrToKeyValuePair p) : first(p->first), second(p) {}
550
551 Key first;
552 PtrToKeyValuePair second;
553 };
554
555 template <typename T> struct CompareByFirstField {
556 bool operator()(const T& a, const T& b) const {
557 return a.first < b.first;
558 }
559 };
560
561 template <typename T> struct CompareByDerefFirst {
562 bool operator()(const T& a, const T& b) const {
563 return a->first < b->first;
564 }
565 };
566
397 } // namespace internal 567 } // namespace internal
398 } // namespace protobuf 568 } // namespace protobuf
399 569
400 } // namespace google 570 } // namespace google
401 #endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ 571 #endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
OLDNEW
« no previous file with comments | « third_party/protobuf/src/google/protobuf/map_entry.h ('k') | third_party/protobuf/src/google/protobuf/map_field.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698