generated_message_table_driven.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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_GENERATED_MESSAGE_TABLE_DRIVEN_H__
  31. #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__
  32. #include <google/protobuf/map.h>
  33. #include <google/protobuf/map_entry_lite.h>
  34. #include <google/protobuf/map_field_lite.h>
  35. #include <google/protobuf/message_lite.h>
  36. #include <google/protobuf/wire_format_lite.h>
  37. #include <google/protobuf/wire_format_lite_inl.h>
  38. // We require C++11 and Clang to use constexpr for variables, as GCC 4.8
  39. // requires constexpr to be consistent between declarations of variables
  40. // unnecessarily (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58541).
  41. // VS 2017 Update 3 also supports this usage of constexpr.
  42. #if defined(__clang__) || (defined(_MSC_VER) && _MSC_VER >= 1911)
  43. #define PROTOBUF_CONSTEXPR_VAR constexpr
  44. #else // !__clang__
  45. #define PROTOBUF_CONSTEXPR_VAR
  46. #endif // !_clang
  47. namespace google {
  48. namespace protobuf {
  49. namespace internal {
  50. // Processing-type masks.
  51. static constexpr const unsigned char kOneofMask = 0x40;
  52. static constexpr const unsigned char kRepeatedMask = 0x20;
  53. // Mask for the raw type: either a WireFormatLite::FieldType or one of the
  54. // ProcessingTypes below, without the oneof or repeated flag.
  55. static constexpr const unsigned char kTypeMask = 0x1f;
  56. // Wire type masks.
  57. static constexpr const unsigned char kNotPackedMask = 0x10;
  58. static constexpr const unsigned char kInvalidMask = 0x20;
  59. enum ProcessingTypes {
  60. TYPE_STRING_INLINED = 23,
  61. TYPE_BYTES_INLINED = 24,
  62. TYPE_MAP = 25,
  63. };
  64. static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum");
  65. // TODO(ckennelly): Add a static assertion to ensure that these masks do not
  66. // conflict with wiretypes.
  67. // ParseTableField is kept small to help simplify instructions for computing
  68. // offsets, as we will always need this information to parse a field.
  69. // Additional data, needed for some types, is stored in
  70. // AuxillaryParseTableField.
  71. struct ParseTableField {
  72. uint32 offset;
  73. // The presence_index ordinarily represents a has_bit index, but for fields
  74. // inside a oneof it represents the index in _oneof_case_.
  75. uint32 presence_index;
  76. unsigned char normal_wiretype;
  77. unsigned char packed_wiretype;
  78. // processing_type is given by:
  79. // (FieldDescriptor->type() << 1) | FieldDescriptor->is_packed()
  80. unsigned char processing_type;
  81. unsigned char tag_size;
  82. };
  83. struct ParseTable;
  84. union AuxillaryParseTableField {
  85. typedef bool (*EnumValidator)(int);
  86. // Enums
  87. struct enum_aux {
  88. EnumValidator validator;
  89. };
  90. enum_aux enums;
  91. // Group, messages
  92. struct message_aux {
  93. // ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
  94. // the tables from being constructed as a constexpr. We use void to avoid
  95. // the cast.
  96. const void* default_message_void;
  97. const MessageLite* default_message() const {
  98. return static_cast<const MessageLite*>(default_message_void);
  99. }
  100. };
  101. message_aux messages;
  102. // Strings
  103. struct string_aux {
  104. const void* default_ptr;
  105. const char* field_name;
  106. };
  107. string_aux strings;
  108. struct map_aux {
  109. bool (*parse_map)(io::CodedInputStream*, void*);
  110. };
  111. map_aux maps;
  112. AuxillaryParseTableField() = default;
  113. constexpr AuxillaryParseTableField(AuxillaryParseTableField::enum_aux e)
  114. : enums(e) {}
  115. constexpr AuxillaryParseTableField(AuxillaryParseTableField::message_aux m)
  116. : messages(m) {}
  117. constexpr AuxillaryParseTableField(AuxillaryParseTableField::string_aux s)
  118. : strings(s) {}
  119. constexpr AuxillaryParseTableField(AuxillaryParseTableField::map_aux m)
  120. : maps(m) {}
  121. };
  122. struct ParseTable {
  123. const ParseTableField* fields;
  124. const AuxillaryParseTableField* aux;
  125. int max_field_number;
  126. // TODO(ckennelly): Do something with this padding.
  127. // TODO(ckennelly): Vet these for sign extension.
  128. int64 has_bits_offset;
  129. int64 oneof_case_offset;
  130. int64 extension_offset;
  131. int64 arena_offset;
  132. // ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
  133. // the tables from being constructed as a constexpr. We use void to avoid
  134. // the cast.
  135. const void* default_instance_void;
  136. const MessageLite* default_instance() const {
  137. return static_cast<const MessageLite*>(default_instance_void);
  138. }
  139. bool unknown_field_set;
  140. };
  141. static_assert(sizeof(ParseTableField) <= 16, "ParseTableField is too large");
  142. // The tables must be composed of POD components to ensure link-time
  143. // initialization.
  144. static_assert(std::is_pod<ParseTableField>::value, "");
  145. static_assert(std::is_pod<AuxillaryParseTableField::enum_aux>::value, "");
  146. static_assert(std::is_pod<AuxillaryParseTableField::message_aux>::value, "");
  147. static_assert(std::is_pod<AuxillaryParseTableField::string_aux>::value, "");
  148. static_assert(std::is_pod<ParseTable>::value, "");
  149. #ifndef __NVCC__ // This assertion currently fails under NVCC.
  150. static_assert(std::is_pod<AuxillaryParseTableField>::value, "");
  151. #endif
  152. // TODO(ckennelly): Consolidate these implementations into a single one, using
  153. // dynamic dispatch to the appropriate unknown field handler.
  154. bool MergePartialFromCodedStream(MessageLite* msg, const ParseTable& table,
  155. io::CodedInputStream* input);
  156. bool MergePartialFromCodedStreamLite(MessageLite* msg, const ParseTable& table,
  157. io::CodedInputStream* input);
  158. template <typename Entry>
  159. bool ParseMap(io::CodedInputStream* input, void* map_field) {
  160. typedef typename MapEntryToMapField<Entry>::MapFieldType MapFieldType;
  161. typedef google::protobuf::Map<typename Entry::EntryKeyType,
  162. typename Entry::EntryValueType>
  163. MapType;
  164. typedef typename Entry::template Parser<MapFieldType, MapType> ParserType;
  165. ParserType parser(static_cast<MapFieldType*>(map_field));
  166. return ::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(input,
  167. &parser);
  168. }
  169. } // namespace internal
  170. } // namespace protobuf
  171. } // namespace google
  172. #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__