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
31#ifndef GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
32#define GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
33
34#include <google/protobuf/io/coded_stream.h>
35#include <google/protobuf/arena.h>
36#include <google/protobuf/arenastring.h>
37#include <google/protobuf/parse_context.h>
38#include <google/protobuf/wire_format_lite.h>
39
40#ifdef SWIG
41#error "You cannot SWIG proto headers"
42#endif
43
44namespace google {
45namespace protobuf {
46namespace internal {
47
48// Used for compile time type selection. MapIf::type will be TrueType if Flag is
49// true and FalseType otherwise.
50template <bool Flag, typename TrueType, typename FalseType>
51struct MapIf;
52
53template <typename TrueType, typename FalseType>
54struct MapIf<true, TrueType, FalseType> {
55 typedef TrueType type;
56};
57
58template <typename TrueType, typename FalseType>
59struct MapIf<false, TrueType, FalseType> {
60 typedef FalseType type;
61};
62
63template <typename Type, bool is_arena_constructable>
64class MapArenaMessageCreator {
65 public:
66 // Use arena to create message if Type is arena constructable. Otherwise,
67 // create the message on heap.
68 static inline Type* CreateMessage(Arena* arena);
69};
70template <typename Type>
71class MapArenaMessageCreator<Type, true> {
72 public:
73 static inline Type* CreateMessage(Arena* arena) {
74 return Arena::CreateMessage<Type>(arena);
75 }
76};
77template <typename Type>
78class MapArenaMessageCreator<Type, false> {
79 public:
80 static inline Type* CreateMessage(Arena* arena) {
81 return Arena::Create<Type>(arena);
82 }
83};
84
85// Define constants for given wire field type
86template <WireFormatLite::FieldType field_type, typename Type>
87class MapWireFieldTypeTraits {};
88
89#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
90 template <typename Type> \
91 class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, Type> { \
92 public: \
93 static const bool kIsMessage = IsMessage; \
94 static const bool kIsEnum = IsEnum; \
95 typedef typename MapIf<kIsMessage, Type*, CType>::type TypeOnMemory; \
96 typedef typename MapIf<kIsEnum, int, Type>::type MapEntryAccessorType; \
97 static const WireFormatLite::WireType kWireType = \
98 WireFormatLite::WIRETYPE_##WireFormatType; \
99 };
100
101TYPE_TRAITS(MESSAGE, Type, LENGTH_DELIMITED, true, false)
102TYPE_TRAITS(STRING, ArenaStringPtr, LENGTH_DELIMITED, false, false)
103TYPE_TRAITS(BYTES, ArenaStringPtr, LENGTH_DELIMITED, false, false)
104TYPE_TRAITS(INT64, int64_t, VARINT, false, false)
105TYPE_TRAITS(UINT64, uint64_t, VARINT, false, false)
106TYPE_TRAITS(INT32, int32_t, VARINT, false, false)
107TYPE_TRAITS(UINT32, uint32_t, VARINT, false, false)
108TYPE_TRAITS(SINT64, int64_t, VARINT, false, false)
109TYPE_TRAITS(SINT32, int32_t, VARINT, false, false)
110TYPE_TRAITS(ENUM, int, VARINT, false, true)
111TYPE_TRAITS(DOUBLE, double, FIXED64, false, false)
112TYPE_TRAITS(FLOAT, float, FIXED32, false, false)
113TYPE_TRAITS(FIXED64, uint64_t, FIXED64, false, false)
114TYPE_TRAITS(FIXED32, uint32_t, FIXED32, false, false)
115TYPE_TRAITS(SFIXED64, int64_t, FIXED64, false, false)
116TYPE_TRAITS(SFIXED32, int32_t, FIXED32, false, false)
117TYPE_TRAITS(BOOL, bool, VARINT, false, false)
118
119#undef TYPE_TRAITS
120
121template <WireFormatLite::FieldType field_type, typename Type>
122class MapTypeHandler {};
123
124template <typename Type>
125class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
126 public:
127 // Enum type cannot be used for MapTypeHandler::Read. Define a type which will
128 // replace Enum with int.
129 typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
130 Type>::MapEntryAccessorType
131 MapEntryAccessorType;
132 // Internal stored type in MapEntryLite for given wire field type.
133 typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
134 Type>::TypeOnMemory TypeOnMemory;
135 // Corresponding wire type for field type.
136 static constexpr WireFormatLite::WireType kWireType =
137 MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType;
138 // Whether wire type is for message.
139 static constexpr bool kIsMessage =
140 MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsMessage;
141 // Whether wire type is for enum.
142 static constexpr bool kIsEnum =
143 MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsEnum;
144
145 // Functions used in parsing and serialization. ===================
146 static inline size_t ByteSize(const MapEntryAccessorType& value);
147 static inline int GetCachedSize(const MapEntryAccessorType& value);
148 static inline bool Read(io::CodedInputStream* input,
149 MapEntryAccessorType* value);
150 static inline const char* Read(const char* ptr, ParseContext* ctx,
151 MapEntryAccessorType* value);
152
153 static inline uint8_t* Write(int field, const MapEntryAccessorType& value,
154 uint8_t* ptr, io::EpsCopyOutputStream* stream);
155
156 // Functions to manipulate data on memory. ========================
157 static inline const Type& GetExternalReference(const Type* value);
158 static inline void DeleteNoArena(const Type* x);
159 static inline void Merge(const Type& from, Type** to, Arena* arena);
160 static inline void Clear(Type** value, Arena* arena);
161 static constexpr TypeOnMemory Constinit();
162
163 static inline Type* EnsureMutable(Type** value, Arena* arena);
164 // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
165 // those already calculate in sizeof(MapField).
166 static inline size_t SpaceUsedInMapEntryLong(const Type* value);
167 // Return default instance if value is not initialized when calling const
168 // reference accessor.
169 static inline const Type& DefaultIfNotInitialized(const Type* value);
170 // Check if all required fields have values set.
171 static inline bool IsInitialized(Type* value);
172};
173
174#define MAP_HANDLER(FieldType) \
175 template <typename Type> \
176 class MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type> { \
177 public: \
178 typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
179 Type>::MapEntryAccessorType \
180 MapEntryAccessorType; \
181 typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
182 Type>::TypeOnMemory TypeOnMemory; \
183 static const WireFormatLite::WireType kWireType = \
184 MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
185 Type>::kWireType; \
186 static const bool kIsMessage = \
187 MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
188 Type>::kIsMessage; \
189 static const bool kIsEnum = \
190 MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
191 Type>::kIsEnum; \
192 static inline int ByteSize(const MapEntryAccessorType& value); \
193 static inline int GetCachedSize(const MapEntryAccessorType& value); \
194 static inline bool Read(io::CodedInputStream* input, \
195 MapEntryAccessorType* value); \
196 static inline const char* Read(const char* begin, ParseContext* ctx, \
197 MapEntryAccessorType* value); \
198 static inline uint8_t* Write(int field, const MapEntryAccessorType& value, \
199 uint8_t* ptr, \
200 io::EpsCopyOutputStream* stream); \
201 static inline const MapEntryAccessorType& GetExternalReference( \
202 const TypeOnMemory& value); \
203 static inline void DeleteNoArena(const TypeOnMemory& x); \
204 static inline void Merge(const MapEntryAccessorType& from, \
205 TypeOnMemory* to, Arena* arena); \
206 static inline void Clear(TypeOnMemory* value, Arena* arena); \
207 static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value); \
208 static inline const MapEntryAccessorType& DefaultIfNotInitialized( \
209 const TypeOnMemory& value); \
210 static inline bool IsInitialized(const TypeOnMemory& value); \
211 static void DeleteNoArena(TypeOnMemory& value); \
212 static constexpr TypeOnMemory Constinit(); \
213 static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \
214 Arena* arena); \
215 };
216MAP_HANDLER(STRING)
217MAP_HANDLER(BYTES)
218MAP_HANDLER(INT64)
219MAP_HANDLER(UINT64)
220MAP_HANDLER(INT32)
221MAP_HANDLER(UINT32)
222MAP_HANDLER(SINT64)
223MAP_HANDLER(SINT32)
224MAP_HANDLER(ENUM)
225MAP_HANDLER(DOUBLE)
226MAP_HANDLER(FLOAT)
227MAP_HANDLER(FIXED64)
228MAP_HANDLER(FIXED32)
229MAP_HANDLER(SFIXED64)
230MAP_HANDLER(SFIXED32)
231MAP_HANDLER(BOOL)
232#undef MAP_HANDLER
233
234template <typename Type>
235inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ByteSize(
236 const MapEntryAccessorType& value) {
237 return WireFormatLite::MessageSizeNoVirtual(value);
238}
239
240#define GOOGLE_PROTOBUF_BYTE_SIZE(FieldType, DeclaredType) \
241 template <typename Type> \
242 inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
243 const MapEntryAccessorType& value) { \
244 return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \
245 }
246
247GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String)
248GOOGLE_PROTOBUF_BYTE_SIZE(BYTES, Bytes)
249GOOGLE_PROTOBUF_BYTE_SIZE(INT64, Int64)
250GOOGLE_PROTOBUF_BYTE_SIZE(UINT64, UInt64)
251GOOGLE_PROTOBUF_BYTE_SIZE(INT32, Int32)
252GOOGLE_PROTOBUF_BYTE_SIZE(UINT32, UInt32)
253GOOGLE_PROTOBUF_BYTE_SIZE(SINT64, SInt64)
254GOOGLE_PROTOBUF_BYTE_SIZE(SINT32, SInt32)
255GOOGLE_PROTOBUF_BYTE_SIZE(ENUM, Enum)
256
257#undef GOOGLE_PROTOBUF_BYTE_SIZE
258
259#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
260 template <typename Type> \
261 inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
262 const MapEntryAccessorType& /* value */) { \
263 return WireFormatLite::k##DeclaredType##Size; \
264 }
265
266FIXED_BYTE_SIZE(DOUBLE, Double)
267FIXED_BYTE_SIZE(FLOAT, Float)
268FIXED_BYTE_SIZE(FIXED64, Fixed64)
269FIXED_BYTE_SIZE(FIXED32, Fixed32)
270FIXED_BYTE_SIZE(SFIXED64, SFixed64)
271FIXED_BYTE_SIZE(SFIXED32, SFixed32)
272FIXED_BYTE_SIZE(BOOL, Bool)
273
274#undef FIXED_BYTE_SIZE
275
276template <typename Type>
277inline int MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetCachedSize(
278 const MapEntryAccessorType& value) {
279 return static_cast<int>(WireFormatLite::LengthDelimitedSize(
280 length: static_cast<size_t>(value.GetCachedSize())));
281}
282
283#define GET_CACHED_SIZE(FieldType, DeclaredType) \
284 template <typename Type> \
285 inline int \
286 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
287 const MapEntryAccessorType& value) { \
288 return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \
289 }
290
291GET_CACHED_SIZE(STRING, String)
292GET_CACHED_SIZE(BYTES, Bytes)
293GET_CACHED_SIZE(INT64, Int64)
294GET_CACHED_SIZE(UINT64, UInt64)
295GET_CACHED_SIZE(INT32, Int32)
296GET_CACHED_SIZE(UINT32, UInt32)
297GET_CACHED_SIZE(SINT64, SInt64)
298GET_CACHED_SIZE(SINT32, SInt32)
299GET_CACHED_SIZE(ENUM, Enum)
300
301#undef GET_CACHED_SIZE
302
303#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
304 template <typename Type> \
305 inline int \
306 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
307 const MapEntryAccessorType& /* value */) { \
308 return WireFormatLite::k##DeclaredType##Size; \
309 }
310
311GET_FIXED_CACHED_SIZE(DOUBLE, Double)
312GET_FIXED_CACHED_SIZE(FLOAT, Float)
313GET_FIXED_CACHED_SIZE(FIXED64, Fixed64)
314GET_FIXED_CACHED_SIZE(FIXED32, Fixed32)
315GET_FIXED_CACHED_SIZE(SFIXED64, SFixed64)
316GET_FIXED_CACHED_SIZE(SFIXED32, SFixed32)
317GET_FIXED_CACHED_SIZE(BOOL, Bool)
318
319#undef GET_FIXED_CACHED_SIZE
320
321template <typename Type>
322inline uint8_t* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Write(
323 int field, const MapEntryAccessorType& value, uint8_t* ptr,
324 io::EpsCopyOutputStream* stream) {
325 ptr = stream->EnsureSpace(ptr);
326 return WireFormatLite::InternalWriteMessage(
327 field_number: field, value, cached_size: value.GetCachedSize(), target: ptr, stream);
328}
329
330#define WRITE_METHOD(FieldType, DeclaredType) \
331 template <typename Type> \
332 inline uint8_t* \
333 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
334 int field, const MapEntryAccessorType& value, uint8_t* ptr, \
335 io::EpsCopyOutputStream* stream) { \
336 ptr = stream->EnsureSpace(ptr); \
337 return stream->Write##DeclaredType(field, value, ptr); \
338 }
339
340WRITE_METHOD(STRING, String)
341WRITE_METHOD(BYTES, Bytes)
342
343#undef WRITE_METHOD
344#define WRITE_METHOD(FieldType, DeclaredType) \
345 template <typename Type> \
346 inline uint8_t* \
347 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
348 int field, const MapEntryAccessorType& value, uint8_t* ptr, \
349 io::EpsCopyOutputStream* stream) { \
350 ptr = stream->EnsureSpace(ptr); \
351 return WireFormatLite::Write##DeclaredType##ToArray(field, value, ptr); \
352 }
353
354WRITE_METHOD(INT64, Int64)
355WRITE_METHOD(UINT64, UInt64)
356WRITE_METHOD(INT32, Int32)
357WRITE_METHOD(UINT32, UInt32)
358WRITE_METHOD(SINT64, SInt64)
359WRITE_METHOD(SINT32, SInt32)
360WRITE_METHOD(ENUM, Enum)
361WRITE_METHOD(DOUBLE, Double)
362WRITE_METHOD(FLOAT, Float)
363WRITE_METHOD(FIXED64, Fixed64)
364WRITE_METHOD(FIXED32, Fixed32)
365WRITE_METHOD(SFIXED64, SFixed64)
366WRITE_METHOD(SFIXED32, SFixed32)
367WRITE_METHOD(BOOL, Bool)
368
369#undef WRITE_METHOD
370
371template <typename Type>
372inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
373 io::CodedInputStream* input, MapEntryAccessorType* value) {
374 return WireFormatLite::ReadMessageNoVirtual(input, value);
375}
376
377template <typename Type>
378inline bool MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
379 io::CodedInputStream* input, MapEntryAccessorType* value) {
380 return WireFormatLite::ReadString(input, value);
381}
382
383template <typename Type>
384inline bool MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
385 io::CodedInputStream* input, MapEntryAccessorType* value) {
386 return WireFormatLite::ReadBytes(input, value);
387}
388
389template <typename Type>
390const char* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
391 const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
392 return ctx->ParseMessage(value, ptr);
393}
394
395template <typename Type>
396const char* MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
397 const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
398 int size = ReadSize(pp: &ptr);
399 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
400 return ctx->ReadString(ptr, size, s: value);
401}
402
403template <typename Type>
404const char* MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
405 const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
406 int size = ReadSize(pp: &ptr);
407 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
408 return ctx->ReadString(ptr, size, s: value);
409}
410
411inline const char* ReadINT64(const char* ptr, int64_t* value) {
412 return VarintParse(p: ptr, out: reinterpret_cast<uint64_t*>(value));
413}
414inline const char* ReadUINT64(const char* ptr, uint64_t* value) {
415 return VarintParse(p: ptr, out: value);
416}
417inline const char* ReadINT32(const char* ptr, int32_t* value) {
418 return VarintParse(p: ptr, out: reinterpret_cast<uint32_t*>(value));
419}
420inline const char* ReadUINT32(const char* ptr, uint32_t* value) {
421 return VarintParse(p: ptr, out: value);
422}
423inline const char* ReadSINT64(const char* ptr, int64_t* value) {
424 *value = ReadVarintZigZag64(p: &ptr);
425 return ptr;
426}
427inline const char* ReadSINT32(const char* ptr, int32_t* value) {
428 *value = ReadVarintZigZag32(p: &ptr);
429 return ptr;
430}
431template <typename E>
432inline const char* ReadENUM(const char* ptr, E* value) {
433 *value = static_cast<E>(ReadVarint32(p: &ptr));
434 return ptr;
435}
436inline const char* ReadBOOL(const char* ptr, bool* value) {
437 *value = static_cast<bool>(ReadVarint32(p: &ptr));
438 return ptr;
439}
440
441template <typename F>
442inline const char* ReadUnaligned(const char* ptr, F* value) {
443 *value = UnalignedLoad<F>(ptr);
444 return ptr + sizeof(F);
445}
446inline const char* ReadFLOAT(const char* ptr, float* value) {
447 return ReadUnaligned(ptr, value);
448}
449inline const char* ReadDOUBLE(const char* ptr, double* value) {
450 return ReadUnaligned(ptr, value);
451}
452inline const char* ReadFIXED64(const char* ptr, uint64_t* value) {
453 return ReadUnaligned(ptr, value);
454}
455inline const char* ReadFIXED32(const char* ptr, uint32_t* value) {
456 return ReadUnaligned(ptr, value);
457}
458inline const char* ReadSFIXED64(const char* ptr, int64_t* value) {
459 return ReadUnaligned(ptr, value);
460}
461inline const char* ReadSFIXED32(const char* ptr, int32_t* value) {
462 return ReadUnaligned(ptr, value);
463}
464
465#define READ_METHOD(FieldType) \
466 template <typename Type> \
467 inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
468 io::CodedInputStream* input, MapEntryAccessorType* value) { \
469 return WireFormatLite::ReadPrimitive<TypeOnMemory, \
470 WireFormatLite::TYPE_##FieldType>( \
471 input, value); \
472 } \
473 template <typename Type> \
474 const char* MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
475 const char* begin, ParseContext* ctx, MapEntryAccessorType* value) { \
476 (void)ctx; \
477 return Read##FieldType(begin, value); \
478 }
479
480READ_METHOD(INT64)
481READ_METHOD(UINT64)
482READ_METHOD(INT32)
483READ_METHOD(UINT32)
484READ_METHOD(SINT64)
485READ_METHOD(SINT32)
486READ_METHOD(ENUM)
487READ_METHOD(DOUBLE)
488READ_METHOD(FLOAT)
489READ_METHOD(FIXED64)
490READ_METHOD(FIXED32)
491READ_METHOD(SFIXED64)
492READ_METHOD(SFIXED32)
493READ_METHOD(BOOL)
494
495#undef READ_METHOD
496
497// Definition for message handler
498
499template <typename Type>
500inline const Type&
501MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetExternalReference(
502 const Type* value) {
503 return *value;
504}
505
506template <typename Type>
507inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
508 Type>::SpaceUsedInMapEntryLong(const Type* value) {
509 return value->SpaceUsedLong();
510}
511
512template <typename Type>
513inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear(
514 Type** value, Arena* /* arena */) {
515 if (*value != nullptr) (*value)->Clear();
516}
517template <typename Type>
518inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Merge(
519 const Type& from, Type** to, Arena* /* arena */) {
520 (*to)->MergeFrom(from);
521}
522
523template <typename Type>
524void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DeleteNoArena(
525 const Type* ptr) {
526 delete ptr;
527}
528
529template <typename Type>
530constexpr auto MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Constinit()
531 -> TypeOnMemory {
532 return nullptr;
533}
534
535template <typename Type>
536inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::EnsureMutable(
537 Type** value, Arena* arena) {
538 if (*value == nullptr) {
539 *value = MapArenaMessageCreator<
540 Type,
541 Arena::is_arena_constructable<Type>::type::value>::CreateMessage(arena);
542 }
543 return *value;
544}
545
546template <typename Type>
547inline const Type&
548MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DefaultIfNotInitialized(
549 const Type* value) {
550 return value != nullptr ? *value : *Type::internal_default_instance();
551}
552
553template <typename Type>
554inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::IsInitialized(
555 Type* value) {
556 return value ? value->IsInitialized() : false;
557}
558
559// Definition for string/bytes handler
560
561#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \
562 template <typename Type> \
563 inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
564 Type>::MapEntryAccessorType& \
565 MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
566 Type>::GetExternalReference(const TypeOnMemory& value) { \
567 return value.Get(); \
568 } \
569 template <typename Type> \
570 inline size_t \
571 MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
572 Type>::SpaceUsedInMapEntryLong(const TypeOnMemory& value) { \
573 return sizeof(value); \
574 } \
575 template <typename Type> \
576 inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
577 TypeOnMemory* value, Arena* /* arena */) { \
578 value->ClearToEmpty(); \
579 } \
580 template <typename Type> \
581 inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
582 const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \
583 to->Set(from, arena); \
584 } \
585 template <typename Type> \
586 void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena( \
587 TypeOnMemory& value) { \
588 value.Destroy(); \
589 } \
590 template <typename Type> \
591 constexpr auto \
592 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \
593 ->TypeOnMemory { \
594 return TypeOnMemory(&internal::fixed_address_empty_string, \
595 ConstantInitialized{}); \
596 } \
597 template <typename Type> \
598 inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
599 Type>::MapEntryAccessorType* \
600 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
601 TypeOnMemory* value, Arena* arena) { \
602 return value->Mutable(arena); \
603 } \
604 template <typename Type> \
605 inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
606 Type>::MapEntryAccessorType& \
607 MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
608 Type>::DefaultIfNotInitialized(const TypeOnMemory& value) { \
609 return value.Get(); \
610 } \
611 template <typename Type> \
612 inline bool \
613 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized( \
614 const TypeOnMemory& /* value */) { \
615 return true; \
616 }
617STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING)
618STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
619#undef STRING_OR_BYTES_HANDLER_FUNCTIONS
620
621#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \
622 template <typename Type> \
623 inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
624 Type>::MapEntryAccessorType& \
625 MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
626 Type>::GetExternalReference(const TypeOnMemory& value) { \
627 return value; \
628 } \
629 template <typename Type> \
630 inline size_t MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>:: \
631 SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) { \
632 return 0; \
633 } \
634 template <typename Type> \
635 inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
636 TypeOnMemory* value, Arena* /* arena */) { \
637 *value = 0; \
638 } \
639 template <typename Type> \
640 inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
641 const MapEntryAccessorType& from, TypeOnMemory* to, \
642 Arena* /* arena */) { \
643 *to = from; \
644 } \
645 template <typename Type> \
646 inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
647 Type>::DeleteNoArena(TypeOnMemory& /* x */) {} \
648 template <typename Type> \
649 constexpr auto \
650 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \
651 ->TypeOnMemory { \
652 return 0; \
653 } \
654 template <typename Type> \
655 inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
656 Type>::MapEntryAccessorType* \
657 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
658 TypeOnMemory* value, Arena* /* arena */) { \
659 return value; \
660 } \
661 template <typename Type> \
662 inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
663 Type>::MapEntryAccessorType& \
664 MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
665 Type>::DefaultIfNotInitialized(const TypeOnMemory& value) { \
666 return value; \
667 } \
668 template <typename Type> \
669 inline bool \
670 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized( \
671 const TypeOnMemory& /* value */) { \
672 return true; \
673 }
674PRIMITIVE_HANDLER_FUNCTIONS(INT64)
675PRIMITIVE_HANDLER_FUNCTIONS(UINT64)
676PRIMITIVE_HANDLER_FUNCTIONS(INT32)
677PRIMITIVE_HANDLER_FUNCTIONS(UINT32)
678PRIMITIVE_HANDLER_FUNCTIONS(SINT64)
679PRIMITIVE_HANDLER_FUNCTIONS(SINT32)
680PRIMITIVE_HANDLER_FUNCTIONS(ENUM)
681PRIMITIVE_HANDLER_FUNCTIONS(DOUBLE)
682PRIMITIVE_HANDLER_FUNCTIONS(FLOAT)
683PRIMITIVE_HANDLER_FUNCTIONS(FIXED64)
684PRIMITIVE_HANDLER_FUNCTIONS(FIXED32)
685PRIMITIVE_HANDLER_FUNCTIONS(SFIXED64)
686PRIMITIVE_HANDLER_FUNCTIONS(SFIXED32)
687PRIMITIVE_HANDLER_FUNCTIONS(BOOL)
688#undef PRIMITIVE_HANDLER_FUNCTIONS
689
690// Functions for operating on a map entry using type handlers.
691//
692// Does not contain any representation (this class is not intended to be
693// instantiated).
694template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
695 WireFormatLite::FieldType kValueFieldType>
696struct MapEntryFuncs {
697 typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
698 typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
699 enum : int {
700 kKeyFieldNumber = 1,
701 kValueFieldNumber = 2
702 };
703
704 static uint8_t* InternalSerialize(int field_number, const Key& key,
705 const Value& value, uint8_t* ptr,
706 io::EpsCopyOutputStream* stream) {
707 ptr = stream->EnsureSpace(ptr);
708 ptr = WireFormatLite::WriteTagToArray(
709 field_number, type: WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target: ptr);
710 ptr = io::CodedOutputStream::WriteVarint32ToArray(value: GetCachedSize(key, value),
711 target: ptr);
712
713 ptr = KeyTypeHandler::Write(kKeyFieldNumber, key, ptr, stream);
714 return ValueTypeHandler::Write(kValueFieldNumber, value, ptr, stream);
715 }
716
717 static size_t ByteSizeLong(const Key& key, const Value& value) {
718 // Tags for key and value will both be one byte (field numbers 1 and 2).
719 size_t inner_length =
720 2 + KeyTypeHandler::ByteSize(key) + ValueTypeHandler::ByteSize(value);
721 return inner_length + io::CodedOutputStream::VarintSize32(
722 value: static_cast<uint32_t>(inner_length));
723 }
724
725 static int GetCachedSize(const Key& key, const Value& value) {
726 // Tags for key and value will both be one byte (field numbers 1 and 2).
727 return 2 + KeyTypeHandler::GetCachedSize(key) +
728 ValueTypeHandler::GetCachedSize(value);
729 }
730};
731
732} // namespace internal
733} // namespace protobuf
734} // namespace google
735
736#endif // GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
737

source code of include/google/protobuf/map_type_handler.h