extension_set_inl.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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_EXTENSION_SET_INL_H__
  31. #define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
  32. #include <google/protobuf/parse_context.h>
  33. #include <google/protobuf/extension_set.h>
  34. #include <google/protobuf/metadata_lite.h>
  35. namespace google {
  36. namespace protobuf {
  37. namespace internal {
  38. template <typename T>
  39. const char* ExtensionSet::ParseFieldWithExtensionInfo(
  40. int number, bool was_packed_on_wire, const ExtensionInfo& extension,
  41. InternalMetadata* metadata, const char* ptr, internal::ParseContext* ctx) {
  42. if (was_packed_on_wire) {
  43. switch (extension.type) {
  44. #define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE) \
  45. case WireFormatLite::TYPE_##UPPERCASE: \
  46. return internal::Packed##CPP_CAMELCASE##Parser( \
  47. MutableRawRepeatedField(number, extension.type, extension.is_packed, \
  48. extension.descriptor), \
  49. ptr, ctx);
  50. HANDLE_TYPE(INT32, Int32);
  51. HANDLE_TYPE(INT64, Int64);
  52. HANDLE_TYPE(UINT32, UInt32);
  53. HANDLE_TYPE(UINT64, UInt64);
  54. HANDLE_TYPE(SINT32, SInt32);
  55. HANDLE_TYPE(SINT64, SInt64);
  56. HANDLE_TYPE(FIXED32, Fixed32);
  57. HANDLE_TYPE(FIXED64, Fixed64);
  58. HANDLE_TYPE(SFIXED32, SFixed32);
  59. HANDLE_TYPE(SFIXED64, SFixed64);
  60. HANDLE_TYPE(FLOAT, Float);
  61. HANDLE_TYPE(DOUBLE, Double);
  62. HANDLE_TYPE(BOOL, Bool);
  63. #undef HANDLE_TYPE
  64. case WireFormatLite::TYPE_ENUM:
  65. return internal::PackedEnumParserArg<T>(
  66. MutableRawRepeatedField(number, extension.type, extension.is_packed,
  67. extension.descriptor),
  68. ptr, ctx, extension.enum_validity_check.func,
  69. extension.enum_validity_check.arg, metadata, number);
  70. case WireFormatLite::TYPE_STRING:
  71. case WireFormatLite::TYPE_BYTES:
  72. case WireFormatLite::TYPE_GROUP:
  73. case WireFormatLite::TYPE_MESSAGE:
  74. GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
  75. break;
  76. }
  77. } else {
  78. switch (extension.type) {
  79. #define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE) \
  80. case WireFormatLite::TYPE_##UPPERCASE: { \
  81. uint64 value; \
  82. ptr = VarintParse(ptr, &value); \
  83. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
  84. if (extension.is_repeated) { \
  85. Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
  86. extension.is_packed, value, extension.descriptor); \
  87. } else { \
  88. Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
  89. extension.descriptor); \
  90. } \
  91. } break
  92. HANDLE_VARINT_TYPE(INT32, Int32);
  93. HANDLE_VARINT_TYPE(INT64, Int64);
  94. HANDLE_VARINT_TYPE(UINT32, UInt32);
  95. HANDLE_VARINT_TYPE(UINT64, UInt64);
  96. HANDLE_VARINT_TYPE(BOOL, Bool);
  97. #undef HANDLE_VARINT_TYPE
  98. #define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE) \
  99. case WireFormatLite::TYPE_##UPPERCASE: { \
  100. uint64 val; \
  101. ptr = VarintParse(ptr, &val); \
  102. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
  103. auto value = WireFormatLite::ZigZagDecode##SIZE(val); \
  104. if (extension.is_repeated) { \
  105. Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
  106. extension.is_packed, value, extension.descriptor); \
  107. } else { \
  108. Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
  109. extension.descriptor); \
  110. } \
  111. } break
  112. HANDLE_SVARINT_TYPE(SINT32, Int32, 32);
  113. HANDLE_SVARINT_TYPE(SINT64, Int64, 64);
  114. #undef HANDLE_SVARINT_TYPE
  115. #define HANDLE_FIXED_TYPE(UPPERCASE, CPP_CAMELCASE, CPPTYPE) \
  116. case WireFormatLite::TYPE_##UPPERCASE: { \
  117. auto value = UnalignedLoad<CPPTYPE>(ptr); \
  118. ptr += sizeof(CPPTYPE); \
  119. if (extension.is_repeated) { \
  120. Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
  121. extension.is_packed, value, extension.descriptor); \
  122. } else { \
  123. Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
  124. extension.descriptor); \
  125. } \
  126. } break
  127. HANDLE_FIXED_TYPE(FIXED32, UInt32, uint32);
  128. HANDLE_FIXED_TYPE(FIXED64, UInt64, uint64);
  129. HANDLE_FIXED_TYPE(SFIXED32, Int32, int32);
  130. HANDLE_FIXED_TYPE(SFIXED64, Int64, int64);
  131. HANDLE_FIXED_TYPE(FLOAT, Float, float);
  132. HANDLE_FIXED_TYPE(DOUBLE, Double, double);
  133. #undef HANDLE_FIXED_TYPE
  134. case WireFormatLite::TYPE_ENUM: {
  135. uint64 val;
  136. ptr = VarintParse(ptr, &val);
  137. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
  138. int value = val;
  139. if (!extension.enum_validity_check.func(
  140. extension.enum_validity_check.arg, value)) {
  141. WriteVarint(number, val, metadata->mutable_unknown_fields<T>());
  142. } else if (extension.is_repeated) {
  143. AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value,
  144. extension.descriptor);
  145. } else {
  146. SetEnum(number, WireFormatLite::TYPE_ENUM, value,
  147. extension.descriptor);
  148. }
  149. break;
  150. }
  151. case WireFormatLite::TYPE_BYTES:
  152. case WireFormatLite::TYPE_STRING: {
  153. std::string* value =
  154. extension.is_repeated
  155. ? AddString(number, WireFormatLite::TYPE_STRING,
  156. extension.descriptor)
  157. : MutableString(number, WireFormatLite::TYPE_STRING,
  158. extension.descriptor);
  159. int size = ReadSize(&ptr);
  160. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
  161. return ctx->ReadString(ptr, size, value);
  162. }
  163. case WireFormatLite::TYPE_GROUP: {
  164. MessageLite* value =
  165. extension.is_repeated
  166. ? AddMessage(number, WireFormatLite::TYPE_GROUP,
  167. *extension.message_info.prototype,
  168. extension.descriptor)
  169. : MutableMessage(number, WireFormatLite::TYPE_GROUP,
  170. *extension.message_info.prototype,
  171. extension.descriptor);
  172. uint32 tag = (number << 3) + WireFormatLite::WIRETYPE_START_GROUP;
  173. return ctx->ParseGroup(value, ptr, tag);
  174. }
  175. case WireFormatLite::TYPE_MESSAGE: {
  176. MessageLite* value =
  177. extension.is_repeated
  178. ? AddMessage(number, WireFormatLite::TYPE_MESSAGE,
  179. *extension.message_info.prototype,
  180. extension.descriptor)
  181. : MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
  182. *extension.message_info.prototype,
  183. extension.descriptor);
  184. return ctx->ParseMessage(value, ptr);
  185. }
  186. }
  187. }
  188. return ptr;
  189. }
  190. template <typename Msg, typename T>
  191. const char* ExtensionSet::ParseMessageSetItemTmpl(
  192. const char* ptr, const Msg* containing_type,
  193. internal::InternalMetadata* metadata, internal::ParseContext* ctx) {
  194. std::string payload;
  195. uint32 type_id = 0;
  196. bool payload_read = false;
  197. while (!ctx->Done(&ptr)) {
  198. uint32 tag = static_cast<uint8>(*ptr++);
  199. if (tag == WireFormatLite::kMessageSetTypeIdTag) {
  200. uint64 tmp;
  201. ptr = ParseBigVarint(ptr, &tmp);
  202. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
  203. type_id = tmp;
  204. if (payload_read) {
  205. ExtensionInfo extension;
  206. bool was_packed_on_wire;
  207. if (!FindExtension(2, type_id, containing_type, ctx, &extension,
  208. &was_packed_on_wire)) {
  209. WriteLengthDelimited(type_id, payload,
  210. metadata->mutable_unknown_fields<T>());
  211. } else {
  212. MessageLite* value =
  213. extension.is_repeated
  214. ? AddMessage(type_id, WireFormatLite::TYPE_MESSAGE,
  215. *extension.message_info.prototype,
  216. extension.descriptor)
  217. : MutableMessage(type_id, WireFormatLite::TYPE_MESSAGE,
  218. *extension.message_info.prototype,
  219. extension.descriptor);
  220. const char* p;
  221. // We can't use regular parse from string as we have to track
  222. // proper recursion depth and descriptor pools.
  223. ParseContext tmp_ctx(ctx->depth(), false, &p, payload);
  224. tmp_ctx.data().pool = ctx->data().pool;
  225. tmp_ctx.data().factory = ctx->data().factory;
  226. GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) &&
  227. tmp_ctx.EndedAtLimit());
  228. }
  229. type_id = 0;
  230. }
  231. } else if (tag == WireFormatLite::kMessageSetMessageTag) {
  232. if (type_id != 0) {
  233. ptr = ParseFieldMaybeLazily(static_cast<uint64>(type_id) * 8 + 2, ptr,
  234. containing_type, metadata, ctx);
  235. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
  236. type_id = 0;
  237. } else {
  238. int32 size = ReadSize(&ptr);
  239. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
  240. ptr = ctx->ReadString(ptr, size, &payload);
  241. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
  242. payload_read = true;
  243. }
  244. } else {
  245. ptr = ReadTag(ptr - 1, &tag);
  246. if (tag == 0 || (tag & 7) == 4) {
  247. ctx->SetLastTag(tag);
  248. return ptr;
  249. }
  250. ptr = ParseField(tag, ptr, containing_type, metadata, ctx);
  251. GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
  252. }
  253. }
  254. return ptr;
  255. }
  256. } // namespace internal
  257. } // namespace protobuf
  258. } // namespace google
  259. #endif // GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__