generated_message_table_driven.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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. // We require C++11 and Clang to use constexpr for variables, as GCC 4.8
  38. // requires constexpr to be consistent between declarations of variables
  39. // unnecessarily (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58541).
  40. // VS 2017 Update 3 also supports this usage of constexpr.
  41. #if defined(__clang__) || (defined(_MSC_VER) && _MSC_VER >= 1911)
  42. #define PROTOBUF_CONSTEXPR_VAR constexpr
  43. #else // !__clang__
  44. #define PROTOBUF_CONSTEXPR_VAR
  45. #endif // !_clang
  46. #ifdef SWIG
  47. #error "You cannot SWIG proto headers"
  48. #endif
  49. #include <google/protobuf/port_def.inc>
  50. namespace google {
  51. namespace protobuf {
  52. namespace internal {
  53. // Processing-type masks.
  54. static constexpr const unsigned char kOneofMask = 0x40;
  55. static constexpr const unsigned char kRepeatedMask = 0x20;
  56. // Mask for the raw type: either a WireFormatLite::FieldType or one of the
  57. // ProcessingTypes below, without the oneof or repeated flag.
  58. static constexpr const unsigned char kTypeMask = 0x1f;
  59. // Wire type masks.
  60. static constexpr const unsigned char kNotPackedMask = 0x10;
  61. static constexpr const unsigned char kInvalidMask = 0x20;
  62. enum ProcessingTypes {
  63. TYPE_STRING_CORD = 19,
  64. TYPE_STRING_STRING_PIECE = 20,
  65. TYPE_BYTES_CORD = 21,
  66. TYPE_BYTES_STRING_PIECE = 22,
  67. TYPE_MAP = 23,
  68. };
  69. static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum");
  70. struct PROTOBUF_EXPORT FieldMetadata {
  71. uint32 offset; // offset of this field in the struct
  72. uint32 tag; // field * 8 + wire_type
  73. // byte offset * 8 + bit_offset;
  74. // if the high bit is set then this is the byte offset of the oneof_case
  75. // for this field.
  76. uint32 has_offset;
  77. uint32 type; // the type of this field.
  78. const void* ptr; // auxiliary data
  79. // From the serializer point of view each fundamental type can occur in
  80. // 4 different ways. For simplicity we treat all combinations as a cartesion
  81. // product although not all combinations are allowed.
  82. enum FieldTypeClass {
  83. kPresence,
  84. kNoPresence,
  85. kRepeated,
  86. kPacked,
  87. kOneOf,
  88. kNumTypeClasses // must be last enum
  89. };
  90. // C++ protobuf has 20 fundamental types, were we added Cord and StringPiece
  91. // and also distinguish the same types if they have different wire format.
  92. enum {
  93. kCordType = 19,
  94. kStringPieceType = 20,
  95. kNumTypes = 20,
  96. kSpecial = kNumTypes * kNumTypeClasses,
  97. };
  98. static int CalculateType(int fundamental_type, FieldTypeClass type_class);
  99. };
  100. // TODO(ckennelly): Add a static assertion to ensure that these masks do not
  101. // conflict with wiretypes.
  102. // ParseTableField is kept small to help simplify instructions for computing
  103. // offsets, as we will always need this information to parse a field.
  104. // Additional data, needed for some types, is stored in
  105. // AuxiliaryParseTableField.
  106. struct ParseTableField {
  107. uint32 offset;
  108. // The presence_index ordinarily represents a has_bit index, but for fields
  109. // inside a oneof it represents the index in _oneof_case_.
  110. uint32 presence_index;
  111. unsigned char normal_wiretype;
  112. unsigned char packed_wiretype;
  113. // processing_type is given by:
  114. // (FieldDescriptor->type() << 1) | FieldDescriptor->is_packed()
  115. unsigned char processing_type;
  116. unsigned char tag_size;
  117. };
  118. struct ParseTable;
  119. union AuxiliaryParseTableField {
  120. typedef bool (*EnumValidator)(int);
  121. // Enums
  122. struct enum_aux {
  123. EnumValidator validator;
  124. };
  125. enum_aux enums;
  126. // Group, messages
  127. struct message_aux {
  128. // ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
  129. // the tables from being constructed as a constexpr. We use void to avoid
  130. // the cast.
  131. const void* default_message_void;
  132. const MessageLite* default_message() const {
  133. return static_cast<const MessageLite*>(default_message_void);
  134. }
  135. };
  136. message_aux messages;
  137. // Strings
  138. struct string_aux {
  139. const void* default_ptr;
  140. const char* field_name;
  141. };
  142. string_aux strings;
  143. struct map_aux {
  144. bool (*parse_map)(io::CodedInputStream*, void*);
  145. };
  146. map_aux maps;
  147. AuxiliaryParseTableField() = default;
  148. constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::enum_aux e)
  149. : enums(e) {}
  150. constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::message_aux m)
  151. : messages(m) {}
  152. constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::string_aux s)
  153. : strings(s) {}
  154. constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::map_aux m)
  155. : maps(m) {}
  156. };
  157. struct ParseTable {
  158. const ParseTableField* fields;
  159. const AuxiliaryParseTableField* aux;
  160. int max_field_number;
  161. // TODO(ckennelly): Do something with this padding.
  162. // TODO(ckennelly): Vet these for sign extension.
  163. int64 has_bits_offset;
  164. int64 oneof_case_offset;
  165. int64 extension_offset;
  166. int64 arena_offset;
  167. // ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
  168. // the tables from being constructed as a constexpr. We use void to avoid
  169. // the cast.
  170. const void* default_instance_void;
  171. const MessageLite* default_instance() const {
  172. return static_cast<const MessageLite*>(default_instance_void);
  173. }
  174. bool unknown_field_set;
  175. };
  176. static_assert(sizeof(ParseTableField) <= 16, "ParseTableField is too large");
  177. // The tables must be composed of POD components to ensure link-time
  178. // initialization.
  179. static_assert(std::is_standard_layout<ParseTableField>::value, "");
  180. static_assert(std::is_trivial<ParseTableField>::value, "");
  181. static_assert(std::is_standard_layout<AuxiliaryParseTableField>::value, "");
  182. static_assert(std::is_trivial<AuxiliaryParseTableField>::value, "");
  183. static_assert(
  184. std::is_standard_layout<AuxiliaryParseTableField::enum_aux>::value, "");
  185. static_assert(std::is_trivial<AuxiliaryParseTableField::enum_aux>::value, "");
  186. static_assert(
  187. std::is_standard_layout<AuxiliaryParseTableField::message_aux>::value, "");
  188. static_assert(std::is_trivial<AuxiliaryParseTableField::message_aux>::value,
  189. "");
  190. static_assert(
  191. std::is_standard_layout<AuxiliaryParseTableField::string_aux>::value, "");
  192. static_assert(std::is_trivial<AuxiliaryParseTableField::string_aux>::value, "");
  193. static_assert(std::is_standard_layout<ParseTable>::value, "");
  194. static_assert(std::is_trivial<ParseTable>::value, "");
  195. // TODO(ckennelly): Consolidate these implementations into a single one, using
  196. // dynamic dispatch to the appropriate unknown field handler.
  197. bool MergePartialFromCodedStream(MessageLite* msg, const ParseTable& table,
  198. io::CodedInputStream* input);
  199. bool MergePartialFromCodedStreamLite(MessageLite* msg, const ParseTable& table,
  200. io::CodedInputStream* input);
  201. template <typename Entry>
  202. bool ParseMap(io::CodedInputStream* input, void* map_field) {
  203. typedef typename MapEntryToMapField<Entry>::MapFieldType MapFieldType;
  204. typedef Map<typename Entry::EntryKeyType, typename Entry::EntryValueType>
  205. MapType;
  206. typedef typename Entry::template Parser<MapFieldType, MapType> ParserType;
  207. ParserType parser(static_cast<MapFieldType*>(map_field));
  208. return WireFormatLite::ReadMessageNoVirtual(input, &parser);
  209. }
  210. struct SerializationTable {
  211. int num_fields;
  212. const FieldMetadata* field_table;
  213. };
  214. PROTOBUF_EXPORT void SerializeInternal(const uint8* base,
  215. const FieldMetadata* table,
  216. int32 num_fields,
  217. io::CodedOutputStream* output);
  218. inline void TableSerialize(const MessageLite& msg,
  219. const SerializationTable* table,
  220. io::CodedOutputStream* output) {
  221. const FieldMetadata* field_table = table->field_table;
  222. int num_fields = table->num_fields - 1;
  223. const uint8* base = reinterpret_cast<const uint8*>(&msg);
  224. // TODO(gerbens) This skips the first test if we could use the fast
  225. // array serialization path, we should make this
  226. // int cached_size =
  227. // *reinterpret_cast<const int32*>(base + field_table->offset);
  228. // SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...)
  229. // But we keep conformance with the old way for now.
  230. SerializeInternal(base, field_table + 1, num_fields, output);
  231. }
  232. PROTOBUF_EXPORT uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table,
  233. int32 num_fields, bool is_deterministic,
  234. uint8* buffer);
  235. inline uint8* TableSerializeToArray(const MessageLite& msg,
  236. const SerializationTable* table,
  237. bool is_deterministic, uint8* buffer) {
  238. const uint8* base = reinterpret_cast<const uint8*>(&msg);
  239. const FieldMetadata* field_table = table->field_table + 1;
  240. int num_fields = table->num_fields - 1;
  241. return SerializeInternalToArray(base, field_table, num_fields,
  242. is_deterministic, buffer);
  243. }
  244. template <typename T>
  245. struct CompareHelper {
  246. bool operator()(const T& a, const T& b) const { return a < b; }
  247. };
  248. template <>
  249. struct CompareHelper<ArenaStringPtr> {
  250. bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) const {
  251. return a.Get() < b.Get();
  252. }
  253. };
  254. struct CompareMapKey {
  255. template <typename T>
  256. bool operator()(const MapEntryHelper<T>& a,
  257. const MapEntryHelper<T>& b) const {
  258. return Compare(a.key_, b.key_);
  259. }
  260. template <typename T>
  261. bool Compare(const T& a, const T& b) const {
  262. return CompareHelper<T>()(a, b);
  263. }
  264. };
  265. template <typename MapFieldType, const SerializationTable* table>
  266. void MapFieldSerializer(const uint8* base, uint32 offset, uint32 tag,
  267. uint32 has_offset, io::CodedOutputStream* output) {
  268. typedef MapEntryHelper<typename MapFieldType::EntryTypeTrait> Entry;
  269. typedef typename MapFieldType::MapType::const_iterator Iter;
  270. const MapFieldType& map_field =
  271. *reinterpret_cast<const MapFieldType*>(base + offset);
  272. const SerializationTable* t =
  273. table +
  274. has_offset; // has_offset is overloaded for maps to mean table offset
  275. if (!output->IsSerializationDeterministic()) {
  276. for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
  277. ++it) {
  278. Entry map_entry(*it);
  279. output->WriteVarint32(tag);
  280. output->WriteVarint32(map_entry._cached_size_);
  281. SerializeInternal(reinterpret_cast<const uint8*>(&map_entry),
  282. t->field_table, t->num_fields, output);
  283. }
  284. } else {
  285. std::vector<Entry> v;
  286. for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
  287. ++it) {
  288. v.push_back(Entry(*it));
  289. }
  290. std::sort(v.begin(), v.end(), CompareMapKey());
  291. for (int i = 0; i < v.size(); i++) {
  292. output->WriteVarint32(tag);
  293. output->WriteVarint32(v[i]._cached_size_);
  294. SerializeInternal(reinterpret_cast<const uint8*>(&v[i]), t->field_table,
  295. t->num_fields, output);
  296. }
  297. }
  298. }
  299. } // namespace internal
  300. } // namespace protobuf
  301. } // namespace google
  302. #include <google/protobuf/port_undef.inc>
  303. #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__