You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

map_entry_lite.h 21 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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_MAP_ENTRY_LITE_H__
  31. #define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
  32. #include <assert.h>
  33. #include <algorithm>
  34. #include <string>
  35. #include <utility>
  36. #include <google/protobuf/stubs/casts.h>
  37. #include <google/protobuf/io/coded_stream.h>
  38. #include <google/protobuf/arena.h>
  39. #include <google/protobuf/port.h>
  40. #include <google/protobuf/arenastring.h>
  41. #include <google/protobuf/generated_message_util.h>
  42. #include <google/protobuf/map.h>
  43. #include <google/protobuf/map_type_handler.h>
  44. #include <google/protobuf/parse_context.h>
  45. #include <google/protobuf/wire_format_lite.h>
  46. // Must be included last.
  47. #include <google/protobuf/port_def.inc>
  48. #ifdef SWIG
  49. #error "You cannot SWIG proto headers"
  50. #endif
  51. namespace google {
  52. namespace protobuf {
  53. namespace internal {
  54. template <typename Derived, typename Key, typename Value,
  55. WireFormatLite::FieldType kKeyFieldType,
  56. WireFormatLite::FieldType kValueFieldType>
  57. class MapEntry;
  58. template <typename Derived, typename Key, typename Value,
  59. WireFormatLite::FieldType kKeyFieldType,
  60. WireFormatLite::FieldType kValueFieldType>
  61. class MapFieldLite;
  62. } // namespace internal
  63. } // namespace protobuf
  64. } // namespace google
  65. namespace google {
  66. namespace protobuf {
  67. namespace internal {
  68. // MoveHelper::Move is used to set *dest. It copies *src, or moves it (in
  69. // the C++11 sense), or swaps it. *src is left in a sane state for
  70. // subsequent destruction, but shouldn't be used for anything.
  71. template <bool is_enum, bool is_message, bool is_stringlike, typename T>
  72. struct MoveHelper { // primitives
  73. static void Move(T* src, T* dest) { *dest = *src; }
  74. };
  75. template <bool is_message, bool is_stringlike, typename T>
  76. struct MoveHelper<true, is_message, is_stringlike, T> { // enums
  77. static void Move(T* src, T* dest) { *dest = *src; }
  78. // T is an enum here, so allow conversions to and from int.
  79. static void Move(T* src, int* dest) { *dest = static_cast<int>(*src); }
  80. static void Move(int* src, T* dest) { *dest = static_cast<T>(*src); }
  81. };
  82. template <bool is_stringlike, typename T>
  83. struct MoveHelper<false, true, is_stringlike, T> { // messages
  84. static void Move(T* src, T* dest) { dest->Swap(src); }
  85. };
  86. template <typename T>
  87. struct MoveHelper<false, false, true, T> { // strings and similar
  88. static void Move(T* src, T* dest) {
  89. *dest = std::move(*src);
  90. }
  91. };
  92. // MapEntryImpl is used to implement parsing and serialization of map entries.
  93. // It uses Curious Recursive Template Pattern (CRTP) to provide the type of
  94. // the eventual code to the template code.
  95. template <typename Derived, typename Base, typename Key, typename Value,
  96. WireFormatLite::FieldType kKeyFieldType,
  97. WireFormatLite::FieldType kValueFieldType>
  98. class MapEntryImpl : public Base {
  99. public:
  100. typedef MapEntryFuncs<Key, Value, kKeyFieldType, kValueFieldType> Funcs;
  101. protected:
  102. // Provide utilities to parse/serialize key/value. Provide utilities to
  103. // manipulate internal stored type.
  104. typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
  105. typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
  106. // Define internal memory layout. Strings and messages are stored as
  107. // pointers, while other types are stored as values.
  108. typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
  109. typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
  110. // Enum type cannot be used for MapTypeHandler::Read. Define a type
  111. // which will replace Enum with int.
  112. typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
  113. typedef
  114. typename ValueTypeHandler::MapEntryAccessorType ValueMapEntryAccessorType;
  115. // Constants for field number.
  116. static const int kKeyFieldNumber = 1;
  117. static const int kValueFieldNumber = 2;
  118. // Constants for field tag.
  119. static const uint8_t kKeyTag =
  120. GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kKeyFieldNumber, KeyTypeHandler::kWireType);
  121. static const uint8_t kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
  122. kValueFieldNumber, ValueTypeHandler::kWireType);
  123. static const size_t kTagSize = 1;
  124. public:
  125. // Work-around for a compiler bug (see repeated_field.h).
  126. typedef void MapEntryHasMergeTypeTrait;
  127. typedef Derived EntryType;
  128. typedef Key EntryKeyType;
  129. typedef Value EntryValueType;
  130. static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType;
  131. static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType;
  132. constexpr MapEntryImpl()
  133. : key_(KeyTypeHandler::Constinit()),
  134. value_(ValueTypeHandler::Constinit()),
  135. _has_bits_{} {}
  136. explicit MapEntryImpl(Arena* arena)
  137. : Base(arena),
  138. key_(KeyTypeHandler::Constinit()),
  139. value_(ValueTypeHandler::Constinit()),
  140. _has_bits_{} {}
  141. ~MapEntryImpl() override {
  142. if (Base::GetArenaForAllocation() != nullptr) return;
  143. KeyTypeHandler::DeleteNoArena(key_);
  144. ValueTypeHandler::DeleteNoArena(value_);
  145. }
  146. // accessors ======================================================
  147. virtual inline const KeyMapEntryAccessorType& key() const {
  148. return KeyTypeHandler::GetExternalReference(key_);
  149. }
  150. virtual inline const ValueMapEntryAccessorType& value() const {
  151. return ValueTypeHandler::DefaultIfNotInitialized(value_);
  152. }
  153. inline KeyMapEntryAccessorType* mutable_key() {
  154. set_has_key();
  155. return KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
  156. }
  157. inline ValueMapEntryAccessorType* mutable_value() {
  158. set_has_value();
  159. return ValueTypeHandler::EnsureMutable(&value_,
  160. Base::GetArenaForAllocation());
  161. }
  162. // implements MessageLite =========================================
  163. // MapEntryImpl is for implementation only and this function isn't called
  164. // anywhere. Just provide a fake implementation here for MessageLite.
  165. std::string GetTypeName() const override { return ""; }
  166. void CheckTypeAndMergeFrom(const MessageLite& other) override {
  167. MergeFromInternal(*::google::protobuf::internal::DownCast<const Derived*>(&other));
  168. }
  169. const char* _InternalParse(const char* ptr, ParseContext* ctx) final {
  170. while (!ctx->Done(&ptr)) {
  171. uint32_t tag;
  172. ptr = ReadTag(ptr, &tag);
  173. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
  174. if (tag == kKeyTag) {
  175. set_has_key();
  176. KeyMapEntryAccessorType* key = mutable_key();
  177. ptr = KeyTypeHandler::Read(ptr, ctx, key);
  178. if (!Derived::ValidateKey(key)) return nullptr;
  179. } else if (tag == kValueTag) {
  180. set_has_value();
  181. ValueMapEntryAccessorType* value = mutable_value();
  182. ptr = ValueTypeHandler::Read(ptr, ctx, value);
  183. if (!Derived::ValidateValue(value)) return nullptr;
  184. } else {
  185. if (tag == 0 || WireFormatLite::GetTagWireType(tag) ==
  186. WireFormatLite::WIRETYPE_END_GROUP) {
  187. ctx->SetLastTag(tag);
  188. return ptr;
  189. }
  190. ptr = UnknownFieldParse(tag, static_cast<std::string*>(nullptr), ptr,
  191. ctx);
  192. }
  193. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
  194. }
  195. return ptr;
  196. }
  197. size_t ByteSizeLong() const override {
  198. size_t size = 0;
  199. size += kTagSize + static_cast<size_t>(KeyTypeHandler::ByteSize(key()));
  200. size += kTagSize + static_cast<size_t>(ValueTypeHandler::ByteSize(value()));
  201. return size;
  202. }
  203. ::uint8_t* _InternalSerialize(
  204. ::uint8_t* ptr, io::EpsCopyOutputStream* stream) const override {
  205. ptr = KeyTypeHandler::Write(kKeyFieldNumber, key(), ptr, stream);
  206. return ValueTypeHandler::Write(kValueFieldNumber, value(), ptr, stream);
  207. }
  208. // Don't override SerializeWithCachedSizesToArray. Use MessageLite's.
  209. int GetCachedSize() const override {
  210. int size = 0;
  211. size += has_key() ? static_cast<int>(kTagSize) +
  212. KeyTypeHandler::GetCachedSize(key())
  213. : 0;
  214. size += has_value() ? static_cast<int>(kTagSize) +
  215. ValueTypeHandler::GetCachedSize(value())
  216. : 0;
  217. return size;
  218. }
  219. bool IsInitialized() const override {
  220. return ValueTypeHandler::IsInitialized(value_);
  221. }
  222. Base* New(Arena* arena) const override {
  223. Derived* entry = Arena::CreateMessage<Derived>(arena);
  224. return entry;
  225. }
  226. protected:
  227. // We can't declare this function directly here as it would hide the other
  228. // overload (const Message&).
  229. void MergeFromInternal(const MapEntryImpl& from) {
  230. if (from._has_bits_[0]) {
  231. if (from.has_key()) {
  232. KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
  233. KeyTypeHandler::Merge(from.key(), &key_, Base::GetArenaForAllocation());
  234. set_has_key();
  235. }
  236. if (from.has_value()) {
  237. ValueTypeHandler::EnsureMutable(&value_, Base::GetArenaForAllocation());
  238. ValueTypeHandler::Merge(from.value(), &value_,
  239. Base::GetArenaForAllocation());
  240. set_has_value();
  241. }
  242. }
  243. }
  244. public:
  245. void Clear() override {
  246. KeyTypeHandler::Clear(&key_, Base::GetArenaForAllocation());
  247. ValueTypeHandler::Clear(&value_, Base::GetArenaForAllocation());
  248. clear_has_key();
  249. clear_has_value();
  250. }
  251. // Parsing using MergePartialFromCodedStream, above, is not as
  252. // efficient as it could be. This helper class provides a speedier way.
  253. template <typename MapField, typename Map>
  254. class Parser {
  255. public:
  256. explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {}
  257. ~Parser() {
  258. if (entry_ != nullptr && entry_->GetArenaForAllocation() == nullptr)
  259. delete entry_;
  260. }
  261. const char* _InternalParse(const char* ptr, ParseContext* ctx) {
  262. if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kKeyTag)) {
  263. ptr = KeyTypeHandler::Read(ptr + 1, ctx, &key_);
  264. if (PROTOBUF_PREDICT_FALSE(!ptr || !Derived::ValidateKey(&key_))) {
  265. return nullptr;
  266. }
  267. if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kValueTag)) {
  268. typename Map::size_type map_size = map_->size();
  269. value_ptr_ = &(*map_)[key_];
  270. if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) {
  271. using T =
  272. typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type;
  273. ptr = ValueTypeHandler::Read(ptr + 1, ctx,
  274. reinterpret_cast<T>(value_ptr_));
  275. if (PROTOBUF_PREDICT_FALSE(!ptr ||
  276. !Derived::ValidateValue(value_ptr_))) {
  277. map_->erase(key_); // Failure! Undo insertion.
  278. return nullptr;
  279. }
  280. if (PROTOBUF_PREDICT_TRUE(ctx->Done(&ptr))) return ptr;
  281. if (!ptr) return nullptr;
  282. NewEntry();
  283. ValueMover::Move(value_ptr_, entry_->mutable_value());
  284. map_->erase(key_);
  285. goto move_key;
  286. }
  287. } else {
  288. if (!ptr) return nullptr;
  289. }
  290. NewEntry();
  291. move_key:
  292. KeyMover::Move(&key_, entry_->mutable_key());
  293. } else {
  294. if (!ptr) return nullptr;
  295. NewEntry();
  296. }
  297. ptr = entry_->_InternalParse(ptr, ctx);
  298. if (ptr) UseKeyAndValueFromEntry();
  299. return ptr;
  300. }
  301. template <typename UnknownType>
  302. const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
  303. bool (*is_valid)(int),
  304. uint32_t field_num,
  305. InternalMetadata* metadata) {
  306. auto entry = NewEntry();
  307. ptr = entry->_InternalParse(ptr, ctx);
  308. if (!ptr) return nullptr;
  309. if (is_valid(entry->value())) {
  310. UseKeyAndValueFromEntry();
  311. } else {
  312. WriteLengthDelimited(field_num, entry->SerializeAsString(),
  313. metadata->mutable_unknown_fields<UnknownType>());
  314. }
  315. return ptr;
  316. }
  317. MapEntryImpl* NewEntry() { return entry_ = mf_->NewEntry(); }
  318. const Key& key() const { return key_; }
  319. const Value& value() const { return *value_ptr_; }
  320. const Key& entry_key() const { return entry_->key(); }
  321. const Value& entry_value() const { return entry_->value(); }
  322. private:
  323. void UseKeyAndValueFromEntry() {
  324. // Update key_ in case we need it later (because key() is called).
  325. // This is potentially inefficient, especially if the key is
  326. // expensive to copy (e.g., a long string), but this is a cold
  327. // path, so it's not a big deal.
  328. key_ = entry_->key();
  329. value_ptr_ = &(*map_)[key_];
  330. ValueMover::Move(entry_->mutable_value(), value_ptr_);
  331. }
  332. // After reading a key and value successfully, and inserting that data
  333. // into map_, we are not at the end of the input. This is unusual, but
  334. // allowed by the spec.
  335. bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD {
  336. NewEntry();
  337. ValueMover::Move(value_ptr_, entry_->mutable_value());
  338. map_->erase(key_);
  339. KeyMover::Move(&key_, entry_->mutable_key());
  340. const bool result = entry_->MergePartialFromCodedStream(input);
  341. if (result) UseKeyAndValueFromEntry();
  342. return result;
  343. }
  344. typedef MoveHelper<KeyTypeHandler::kIsEnum, KeyTypeHandler::kIsMessage,
  345. KeyTypeHandler::kWireType ==
  346. WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
  347. Key>
  348. KeyMover;
  349. typedef MoveHelper<ValueTypeHandler::kIsEnum, ValueTypeHandler::kIsMessage,
  350. ValueTypeHandler::kWireType ==
  351. WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
  352. Value>
  353. ValueMover;
  354. MapField* const mf_;
  355. Map* const map_;
  356. Key key_;
  357. Value* value_ptr_;
  358. MapEntryImpl* entry_ = nullptr;
  359. };
  360. protected:
  361. void set_has_key() { _has_bits_[0] |= 0x00000001u; }
  362. bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
  363. void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
  364. void set_has_value() { _has_bits_[0] |= 0x00000002u; }
  365. bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
  366. void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
  367. public:
  368. inline Arena* GetArena() const { return Base::GetArena(); }
  369. protected: // Needed for constructing tables
  370. KeyOnMemory key_;
  371. ValueOnMemory value_;
  372. uint32_t _has_bits_[1];
  373. private:
  374. friend class ::PROTOBUF_NAMESPACE_ID::Arena;
  375. typedef void InternalArenaConstructable_;
  376. typedef void DestructorSkippable_;
  377. template <typename C, typename K, typename V, WireFormatLite::FieldType,
  378. WireFormatLite::FieldType>
  379. friend class internal::MapEntry;
  380. template <typename C, typename K, typename V, WireFormatLite::FieldType,
  381. WireFormatLite::FieldType>
  382. friend class internal::MapFieldLite;
  383. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl);
  384. };
  385. template <typename T, typename Key, typename Value,
  386. WireFormatLite::FieldType kKeyFieldType,
  387. WireFormatLite::FieldType kValueFieldType>
  388. class MapEntryLite : public MapEntryImpl<T, MessageLite, Key, Value,
  389. kKeyFieldType, kValueFieldType> {
  390. public:
  391. typedef MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
  392. kValueFieldType>
  393. SuperType;
  394. constexpr MapEntryLite() {}
  395. explicit MapEntryLite(Arena* arena) : SuperType(arena) {}
  396. ~MapEntryLite() override {
  397. MessageLite::_internal_metadata_.template Delete<std::string>();
  398. }
  399. void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); }
  400. private:
  401. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
  402. };
  403. // Helpers for deterministic serialization =============================
  404. // Iterator base for MapSorterFlat and MapSorterPtr.
  405. template <typename storage_type>
  406. struct MapSorterIt {
  407. storage_type* ptr;
  408. MapSorterIt(storage_type* ptr) : ptr(ptr) {}
  409. bool operator==(const MapSorterIt& other) const { return ptr == other.ptr; }
  410. bool operator!=(const MapSorterIt& other) const { return !(*this == other); }
  411. MapSorterIt& operator++() { ++ptr; return *this; }
  412. MapSorterIt operator++(int) { auto other = *this; ++ptr; return other; }
  413. MapSorterIt operator+(int v) { return MapSorterIt{ptr + v}; }
  414. };
  415. // MapSorterFlat stores keys inline with pointers to map entries, so that
  416. // keys can be compared without indirection. This type is used for maps with
  417. // keys that are not strings.
  418. template <typename MapT>
  419. class MapSorterFlat {
  420. public:
  421. using value_type = typename MapT::value_type;
  422. using storage_type = std::pair<typename MapT::key_type, const value_type*>;
  423. // This const_iterator dereferenes to the map entry stored in the sorting
  424. // array pairs. This is the same interface as the Map::const_iterator type,
  425. // and allows generated code to use the same loop body with either form:
  426. // for (const auto& entry : map) { ... }
  427. // for (const auto& entry : MapSorterFlat(map)) { ... }
  428. struct const_iterator : public MapSorterIt<storage_type> {
  429. using pointer = const typename MapT::value_type*;
  430. using reference = const typename MapT::value_type&;
  431. using MapSorterIt<storage_type>::MapSorterIt;
  432. pointer operator->() const { return this->ptr->second; }
  433. reference operator*() const { return *this->operator->(); }
  434. };
  435. explicit MapSorterFlat(const MapT& m)
  436. : size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
  437. if (!size_) return;
  438. storage_type* it = &items_[0];
  439. for (const auto& entry : m) {
  440. *it++ = {entry.first, &entry};
  441. }
  442. std::sort(&items_[0], &items_[size_],
  443. [](const storage_type& a, const storage_type& b) {
  444. return a.first < b.first;
  445. });
  446. }
  447. size_t size() const { return size_; }
  448. const_iterator begin() const { return {items_.get()}; }
  449. const_iterator end() const { return {items_.get() + size_}; }
  450. private:
  451. size_t size_;
  452. std::unique_ptr<storage_type[]> items_;
  453. };
  454. // MapSorterPtr stores and sorts pointers to map entries. This type is used for
  455. // maps with keys that are strings.
  456. template <typename MapT>
  457. class MapSorterPtr {
  458. public:
  459. using value_type = typename MapT::value_type;
  460. using storage_type = const typename MapT::value_type*;
  461. // This const_iterator dereferenes the map entry pointer stored in the sorting
  462. // array. This is the same interface as the Map::const_iterator type, and
  463. // allows generated code to use the same loop body with either form:
  464. // for (const auto& entry : map) { ... }
  465. // for (const auto& entry : MapSorterPtr(map)) { ... }
  466. struct const_iterator : public MapSorterIt<storage_type> {
  467. using pointer = const typename MapT::value_type*;
  468. using reference = const typename MapT::value_type&;
  469. using MapSorterIt<storage_type>::MapSorterIt;
  470. pointer operator->() const { return *this->ptr; }
  471. reference operator*() const { return *this->operator->(); }
  472. };
  473. explicit MapSorterPtr(const MapT& m)
  474. : size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
  475. if (!size_) return;
  476. storage_type* it = &items_[0];
  477. for (const auto& entry : m) {
  478. *it++ = &entry;
  479. }
  480. std::sort(&items_[0], &items_[size_],
  481. [](const storage_type& a, const storage_type& b) {
  482. return a->first < b->first;
  483. });
  484. }
  485. size_t size() const { return size_; }
  486. const_iterator begin() const { return {items_.get()}; }
  487. const_iterator end() const { return {items_.get() + size_}; }
  488. private:
  489. size_t size_;
  490. std::unique_ptr<storage_type[]> items_;
  491. };
  492. } // namespace internal
  493. } // namespace protobuf
  494. } // namespace google
  495. #include <google/protobuf/port_undef.inc>
  496. #endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__